/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { uint32_t act_cmd; char *act_name; char *act_type; } arp_cmd_tbl; /* * removed all the ace/arl related stuff. The only thing that remains * is code for dealing with ioctls and printing out arp header that * should probably be moved into the ip/mdb module. */ /* * Print an ARP hardware and protocol address pair; used when printing an ARP * message. */ static void print_arp(char field_id, const uchar_t *buf, const arh_t *arh, uint16_t ptype) { char macstr[ARP_MAX_ADDR_LEN*3]; in_addr_t inaddr; if (arh->arh_hlen == 0) (void) strcpy(macstr, "(none)"); else mdb_mac_addr(buf, arh->arh_hlen, macstr, sizeof (macstr)); mdb_printf("%?s ar$%cha %s\n", "", field_id, macstr); if (arh->arh_plen == 0) { mdb_printf("%?s ar$%cpa (none)\n", "", field_id); } else if (ptype == IP_ARP_PROTO_TYPE) { mdb_printf("%?s ar$%cpa (unknown)\n", "", field_id); } else if (arh->arh_plen == sizeof (in_addr_t)) { (void) memcpy(&inaddr, buf + arh->arh_hlen, sizeof (inaddr)); mdb_printf("%?s ar$%cpa %I\n", "", field_id, inaddr); } else { mdb_printf("%?s ar$%cpa (malformed IP)\n", "", field_id); } } /* * Decode an ARP message and display it. */ /* ARGSUSED2 */ static int arphdr_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { struct { arh_t arh; uchar_t addrs[4 * ARP_MAX_ADDR_LEN]; } arp; size_t blen; uint16_t htype, ptype, op; const char *cp; if (!(flags & DCMD_ADDRSPEC)) { mdb_warn("address required to print ARP header\n"); return (DCMD_ERR); } if (mdb_vread(&arp.arh, sizeof (arp.arh), addr) == -1) { mdb_warn("unable to read ARP header at %p", addr); return (DCMD_ERR); } mdb_nhconvert(&htype, arp.arh.arh_hardware, sizeof (htype)); mdb_nhconvert(&ptype, arp.arh.arh_proto, sizeof (ptype)); mdb_nhconvert(&op, arp.arh.arh_operation, sizeof (op)); switch (htype) { case ARPHRD_ETHER: cp = "Ether"; break; case ARPHRD_IEEE802: cp = "IEEE802"; break; case ARPHRD_IB: cp = "InfiniBand"; break; default: cp = "Unknown"; break; } mdb_printf("%?p: ar$hrd %x (%s)\n", addr, htype, cp); mdb_printf("%?s ar$pro %x (%s)\n", "", ptype, ptype == IP_ARP_PROTO_TYPE ? "IP" : "Unknown"); switch (op) { case ARPOP_REQUEST: cp = "ares_op$REQUEST"; break; case ARPOP_REPLY: cp = "ares_op$REPLY"; break; case REVARP_REQUEST: cp = "arev_op$REQUEST"; break; case REVARP_REPLY: cp = "arev_op$REPLY"; break; default: cp = "Unknown"; break; } mdb_printf("%?s ar$op %d (%s)\n", "", op, cp); /* * Note that we go to some length to attempt to print out the fixed * header data before trying to decode the variable-length data. This * is done to maximize the amount of useful information shown when the * buffer is truncated or otherwise corrupt. */ blen = 2 * (arp.arh.arh_hlen + arp.arh.arh_plen); if (mdb_vread(&arp.addrs, blen, addr + sizeof (arp.arh)) == -1) { mdb_warn("unable to read ARP body at %p", addr); return (DCMD_ERR); } print_arp('s', arp.addrs, &arp.arh, ptype); print_arp('t', arp.addrs + arp.arh.arh_hlen + arp.arh.arh_plen, &arp.arh, ptype); return (DCMD_OK); } static const mdb_dcmd_t dcmds[] = { { "arphdr", ":", "display an ARP header", arphdr_cmd, NULL }, { NULL } }; /* Note: ar_t walker is in genunix.c and net.c; generic MI walker */ static const mdb_walker_t walkers[] = { { NULL } }; static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; const mdb_modinfo_t * _mdb_init(void) { return (&modinfo); } void _mdb_fini(void) { }