arp.c revision 69bb4bb45c98da60d21839c4dc3c01ea1be60585
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/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Use is subject to license terms.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#pragma ident "%Z%%M% %I% %E% SMI"
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>
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#include <inet/led.h>
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#include <inet/common.h>
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#include <inet/mi.h>
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#include <inet/arp.h>
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj#include <inet/arp_impl.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/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Table of ARP commands and structure types used for messages between ARP and
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * IP.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic const arp_cmd_tbl act_list[] = {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ENTRY_ADD, "AR_ENTRY_ADD", "arp`area_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ENTRY_DELETE, "AR_ENTRY_DELETE", "arp`ared_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ENTRY_QUERY, "AR_ENTRY_QUERY", "arp`areq_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ENTRY_SQUERY, "AR_ENTRY_SQUERY", "arp`area_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_MAPPING_ADD, "AR_MAPPING_ADD", "arp`arma_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_CLIENT_NOTIFY, "AR_CLIENT_NOTIFY", "arp`arcn_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_INTERFACE_UP, "AR_INTERFACE_UP", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_INTERFACE_DOWN, "AR_INTERFACE_DOWN", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_INTERFACE_ON, "AR_INTERFACE_ON", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_INTERFACE_OFF, "AR_INTERFACE_OFF", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_DLPIOP_DONE, "AR_DLPIOP_DONE", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ARP_CLOSING, "AR_ARP_CLOSING", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { AR_ARP_EXTEND, "AR_ARP_EXTEND", "arp`arc_t" },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { 0, "unknown command", "arp`arc_t" }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj};
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * State information kept during walk over ACE hash table and unhashed mask
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * list.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjtypedef struct ace_walk_data {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_t *awd_hash_tbl[ARP_HASH_SIZE];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_t *awd_masks;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj int awd_idx;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj} ace_walk_data_t;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarl_walk_init(mdb_walk_state_t *wsp)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (wsp->walk_addr == NULL &&
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_readvar(&wsp->walk_addr, "arl_g_head") == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read 'arl_g_head'");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_NEXT);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarl_walk_step(mdb_walk_state_t *wsp)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uintptr_t addr = wsp->walk_addr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arl_t arl;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (wsp->walk_addr == NULL)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_DONE);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&arl, sizeof (arl), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read arl_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_addr = (uintptr_t)arl.arl_next;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return ((*wsp->walk_callback)(addr, &arl, wsp->walk_cbdata));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjace_walk_init(mdb_walk_state_t *wsp)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_walk_data_t *aw;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (wsp->walk_addr != NULL) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("ace supports only global walks\n");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj aw = mdb_alloc(sizeof (ace_walk_data_t), UM_SLEEP);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_readsym(aw->awd_hash_tbl, sizeof (aw->awd_hash_tbl),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "ar_ce_hash_tbl") == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read 'ar_ce_hash_tbl'");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_free(aw, sizeof (ace_walk_data_t));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_readvar(&aw->awd_masks, "ar_ce_mask_entries") == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read 'ar_ce_mask_entries'");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_free(aw, sizeof (ace_walk_data_t));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /* The step routine will start off by incrementing to index 0 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj aw->awd_idx = -1;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_addr = 0;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_data = aw;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_NEXT);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjace_walk_step(mdb_walk_state_t *wsp)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uintptr_t addr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_walk_data_t *aw = wsp->walk_data;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_t ace;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * If we're at the end of the previous list, then find the start of the
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * next list to process.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj while (wsp->walk_addr == NULL) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (aw->awd_idx == ARP_HASH_SIZE)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_DONE);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (++aw->awd_idx == ARP_HASH_SIZE) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_addr = (uintptr_t)aw->awd_masks;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_addr =
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)aw->awd_hash_tbl[aw->awd_idx];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj addr = wsp->walk_addr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&ace, sizeof (ace), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read ace_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj wsp->walk_addr = (uintptr_t)ace.ace_next;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (wsp->walk_callback(addr, &ace, wsp->walk_cbdata));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic void
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjace_walk_fini(mdb_walk_state_t *wsp)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_free(wsp->walk_data, sizeof (ace_walk_data_t));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* Common routine to produce an 'ar' text description */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic void
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjar_describe(const ar_t *ar, char *buf, size_t nbytes, boolean_t addmac)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (ar->ar_arl == NULL) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj queue_t wq, ipq;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ill_t ill;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char name[LIFNAMSIZ];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj GElf_Sym sym;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj boolean_t nextip;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&wq, sizeof (wq), (uintptr_t)ar->ar_wq) == -1 ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_vread(&ipq, sizeof (ipq), (uintptr_t)wq.q_next) == -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj nextip =
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0 &&
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)sym.st_value == (uintptr_t)ipq.q_qinfo);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (!ar->ar_on_ill_stream) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(buf, nextip ? "Client" : "Unknown");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (!nextip ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_vread(&ill, sizeof (ill), (uintptr_t)ipq.q_ptr) == -1 ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_readstr(name, sizeof (name),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)ill.ill_name) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) mdb_snprintf(buf, nbytes, "IP %s", name);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arl_t arl;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ssize_t retv;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uint32_t alen;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uchar_t macaddr[ARP_MAX_ADDR_LEN];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&arl, sizeof (arl), (uintptr_t)ar->ar_arl) == -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj retv = mdb_snprintf(buf, nbytes, "ARP %s ", arl.arl_name);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (retv >= nbytes || !addmac)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj alen = arl.arl_hw_addr_length;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (arl.arl_hw_addr == NULL || alen == 0 ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj alen > sizeof (macaddr))
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(macaddr, alen, (uintptr_t)arl.arl_hw_addr) == -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_mac_addr(macaddr, alen, buf + retv, nbytes - retv);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjar_cb(uintptr_t addr, const void *arptr, void *dummy)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const ar_t *ar = arptr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char ardesc[sizeof ("ARP ") + LIFNAMSIZ];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_describe(ar, ardesc, sizeof (ardesc), B_FALSE);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%?p %?p %?p %s\n", addr, ar->ar_wq, ar->ar_arl, ardesc);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_NEXT);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Print out ARP client structures.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjar_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_t ar;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%<u>%?s %?s %?s %s%</u>\n",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "AR", "WQ", "ARL", "TYPE");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (flags & DCMD_ADDRSPEC) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&ar, sizeof (ar), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read ar_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) ar_cb(addr, &ar, NULL);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_walk("ar", ar_cb, NULL) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("cannot walk ar_t structures");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_OK);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarl_cb(uintptr_t addr, const void *arlptr, void *dummy)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const arl_t *arl = arlptr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uchar_t macaddr[ARP_MAX_ADDR_LEN];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char macstr[ARP_MAX_ADDR_LEN*3];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char flags[4];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const char *primstr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%?p ", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (arl->arl_dlpi_pending == DL_PRIM_INVAL)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%16s", "--");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj else if ((primstr = mdb_dlpi_prim(arl->arl_dlpi_pending)) != NULL)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%16s", primstr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj else
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%16x", arl->arl_dlpi_pending);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (arl->arl_hw_addr_length == 0 ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arl->arl_hw_addr_length > sizeof (macaddr)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(macstr, "--");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else if (mdb_vread(macaddr, arl->arl_hw_addr_length,
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)arl->arl_hw_addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(macstr, "?");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_mac_addr(macaddr, arl->arl_hw_addr_length, macstr,
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj sizeof (macstr));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /* Print both the link-layer state and the NOARP flag */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj flags[0] = '\0';
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (arl->arl_flags & ARL_F_NOARP)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcat(flags, "N");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj switch (arl->arl_state) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj case ARL_S_DOWN:
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcat(flags, "d");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj break;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj case ARL_S_PENDING:
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcat(flags, "P");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj break;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj case ARL_S_UP:
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcat(flags, "U");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj break;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj default:
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcat(flags, "?");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj break;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf(" %8d %-3s %-9s %s\n",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_mblk_count(arl->arl_dlpi_deferred), flags, arl->arl_name,
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj macstr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_NEXT);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Print out ARP link-layer elements.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarl_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arl_t arl;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%<u>%?s %16s %8s %3s %9s %s%</u>\n",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "ARL", "DLPI REQ", "DLPI CNT", "FLG", "INTERFACE",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "HW ADDR");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (flags & DCMD_ADDRSPEC) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&arl, sizeof (arl), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read arl_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) arl_cb(addr, &arl, NULL);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_walk("arl", arl_cb, NULL) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("cannot walk arl_t structures");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_OK);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjace_cb(uintptr_t addr, const void *aceptr, void *dummy)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const ace_t *ace = aceptr;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj uchar_t macaddr[ARP_MAX_ADDR_LEN];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char macstr[ARP_MAX_ADDR_LEN*3];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /* The %b format isn't compact enough for long listings */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj static const char ace_flags[] = "SPDRMLdA ofya";
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const char *cp;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char flags[sizeof (ace_flags)], *fp;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj int flg;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj in_addr_t inaddr, mask;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj char addrstr[sizeof ("255.255.255.255/32")];
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /* Walk the list of flags and produce a string */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj cp = ace_flags;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj fp = flags;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj for (flg = 1; *cp != '\0'; flg <<= 1, cp++) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if ((flg & ace->ace_flags) && *cp != ' ')
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj *fp++ = *cp;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj *fp = '\0';
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /* If it's not resolved, then it has no hardware address */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (!(ace->ace_flags & ACE_F_RESOLVED) ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace->ace_hw_addr_length == 0 ||
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace->ace_hw_addr_length > sizeof (macaddr)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(macstr, "--");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else if (mdb_vread(macaddr, ace->ace_hw_addr_length,
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)ace->ace_hw_addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(macstr, "?");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_mac_addr(macaddr, ace->ace_hw_addr_length, macstr,
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj sizeof (macstr));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Nothing other than IP uses ARP these days, so we don't try very hard
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * here to switch out on ARP protocol type. (Note that ARP protocol
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * types are roughly Ethertypes, but are allocated separately at IANA.)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (ace->ace_proto != IP_ARP_PROTO_TYPE) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) mdb_snprintf(addrstr, sizeof (addrstr),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "Unknown proto %x", ace->ace_proto);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else if (mdb_vread(&inaddr, sizeof (inaddr),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)ace->ace_proto_addr) != -1 &&
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_vread(&mask, sizeof (mask), (uintptr_t)ace->ace_proto_mask) !=
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * If it's the standard host mask, then print it normally.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Otherwise, use "/n" notation.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mask == (in_addr_t)~0) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) mdb_snprintf(addrstr, sizeof (addrstr), "%I",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj inaddr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) mdb_snprintf(addrstr, sizeof (addrstr), "%I/%d",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj inaddr, mask == 0 ? 0 : 33 - mdb_ffs(mask));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) strcpy(addrstr, "?");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%?p %-18s %-8s %s\n", addr, addrstr, flags, macstr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (WALK_NEXT);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Print out ARP cache entry (ace_t) elements.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjace_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_t ace;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%<u>%?s %-18s %-8s %s%</u>\n",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj "ACE", "PROTOADDR", "FLAGS", "HWADDR");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (flags & DCMD_ADDRSPEC) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&ace, sizeof (ace), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("failed to read ace_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (void) ace_cb(addr, &ace, NULL);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } else {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_walk("ace", ace_cb, NULL) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("cannot walk ace_t structures");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_OK);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
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
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * Print out an arp command formatted in a reasonable manner. This implements
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * the type switch used by ARP.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj *
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * It could also dump the data that follows the header (using offset and length
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * in the various structures), but it currently does not.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/* ARGSUSED2 */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic int
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarpcmd_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arc_t arc;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj const arp_cmd_tbl *tp;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_arg_t subargv;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (!(flags & DCMD_ADDRSPEC)) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("address required to print ARP command\n");
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&arc, sizeof (arc), addr) == -1) {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_warn("unable to read arc_t at %p", addr);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj for (tp = act_list; tp->act_cmd != 0; tp++)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (tp->act_cmd == arc.arc_cmd)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj break;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_printf("%p %s (%s) = ", addr, tp->act_name, tp->act_type);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj subargv.a_type = MDB_TYPE_STRING;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj subargv.a_un.a_str = tp->act_type;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_call_dcmd("print", addr, DCMD_ADDRSPEC, 1, &subargv) == -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_ERR);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj else
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (DCMD_OK);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic size_t
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjmi_osize(const queue_t *q)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj /*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * The code in common/inet/mi.c allocates an extra word to store the
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj struct mi_block {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj size_t mi_nbytes;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj struct mi_o_s mi_o;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj } m;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - sizeof (m)) != -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (m.mi_nbytes - sizeof (m));
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (0);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj/*
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * This is called when ::stream is used and an ARP module is seen on the
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * stream. Determine what sort of ARP usage is involved and show an
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj * appropriate message.
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj */
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic void
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarp_qinfo(const queue_t *qp, char *buf, size_t nbytes)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj size_t size = mi_osize(qp);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_t ar;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (size != sizeof (ar_t))
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_vread(&ar, sizeof (ar), (uintptr_t)qp->q_ptr) == -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_describe(&ar, buf, nbytes, B_TRUE);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic uintptr_t
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarp_rnext(const queue_t *q)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj size_t size = mi_osize(q);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_t ar;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (size == sizeof (ar_t) && mdb_vread(&ar, sizeof (ar),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)q->q_ptr) != -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return ((uintptr_t)ar.ar_rq);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (NULL);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic uintptr_t
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjarp_wnext(const queue_t *q)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj size_t size = mi_osize(q);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ar_t ar;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (size == sizeof (ar_t) && mdb_vread(&ar, sizeof (ar),
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj (uintptr_t)q->q_ptr) != -1)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return ((uintptr_t)ar.ar_wq);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (NULL);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic const mdb_dcmd_t dcmds[] = {
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "ar", "?", "display ARP client streams", ar_cmd, NULL },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "arl", "?", "display ARP link layers", arl_cmd, NULL },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "ace", "?", "display ARP cache entries", ace_cmd, NULL },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "arphdr", ":", "display an ARP header", arphdr_cmd, NULL },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "arpcmd", ":", "display an ARP command", arpcmd_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 { "arl", "walk list of arl_t links",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj arl_walk_init, arl_walk_step, NULL },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { "ace", "walk list of ace_t entries",
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj ace_walk_init, ace_walk_step, ace_walk_fini },
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj { NULL }
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj};
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic const mdb_qops_t arp_qops = { arp_qinfo, arp_rnext, arp_wnext };
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjstatic const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjconst mdb_modinfo_t *
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj_mdb_init(void)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj GElf_Sym sym;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_lookup_by_obj("arp", "winit", &sym) == 0)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_qops_install(&arp_qops, (uintptr_t)sym.st_value);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj return (&modinfo);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonjvoid
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj_mdb_fini(void)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj{
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj GElf_Sym sym;
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj if (mdb_lookup_by_obj("arp", "winit", &sym) == 0)
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj mdb_qops_remove(&arp_qops, (uintptr_t)sym.st_value);
69bb4bb45c98da60d21839c4dc3c01ea1be60585carlsonj}