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(&eth_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.

Reply via email to