Add ARP protocol generation: trafgen/trafgen --dev lo eth da = AA:BB:CC:DD:EE:FF sa=11:22:33:44:55:66, arp op=rep tip=192.168.1.1 -n 1 trafgen/trafgen --dev lo arp -n 1
By default 'Gratuitous' ARP packet is sent. Signed-off-by: Vadim Kochan <vadi...@gmail.com> --- layer2_gen.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/layer2_gen.c b/layer2_gen.c index a338dbd..6cc2cdf 100644 --- a/layer2_gen.c +++ b/layer2_gen.c @@ -139,7 +139,172 @@ static struct proto_gen eth_gen = { .check_fields = eth_check_fields, }; +enum arp_field { + ARP_HW_TYPE, + ARP_PROT_TYPE, + ARP_HW_LEN, + ARP_PROT_LEN, + ARP_OP_TYPE, + ARP_SNDR_HADDR, + ARP_SNDR_PADDR, + ARP_TRGT_HADDR, + ARP_TRGT_PADDR, +}; + +static void arp_proto_init(struct proto_gen *prot) +{ + proto_field_add(prot, ARP_HW_TYPE, 2); + proto_field_add(prot, ARP_PROT_TYPE, 2); + proto_field_add(prot, ARP_HW_LEN, 1); + proto_field_add(prot, ARP_PROT_LEN, 1); + proto_field_add(prot, ARP_OP_TYPE, 2); + proto_field_add(prot, ARP_SNDR_HADDR, 6); + proto_field_add(prot, ARP_SNDR_PADDR, 4); + proto_field_add(prot, ARP_TRGT_HADDR, 6); + proto_field_add(prot, ARP_TRGT_PADDR, 4); + + /* set defaults */ + proto_field_set_value(prot, ARP_HW_TYPE, htons(ARPHRD_ETHER)); + proto_field_set_value(prot, ARP_PROT_TYPE, htons(ETH_P_IP)); + proto_field_set_value(prot, ARP_HW_LEN, 6); + proto_field_set_value(prot, ARP_PROT_LEN, 4); + proto_field_set_value(prot, ARP_OP_TYPE, htons(ARPOP_REQUEST)); +} + +static int arp_parse_param(struct proto_gen *prot, char *name, char *val) +{ + if (!strcasecmp("tmac", name) || !strcasecmp("tha", name) || + !strcasecmp("targetmac", name)) { + + uint8_t mac[6]; + int ret = str2mac(val, &mac[0]); + + proto_field_set_bytes(prot, ARP_TRGT_HADDR, &mac[0]); + return ret == 0 ? ARP_TRGT_HADDR : -1; + } + + if (!strcasecmp("smac", name) || !strcasecmp("tha", name) || + !strcasecmp("sendermac", name)) { + + uint8_t mac[6]; + int ret = str2mac(val, &mac[0]); + + proto_field_set_bytes(prot, ARP_SNDR_HADDR, &mac[0]); + return ret == 0 ? ARP_SNDR_HADDR : -1; + } + + if (!strcasecmp("tip", name) || !strcasecmp("tpa", name) || + !strcasecmp("targetip", name)) { + + uint8_t ip[4]; + int ret = str2addr(AF_INET, val, &ip[0]); + + proto_field_set_bytes(prot, ARP_TRGT_PADDR, &ip[0]); + return ret == 0 ? ARP_TRGT_PADDR : -1; + } + + if (!strcasecmp("sip", name) || !strcasecmp("spa", name) || + !strcasecmp("senderip", name)) { + + uint8_t ip[4]; + int ret = str2addr(AF_INET, val, &ip[0]); + + proto_field_set_bytes(prot, ARP_SNDR_PADDR, &ip[0]); + return ret == 0 ? ARP_SNDR_PADDR : -1; + } + + if (!strcasecmp("op", name) || !strcasecmp("oper", name)) { + int op = ARPOP_REQUEST; + + if (!strncasecmp("rep", val, 3)) + op = ARPOP_REPLY; + else if (!strncasecmp("rreq", val, 4)) + op = ARPOP_RREQUEST; + else if (!strncasecmp("rrep", val, 4)) + op = ARPOP_RREPLY; + else if (!strncasecmp("in-req", val, 5)) + op = ARPOP_InREQUEST; + else if (!strncasecmp("in-rep", val, 5)) + op = ARPOP_InREPLY; + else if (!strcasecmp("nak", val)) + op = ARPOP_NAK; + else if (strncasecmp("req", val, 3)) + return -1; + + proto_field_set_value(prot, ARP_OP_TYPE, htons(op)); + return ARP_OP_TYPE; + } + + return -1; +} + +static void arp_print_help(struct proto_gen *prot) +{ +#define ARP_PROT_HELP \ + "| arp proto: Sends ARP packets.\n" \ + "| Parameters:\n" \ + "|\n" \ + "| sip,spa,senderip = XXX.XXX.XXX.XXX ..... Sender Proto address\n" \ + "| smac,sha,sendermac = XX:XX:XX:XX:XX:XX ..... Sender HW address\n" \ + "| tip,tpa,targetip = XXX.XXX.XXX.XXX ..... Target Proto address\n" \ + "| tmac,tha,targetmac = XX:XX:XX:XX:XX:XX ..... Target HW address\n" \ + "| op,oper = rep{ly}|req{uest}|rreq{uest}|in-req{uest}|nak ..... Operation type\n" \ + "|\n" \ + "| EXAMPLES:\n" \ + "| trafgen/trafgen --dev lo eth da = AA:BB:CC:DD:EE:FF sa=11:22:33:44:55:66, arp op=rep tip=192.168.1.1 -n 1\n" \ + "| trafgen/trafgen --dev lo arp -n 1\n" \ + "|\n" \ + "\n" + + printf(ARP_PROT_HELP); +} + +static void arp_check_fields(struct proto_gen *prot) +{ + if (!proto_field_is_set(prot, ARP_SNDR_HADDR)) { + uint8_t addr[6]; + + if (!device_hw_address(prot->ctx->device, &addr[0])) + proto_field_set_bytes(prot, ARP_SNDR_HADDR, &addr[0]); + } + + if (!proto_field_is_set(prot, ARP_TRGT_HADDR)) { + uint8_t bcast[6] = ETH_BCAST_ADDR; + + proto_field_set_bytes(prot, ARP_TRGT_HADDR, &bcast[0]); + } + + if (!proto_field_is_set(prot, ARP_SNDR_PADDR)) { + struct sockaddr_storage ss; + struct sockaddr_in *ss4 = (struct sockaddr_in *)&ss; + + if (!device_address(prot->ctx->device, AF_INET, &ss)) + proto_field_set_value(prot, ARP_SNDR_PADDR, + ss4->sin_addr.s_addr); + } + + if (!proto_field_is_set(prot, ARP_TRGT_PADDR)) { + struct sockaddr_storage ss; + struct sockaddr_in *ss4 = (struct sockaddr_in *)&ss; + + if (!device_address(prot->ctx->device, AF_INET, &ss)) + proto_field_set_value(prot, ARP_TRGT_PADDR, + ss4->sin_addr.s_addr); + } +} + +static struct proto_gen arp_gen = { + .id = NET_PROTO_ARP, + .layer_proto = NET_PROTO_ETH, + .name = "arp", + .proto_init = arp_proto_init, + .parse_param = arp_parse_param, + .print_help = arp_print_help, + .check_fields = arp_check_fields, +}; + void layer2_gen_register(void) { proto_gen_register(ð_gen); + proto_gen_register(&arp_gen); } -- 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.