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 <[email protected]>
---
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 [email protected].
For more options, visit https://groups.google.com/d/optout.