xref: /illumos-gate/usr/src/cmd/mdb/common/modules/arp/arp.c (revision bd670b35a010421b6e1a5536c34453a827007c81)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/stropts.h>
29 #include <sys/stream.h>
30 #include <sys/dlpi.h>
31 #include <sys/hook.h>
32 #include <sys/hook_event.h>
33 #include <inet/led.h>
34 #include <inet/common.h>
35 #include <inet/mi.h>
36 #include <inet/arp.h>
37 #include <inet/ip.h>
38 #include <netinet/arp.h>
39 
40 #include <mdb/mdb_modapi.h>
41 #include <mdb/mdb_ks.h>
42 
43 typedef struct {
44 	uint32_t	act_cmd;
45 	char		*act_name;
46 	char		*act_type;
47 } arp_cmd_tbl;
48 
49 /*
50  * removed all the ace/arl related stuff. The only thing that remains
51  * is code for dealing with ioctls and printing out arp header that
52  * should probably be moved into the ip/mdb module.
53  */
54 
55 /*
56  * Print an ARP hardware and protocol address pair; used when printing an ARP
57  * message.
58  */
59 static void
60 print_arp(char field_id, const uchar_t *buf, const arh_t *arh, uint16_t ptype)
61 {
62 	char macstr[ARP_MAX_ADDR_LEN*3];
63 	in_addr_t inaddr;
64 
65 	if (arh->arh_hlen == 0)
66 		(void) strcpy(macstr, "(none)");
67 	else
68 		mdb_mac_addr(buf, arh->arh_hlen, macstr, sizeof (macstr));
69 	mdb_printf("%?s  ar$%cha %s\n", "", field_id, macstr);
70 	if (arh->arh_plen == 0) {
71 		mdb_printf("%?s  ar$%cpa (none)\n", "", field_id);
72 	} else if (ptype == IP_ARP_PROTO_TYPE) {
73 		mdb_printf("%?s  ar$%cpa (unknown)\n", "", field_id);
74 	} else if (arh->arh_plen == sizeof (in_addr_t)) {
75 		(void) memcpy(&inaddr, buf + arh->arh_hlen, sizeof (inaddr));
76 		mdb_printf("%?s  ar$%cpa %I\n", "", field_id, inaddr);
77 	} else {
78 		mdb_printf("%?s  ar$%cpa (malformed IP)\n", "", field_id);
79 	}
80 }
81 
82 /*
83  * Decode an ARP message and display it.
84  */
85 /* ARGSUSED2 */
86 static int
87 arphdr_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
88 {
89 	struct {
90 		arh_t arh;
91 		uchar_t addrs[4 * ARP_MAX_ADDR_LEN];
92 	} arp;
93 	size_t blen;
94 	uint16_t htype, ptype, op;
95 	const char *cp;
96 
97 	if (!(flags & DCMD_ADDRSPEC)) {
98 		mdb_warn("address required to print ARP header\n");
99 		return (DCMD_ERR);
100 	}
101 
102 	if (mdb_vread(&arp.arh, sizeof (arp.arh), addr) == -1) {
103 		mdb_warn("unable to read ARP header at %p", addr);
104 		return (DCMD_ERR);
105 	}
106 	mdb_nhconvert(&htype, arp.arh.arh_hardware, sizeof (htype));
107 	mdb_nhconvert(&ptype, arp.arh.arh_proto, sizeof (ptype));
108 	mdb_nhconvert(&op, arp.arh.arh_operation, sizeof (op));
109 
110 	switch (htype) {
111 	case ARPHRD_ETHER:
112 		cp = "Ether";
113 		break;
114 	case ARPHRD_IEEE802:
115 		cp = "IEEE802";
116 		break;
117 	case ARPHRD_IB:
118 		cp = "InfiniBand";
119 		break;
120 	default:
121 		cp = "Unknown";
122 		break;
123 	}
124 	mdb_printf("%?p: ar$hrd %x (%s)\n", addr, htype, cp);
125 	mdb_printf("%?s  ar$pro %x (%s)\n", "", ptype,
126 	    ptype == IP_ARP_PROTO_TYPE ? "IP" : "Unknown");
127 
128 	switch (op) {
129 	case ARPOP_REQUEST:
130 		cp = "ares_op$REQUEST";
131 		break;
132 	case ARPOP_REPLY:
133 		cp = "ares_op$REPLY";
134 		break;
135 	case REVARP_REQUEST:
136 		cp = "arev_op$REQUEST";
137 		break;
138 	case REVARP_REPLY:
139 		cp = "arev_op$REPLY";
140 		break;
141 	default:
142 		cp = "Unknown";
143 		break;
144 	}
145 	mdb_printf("%?s  ar$op %d (%s)\n", "", op, cp);
146 
147 	/*
148 	 * Note that we go to some length to attempt to print out the fixed
149 	 * header data before trying to decode the variable-length data.  This
150 	 * is done to maximize the amount of useful information shown when the
151 	 * buffer is truncated or otherwise corrupt.
152 	 */
153 	blen = 2 * (arp.arh.arh_hlen + arp.arh.arh_plen);
154 	if (mdb_vread(&arp.addrs, blen, addr + sizeof (arp.arh)) == -1) {
155 		mdb_warn("unable to read ARP body at %p", addr);
156 		return (DCMD_ERR);
157 	}
158 
159 	print_arp('s', arp.addrs, &arp.arh, ptype);
160 	print_arp('t', arp.addrs + arp.arh.arh_hlen + arp.arh.arh_plen,
161 	    &arp.arh, ptype);
162 	return (DCMD_OK);
163 }
164 
165 static const mdb_dcmd_t dcmds[] = {
166 	{ "arphdr", ":", "display an ARP header", arphdr_cmd, NULL },
167 	{ NULL }
168 };
169 
170 /* Note: ar_t walker is in genunix.c and net.c; generic MI walker */
171 static const mdb_walker_t walkers[] = {
172 	{ NULL }
173 };
174 
175 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
176 
177 const mdb_modinfo_t *
178 _mdb_init(void)
179 {
180 	return (&modinfo);
181 }
182 
183 void
184 _mdb_fini(void)
185 {
186 }
187