print-arp.c revision 146778
117680Spst/*
239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2056896Sfenner *
2156896Sfenner * $FreeBSD: head/contrib/tcpdump/print-arp.c 146778 2005-05-29 19:09:28Z sam $
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
25127675Sbmsstatic const char rcsid[] _U_ =
26146778Ssam    "@(#) $Header: /tcpdump/master/tcpdump/print-arp.c,v 1.64 2004/04/30 16:42:14 mcr Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
33127675Sbms#include <tcpdump-stdinc.h>
3417680Spst
3517680Spst#include <stdio.h>
3617680Spst#include <string.h>
3717680Spst
38146778Ssam#include "netdissect.h"
3917680Spst#include "addrtoname.h"
4075118Sfenner#include "ether.h"
4117680Spst#include "ethertype.h"
4217680Spst#include "extract.h"			/* must come after interface.h */
4317680Spst
4475118Sfenner/*
4575118Sfenner * Address Resolution Protocol.
4675118Sfenner *
4775118Sfenner * See RFC 826 for protocol description.  ARP packets are variable
4875118Sfenner * in size; the arphdr structure defines the fixed-length portion.
4975118Sfenner * Protocol type values are the same as those for 10 Mb/s Ethernet.
5075118Sfenner * It is followed by the variable-sized fields ar_sha, arp_spa,
5175118Sfenner * arp_tha and arp_tpa in that order, according to the lengths
5275118Sfenner * specified.  Field names used correspond to RFC 826.
5375118Sfenner */
54111729Sfennerstruct	arp_pkthdr {
5575118Sfenner	u_short	ar_hrd;		/* format of hardware address */
5675118Sfenner#define ARPHRD_ETHER 	1	/* ethernet hardware format */
5775118Sfenner#define ARPHRD_IEEE802	6	/* token-ring hardware format */
5898527Sfenner#define ARPHRD_ARCNET	7	/* arcnet hardware format */
5975118Sfenner#define ARPHRD_FRELAY 	15	/* frame relay hardware format */
6098527Sfenner#define ARPHRD_STRIP 	23	/* Ricochet Starmode Radio hardware format */
6198527Sfenner#define ARPHRD_IEEE1394	24	/* IEEE 1394 (FireWire) hardware format */
6275118Sfenner	u_short	ar_pro;		/* format of protocol address */
6375118Sfenner	u_char	ar_hln;		/* length of hardware address */
6475118Sfenner	u_char	ar_pln;		/* length of protocol address */
6575118Sfenner	u_short	ar_op;		/* one of: */
6675118Sfenner#define	ARPOP_REQUEST	1	/* request to resolve address */
6775118Sfenner#define	ARPOP_REPLY	2	/* response to previous request */
6875118Sfenner#define	ARPOP_REVREQUEST 3	/* request protocol address given hardware */
6975118Sfenner#define	ARPOP_REVREPLY	4	/* response giving protocol address */
7075118Sfenner#define ARPOP_INVREQUEST 8 	/* request to identify peer */
7175118Sfenner#define ARPOP_INVREPLY	9	/* response identifying peer */
7275118Sfenner/*
7375118Sfenner * The remaining fields are variable in size,
7475118Sfenner * according to the sizes above.
7575118Sfenner */
7675118Sfenner#ifdef COMMENT_ONLY
7775118Sfenner	u_char	ar_sha[];	/* sender hardware address */
7875118Sfenner	u_char	ar_spa[];	/* sender protocol address */
7975118Sfenner	u_char	ar_tha[];	/* target hardware address */
8075118Sfenner	u_char	ar_tpa[];	/* target protocol address */
8175118Sfenner#endif
82111729Sfenner#define ar_sha(ap)	(((const u_char *)((ap)+1))+0)
83111729Sfenner#define ar_spa(ap)	(((const u_char *)((ap)+1))+  (ap)->ar_hln)
84111729Sfenner#define ar_tha(ap)	(((const u_char *)((ap)+1))+  (ap)->ar_hln+(ap)->ar_pln)
85111729Sfenner#define ar_tpa(ap)	(((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln)
8675118Sfenner};
8775118Sfenner
8875118Sfenner#define ARP_HDRLEN	8
8975118Sfenner
90127675Sbms#define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd)
9198527Sfenner#define HLN(ap) ((ap)->ar_hln)
9298527Sfenner#define PLN(ap) ((ap)->ar_pln)
93127675Sbms#define OP(ap)  EXTRACT_16BITS(&(ap)->ar_op)
94127675Sbms#define PRO(ap) EXTRACT_16BITS(&(ap)->ar_pro)
9598527Sfenner#define SHA(ap) (ar_sha(ap))
9698527Sfenner#define SPA(ap) (ar_spa(ap))
9798527Sfenner#define THA(ap) (ar_tha(ap))
9898527Sfenner#define TPA(ap) (ar_tpa(ap))
9975118Sfenner
100127675Sbms/*
101127675Sbms * ATM Address Resolution Protocol.
102127675Sbms *
103127675Sbms * See RFC 2225 for protocol description.  ATMARP packets are similar
104127675Sbms * to ARP packets, except that there are no length fields for the
105127675Sbms * protocol address - instead, there are type/length fields for
106127675Sbms * the ATM number and subaddress - and the hardware addresses consist
107127675Sbms * of an ATM number and an ATM subaddress.
108127675Sbms */
109127675Sbmsstruct	atmarp_pkthdr {
110127675Sbms	u_short	aar_hrd;	/* format of hardware address */
111127675Sbms#define ARPHRD_ATM2225	19	/* ATM (RFC 2225) */
112127675Sbms	u_short	aar_pro;	/* format of protocol address */
113127675Sbms	u_char	aar_shtl;	/* length of source ATM number */
114127675Sbms	u_char	aar_sstl;	/* length of source ATM subaddress */
115127675Sbms#define ATMARP_IS_E164	0x40	/* bit in type/length for E.164 format */
116127675Sbms#define ATMARP_LEN_MASK	0x3F	/* length of {sub}address in type/length */
117127675Sbms	u_short	aar_op;		/* same as regular ARP */
118127675Sbms#define ATMARPOP_NAK	10	/* NAK */
119127675Sbms	u_char	aar_spln;	/* length of source protocol address */
120127675Sbms	u_char	aar_thtl;	/* length of target ATM number */
121127675Sbms	u_char	aar_tstl;	/* length of target ATM subaddress */
122127675Sbms	u_char	aar_tpln;	/* length of target protocol address */
123127675Sbms/*
124127675Sbms * The remaining fields are variable in size,
125127675Sbms * according to the sizes above.
126127675Sbms */
127127675Sbms#ifdef COMMENT_ONLY
128127675Sbms	u_char	aar_sha[];	/* source ATM number */
129127675Sbms	u_char	aar_ssa[];	/* source ATM subaddress */
130127675Sbms	u_char	aar_spa[];	/* sender protocol address */
131127675Sbms	u_char	aar_tha[];	/* target ATM number */
132127675Sbms	u_char	aar_tsa[];	/* target ATM subaddress */
133127675Sbms	u_char	aar_tpa[];	/* target protocol address */
134127675Sbms#endif
135127675Sbms
136127675Sbms#define ATMHRD(ap)  EXTRACT_16BITS(&(ap)->aar_hrd)
137127675Sbms#define ATMSHLN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK)
138127675Sbms#define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK)
139127675Sbms#define ATMSPLN(ap) ((ap)->aar_spln)
140127675Sbms#define ATMOP(ap)   EXTRACT_16BITS(&(ap)->aar_op)
141127675Sbms#define ATMPRO(ap)  EXTRACT_16BITS(&(ap)->aar_pro)
142127675Sbms#define ATMTHLN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK)
143127675Sbms#define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK)
144127675Sbms#define ATMTPLN(ap) ((ap)->aar_tpln)
145127675Sbms#define aar_sha(ap)	((const u_char *)((ap)+1))
146127675Sbms#define aar_ssa(ap)	(aar_sha(ap) + ATMSHLN(ap))
147127675Sbms#define aar_spa(ap)	(aar_ssa(ap) + ATMSSLN(ap))
148127675Sbms#define aar_tha(ap)	(aar_spa(ap) + ATMSPLN(ap))
149127675Sbms#define aar_tsa(ap)	(aar_tha(ap) + ATMTHLN(ap))
150127675Sbms#define aar_tpa(ap)	(aar_tsa(ap) + ATMTSLN(ap))
151127675Sbms};
152127675Sbms
153127675Sbms#define ATMSHA(ap) (aar_sha(ap))
154127675Sbms#define ATMSSA(ap) (aar_ssa(ap))
155127675Sbms#define ATMSPA(ap) (aar_spa(ap))
156127675Sbms#define ATMTHA(ap) (aar_tha(ap))
157127675Sbms#define ATMTSA(ap) (aar_tsa(ap))
158127675Sbms#define ATMTPA(ap) (aar_tpa(ap))
159127675Sbms
16017680Spststatic u_char ezero[6];
16117680Spst
162127675Sbmsstatic void
163146778Ssamatmarp_addr_print(netdissect_options *ndo,
164146778Ssam		  const u_char *ha, u_int ha_len, const u_char *srca,
165127675Sbms    u_int srca_len)
166127675Sbms{
167127675Sbms	if (ha_len == 0)
168146778Ssam		ND_PRINT((ndo, "<No address>"));
169127675Sbms	else {
170146778Ssam		ND_PRINT((ndo, "%s", linkaddr_string(ha, ha_len)));
171146778Ssam		if (srca_len != 0)
172146778Ssam			ND_PRINT((ndo, ",%s",
173146778Ssam				  linkaddr_string(srca, srca_len)));
174127675Sbms	}
175127675Sbms}
176127675Sbms
177127675Sbmsstatic void
178146778Ssamatmarp_print(netdissect_options *ndo,
179146778Ssam	     const u_char *bp, u_int length, u_int caplen)
180127675Sbms{
181127675Sbms	const struct atmarp_pkthdr *ap;
182127675Sbms	u_short pro, hrd, op;
183127675Sbms
184127675Sbms	ap = (const struct atmarp_pkthdr *)bp;
185146778Ssam	ND_TCHECK(*ap);
186127675Sbms
187127675Sbms	hrd = ATMHRD(ap);
188127675Sbms	pro = ATMPRO(ap);
189127675Sbms	op = ATMOP(ap);
190127675Sbms
191146778Ssam	if (!ND_TTEST2(*aar_tpa(ap), ATMTPLN(ap))) {
192146778Ssam		ND_PRINT((ndo, "truncated-atmarp"));
193146778Ssam		ND_DEFAULTPRINT((const u_char *)ap, length);
194127675Sbms		return;
195127675Sbms	}
196127675Sbms
197127675Sbms	if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
198127675Sbms	    ATMSPLN(ap) != 4 || ATMTPLN(ap) != 4) {
199146778Ssam		ND_PRINT((ndo, "atmarp-#%d for proto #%d (%d/%d) hardware #%d",
200146778Ssam			  op, pro, ATMSPLN(ap), ATMTPLN(ap), hrd));
201127675Sbms		return;
202127675Sbms	}
203127675Sbms	if (pro == ETHERTYPE_TRAIL)
204146778Ssam		ND_PRINT((ndo, "trailer-"));
205127675Sbms	switch (op) {
206127675Sbms
207127675Sbms	case ARPOP_REQUEST:
208146778Ssam		ND_PRINT((ndo, "arp who-has %s", ipaddr_string(ATMTPA(ap))));
209127675Sbms		if (ATMTHLN(ap) != 0) {
210146778Ssam			ND_PRINT((ndo, " ("));
211146778Ssam			atmarp_addr_print(ndo, ATMTHA(ap), ATMTHLN(ap),
212127675Sbms			    ATMTSA(ap), ATMTSLN(ap));
213146778Ssam			ND_PRINT((ndo, ")"));
214127675Sbms		}
215146778Ssam		ND_PRINT((ndo, " tell %s", ipaddr_string(ATMSPA(ap))));
216127675Sbms		break;
217127675Sbms
218127675Sbms	case ARPOP_REPLY:
219146778Ssam		ND_PRINT((ndo, "arp reply %s", ipaddr_string(ATMSPA(ap))));
220146778Ssam		ND_PRINT((ndo, " is-at "));
221146778Ssam		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
222127675Sbms		    ATMSSLN(ap));
223127675Sbms		break;
224127675Sbms
225127675Sbms	case ARPOP_INVREQUEST:
226146778Ssam		ND_PRINT((ndo, "invarp who-is "));
227146778Ssam		atmarp_addr_print(ndo, ATMTHA(ap), ATMTHLN(ap), ATMTSA(ap),
228127675Sbms		    ATMTSLN(ap));
229146778Ssam		ND_PRINT((ndo, " tell "));
230146778Ssam		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
231127675Sbms		    ATMSSLN(ap));
232127675Sbms		break;
233127675Sbms
234127675Sbms	case ARPOP_INVREPLY:
235146778Ssam		ND_PRINT((ndo, "invarp reply "));
236146778Ssam		atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
237127675Sbms		    ATMSSLN(ap));
238146778Ssam		ND_PRINT((ndo, " at %s", ipaddr_string(ATMSPA(ap))));
239127675Sbms		break;
240127675Sbms
241127675Sbms	case ATMARPOP_NAK:
242146778Ssam		ND_PRINT((ndo, "nak reply for %s",
243146778Ssam			  ipaddr_string(ATMSPA(ap))));
244127675Sbms		break;
245127675Sbms
246127675Sbms	default:
247146778Ssam		ND_PRINT((ndo, "atmarp-#%d", op));
248146778Ssam		ND_DEFAULTPRINT((const u_char *)ap, caplen);
249127675Sbms		return;
250127675Sbms	}
251127675Sbms	return;
252127675Sbmstrunc:
253146778Ssam	ND_PRINT((ndo, "[|atmarp]"));
254127675Sbms}
255127675Sbms
25617680Spstvoid
257146778Ssamarp_print(netdissect_options *ndo,
258146778Ssam	  const u_char *bp, u_int length, u_int caplen)
25917680Spst{
260111729Sfenner	const struct arp_pkthdr *ap;
26198527Sfenner	u_short pro, hrd, op;
26217680Spst
263111729Sfenner	ap = (const struct arp_pkthdr *)bp;
264146778Ssam	ND_TCHECK(*ap);
265127675Sbms	hrd = HRD(ap);
266127675Sbms	if (hrd == ARPHRD_ATM2225) {
267146778Ssam	        atmarp_print(ndo, bp, length, caplen);
268127675Sbms		return;
269127675Sbms	}
270127675Sbms	pro = PRO(ap);
271127675Sbms	op = OP(ap);
272127675Sbms
273146778Ssam	if (!ND_TTEST2(*ar_tpa(ap), PLN(ap))) {
274146778Ssam		ND_PRINT((ndo, "truncated-arp"));
275146778Ssam		ND_DEFAULTPRINT((const u_char *)ap, length);
27617680Spst		return;
27717680Spst	}
27817680Spst
279127675Sbms	if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
280127675Sbms	    PLN(ap) != 4 || HLN(ap) == 0) {
281146778Ssam		ND_PRINT((ndo, "arp-#%d for proto #%d (%d) hardware #%d (%d)",
282146778Ssam			  op, pro, PLN(ap), hrd, HLN(ap)));
28317680Spst		return;
28417680Spst	}
28517680Spst	if (pro == ETHERTYPE_TRAIL)
286146778Ssam		ND_PRINT((ndo, "trailer-"));
28717680Spst	switch (op) {
28817680Spst
28917680Spst	case ARPOP_REQUEST:
290146778Ssam		ND_PRINT((ndo, "arp who-has %s", ipaddr_string(TPA(ap))));
29198527Sfenner		if (memcmp((const char *)ezero, (const char *)THA(ap), HLN(ap)) != 0)
292146778Ssam			ND_PRINT((ndo, " (%s)",
293146778Ssam				  linkaddr_string(THA(ap), HLN(ap))));
294146778Ssam		ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap))));
29517680Spst		break;
29617680Spst
29717680Spst	case ARPOP_REPLY:
298146778Ssam		ND_PRINT((ndo, "arp reply %s", ipaddr_string(SPA(ap))));
299146778Ssam		ND_PRINT((ndo, " is-at %s", linkaddr_string(SHA(ap), HLN(ap))));
30017680Spst		break;
30117680Spst
30298527Sfenner	case ARPOP_REVREQUEST:
303146778Ssam		ND_PRINT((ndo, "rarp who-is %s tell %s",
304146778Ssam			  linkaddr_string(THA(ap), HLN(ap)),
305146778Ssam			  linkaddr_string(SHA(ap), HLN(ap))));
30617680Spst		break;
30717680Spst
30898527Sfenner	case ARPOP_REVREPLY:
309146778Ssam		ND_PRINT((ndo, "rarp reply %s at %s",
310146778Ssam			  linkaddr_string(THA(ap), HLN(ap)),
311146778Ssam			  ipaddr_string(TPA(ap))));
31217680Spst		break;
31317680Spst
314127675Sbms	case ARPOP_INVREQUEST:
315146778Ssam		ND_PRINT((ndo, "invarp who-is %s tell %s",
316146778Ssam			  linkaddr_string(THA(ap), HLN(ap)),
317146778Ssam			  linkaddr_string(SHA(ap), HLN(ap))));
318127675Sbms		break;
319127675Sbms
320127675Sbms	case ARPOP_INVREPLY:
321146778Ssam		ND_PRINT((ndo,"invarp reply %s at %s",
322146778Ssam			  linkaddr_string(THA(ap), HLN(ap)),
323146778Ssam			  ipaddr_string(TPA(ap))));
324127675Sbms		break;
325127675Sbms
32617680Spst	default:
327146778Ssam		ND_PRINT((ndo, "arp-#%d", op));
328146778Ssam		ND_DEFAULTPRINT((const u_char *)ap, caplen);
32917680Spst		return;
33017680Spst	}
33117680Spst	if (hrd != ARPHRD_ETHER)
332146778Ssam		ND_PRINT((ndo, " hardware #%d", hrd));
33398527Sfenner	return;
33498527Sfennertrunc:
335146778Ssam	ND_PRINT((ndo, "[|arp]"));
33617680Spst}
337146778Ssam
338146778Ssam/*
339146778Ssam * Local Variables:
340146778Ssam * c-style: bsd
341146778Ssam * End:
342146778Ssam */
343146778Ssam
344