xref: /freebsd/contrib/tcpdump/print-arp.c (revision 3c602fabf9b894ff79f08a80cbb7ad3b1eb84e62)
14edb46e9SPaul Traina /*
2699fc314SBill Fenner  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20a88113a8SBill Fenner  *
21a88113a8SBill Fenner  * $FreeBSD$
224edb46e9SPaul Traina  */
234edb46e9SPaul Traina 
24*3c602fabSXin LI #define NETDISSECT_REWORKED
25a88113a8SBill Fenner #ifdef HAVE_CONFIG_H
26a88113a8SBill Fenner #include "config.h"
274edb46e9SPaul Traina #endif
284edb46e9SPaul Traina 
29cc391cceSBruce M Simpson #include <tcpdump-stdinc.h>
304edb46e9SPaul Traina 
314edb46e9SPaul Traina #include <string.h>
324edb46e9SPaul Traina 
33*3c602fabSXin LI #include "interface.h"
344edb46e9SPaul Traina #include "addrtoname.h"
35943ee2b1SBill Fenner #include "ether.h"
364edb46e9SPaul Traina #include "ethertype.h"
374edb46e9SPaul Traina #include "extract.h"			/* must come after interface.h */
384edb46e9SPaul Traina 
39*3c602fabSXin LI static const char tstr[] = "[|ARP]";
40*3c602fabSXin LI 
41943ee2b1SBill Fenner /*
42943ee2b1SBill Fenner  * Address Resolution Protocol.
43943ee2b1SBill Fenner  *
44943ee2b1SBill Fenner  * See RFC 826 for protocol description.  ARP packets are variable
45943ee2b1SBill Fenner  * in size; the arphdr structure defines the fixed-length portion.
46943ee2b1SBill Fenner  * Protocol type values are the same as those for 10 Mb/s Ethernet.
47943ee2b1SBill Fenner  * It is followed by the variable-sized fields ar_sha, arp_spa,
48943ee2b1SBill Fenner  * arp_tha and arp_tpa in that order, according to the lengths
49943ee2b1SBill Fenner  * specified.  Field names used correspond to RFC 826.
50943ee2b1SBill Fenner  */
510e0def19SBill Fenner struct  arp_pkthdr {
52943ee2b1SBill Fenner         u_short ar_hrd;         /* format of hardware address */
53943ee2b1SBill Fenner #define ARPHRD_ETHER    1       /* ethernet hardware format */
54943ee2b1SBill Fenner #define ARPHRD_IEEE802  6       /* token-ring hardware format */
55a1c2090eSBill Fenner #define ARPHRD_ARCNET   7       /* arcnet hardware format */
56943ee2b1SBill Fenner #define ARPHRD_FRELAY   15      /* frame relay hardware format */
57a5779b6eSRui Paulo #define ARPHRD_ATM2225  19      /* ATM (RFC 2225) */
58a1c2090eSBill Fenner #define ARPHRD_STRIP    23      /* Ricochet Starmode Radio hardware format */
59a1c2090eSBill Fenner #define ARPHRD_IEEE1394 24      /* IEEE 1394 (FireWire) hardware format */
60943ee2b1SBill Fenner         u_short ar_pro;         /* format of protocol address */
61943ee2b1SBill Fenner         u_char  ar_hln;         /* length of hardware address */
62943ee2b1SBill Fenner         u_char  ar_pln;         /* length of protocol address */
63943ee2b1SBill Fenner         u_short ar_op;          /* one of: */
64943ee2b1SBill Fenner #define ARPOP_REQUEST   1       /* request to resolve address */
65943ee2b1SBill Fenner #define ARPOP_REPLY     2       /* response to previous request */
66943ee2b1SBill Fenner #define ARPOP_REVREQUEST 3      /* request protocol address given hardware */
67943ee2b1SBill Fenner #define ARPOP_REVREPLY  4       /* response giving protocol address */
68943ee2b1SBill Fenner #define ARPOP_INVREQUEST 8      /* request to identify peer */
69943ee2b1SBill Fenner #define ARPOP_INVREPLY  9       /* response identifying peer */
70a5779b6eSRui Paulo #define ARPOP_NAK       10      /* NAK - only valif for ATM ARP */
71a5779b6eSRui Paulo 
72943ee2b1SBill Fenner /*
73943ee2b1SBill Fenner  * The remaining fields are variable in size,
74943ee2b1SBill Fenner  * according to the sizes above.
75943ee2b1SBill Fenner  */
76943ee2b1SBill Fenner #ifdef COMMENT_ONLY
77943ee2b1SBill Fenner 	u_char	ar_sha[];	/* sender hardware address */
78943ee2b1SBill Fenner 	u_char	ar_spa[];	/* sender protocol address */
79943ee2b1SBill Fenner 	u_char	ar_tha[];	/* target hardware address */
80943ee2b1SBill Fenner 	u_char	ar_tpa[];	/* target protocol address */
81943ee2b1SBill Fenner #endif
820e0def19SBill Fenner #define ar_sha(ap)	(((const u_char *)((ap)+1))+0)
830e0def19SBill Fenner #define ar_spa(ap)	(((const u_char *)((ap)+1))+  (ap)->ar_hln)
840e0def19SBill Fenner #define ar_tha(ap)	(((const u_char *)((ap)+1))+  (ap)->ar_hln+(ap)->ar_pln)
850e0def19SBill Fenner #define ar_tpa(ap)	(((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln)
86943ee2b1SBill Fenner };
87943ee2b1SBill Fenner 
88943ee2b1SBill Fenner #define ARP_HDRLEN	8
89943ee2b1SBill Fenner 
90cc391cceSBruce M Simpson #define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd)
91a5779b6eSRui Paulo #define HRD_LEN(ap) ((ap)->ar_hln)
92a5779b6eSRui Paulo #define PROTO_LEN(ap) ((ap)->ar_pln)
93cc391cceSBruce M Simpson #define OP(ap)  EXTRACT_16BITS(&(ap)->ar_op)
94cc391cceSBruce M Simpson #define PRO(ap) EXTRACT_16BITS(&(ap)->ar_pro)
95a1c2090eSBill Fenner #define SHA(ap) (ar_sha(ap))
96a1c2090eSBill Fenner #define SPA(ap) (ar_spa(ap))
97a1c2090eSBill Fenner #define THA(ap) (ar_tha(ap))
98a1c2090eSBill Fenner #define TPA(ap) (ar_tpa(ap))
994edb46e9SPaul Traina 
100a5779b6eSRui Paulo 
101*3c602fabSXin LI static const struct tok arpop_values[] = {
102a5779b6eSRui Paulo     { ARPOP_REQUEST, "Request" },
103a5779b6eSRui Paulo     { ARPOP_REPLY, "Reply" },
104a5779b6eSRui Paulo     { ARPOP_REVREQUEST, "Reverse Request" },
105a5779b6eSRui Paulo     { ARPOP_REVREPLY, "Reverse Reply" },
106a5779b6eSRui Paulo     { ARPOP_INVREQUEST, "Inverse Request" },
107a5779b6eSRui Paulo     { ARPOP_INVREPLY, "Inverse Reply" },
108a5779b6eSRui Paulo     { ARPOP_NAK, "NACK Reply" },
109a5779b6eSRui Paulo     { 0, NULL }
110a5779b6eSRui Paulo };
111a5779b6eSRui Paulo 
112*3c602fabSXin LI static const struct tok arphrd_values[] = {
113a5779b6eSRui Paulo     { ARPHRD_ETHER, "Ethernet" },
114a5779b6eSRui Paulo     { ARPHRD_IEEE802, "TokenRing" },
115a5779b6eSRui Paulo     { ARPHRD_ARCNET, "ArcNet" },
116a5779b6eSRui Paulo     { ARPHRD_FRELAY, "FrameRelay" },
117a5779b6eSRui Paulo     { ARPHRD_STRIP, "Strip" },
118a5779b6eSRui Paulo     { ARPHRD_IEEE1394, "IEEE 1394" },
119a5779b6eSRui Paulo     { ARPHRD_ATM2225, "ATM" },
120a5779b6eSRui Paulo     { 0, NULL }
121a5779b6eSRui Paulo };
122a5779b6eSRui Paulo 
123cc391cceSBruce M Simpson /*
124cc391cceSBruce M Simpson  * ATM Address Resolution Protocol.
125cc391cceSBruce M Simpson  *
126cc391cceSBruce M Simpson  * See RFC 2225 for protocol description.  ATMARP packets are similar
127cc391cceSBruce M Simpson  * to ARP packets, except that there are no length fields for the
128cc391cceSBruce M Simpson  * protocol address - instead, there are type/length fields for
129cc391cceSBruce M Simpson  * the ATM number and subaddress - and the hardware addresses consist
130cc391cceSBruce M Simpson  * of an ATM number and an ATM subaddress.
131cc391cceSBruce M Simpson  */
132cc391cceSBruce M Simpson struct  atmarp_pkthdr {
133cc391cceSBruce M Simpson         u_short aar_hrd;        /* format of hardware address */
134cc391cceSBruce M Simpson         u_short aar_pro;        /* format of protocol address */
135cc391cceSBruce M Simpson         u_char  aar_shtl;       /* length of source ATM number */
136cc391cceSBruce M Simpson         u_char  aar_sstl;       /* length of source ATM subaddress */
137cc391cceSBruce M Simpson #define ATMARP_IS_E164  0x40    /* bit in type/length for E.164 format */
138cc391cceSBruce M Simpson #define ATMARP_LEN_MASK 0x3F    /* length of {sub}address in type/length */
139cc391cceSBruce M Simpson         u_short aar_op;         /* same as regular ARP */
140cc391cceSBruce M Simpson         u_char  aar_spln;       /* length of source protocol address */
141cc391cceSBruce M Simpson         u_char  aar_thtl;       /* length of target ATM number */
142cc391cceSBruce M Simpson         u_char  aar_tstl;       /* length of target ATM subaddress */
143cc391cceSBruce M Simpson         u_char  aar_tpln;       /* length of target protocol address */
144cc391cceSBruce M Simpson /*
145cc391cceSBruce M Simpson  * The remaining fields are variable in size,
146cc391cceSBruce M Simpson  * according to the sizes above.
147cc391cceSBruce M Simpson  */
148cc391cceSBruce M Simpson #ifdef COMMENT_ONLY
149cc391cceSBruce M Simpson 	u_char	aar_sha[];	/* source ATM number */
150cc391cceSBruce M Simpson 	u_char	aar_ssa[];	/* source ATM subaddress */
151cc391cceSBruce M Simpson 	u_char	aar_spa[];	/* sender protocol address */
152cc391cceSBruce M Simpson 	u_char	aar_tha[];	/* target ATM number */
153cc391cceSBruce M Simpson 	u_char	aar_tsa[];	/* target ATM subaddress */
154cc391cceSBruce M Simpson 	u_char	aar_tpa[];	/* target protocol address */
155cc391cceSBruce M Simpson #endif
156cc391cceSBruce M Simpson 
157cc391cceSBruce M Simpson #define ATMHRD(ap)  EXTRACT_16BITS(&(ap)->aar_hrd)
158a5779b6eSRui Paulo #define ATMSHRD_LEN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK)
159cc391cceSBruce M Simpson #define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK)
160a5779b6eSRui Paulo #define ATMSPROTO_LEN(ap) ((ap)->aar_spln)
161cc391cceSBruce M Simpson #define ATMOP(ap)   EXTRACT_16BITS(&(ap)->aar_op)
162cc391cceSBruce M Simpson #define ATMPRO(ap)  EXTRACT_16BITS(&(ap)->aar_pro)
163a5779b6eSRui Paulo #define ATMTHRD_LEN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK)
164cc391cceSBruce M Simpson #define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK)
165a5779b6eSRui Paulo #define ATMTPROTO_LEN(ap) ((ap)->aar_tpln)
166cc391cceSBruce M Simpson #define aar_sha(ap)	((const u_char *)((ap)+1))
167a5779b6eSRui Paulo #define aar_ssa(ap)	(aar_sha(ap) + ATMSHRD_LEN(ap))
168cc391cceSBruce M Simpson #define aar_spa(ap)	(aar_ssa(ap) + ATMSSLN(ap))
169a5779b6eSRui Paulo #define aar_tha(ap)	(aar_spa(ap) + ATMSPROTO_LEN(ap))
170a5779b6eSRui Paulo #define aar_tsa(ap)	(aar_tha(ap) + ATMTHRD_LEN(ap))
171cc391cceSBruce M Simpson #define aar_tpa(ap)	(aar_tsa(ap) + ATMTSLN(ap))
172cc391cceSBruce M Simpson };
173cc391cceSBruce M Simpson 
174cc391cceSBruce M Simpson #define ATMSHA(ap) (aar_sha(ap))
175cc391cceSBruce M Simpson #define ATMSSA(ap) (aar_ssa(ap))
176cc391cceSBruce M Simpson #define ATMSPA(ap) (aar_spa(ap))
177cc391cceSBruce M Simpson #define ATMTHA(ap) (aar_tha(ap))
178cc391cceSBruce M Simpson #define ATMTSA(ap) (aar_tsa(ap))
179cc391cceSBruce M Simpson #define ATMTPA(ap) (aar_tpa(ap))
180cc391cceSBruce M Simpson 
1814edb46e9SPaul Traina static u_char ezero[6];
1824edb46e9SPaul Traina 
183cc391cceSBruce M Simpson static void
184c1ad1296SSam Leffler atmarp_addr_print(netdissect_options *ndo,
185c1ad1296SSam Leffler 		  const u_char *ha, u_int ha_len, const u_char *srca,
186cc391cceSBruce M Simpson     u_int srca_len)
187cc391cceSBruce M Simpson {
188cc391cceSBruce M Simpson 	if (ha_len == 0)
189c1ad1296SSam Leffler 		ND_PRINT((ndo, "<No address>"));
190cc391cceSBruce M Simpson 	else {
191*3c602fabSXin LI 		ND_PRINT((ndo, "%s", linkaddr_string(ndo, ha, LINKADDR_ATM, ha_len)));
192cc391cceSBruce M Simpson 		if (srca_len != 0)
193c1ad1296SSam Leffler 			ND_PRINT((ndo, ",%s",
194*3c602fabSXin LI 				  linkaddr_string(ndo, srca, LINKADDR_ATM, srca_len)));
195cc391cceSBruce M Simpson 	}
196cc391cceSBruce M Simpson }
197cc391cceSBruce M Simpson 
198cc391cceSBruce M Simpson static void
199c1ad1296SSam Leffler atmarp_print(netdissect_options *ndo,
200c1ad1296SSam Leffler 	     const u_char *bp, u_int length, u_int caplen)
201cc391cceSBruce M Simpson {
202cc391cceSBruce M Simpson 	const struct atmarp_pkthdr *ap;
203cc391cceSBruce M Simpson 	u_short pro, hrd, op;
204cc391cceSBruce M Simpson 
205cc391cceSBruce M Simpson 	ap = (const struct atmarp_pkthdr *)bp;
206c1ad1296SSam Leffler 	ND_TCHECK(*ap);
207cc391cceSBruce M Simpson 
208cc391cceSBruce M Simpson 	hrd = ATMHRD(ap);
209cc391cceSBruce M Simpson 	pro = ATMPRO(ap);
210cc391cceSBruce M Simpson 	op = ATMOP(ap);
211cc391cceSBruce M Simpson 
212a5779b6eSRui Paulo 	if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) {
213*3c602fabSXin LI 		ND_PRINT((ndo, "%s", tstr));
214c1ad1296SSam Leffler 		ND_DEFAULTPRINT((const u_char *)ap, length);
215cc391cceSBruce M Simpson 		return;
216cc391cceSBruce M Simpson 	}
217cc391cceSBruce M Simpson 
218a5779b6eSRui Paulo         if (!ndo->ndo_eflag) {
219a5779b6eSRui Paulo             ND_PRINT((ndo, "ARP, "));
220cc391cceSBruce M Simpson         }
221a5779b6eSRui Paulo 
222a5779b6eSRui Paulo 	if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
223a5779b6eSRui Paulo 	    ATMSPROTO_LEN(ap) != 4 ||
224a5779b6eSRui Paulo             ATMTPROTO_LEN(ap) != 4 ||
225a5779b6eSRui Paulo             ndo->ndo_vflag) {
226a5779b6eSRui Paulo                 ND_PRINT((ndo, "%s, %s (len %u/%u)",
227a5779b6eSRui Paulo                           tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
228a5779b6eSRui Paulo                           tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
229a5779b6eSRui Paulo                           ATMSPROTO_LEN(ap),
230a5779b6eSRui Paulo                           ATMTPROTO_LEN(ap)));
231a5779b6eSRui Paulo 
232a5779b6eSRui Paulo                 /* don't know know about the address formats */
233a5779b6eSRui Paulo                 if (!ndo->ndo_vflag) {
234a5779b6eSRui Paulo                     goto out;
235a5779b6eSRui Paulo                 }
236a5779b6eSRui Paulo 	}
237a5779b6eSRui Paulo 
238a5779b6eSRui Paulo         /* print operation */
239*3c602fabSXin LI         ND_PRINT((ndo, "%s%s ",
240a5779b6eSRui Paulo                ndo->ndo_vflag ? ", " : "",
241*3c602fabSXin LI                tok2str(arpop_values, "Unknown (%u)", op)));
242a5779b6eSRui Paulo 
243cc391cceSBruce M Simpson 	switch (op) {
244cc391cceSBruce M Simpson 
245cc391cceSBruce M Simpson 	case ARPOP_REQUEST:
246*3c602fabSXin LI 		ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, ATMTPA(ap))));
247a5779b6eSRui Paulo 		if (ATMTHRD_LEN(ap) != 0) {
248c1ad1296SSam Leffler 			ND_PRINT((ndo, " ("));
249a5779b6eSRui Paulo 			atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap),
250cc391cceSBruce M Simpson 			    ATMTSA(ap), ATMTSLN(ap));
251c1ad1296SSam Leffler 			ND_PRINT((ndo, ")"));
252cc391cceSBruce M Simpson 		}
253*3c602fabSXin LI 		ND_PRINT((ndo, "tell %s", ipaddr_string(ndo, ATMSPA(ap))));
254cc391cceSBruce M Simpson 		break;
255cc391cceSBruce M Simpson 
256cc391cceSBruce M Simpson 	case ARPOP_REPLY:
257*3c602fabSXin LI 		ND_PRINT((ndo, "%s is-at ", ipaddr_string(ndo, ATMSPA(ap))));
258a5779b6eSRui Paulo 		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
259cc391cceSBruce M Simpson                                   ATMSSLN(ap));
260cc391cceSBruce M Simpson 		break;
261cc391cceSBruce M Simpson 
262cc391cceSBruce M Simpson 	case ARPOP_INVREQUEST:
263a5779b6eSRui Paulo 		ND_PRINT((ndo, "who-is "));
264a5779b6eSRui Paulo 		atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap),
265cc391cceSBruce M Simpson 		    ATMTSLN(ap));
266c1ad1296SSam Leffler 		ND_PRINT((ndo, " tell "));
267a5779b6eSRui Paulo 		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
268cc391cceSBruce M Simpson 		    ATMSSLN(ap));
269cc391cceSBruce M Simpson 		break;
270cc391cceSBruce M Simpson 
271cc391cceSBruce M Simpson 	case ARPOP_INVREPLY:
272a5779b6eSRui Paulo 		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
273cc391cceSBruce M Simpson 		    ATMSSLN(ap));
274*3c602fabSXin LI 		ND_PRINT((ndo, "at %s", ipaddr_string(ndo, ATMSPA(ap))));
275cc391cceSBruce M Simpson 		break;
276cc391cceSBruce M Simpson 
277a5779b6eSRui Paulo 	case ARPOP_NAK:
278*3c602fabSXin LI 		ND_PRINT((ndo, "for %s", ipaddr_string(ndo, ATMSPA(ap))));
279cc391cceSBruce M Simpson 		break;
280cc391cceSBruce M Simpson 
281cc391cceSBruce M Simpson 	default:
282c1ad1296SSam Leffler 		ND_DEFAULTPRINT((const u_char *)ap, caplen);
283cc391cceSBruce M Simpson 		return;
284cc391cceSBruce M Simpson 	}
285a5779b6eSRui Paulo 
286a5779b6eSRui Paulo  out:
287a5779b6eSRui Paulo         ND_PRINT((ndo, ", length %u", length));
288cc391cceSBruce M Simpson         return;
289a5779b6eSRui Paulo 
290cc391cceSBruce M Simpson trunc:
291*3c602fabSXin LI 	ND_PRINT((ndo, "%s", tstr));
292cc391cceSBruce M Simpson }
293cc391cceSBruce M Simpson 
2944edb46e9SPaul Traina void
295c1ad1296SSam Leffler arp_print(netdissect_options *ndo,
296c1ad1296SSam Leffler 	  const u_char *bp, u_int length, u_int caplen)
2974edb46e9SPaul Traina {
2980e0def19SBill Fenner 	const struct arp_pkthdr *ap;
299a5779b6eSRui Paulo 	u_short pro, hrd, op, linkaddr;
3004edb46e9SPaul Traina 
3010e0def19SBill Fenner 	ap = (const struct arp_pkthdr *)bp;
302c1ad1296SSam Leffler 	ND_TCHECK(*ap);
303a5779b6eSRui Paulo 
304cc391cceSBruce M Simpson 	hrd = HRD(ap);
305cc391cceSBruce M Simpson 	pro = PRO(ap);
306cc391cceSBruce M Simpson 	op = OP(ap);
307cc391cceSBruce M Simpson 
308a5779b6eSRui Paulo 
309a5779b6eSRui Paulo         /* if its ATM then call the ATM ARP printer
310a5779b6eSRui Paulo            for Frame-relay ARP most of the fields
311a5779b6eSRui Paulo            are similar to Ethernet so overload the Ethernet Printer
312*3c602fabSXin LI            and set the linkaddr type for linkaddr_string(ndo, ) accordingly */
313a5779b6eSRui Paulo 
314a5779b6eSRui Paulo         switch(hrd) {
315a5779b6eSRui Paulo         case ARPHRD_ATM2225:
316a5779b6eSRui Paulo             atmarp_print(ndo, bp, length, caplen);
317a5779b6eSRui Paulo             return;
318a5779b6eSRui Paulo         case ARPHRD_FRELAY:
319a5779b6eSRui Paulo             linkaddr = LINKADDR_FRELAY;
320cac3dcd5SXin LI             break;
321a5779b6eSRui Paulo         default:
322a5779b6eSRui Paulo             linkaddr = LINKADDR_ETHER;
323a5779b6eSRui Paulo             break;
324a5779b6eSRui Paulo 	}
325a5779b6eSRui Paulo 
326a5779b6eSRui Paulo 	if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) {
327*3c602fabSXin LI 		ND_PRINT((ndo, "%s", tstr));
328c1ad1296SSam Leffler 		ND_DEFAULTPRINT((const u_char *)ap, length);
3294edb46e9SPaul Traina 		return;
3304edb46e9SPaul Traina 	}
3314edb46e9SPaul Traina 
332a5779b6eSRui Paulo         if (!ndo->ndo_eflag) {
333a5779b6eSRui Paulo             ND_PRINT((ndo, "ARP, "));
3344edb46e9SPaul Traina         }
335a5779b6eSRui Paulo 
336a5779b6eSRui Paulo         /* print hardware type/len and proto type/len */
337a5779b6eSRui Paulo         if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
338a5779b6eSRui Paulo 	    PROTO_LEN(ap) != 4 ||
339a5779b6eSRui Paulo             HRD_LEN(ap) == 0 ||
340a5779b6eSRui Paulo             ndo->ndo_vflag) {
341a5779b6eSRui Paulo             ND_PRINT((ndo, "%s (len %u), %s (len %u)",
342a5779b6eSRui Paulo                       tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
343a5779b6eSRui Paulo                       HRD_LEN(ap),
344a5779b6eSRui Paulo                       tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
345a5779b6eSRui Paulo                       PROTO_LEN(ap)));
346a5779b6eSRui Paulo 
347a5779b6eSRui Paulo             /* don't know know about the address formats */
348a5779b6eSRui Paulo             if (!ndo->ndo_vflag) {
349a5779b6eSRui Paulo                 goto out;
350a5779b6eSRui Paulo             }
351a5779b6eSRui Paulo 	}
352a5779b6eSRui Paulo 
353a5779b6eSRui Paulo         /* print operation */
354*3c602fabSXin LI         ND_PRINT((ndo, "%s%s ",
355a5779b6eSRui Paulo                ndo->ndo_vflag ? ", " : "",
356*3c602fabSXin LI                tok2str(arpop_values, "Unknown (%u)", op)));
357a5779b6eSRui Paulo 
3584edb46e9SPaul Traina 	switch (op) {
3594edb46e9SPaul Traina 
3604edb46e9SPaul Traina 	case ARPOP_REQUEST:
361*3c602fabSXin LI 		ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, TPA(ap))));
362a5779b6eSRui Paulo 		if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0)
363c1ad1296SSam Leffler 			ND_PRINT((ndo, " (%s)",
364*3c602fabSXin LI 				  linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap))));
365*3c602fabSXin LI 		ND_PRINT((ndo, " tell %s", ipaddr_string(ndo, SPA(ap))));
3664edb46e9SPaul Traina 		break;
3674edb46e9SPaul Traina 
3684edb46e9SPaul Traina 	case ARPOP_REPLY:
369a5779b6eSRui Paulo 		ND_PRINT((ndo, "%s is-at %s",
370*3c602fabSXin LI                           ipaddr_string(ndo, SPA(ap)),
371*3c602fabSXin LI                           linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
3724edb46e9SPaul Traina 		break;
3734edb46e9SPaul Traina 
374a1c2090eSBill Fenner 	case ARPOP_REVREQUEST:
375a5779b6eSRui Paulo 		ND_PRINT((ndo, "who-is %s tell %s",
376*3c602fabSXin LI 			  linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
377*3c602fabSXin LI 			  linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
3784edb46e9SPaul Traina 		break;
3794edb46e9SPaul Traina 
380a1c2090eSBill Fenner 	case ARPOP_REVREPLY:
381a5779b6eSRui Paulo 		ND_PRINT((ndo, "%s at %s",
382*3c602fabSXin LI 			  linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
383*3c602fabSXin LI 			  ipaddr_string(ndo, TPA(ap))));
3844edb46e9SPaul Traina 		break;
3854edb46e9SPaul Traina 
386cc391cceSBruce M Simpson 	case ARPOP_INVREQUEST:
387a5779b6eSRui Paulo 		ND_PRINT((ndo, "who-is %s tell %s",
388*3c602fabSXin LI 			  linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
389*3c602fabSXin LI 			  linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap))));
390cc391cceSBruce M Simpson 		break;
391cc391cceSBruce M Simpson 
392cc391cceSBruce M Simpson 	case ARPOP_INVREPLY:
393a5779b6eSRui Paulo 		ND_PRINT((ndo,"%s at %s",
394*3c602fabSXin LI 			  linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)),
395*3c602fabSXin LI 			  ipaddr_string(ndo, TPA(ap))));
396cc391cceSBruce M Simpson 		break;
397cc391cceSBruce M Simpson 
3984edb46e9SPaul Traina 	default:
399c1ad1296SSam Leffler 		ND_DEFAULTPRINT((const u_char *)ap, caplen);
4004edb46e9SPaul Traina 		return;
4014edb46e9SPaul Traina 	}
402a5779b6eSRui Paulo 
403a5779b6eSRui Paulo  out:
404a5779b6eSRui Paulo         ND_PRINT((ndo, ", length %u", length));
405a5779b6eSRui Paulo 
406a1c2090eSBill Fenner 	return;
407a1c2090eSBill Fenner trunc:
408*3c602fabSXin LI 	ND_PRINT((ndo, "%s", tstr));
4094edb46e9SPaul Traina }
410c1ad1296SSam Leffler 
411c1ad1296SSam Leffler /*
412c1ad1296SSam Leffler  * Local Variables:
413c1ad1296SSam Leffler  * c-style: bsd
414c1ad1296SSam Leffler  * End:
415c1ad1296SSam Leffler  */
416c1ad1296SSam Leffler 
417