1/*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22/* \summary: Address Resolution Protocol (ARP) printer */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include "netdissect-stdinc.h"
29
30#define ND_LONGJMP_FROM_TCHECK
31#include "netdissect.h"
32#include "addrtoname.h"
33#include "ethertype.h"
34#include "extract.h"
35
36
37/*
38 * Address Resolution Protocol.
39 *
40 * See RFC 826 for protocol description.  ARP packets are variable
41 * in size; the arphdr structure defines the fixed-length portion.
42 * Protocol type values are the same as those for 10 Mb/s Ethernet.
43 * It is followed by the variable-sized fields ar_sha, arp_spa,
44 * arp_tha and arp_tpa in that order, according to the lengths
45 * specified.  Field names used correspond to RFC 826.
46 */
47struct  arp_pkthdr {
48        nd_uint16_t ar_hrd;     /* format of hardware address */
49#define ARPHRD_ETHER    1       /* ethernet hardware format */
50#define ARPHRD_IEEE802  6       /* token-ring hardware format */
51#define ARPHRD_ARCNET   7       /* arcnet hardware format */
52#define ARPHRD_FRELAY   15      /* frame relay hardware format */
53#define ARPHRD_ATM2225  19      /* ATM (RFC 2225) */
54#define ARPHRD_STRIP    23      /* Ricochet Starmode Radio hardware format */
55#define ARPHRD_IEEE1394 24      /* IEEE 1394 (FireWire) hardware format */
56#define ARPHRD_INFINIBAND 32    /* InfiniBand RFC 4391 */
57        nd_uint16_t ar_pro;     /* format of protocol address */
58        nd_uint8_t  ar_hln;     /* length of hardware address */
59        nd_uint8_t  ar_pln;     /* length of protocol address */
60        nd_uint16_t ar_op;      /* one of: */
61#define ARPOP_REQUEST   1       /* request to resolve address */
62#define ARPOP_REPLY     2       /* response to previous request */
63#define ARPOP_REVREQUEST 3      /* request protocol address given hardware */
64#define ARPOP_REVREPLY  4       /* response giving protocol address */
65#define ARPOP_INVREQUEST 8      /* request to identify peer */
66#define ARPOP_INVREPLY  9       /* response identifying peer */
67#define ARPOP_NAK       10      /* NAK - only valid for ATM ARP */
68
69/*
70 * The remaining fields are variable in size,
71 * according to the sizes above.
72 */
73#ifdef COMMENT_ONLY
74	nd_byte		ar_sha[];	/* sender hardware address */
75	nd_byte		ar_spa[];	/* sender protocol address */
76	nd_byte		ar_tha[];	/* target hardware address */
77	nd_byte		ar_tpa[];	/* target protocol address */
78#endif
79#define ar_sha(ap)	(((const u_char *)((ap)+1))+  0)
80#define ar_spa(ap)	(((const u_char *)((ap)+1))+  GET_U_1((ap)->ar_hln))
81#define ar_tha(ap)	(((const u_char *)((ap)+1))+  GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln))
82#define ar_tpa(ap)	(((const u_char *)((ap)+1))+2*GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln))
83};
84
85#define ARP_HDRLEN	8
86
87#define HRD(ap) GET_BE_U_2((ap)->ar_hrd)
88#define HRD_LEN(ap) GET_U_1((ap)->ar_hln)
89#define PROTO_LEN(ap) GET_U_1((ap)->ar_pln)
90#define OP(ap)  GET_BE_U_2((ap)->ar_op)
91#define PRO(ap) GET_BE_U_2((ap)->ar_pro)
92#define SHA(ap) (ar_sha(ap))
93#define SPA(ap) (ar_spa(ap))
94#define THA(ap) (ar_tha(ap))
95#define TPA(ap) (ar_tpa(ap))
96
97
98static const struct tok arpop_values[] = {
99    { ARPOP_REQUEST, "Request" },
100    { ARPOP_REPLY, "Reply" },
101    { ARPOP_REVREQUEST, "Reverse Request" },
102    { ARPOP_REVREPLY, "Reverse Reply" },
103    { ARPOP_INVREQUEST, "Inverse Request" },
104    { ARPOP_INVREPLY, "Inverse Reply" },
105    { ARPOP_NAK, "NACK Reply" },
106    { 0, NULL }
107};
108
109static const struct tok arphrd_values[] = {
110    { ARPHRD_ETHER, "Ethernet" },
111    { ARPHRD_IEEE802, "TokenRing" },
112    { ARPHRD_ARCNET, "ArcNet" },
113    { ARPHRD_FRELAY, "FrameRelay" },
114    { ARPHRD_STRIP, "Strip" },
115    { ARPHRD_IEEE1394, "IEEE 1394" },
116    { ARPHRD_ATM2225, "ATM" },
117    { ARPHRD_INFINIBAND, "InfiniBand" },
118    { 0, NULL }
119};
120
121/*
122 * ATM Address Resolution Protocol.
123 *
124 * See RFC 2225 for protocol description.  ATMARP packets are similar
125 * to ARP packets, except that there are no length fields for the
126 * protocol address - instead, there are type/length fields for
127 * the ATM number and subaddress - and the hardware addresses consist
128 * of an ATM number and an ATM subaddress.
129 */
130struct  atmarp_pkthdr {
131        nd_uint16_t aar_hrd;    /* format of hardware address */
132        nd_uint16_t aar_pro;    /* format of protocol address */
133        nd_uint8_t  aar_shtl;   /* length of source ATM number */
134        nd_uint8_t  aar_sstl;   /* length of source ATM subaddress */
135#define ATMARP_IS_E164  0x40    /* bit in type/length for E.164 format */
136#define ATMARP_LEN_MASK 0x3F    /* length of {sub}address in type/length */
137        nd_uint16_t aar_op;     /* same as regular ARP */
138        nd_uint8_t  aar_spln;   /* length of source protocol address */
139        nd_uint8_t  aar_thtl;   /* length of target ATM number */
140        nd_uint8_t  aar_tstl;   /* length of target ATM subaddress */
141        nd_uint8_t  aar_tpln;   /* length of target protocol address */
142/*
143 * The remaining fields are variable in size,
144 * according to the sizes above.
145 */
146#ifdef COMMENT_ONLY
147	nd_byte		aar_sha[];	/* source ATM number */
148	nd_byte		aar_ssa[];	/* source ATM subaddress */
149	nd_byte		aar_spa[];	/* sender protocol address */
150	nd_byte		aar_tha[];	/* target ATM number */
151	nd_byte		aar_tsa[];	/* target ATM subaddress */
152	nd_byte		aar_tpa[];	/* target protocol address */
153#endif
154
155#define ATMHRD(ap)  GET_BE_U_2((ap)->aar_hrd)
156#define ATMSHRD_LEN(ap) (GET_U_1((ap)->aar_shtl) & ATMARP_LEN_MASK)
157#define ATMSSLN(ap) (GET_U_1((ap)->aar_sstl) & ATMARP_LEN_MASK)
158#define ATMSPROTO_LEN(ap) GET_U_1((ap)->aar_spln)
159#define ATMOP(ap)   GET_BE_U_2((ap)->aar_op)
160#define ATMPRO(ap)  GET_BE_U_2((ap)->aar_pro)
161#define ATMTHRD_LEN(ap) (GET_U_1((ap)->aar_thtl) & ATMARP_LEN_MASK)
162#define ATMTSLN(ap) (GET_U_1((ap)->aar_tstl) & ATMARP_LEN_MASK)
163#define ATMTPROTO_LEN(ap) GET_U_1((ap)->aar_tpln)
164#define aar_sha(ap)	((const u_char *)((ap)+1))
165#define aar_ssa(ap)	(aar_sha(ap) + ATMSHRD_LEN(ap))
166#define aar_spa(ap)	(aar_ssa(ap) + ATMSSLN(ap))
167#define aar_tha(ap)	(aar_spa(ap) + ATMSPROTO_LEN(ap))
168#define aar_tsa(ap)	(aar_tha(ap) + ATMTHRD_LEN(ap))
169#define aar_tpa(ap)	(aar_tsa(ap) + ATMTSLN(ap))
170};
171
172#define ATMSHA(ap) (aar_sha(ap))
173#define ATMSSA(ap) (aar_ssa(ap))
174#define ATMSPA(ap) (aar_spa(ap))
175#define ATMTHA(ap) (aar_tha(ap))
176#define ATMTSA(ap) (aar_tsa(ap))
177#define ATMTPA(ap) (aar_tpa(ap))
178
179static int
180isnonzero(netdissect_options *ndo, const u_char *a, size_t len)
181{
182	while (len > 0) {
183		if (GET_U_1(a) != 0)
184			return (1);
185		a++;
186		len--;
187	}
188	return (0);
189}
190
191static void
192tpaddr_print_ip(netdissect_options *ndo,
193	        const struct arp_pkthdr *ap, u_short pro)
194{
195	if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
196		ND_PRINT("<wrong proto type>");
197	else if (PROTO_LEN(ap) != 4)
198		ND_PRINT("<wrong len>");
199	else
200		ND_PRINT("%s", GET_IPADDR_STRING(TPA(ap)));
201}
202
203static void
204spaddr_print_ip(netdissect_options *ndo,
205	        const struct arp_pkthdr *ap, u_short pro)
206{
207	if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
208		ND_PRINT("<wrong proto type>");
209	else if (PROTO_LEN(ap) != 4)
210		ND_PRINT("<wrong len>");
211	else
212		ND_PRINT("%s", GET_IPADDR_STRING(SPA(ap)));
213}
214
215static void
216atmarp_addr_print(netdissect_options *ndo,
217		  const u_char *ha, u_int ha_len, const u_char *srca,
218    u_int srca_len)
219{
220	if (ha_len == 0)
221		ND_PRINT("<No address>");
222	else {
223		ND_PRINT("%s", GET_LINKADDR_STRING(ha, LINKADDR_ATM, ha_len));
224		if (srca_len != 0)
225			ND_PRINT(",%s",
226				  GET_LINKADDR_STRING(srca, LINKADDR_ATM, srca_len));
227	}
228}
229
230static void
231atmarp_tpaddr_print(netdissect_options *ndo,
232		    const struct atmarp_pkthdr *ap, u_short pro)
233{
234	if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
235		ND_PRINT("<wrong proto type>");
236	else if (ATMTPROTO_LEN(ap) != 4)
237		ND_PRINT("<wrong tplen>");
238	else
239		ND_PRINT("%s", GET_IPADDR_STRING(ATMTPA(ap)));
240}
241
242static void
243atmarp_spaddr_print(netdissect_options *ndo,
244		    const struct atmarp_pkthdr *ap, u_short pro)
245{
246	if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
247		ND_PRINT("<wrong proto type>");
248	else if (ATMSPROTO_LEN(ap) != 4)
249		ND_PRINT("<wrong splen>");
250	else
251		ND_PRINT("%s", GET_IPADDR_STRING(ATMSPA(ap)));
252}
253
254static void
255atmarp_print(netdissect_options *ndo,
256	     const u_char *bp, u_int length, u_int caplen)
257{
258	const struct atmarp_pkthdr *ap;
259	u_short pro, hrd, op;
260
261	ap = (const struct atmarp_pkthdr *)bp;
262	ND_TCHECK_SIZE(ap);
263
264	hrd = ATMHRD(ap);
265	pro = ATMPRO(ap);
266	op = ATMOP(ap);
267
268	ND_TCHECK_LEN(ATMTPA(ap), ATMTPROTO_LEN(ap));
269
270        if (!ndo->ndo_eflag) {
271            ND_PRINT("ARP, ");
272        }
273
274	if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
275	    ATMSPROTO_LEN(ap) != 4 ||
276            ATMTPROTO_LEN(ap) != 4 ||
277            ndo->ndo_vflag) {
278                ND_PRINT("%s, %s (len %u/%u)",
279                          tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
280                          tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
281                          ATMSPROTO_LEN(ap),
282                          ATMTPROTO_LEN(ap));
283
284                /* don't know about the address formats */
285                if (!ndo->ndo_vflag) {
286                    goto out;
287                }
288	}
289
290        /* print operation */
291        ND_PRINT("%s%s ",
292               ndo->ndo_vflag ? ", " : "",
293               tok2str(arpop_values, "Unknown (%u)", op));
294
295	switch (op) {
296
297	case ARPOP_REQUEST:
298		ND_PRINT("who-has ");
299		atmarp_tpaddr_print(ndo, ap, pro);
300		if (ATMTHRD_LEN(ap) != 0) {
301			ND_PRINT(" (");
302			atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap),
303			    ATMTSA(ap), ATMTSLN(ap));
304			ND_PRINT(")");
305		}
306		ND_PRINT(" tell ");
307		atmarp_spaddr_print(ndo, ap, pro);
308		break;
309
310	case ARPOP_REPLY:
311		atmarp_spaddr_print(ndo, ap, pro);
312		ND_PRINT(" is-at ");
313		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
314                                  ATMSSLN(ap));
315		break;
316
317	case ARPOP_INVREQUEST:
318		ND_PRINT("who-is ");
319		atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap),
320		    ATMTSLN(ap));
321		ND_PRINT(" tell ");
322		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
323		    ATMSSLN(ap));
324		break;
325
326	case ARPOP_INVREPLY:
327		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
328		    ATMSSLN(ap));
329		ND_PRINT("at ");
330		atmarp_spaddr_print(ndo, ap, pro);
331		break;
332
333	case ARPOP_NAK:
334		ND_PRINT("for ");
335		atmarp_spaddr_print(ndo, ap, pro);
336		break;
337
338	default:
339		ND_DEFAULTPRINT((const u_char *)ap, caplen);
340		return;
341	}
342
343 out:
344        ND_PRINT(", length %u", length);
345}
346
347void
348arp_print(netdissect_options *ndo,
349	  const u_char *bp, u_int length, u_int caplen)
350{
351	const struct arp_pkthdr *ap;
352	u_short pro, hrd, op, linkaddr;
353
354	ndo->ndo_protocol = "arp";
355	ap = (const struct arp_pkthdr *)bp;
356	ND_TCHECK_SIZE(ap);
357
358	hrd = HRD(ap);
359	pro = PRO(ap);
360	op = OP(ap);
361
362
363        /* if its ATM then call the ATM ARP printer
364           for Frame-relay ARP most of the fields
365           are similar to Ethernet so overload the Ethernet Printer
366           and set the linkaddr type for GET_LINKADDR_STRING() accordingly */
367
368        switch(hrd) {
369        case ARPHRD_ATM2225:
370            atmarp_print(ndo, bp, length, caplen);
371            return;
372        case ARPHRD_FRELAY:
373            linkaddr = LINKADDR_FRELAY;
374            break;
375        default:
376            linkaddr = LINKADDR_ETHER;
377            break;
378	}
379
380	ND_TCHECK_LEN(TPA(ap), PROTO_LEN(ap));
381
382        if (!ndo->ndo_eflag) {
383            ND_PRINT("ARP, ");
384        }
385
386        /* print hardware type/len and proto type/len */
387        if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
388	    PROTO_LEN(ap) != 4 ||
389            HRD_LEN(ap) == 0 ||
390            ndo->ndo_vflag) {
391            ND_PRINT("%s (len %u), %s (len %u)",
392                      tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
393                      HRD_LEN(ap),
394                      tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
395                      PROTO_LEN(ap));
396
397            /* don't know about the address formats */
398            if (!ndo->ndo_vflag) {
399                goto out;
400            }
401	}
402
403        /* print operation */
404        ND_PRINT("%s%s ",
405               ndo->ndo_vflag ? ", " : "",
406               tok2str(arpop_values, "Unknown (%u)", op));
407
408	switch (op) {
409
410	case ARPOP_REQUEST:
411		ND_PRINT("who-has ");
412		tpaddr_print_ip(ndo, ap, pro);
413		if (isnonzero(ndo, (const u_char *)THA(ap), HRD_LEN(ap)))
414			ND_PRINT(" (%s)",
415				  GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
416		ND_PRINT(" tell ");
417		spaddr_print_ip(ndo, ap, pro);
418		break;
419
420	case ARPOP_REPLY:
421		spaddr_print_ip(ndo, ap, pro);
422		ND_PRINT(" is-at %s",
423                          GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
424		break;
425
426	case ARPOP_REVREQUEST:
427		/*
428		 * XXX - GET_LINKADDR_STRING() may return a pointer to
429		 * a static buffer, so we only have one call to it per
430		 * ND_PRINT() call.
431		 *
432		 * This should be done in a cleaner fashion.
433		 */
434		ND_PRINT("who-is %s",
435			  GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
436		ND_PRINT(" tell %s",
437			  GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
438		break;
439
440	case ARPOP_REVREPLY:
441		ND_PRINT("%s at ",
442			  GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
443		tpaddr_print_ip(ndo, ap, pro);
444		break;
445
446	case ARPOP_INVREQUEST:
447		/*
448		 * XXX - GET_LINKADDR_STRING() may return a pointer to
449		 * a static buffer, so we only have one call to it per
450		 * ND_PRINT() call.
451		 *
452		 * This should be done in a cleaner fashion.
453		 */
454		ND_PRINT("who-is %s",
455			  GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
456		ND_PRINT(" tell %s",
457			  GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
458		break;
459
460	case ARPOP_INVREPLY:
461		ND_PRINT("%s at ",
462			  GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
463		spaddr_print_ip(ndo, ap, pro);
464		break;
465
466	default:
467		ND_DEFAULTPRINT((const u_char *)ap, caplen);
468		return;
469	}
470
471 out:
472        ND_PRINT(", length %u", length);
473}
474