xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_arp.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1991-2001, 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/errno.h>
31*0Sstevel@tonic-gate #include <setjmp.h>
32*0Sstevel@tonic-gate #include <sys/socket.h>
33*0Sstevel@tonic-gate #include <net/if.h>
34*0Sstevel@tonic-gate #include <net/if_arp.h>
35*0Sstevel@tonic-gate #include <netinet/in_systm.h>
36*0Sstevel@tonic-gate #include <netinet/in.h>
37*0Sstevel@tonic-gate #include <netinet/ip.h>
38*0Sstevel@tonic-gate #include <netinet/if_ether.h>
39*0Sstevel@tonic-gate #include <netdb.h>
40*0Sstevel@tonic-gate #include <net/if_types.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include "snoop.h"
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate extern char *dlc_header;
45*0Sstevel@tonic-gate extern jmp_buf xdr_err;
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate static char *printip(unsigned char *);
48*0Sstevel@tonic-gate static char *addrtoname_align(unsigned char *);
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate static char unarp_addr[] = "Unknown";
51*0Sstevel@tonic-gate char *opname[] = {
52*0Sstevel@tonic-gate 	"",
53*0Sstevel@tonic-gate 	"ARP Request",
54*0Sstevel@tonic-gate 	"ARP Reply",
55*0Sstevel@tonic-gate 	"REVARP Request",
56*0Sstevel@tonic-gate 	"REVARP Reply",
57*0Sstevel@tonic-gate };
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate void
60*0Sstevel@tonic-gate interpret_arp(int flags, struct arphdr *ap, int alen)
61*0Sstevel@tonic-gate {
62*0Sstevel@tonic-gate 	char *line;
63*0Sstevel@tonic-gate 	extern char *src_name, *dst_name;
64*0Sstevel@tonic-gate 	unsigned char *sip, *tip, *sha, *tha;
65*0Sstevel@tonic-gate 	char *smacbuf = NULL, *dmacbuf = NULL;
66*0Sstevel@tonic-gate 	int maclen;
67*0Sstevel@tonic-gate 	ushort_t arpop;
68*0Sstevel@tonic-gate 	boolean_t is_ip = B_FALSE;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	/*
71*0Sstevel@tonic-gate 	 * Check that at least the generic ARP header was received.
72*0Sstevel@tonic-gate 	 */
73*0Sstevel@tonic-gate 	if (sizeof (struct arphdr) > alen)
74*0Sstevel@tonic-gate 		goto short_packet;
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	arpop = ntohs(ap->ar_op);
77*0Sstevel@tonic-gate 	maclen = ap->ar_hln;
78*0Sstevel@tonic-gate 	if (ntohs(ap->ar_pro) == ETHERTYPE_IP)
79*0Sstevel@tonic-gate 		is_ip = B_TRUE;
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	sha = (unsigned char *)(ap + 1);
82*0Sstevel@tonic-gate 	sip = sha + maclen;
83*0Sstevel@tonic-gate 	tha = sip + ap->ar_pln;
84*0Sstevel@tonic-gate 	tip = tha + maclen;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	/*
87*0Sstevel@tonic-gate 	 * Check that the protocol/hardware addresses were received.
88*0Sstevel@tonic-gate 	 */
89*0Sstevel@tonic-gate 	if ((tip + ap->ar_pln) > ((unsigned char *)ap + alen))
90*0Sstevel@tonic-gate 		goto short_packet;
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 	if (maclen == 0) {
93*0Sstevel@tonic-gate 		smacbuf = dmacbuf = unarp_addr;
94*0Sstevel@tonic-gate 	} else {
95*0Sstevel@tonic-gate 		if (((flags & F_DTAIL) && is_ip) || (arpop == ARPOP_REPLY)) {
96*0Sstevel@tonic-gate 			smacbuf = _link_ntoa(sha, NULL, maclen, IFT_OTHER);
97*0Sstevel@tonic-gate 			if (smacbuf == NULL)
98*0Sstevel@tonic-gate 				pr_err("Warning: malloc failure");
99*0Sstevel@tonic-gate 		}
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 		if (((flags & F_DTAIL) && is_ip) || (arpop ==
102*0Sstevel@tonic-gate 		    REVARP_REQUEST) || (arpop == REVARP_REPLY)) {
103*0Sstevel@tonic-gate 			dmacbuf = _link_ntoa(tha, NULL, maclen, IFT_OTHER);
104*0Sstevel@tonic-gate 			if (dmacbuf == NULL)
105*0Sstevel@tonic-gate 				pr_err("Warning: malloc failure");
106*0Sstevel@tonic-gate 		}
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	src_name = addrtoname_align(sip);
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	if (flags & F_SUM) {
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 		line = get_sum_line();
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 		switch (arpop) {
116*0Sstevel@tonic-gate 		case ARPOP_REQUEST:
117*0Sstevel@tonic-gate 			(void) snprintf(line, MAXLINE, "ARP C Who is %s ?",
118*0Sstevel@tonic-gate 			    printip(tip));
119*0Sstevel@tonic-gate 			break;
120*0Sstevel@tonic-gate 		case ARPOP_REPLY:
121*0Sstevel@tonic-gate 			(void) snprintf(line, MAXLINE, "ARP R %s is %s",
122*0Sstevel@tonic-gate 			    printip(sip), smacbuf);
123*0Sstevel@tonic-gate 			dst_name = addrtoname_align(tip);
124*0Sstevel@tonic-gate 			break;
125*0Sstevel@tonic-gate 		case REVARP_REQUEST:
126*0Sstevel@tonic-gate 			(void) snprintf(line, MAXLINE, "RARP C Who is %s ?",
127*0Sstevel@tonic-gate 			    dmacbuf);
128*0Sstevel@tonic-gate 			break;
129*0Sstevel@tonic-gate 		case REVARP_REPLY:
130*0Sstevel@tonic-gate 			(void) snprintf(line, MAXLINE, "RARP R %s is %s",
131*0Sstevel@tonic-gate 			    dmacbuf, printip(tip));
132*0Sstevel@tonic-gate 			dst_name = addrtoname_align(tip);
133*0Sstevel@tonic-gate 			break;
134*0Sstevel@tonic-gate 		}
135*0Sstevel@tonic-gate 	}
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	if (flags & F_DTAIL) {
138*0Sstevel@tonic-gate 		show_header("ARP:  ", "ARP/RARP Frame", alen);
139*0Sstevel@tonic-gate 		show_space();
140*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
141*0Sstevel@tonic-gate 		    "Hardware type = %d", ntohs(ap->ar_hrd));
142*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
143*0Sstevel@tonic-gate 		    "Protocol type = %04x (%s)", ntohs(ap->ar_pro),
144*0Sstevel@tonic-gate 		    print_ethertype(ntohs(ap->ar_pro)));
145*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
146*0Sstevel@tonic-gate 		    "Length of hardware address = %d bytes", ap->ar_hln);
147*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
148*0Sstevel@tonic-gate 		    "Length of protocol address = %d bytes", ap->ar_pln);
149*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
150*0Sstevel@tonic-gate 		    "Opcode %d (%s)", arpop,
151*0Sstevel@tonic-gate 		    (arpop > REVARP_REPLY) ? opname[0] : opname[arpop]);
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 		if (is_ip) {
154*0Sstevel@tonic-gate 			(void) snprintf(get_line(0, 0), get_line_remain(),
155*0Sstevel@tonic-gate 			    "Sender's hardware address = %s", smacbuf);
156*0Sstevel@tonic-gate 			(void) snprintf(get_line(0, 0), get_line_remain(),
157*0Sstevel@tonic-gate 			    "Sender's protocol address = %s",
158*0Sstevel@tonic-gate 			    printip(sip));
159*0Sstevel@tonic-gate 			(void) snprintf(get_line(0, 0), get_line_remain(),
160*0Sstevel@tonic-gate 			    "Target hardware address = %s",
161*0Sstevel@tonic-gate 			    arpop == ARPOP_REQUEST ? "?" : dmacbuf);
162*0Sstevel@tonic-gate 			(void) snprintf(get_line(0, 0), get_line_remain(),
163*0Sstevel@tonic-gate 			    "Target protocol address = %s",
164*0Sstevel@tonic-gate 			    arpop == REVARP_REQUEST ? "?" :
165*0Sstevel@tonic-gate 			    printip(tip));
166*0Sstevel@tonic-gate 		}
167*0Sstevel@tonic-gate 		show_trailer();
168*0Sstevel@tonic-gate 	}
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	if (maclen != 0) {
171*0Sstevel@tonic-gate 		free(smacbuf);
172*0Sstevel@tonic-gate 		free(dmacbuf);
173*0Sstevel@tonic-gate 	}
174*0Sstevel@tonic-gate 	return;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate short_packet:
177*0Sstevel@tonic-gate 	if (flags & F_SUM) {
178*0Sstevel@tonic-gate 		(void) snprintf(get_sum_line(), MAXLINE,
179*0Sstevel@tonic-gate 		    "ARP (short packet)");
180*0Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
181*0Sstevel@tonic-gate 		show_header("ARP:  ", "ARP/RARP Frame", alen);
182*0Sstevel@tonic-gate 		show_space();
183*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
184*0Sstevel@tonic-gate 		    "ARP (short packet)");
185*0Sstevel@tonic-gate 	}
186*0Sstevel@tonic-gate }
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate char *
189*0Sstevel@tonic-gate printip(unsigned char *p)
190*0Sstevel@tonic-gate {
191*0Sstevel@tonic-gate 	static char buff[MAXHOSTNAMELEN + 32];
192*0Sstevel@tonic-gate 	char *ap, *np;
193*0Sstevel@tonic-gate 	struct in_addr a;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 	memcpy(&a, p, 4);
196*0Sstevel@tonic-gate 	ap = (char *)inet_ntoa(a);
197*0Sstevel@tonic-gate 	np = (char *)addrtoname(AF_INET, &a);
198*0Sstevel@tonic-gate 	(void) snprintf(buff, MAXHOSTNAMELEN, "%s, %s", ap, np);
199*0Sstevel@tonic-gate 	return (buff);
200*0Sstevel@tonic-gate }
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate char *
203*0Sstevel@tonic-gate addrtoname_align(unsigned char *p)
204*0Sstevel@tonic-gate {
205*0Sstevel@tonic-gate 	struct in_addr a;
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	memcpy(&a, p, 4);
208*0Sstevel@tonic-gate 	return ((char *)addrtoname(AF_INET, &a));
209*0Sstevel@tonic-gate }
210