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