dissectors: arp: Print hardware & protocol addresses
[netsniff-ng.git] / proto_arp.c
blob9f2a4e04feb68c67e28907048565ef2eca7f1938
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 char *dir = addr_dir == ADDR_SENDER ? "Sender" : "Target";
55 bool has_eth;
56 bool has_ip4;
58 has_eth = ntohs(arp->ar_hrd) == ARPHRD_ETHER;
59 has_ip4 = ntohs(arp->ar_pro) == ETH_P_IP;
61 if (has_eth) {
62 uint8_t *mac;
64 mac = addr_dir == ADDR_SENDER ? &arp->ar_sha[0] : &arp->ar_tha[0];
66 tprintf(", %s MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x)",
67 dir, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
70 if (has_ip4) {
71 char ip_str[INET_ADDRSTRLEN];
72 uint32_t ip;
74 if (addr_dir == ADDR_SENDER)
75 ip = *(uint32_t *)&arp->ar_sip[0];
76 else
77 ip = *(uint32_t *)&arp->ar_tip[0];
79 inet_ntop(AF_INET, &ip, ip_str, sizeof(ip_str));
81 tprintf(", %s IP (%s)", dir, ip_str);
85 static void arp(struct pkt_buff *pkt)
87 char *hrd;
88 const char *pro;
89 char *opcode;
90 struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp));
92 if (arp == NULL)
93 return;
95 switch (ntohs(arp->ar_hrd)) {
96 case ARPHRD_ETHER:
97 hrd = "Ethernet";
98 break;
99 case ARPHRD_IEEE802:
100 hrd = "IEEE 802";
101 break;
102 case ARPHRD_ARCNET:
103 hrd = "ARCNET";
104 break;
105 case ARPHRD_ATM:
106 case ARPHRD_ATM2:
107 case ARPHRD_ATM3:
108 hrd = "ATM";
109 break;
110 case ARPHRD_SERIAL:
111 hrd = "Serial Line";
112 break;
113 case ARPHRD_IEEE1394:
114 hrd = "IEEE 1394.1995";
115 break;
116 default:
117 hrd = "Unknown";
118 break;
121 pro = lookup_ether_type(ntohs(arp->ar_pro));
122 if (pro == NULL)
123 pro = "Unknown";
125 switch (ntohs(arp->ar_op)) {
126 case ARPOP_REQUEST:
127 opcode = "ARP request";
128 break;
129 case ARPOP_REPLY:
130 opcode = "ARP reply";
131 break;
132 case ARPOP_RREQUEST:
133 opcode = "RARP request";
134 break;
135 case ARPOP_RREPLY:
136 opcode = "RARP reply";
137 break;
138 case ARPOP_InREQUEST:
139 opcode = "InARP request";
140 break;
141 case ARPOP_InREPLY:
142 opcode = "InARP reply";
143 break;
144 case ARPOP_NAK:
145 opcode = "(ATM) ARP NAK";
146 break;
147 default:
148 opcode = "Unknown";
149 break;
152 tprintf(" [ ARP ");
153 tprintf("Format HA (%u => %s), ", ntohs(arp->ar_hrd), hrd);
154 tprintf("Format Proto (0x%.4x => %s), ", ntohs(arp->ar_pro), pro);
155 tprintf("HA Len (%u), ", arp->ar_hln);
156 tprintf("Proto Len (%u), ", arp->ar_pln);
157 tprintf("Opcode (%u => %s)", ntohs(arp->ar_op), opcode);
159 arp_print_addrs(arp, ADDR_SENDER);
160 arp_print_addrs(arp, ADDR_TARGET);
162 tprintf(" ]\n");
165 static void arp_less(struct pkt_buff *pkt)
167 char *opcode = NULL;
168 struct arphdr *arp = (struct arphdr *) pkt_pull(pkt, sizeof(*arp));
170 if (arp == NULL)
171 return;
173 switch (ntohs(arp->ar_op)) {
174 case ARPOP_REQUEST:
175 opcode = "ARP request";
176 break;
177 case ARPOP_REPLY:
178 opcode = "ARP reply";
179 break;
180 case ARPOP_RREQUEST:
181 opcode = "RARP request";
182 break;
183 case ARPOP_RREPLY:
184 opcode = "RARP reply";
185 break;
186 case ARPOP_InREQUEST:
187 opcode = "InARP request";
188 break;
189 case ARPOP_InREPLY:
190 opcode = "InARP reply";
191 break;
192 case ARPOP_NAK:
193 opcode = "(ATM) ARP NAK";
194 break;
195 default:
196 opcode = "Unknown";
197 break;
200 tprintf(" Op %s", opcode);
203 struct protocol arp_ops = {
204 .key = 0x0806,
205 .print_full = arp,
206 .print_less = arp_less,