ring_tx: handle EINTR from sendto
[netsniff-ng.git] / proto_arp.c
blob3560cd12f0748f32cb4bc036bd3f41d379658334
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdint.h>
8 #include <arpa/inet.h>
9 #include <netinet/in.h> /* for ntohs() */
10 #include <linux/if_ether.h>
12 #include "proto.h"
13 #include "protos.h"
14 #include "lookup.h"
15 #include "pkt_buff.h"
16 #include "built_in.h"
18 struct arphdr {
19 uint16_t ar_hrd; /* format of hardware address */
20 uint16_t ar_pro; /* format of protocol address */
21 uint8_t ar_hln; /* length of hardware address */
22 uint8_t ar_pln; /* length of protocol address */
23 uint16_t ar_op; /* ARP opcode (command) */
24 uint8_t ar_sha[6]; /* sender hardware address */
25 uint8_t ar_sip[4]; /* sender IP address */
26 uint8_t ar_tha[6]; /* target hardware address */
27 uint8_t ar_tip[4]; /* target IP address */
28 } __packed;
30 #define ARPHRD_ETHER 1
31 #define ARPHRD_IEEE802 6
32 #define ARPHRD_ARCNET 7
33 #define ARPHRD_ATM 16
34 #define ARPHRD_ATM2 19
35 #define ARPHRD_SERIAL 20
36 #define ARPHRD_ATM3 21
37 #define ARPHRD_IEEE1394 24
39 #define ARPOP_REQUEST 1 /* ARP request */
40 #define ARPOP_REPLY 2 /* ARP reply */
41 #define ARPOP_RREQUEST 3 /* RARP request */
42 #define ARPOP_RREPLY 4 /* RARP reply */
43 #define ARPOP_InREQUEST 8 /* InARP request */
44 #define ARPOP_InREPLY 9 /* InARP reply */
45 #define ARPOP_NAK 10 /* (ATM)ARP NAK */
47 enum addr_direct {
48 ADDR_SENDER,
49 ADDR_TARGET,
52 static void arp_print_addrs(struct arphdr *arp, enum addr_direct addr_dir)
54 const char *dir = addr_dir == ADDR_SENDER ? "Sender" : "Target";
56 if (ntohs(arp->ar_hrd) == ARPHRD_ETHER) {
57 uint8_t *mac;
59 mac = addr_dir == ADDR_SENDER ? &arp->ar_sha[0] : &arp->ar_tha[0];
61 tprintf(", %s MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x)",
62 dir, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
65 if (ntohs(arp->ar_pro) == ETH_P_IP) {
66 char ip_str[INET_ADDRSTRLEN];
67 uint32_t ip;
69 if (addr_dir == ADDR_SENDER)
70 ip = *(uint32_t *)&arp->ar_sip[0];
71 else
72 ip = *(uint32_t *)&arp->ar_tip[0];
74 inet_ntop(AF_INET, &ip, ip_str, sizeof(ip_str));
76 tprintf(", %s IP (%s)", dir, ip_str);
80 static void arp(struct pkt_buff *pkt)
82 char *hrd;
83 const char *pro;
84 char *opcode;
85 struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp));
87 if (arp == NULL)
88 return;
90 switch (ntohs(arp->ar_hrd)) {
91 case ARPHRD_ETHER:
92 hrd = "Ethernet";
93 break;
94 case ARPHRD_IEEE802:
95 hrd = "IEEE 802";
96 break;
97 case ARPHRD_ARCNET:
98 hrd = "ARCNET";
99 break;
100 case ARPHRD_ATM:
101 case ARPHRD_ATM2:
102 case ARPHRD_ATM3:
103 hrd = "ATM";
104 break;
105 case ARPHRD_SERIAL:
106 hrd = "Serial Line";
107 break;
108 case ARPHRD_IEEE1394:
109 hrd = "IEEE 1394.1995";
110 break;
111 default:
112 hrd = "Unknown";
113 break;
116 pro = lookup_ether_type(ntohs(arp->ar_pro));
117 if (pro == NULL)
118 pro = "Unknown";
120 switch (ntohs(arp->ar_op)) {
121 case ARPOP_REQUEST:
122 opcode = "ARP request";
123 break;
124 case ARPOP_REPLY:
125 opcode = "ARP reply";
126 break;
127 case ARPOP_RREQUEST:
128 opcode = "RARP request";
129 break;
130 case ARPOP_RREPLY:
131 opcode = "RARP reply";
132 break;
133 case ARPOP_InREQUEST:
134 opcode = "InARP request";
135 break;
136 case ARPOP_InREPLY:
137 opcode = "InARP reply";
138 break;
139 case ARPOP_NAK:
140 opcode = "(ATM) ARP NAK";
141 break;
142 default:
143 opcode = "Unknown";
144 break;
147 tprintf(" [ ARP ");
148 tprintf("Format HA (%u => %s), ", ntohs(arp->ar_hrd), hrd);
149 tprintf("Format Proto (0x%.4x => %s), ", ntohs(arp->ar_pro), pro);
150 tprintf("HA Len (%u), ", arp->ar_hln);
151 tprintf("Proto Len (%u), ", arp->ar_pln);
152 tprintf("Opcode (%u => %s)", ntohs(arp->ar_op), opcode);
154 arp_print_addrs(arp, ADDR_SENDER);
155 arp_print_addrs(arp, ADDR_TARGET);
157 tprintf(" ]\n");
160 static void arp_less(struct pkt_buff *pkt)
162 char *opcode = NULL;
163 struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp));
165 if (arp == NULL)
166 return;
168 switch (ntohs(arp->ar_op)) {
169 case ARPOP_REQUEST:
170 opcode = "ARP request";
171 break;
172 case ARPOP_REPLY:
173 opcode = "ARP reply";
174 break;
175 case ARPOP_RREQUEST:
176 opcode = "RARP request";
177 break;
178 case ARPOP_RREPLY:
179 opcode = "RARP reply";
180 break;
181 case ARPOP_InREQUEST:
182 opcode = "InARP request";
183 break;
184 case ARPOP_InREPLY:
185 opcode = "InARP reply";
186 break;
187 case ARPOP_NAK:
188 opcode = "(ATM) ARP NAK";
189 break;
190 default:
191 opcode = "Unknown";
192 break;
195 tprintf(" Op %s", opcode);
198 struct protocol arp_ops = {
199 .key = 0x0806,
200 .print_full = arp,
201 .print_less = arp_less,