Add Ethernet packet generation via command line: trafgen --dev eth0 eth sa=af:cd:4b:c3:56:6a da=af:cd:4b:c3:56:6a proto=0x0800
Added separated layer2_gen.c module which will contain L2 related proto generators. By default source MAC address is used from specified device, and destination MAC address is broadcast FF:FF:FF:FF:FF:FF. Signed-off-by: Vadim Kochan <vadi...@gmail.com> --- layer2_gen.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ proto_gen.c | 3 ++ trafgen/Makefile | 2 + 3 files changed, 150 insertions(+) create mode 100644 layer2_gen.c diff --git a/layer2_gen.c b/layer2_gen.c new file mode 100644 index 0000000..a338dbd --- /dev/null +++ b/layer2_gen.c @@ -0,0 +1,145 @@ +/* + * netsniff-ng - the packet sniffing beast + * Subject to the GPL, version 2. + */ + +#include <net/if_arp.h> +#include <linux/if_ether.h> + +#include "dev.h" +#include "xmalloc.h" +#include "net_utils.h" +#include "proto_gen.h" + +#define ETH_BCAST_ADDR { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } + +enum eth_field { + ETH_DST_ADDR, + ETH_SRC_ADDR, + ETH_PROTO_ID, +}; + +static void eth_set_proto_field(struct proto_gen *prot, int proto_id) +{ + if (!proto_field_exist(prot, ETH_PROTO_ID)) + proto_field_add(prot, ETH_PROTO_ID, 2); + + proto_field_set_value(prot, ETH_PROTO_ID, proto_id); +} + +static int eth_parse_param(struct proto_gen *prot, char *name, char *val) +{ + uint8_t addr[6] = {}; + + if (!strcasecmp("dst", name) || !strcasecmp("da", name)) { + int ret = str2mac(val, &addr[0]); + proto_field_set_bytes(prot, ETH_DST_ADDR, &addr[0]); + + return ret == 0 ? ETH_DST_ADDR : -1; + } + + if (!strcasecmp("src", name) || !strcasecmp("sa", name)) { + int ret = str2mac(val, &addr[0]); + proto_field_set_bytes(prot, ETH_SRC_ADDR, &addr[0]); + + return ret == 0 ? ETH_SRC_ADDR : -1; + } + + if (!strcasecmp("type", name) || !strcasecmp("proto", name)) { + char *ptr = NULL; + int proto_id = htons(strtol(val, &ptr, 0)); + + if (errno == ERANGE || errno == EINVAL || ptr == val) + return -1; + + eth_set_proto_field(prot, proto_id); + return ETH_PROTO_ID; + } + + return -1; +} + +static void eth_set_next_proto(struct proto_gen *prot, struct proto_gen *next) +{ + int proto_id = 0; + + switch (next->id) { + case NET_PROTO_ARP: + proto_id = ETH_P_ARP; + break; + case NET_PROTO_IPV4: + proto_id = ETH_P_IP; + break; + case NET_PROTO_IPV6: + proto_id = ETH_P_IPV6; + break; + case NET_PROTO_NONE: + case NET_PROTO_ETH: + case NET_PROTO_UDP: + case NET_PROTO_TCP: + break; + } + + eth_set_proto_field(prot, htons(proto_id)); +} + +static void eth_print_help(struct proto_gen *prot) +{ +#define ETH_PROT_HELP \ + "| eth proto: Sends Ethernet packets.\n" \ + "| Parameters:\n" \ + "|\n" \ + "| src,sa = XX:XX:XX:XX:XX:XX ..... Source MAC address\n" \ + "| dst,da = XX:XX:XX:XX:XX:XX ..... Destination MAC address\n" \ + "| proto,type = decimal | 0xXXX ..... Sets proto/type/len value\n" \ + "| data,payload = hexadecimal ..... Binary payload data\n" \ + "| text = ascii string ..... Textual payload data\n" \ + "|\n" \ + "| EXAMPLES:\n" \ + "| trafgen --dev eth0 eth sa=af:cd:4b:c3:56:6a da=af:cd:4b:c3:56:6a proto=0x0800\n" \ + "|\n" \ + "\n" + + printf(ETH_PROT_HELP); +} + +static void eth_check_fields(struct proto_gen *prot) +{ + if (!proto_field_is_set(prot, ETH_DST_ADDR)) { + uint8_t bcast[6] = ETH_BCAST_ADDR; + + proto_field_set_bytes(prot, ETH_DST_ADDR, &bcast[0]); + } + + if (!proto_field_is_set(prot, ETH_SRC_ADDR)) { + uint8_t addr[6] = {0}; + + if (!device_hw_address(prot->ctx->device, &addr[0])) + proto_field_set_bytes(prot, ETH_SRC_ADDR, &addr[0]); + } +} + +static void eth_proto_init(struct proto_gen *prot) +{ + proto_field_add(prot, ETH_DST_ADDR, 6); + proto_field_add(prot, ETH_SRC_ADDR, 6); + + /* Do not add proto field here as it can be set + * from specified payload or after vlan headers */ +} + +static struct proto_gen eth_gen = { + .id = NET_PROTO_ETH, + .name = "eth", + .min_size = 15, + .proto_init = eth_proto_init, + .parse_param = eth_parse_param, + .set_next_proto = eth_set_next_proto, + .print_help = eth_print_help, + .check_fields = eth_check_fields, +}; + +void layer2_gen_register(void) +{ + proto_gen_register(ð_gen); +} diff --git a/proto_gen.c b/proto_gen.c index eee6227..1abebab 100644 --- a/proto_gen.c +++ b/proto_gen.c @@ -11,6 +11,8 @@ static struct proto_gen *protos; +extern void layer2_gen_register(void); + struct proto_gen *proto_gen_by_name(char *name) { struct proto_gen *p = protos; @@ -41,6 +43,7 @@ void proto_gen_register(struct proto_gen *prot) void proto_gen_init(void) { + layer2_gen_register(); } void proto_gen_uninit(void) diff --git a/trafgen/Makefile b/trafgen/Makefile index c935c0b..723cd8d 100644 --- a/trafgen/Makefile +++ b/trafgen/Makefile @@ -18,6 +18,8 @@ trafgen-objs = xmalloc.o \ ring.o \ timer.o \ proto_gen.o \ + net_utils.o \ + layer2_gen.o \ trafgen_lexer.yy.o \ trafgen_parser.tab.o \ trafgen.o -- 2.4.2 -- You received this message because you are subscribed to the Google Groups "netsniff-ng" group. To unsubscribe from this group and stop receiving emails from it, send an email to netsniff-ng+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.