xref: /illumos-gate/usr/src/cmd/mdb/common/modules/arp/arp.c (revision bd670b35)
169bb4bb4Scarlsonj /*
269bb4bb4Scarlsonj  * CDDL HEADER START
369bb4bb4Scarlsonj  *
469bb4bb4Scarlsonj  * The contents of this file are subject to the terms of the
569bb4bb4Scarlsonj  * Common Development and Distribution License (the "License").
669bb4bb4Scarlsonj  * You may not use this file except in compliance with the License.
769bb4bb4Scarlsonj  *
869bb4bb4Scarlsonj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
969bb4bb4Scarlsonj  * or http://www.opensolaris.org/os/licensing.
1069bb4bb4Scarlsonj  * See the License for the specific language governing permissions
1169bb4bb4Scarlsonj  * and limitations under the License.
1269bb4bb4Scarlsonj  *
1369bb4bb4Scarlsonj  * When distributing Covered Code, include this CDDL HEADER in each
1469bb4bb4Scarlsonj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1569bb4bb4Scarlsonj  * If applicable, add the following below this CDDL HEADER, with the
1669bb4bb4Scarlsonj  * fields enclosed by brackets "[]" replaced with your own identifying
1769bb4bb4Scarlsonj  * information: Portions Copyright [yyyy] [name of copyright owner]
1869bb4bb4Scarlsonj  *
1969bb4bb4Scarlsonj  * CDDL HEADER END
2069bb4bb4Scarlsonj  */
2169bb4bb4Scarlsonj /*
22*bd670b35SErik Nordmark  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2369bb4bb4Scarlsonj  * Use is subject to license terms.
2469bb4bb4Scarlsonj  */
2569bb4bb4Scarlsonj 
2669bb4bb4Scarlsonj #include <stdio.h>
2769bb4bb4Scarlsonj #include <sys/types.h>
2869bb4bb4Scarlsonj #include <sys/stropts.h>
2969bb4bb4Scarlsonj #include <sys/stream.h>
3069bb4bb4Scarlsonj #include <sys/dlpi.h>
31381a2a9aSdr #include <sys/hook.h>
32381a2a9aSdr #include <sys/hook_event.h>
3369bb4bb4Scarlsonj #include <inet/led.h>
3469bb4bb4Scarlsonj #include <inet/common.h>
3569bb4bb4Scarlsonj #include <inet/mi.h>
3669bb4bb4Scarlsonj #include <inet/arp.h>
3769bb4bb4Scarlsonj #include <inet/ip.h>
3869bb4bb4Scarlsonj #include <netinet/arp.h>
3969bb4bb4Scarlsonj 
4069bb4bb4Scarlsonj #include <mdb/mdb_modapi.h>
4169bb4bb4Scarlsonj #include <mdb/mdb_ks.h>
4269bb4bb4Scarlsonj 
4369bb4bb4Scarlsonj typedef struct {
4469bb4bb4Scarlsonj 	uint32_t	act_cmd;
4569bb4bb4Scarlsonj 	char		*act_name;
4669bb4bb4Scarlsonj 	char		*act_type;
4769bb4bb4Scarlsonj } arp_cmd_tbl;
4869bb4bb4Scarlsonj 
4969bb4bb4Scarlsonj /*
50*bd670b35SErik Nordmark  * removed all the ace/arl related stuff. The only thing that remains
51*bd670b35SErik Nordmark  * is code for dealing with ioctls and printing out arp header that
52*bd670b35SErik Nordmark  * should probably be moved into the ip/mdb module.
5384f43adeSzf  */
5469bb4bb4Scarlsonj 
5569bb4bb4Scarlsonj /*
5669bb4bb4Scarlsonj  * Print an ARP hardware and protocol address pair; used when printing an ARP
5769bb4bb4Scarlsonj  * message.
5869bb4bb4Scarlsonj  */
5969bb4bb4Scarlsonj static void
print_arp(char field_id,const uchar_t * buf,const arh_t * arh,uint16_t ptype)6069bb4bb4Scarlsonj print_arp(char field_id, const uchar_t *buf, const arh_t *arh, uint16_t ptype)
6169bb4bb4Scarlsonj {
6269bb4bb4Scarlsonj 	char macstr[ARP_MAX_ADDR_LEN*3];
6369bb4bb4Scarlsonj 	in_addr_t inaddr;
6469bb4bb4Scarlsonj 
6569bb4bb4Scarlsonj 	if (arh->arh_hlen == 0)
6669bb4bb4Scarlsonj 		(void) strcpy(macstr, "(none)");
6769bb4bb4Scarlsonj 	else
6869bb4bb4Scarlsonj 		mdb_mac_addr(buf, arh->arh_hlen, macstr, sizeof (macstr));
6969bb4bb4Scarlsonj 	mdb_printf("%?s  ar$%cha %s\n", "", field_id, macstr);
7069bb4bb4Scarlsonj 	if (arh->arh_plen == 0) {
7169bb4bb4Scarlsonj 		mdb_printf("%?s  ar$%cpa (none)\n", "", field_id);
7269bb4bb4Scarlsonj 	} else if (ptype == IP_ARP_PROTO_TYPE) {
7369bb4bb4Scarlsonj 		mdb_printf("%?s  ar$%cpa (unknown)\n", "", field_id);
7469bb4bb4Scarlsonj 	} else if (arh->arh_plen == sizeof (in_addr_t)) {
7569bb4bb4Scarlsonj 		(void) memcpy(&inaddr, buf + arh->arh_hlen, sizeof (inaddr));
7669bb4bb4Scarlsonj 		mdb_printf("%?s  ar$%cpa %I\n", "", field_id, inaddr);
7769bb4bb4Scarlsonj 	} else {
7869bb4bb4Scarlsonj 		mdb_printf("%?s  ar$%cpa (malformed IP)\n", "", field_id);
7969bb4bb4Scarlsonj 	}
8069bb4bb4Scarlsonj }
8169bb4bb4Scarlsonj 
8269bb4bb4Scarlsonj /*
8369bb4bb4Scarlsonj  * Decode an ARP message and display it.
8469bb4bb4Scarlsonj  */
8569bb4bb4Scarlsonj /* ARGSUSED2 */
8669bb4bb4Scarlsonj static int
arphdr_cmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8769bb4bb4Scarlsonj arphdr_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8869bb4bb4Scarlsonj {
8969bb4bb4Scarlsonj 	struct {
9069bb4bb4Scarlsonj 		arh_t arh;
9169bb4bb4Scarlsonj 		uchar_t addrs[4 * ARP_MAX_ADDR_LEN];
9269bb4bb4Scarlsonj 	} arp;
9369bb4bb4Scarlsonj 	size_t blen;
9469bb4bb4Scarlsonj 	uint16_t htype, ptype, op;
9569bb4bb4Scarlsonj 	const char *cp;
9669bb4bb4Scarlsonj 
9769bb4bb4Scarlsonj 	if (!(flags & DCMD_ADDRSPEC)) {
9869bb4bb4Scarlsonj 		mdb_warn("address required to print ARP header\n");
9969bb4bb4Scarlsonj 		return (DCMD_ERR);
10069bb4bb4Scarlsonj 	}
10169bb4bb4Scarlsonj 
10269bb4bb4Scarlsonj 	if (mdb_vread(&arp.arh, sizeof (arp.arh), addr) == -1) {
10369bb4bb4Scarlsonj 		mdb_warn("unable to read ARP header at %p", addr);
10469bb4bb4Scarlsonj 		return (DCMD_ERR);
10569bb4bb4Scarlsonj 	}
10669bb4bb4Scarlsonj 	mdb_nhconvert(&htype, arp.arh.arh_hardware, sizeof (htype));
10769bb4bb4Scarlsonj 	mdb_nhconvert(&ptype, arp.arh.arh_proto, sizeof (ptype));
10869bb4bb4Scarlsonj 	mdb_nhconvert(&op, arp.arh.arh_operation, sizeof (op));
10969bb4bb4Scarlsonj 
11069bb4bb4Scarlsonj 	switch (htype) {
11169bb4bb4Scarlsonj 	case ARPHRD_ETHER:
11269bb4bb4Scarlsonj 		cp = "Ether";
11369bb4bb4Scarlsonj 		break;
11469bb4bb4Scarlsonj 	case ARPHRD_IEEE802:
11569bb4bb4Scarlsonj 		cp = "IEEE802";
11669bb4bb4Scarlsonj 		break;
11769bb4bb4Scarlsonj 	case ARPHRD_IB:
11869bb4bb4Scarlsonj 		cp = "InfiniBand";
11969bb4bb4Scarlsonj 		break;
12069bb4bb4Scarlsonj 	default:
12169bb4bb4Scarlsonj 		cp = "Unknown";
12269bb4bb4Scarlsonj 		break;
12369bb4bb4Scarlsonj 	}
12469bb4bb4Scarlsonj 	mdb_printf("%?p: ar$hrd %x (%s)\n", addr, htype, cp);
12569bb4bb4Scarlsonj 	mdb_printf("%?s  ar$pro %x (%s)\n", "", ptype,
12669bb4bb4Scarlsonj 	    ptype == IP_ARP_PROTO_TYPE ? "IP" : "Unknown");
12769bb4bb4Scarlsonj 
12869bb4bb4Scarlsonj 	switch (op) {
12969bb4bb4Scarlsonj 	case ARPOP_REQUEST:
13069bb4bb4Scarlsonj 		cp = "ares_op$REQUEST";
13169bb4bb4Scarlsonj 		break;
13269bb4bb4Scarlsonj 	case ARPOP_REPLY:
13369bb4bb4Scarlsonj 		cp = "ares_op$REPLY";
13469bb4bb4Scarlsonj 		break;
13569bb4bb4Scarlsonj 	case REVARP_REQUEST:
13669bb4bb4Scarlsonj 		cp = "arev_op$REQUEST";
13769bb4bb4Scarlsonj 		break;
13869bb4bb4Scarlsonj 	case REVARP_REPLY:
13969bb4bb4Scarlsonj 		cp = "arev_op$REPLY";
14069bb4bb4Scarlsonj 		break;
14169bb4bb4Scarlsonj 	default:
14269bb4bb4Scarlsonj 		cp = "Unknown";
14369bb4bb4Scarlsonj 		break;
14469bb4bb4Scarlsonj 	}
14569bb4bb4Scarlsonj 	mdb_printf("%?s  ar$op %d (%s)\n", "", op, cp);
14669bb4bb4Scarlsonj 
14769bb4bb4Scarlsonj 	/*
14869bb4bb4Scarlsonj 	 * Note that we go to some length to attempt to print out the fixed
14969bb4bb4Scarlsonj 	 * header data before trying to decode the variable-length data.  This
15069bb4bb4Scarlsonj 	 * is done to maximize the amount of useful information shown when the
15169bb4bb4Scarlsonj 	 * buffer is truncated or otherwise corrupt.
15269bb4bb4Scarlsonj 	 */
15369bb4bb4Scarlsonj 	blen = 2 * (arp.arh.arh_hlen + arp.arh.arh_plen);
15469bb4bb4Scarlsonj 	if (mdb_vread(&arp.addrs, blen, addr + sizeof (arp.arh)) == -1) {
15569bb4bb4Scarlsonj 		mdb_warn("unable to read ARP body at %p", addr);
15669bb4bb4Scarlsonj 		return (DCMD_ERR);
15769bb4bb4Scarlsonj 	}
15869bb4bb4Scarlsonj 
15969bb4bb4Scarlsonj 	print_arp('s', arp.addrs, &arp.arh, ptype);
16069bb4bb4Scarlsonj 	print_arp('t', arp.addrs + arp.arh.arh_hlen + arp.arh.arh_plen,
16169bb4bb4Scarlsonj 	    &arp.arh, ptype);
16269bb4bb4Scarlsonj 	return (DCMD_OK);
16369bb4bb4Scarlsonj }
16469bb4bb4Scarlsonj 
16569bb4bb4Scarlsonj static const mdb_dcmd_t dcmds[] = {
16669bb4bb4Scarlsonj 	{ "arphdr", ":", "display an ARP header", arphdr_cmd, NULL },
16769bb4bb4Scarlsonj 	{ NULL }
16869bb4bb4Scarlsonj };
16969bb4bb4Scarlsonj 
17069bb4bb4Scarlsonj /* Note: ar_t walker is in genunix.c and net.c; generic MI walker */
17169bb4bb4Scarlsonj static const mdb_walker_t walkers[] = {
17269bb4bb4Scarlsonj 	{ NULL }
17369bb4bb4Scarlsonj };
17469bb4bb4Scarlsonj 
17569bb4bb4Scarlsonj static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
17669bb4bb4Scarlsonj 
17769bb4bb4Scarlsonj const mdb_modinfo_t *
_mdb_init(void)17869bb4bb4Scarlsonj _mdb_init(void)
17969bb4bb4Scarlsonj {
18069bb4bb4Scarlsonj 	return (&modinfo);
18169bb4bb4Scarlsonj }
18269bb4bb4Scarlsonj 
18369bb4bb4Scarlsonj void
_mdb_fini(void)18469bb4bb4Scarlsonj _mdb_fini(void)
18569bb4bb4Scarlsonj {
18669bb4bb4Scarlsonj }
187