netstat.c revision e11c3f44f531fdff80941ce57c065d2ae861cefc
/*
* 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
* 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.
*/
/*
* Copyright (c) 1990 Mentat Inc.
* netstat.c 2.2, last change 9/9/91
* MROUTING Revision 3.5
*/
/*
*
* NOTES:
* 1. A comment "LINTED: (note 1)" appears before certain lines where
* lint would have complained, "pointer cast may result in improper
* alignment". These are lines where lint had suspected potential
* improper alignment of a data structure; in each such situation
* we have relied on the kernel guaranteeing proper alignment.
* 2. Some 'for' loops have been commented as "'for' loop 1", etc
* because they have 'continue' or 'break' statements in their
* bodies. 'continue' statements have been used inside some loops
* where avoiding them would have led to deep levels of indentation.
*
* TODO:
* Add ability to request subsets from kernel (with level = MIB2_IP;
* name = 0 meaning everything for compatibility)
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <kstat.h>
#include <assert.h>
#include <stropts.h>
#include <netinet/igmp_var.h>
#include <netinet/ip_mroute.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/systeminfo.h>
#include <dhcpagent_ipc.h>
#include <dhcpagent_util.h>
#include <compat.h>
#include <libtsnet.h>
#define STR_EXPAND 4
/*
* This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
* Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
* possible for an administrator to plumb new interfaces between those two
* calls, resulting in the failure of the latter. This addition makes that
* less likely.
*/
#define LIFN_GUARD_VALUE 10
typedef struct mib_item_s {
struct mib_item_s *next_item;
int group;
int mib_id;
int length;
void *valp;
} mib_item_t;
struct ifstat {
};
struct iflist {
};
static int mibopen(void);
mib_item_t *item2);
static const char *mitcp_state(int code,
const mib2_transportMLPEntry_t *attr);
static const char *miudp_state(int code,
const mib2_transportMLPEntry_t *attr);
char ifname[], char logintname[],
char ifname[], char logintname[],
static void m_report(void);
static void dhcp_report(char *);
void fail(int, char *, ...);
static int isnum(char *);
static char *plural(int n);
static char *pluraly(int n);
static char *plurales(int n);
static void process_filter(char *arg);
static char *ifindex2str(uint_t, char *);
static void usage(char *);
static int v4compat = 0; /* Compatible printing format for status */
/*
* Sizes of data structures extracted from the base mib.
* This allows the size of the tables entries to grow while preserving
* binary compatibility.
*/
static int ipAddrEntrySize;
static int ipRouteEntrySize;
static int ipNetToMediaEntrySize;
static int ipMemberEntrySize;
static int ipGroupSourceEntrySize;
static int ipRouteAttributeSize;
static int vifctlSize;
static int mfcctlSize;
static int ipv6IfStatsEntrySize;
static int ipv6IfIcmpEntrySize;
static int ipv6AddrEntrySize;
static int ipv6RouteEntrySize;
static int ipv6NetToMediaEntrySize;
static int ipv6MemberEntrySize;
static int ipv6GroupSourceEntrySize;
static int transportMLPSize;
static int tcpConnEntrySize;
static int tcp6ConnEntrySize;
static int udpEntrySize;
static int udp6EntrySize;
static int sctpEntrySize;
static int sctpLocalEntrySize;
static int sctpRemoteEntrySize;
/* Machinery used for -f (filter) option */
static const char *filter_keys[NFILTERKEYS] = {
"af", "outif", "dst", "flags"
};
/* Flags on routes */
#define FLF_A 0x00000001
#define FLF_B 0x00000002
#define FLF_D 0x00000004
#define FLF_G 0x00000008
#define FLF_H 0x00000010
#define FLF_L 0x00000020
#define FLF_U 0x00000040
#define FLF_M 0x00000080
#define FLF_S 0x00000100
static const char flag_list[] = "ABDGHLUMS";
typedef struct filter_rule filter_t;
struct filter_rule {
union {
int f_family;
const char *f_ifname;
struct {
} a;
struct {
} f;
} u;
};
/*
* The user-specified filters are linked into lists separated by
* keyword (type of filter). Thus, the matching algorithm is:
* For each non-empty filter list
* If no filters in the list match
* then stop here; route doesn't match
* If loop above completes, then route does match and will be
* displayed.
*/
int
{
char *name;
int sd = -1;
int interval = 0; /* Single time by default */
int c;
int d;
/*
* Possible values of 'Iflag_only':
* -1, no feature-flags;
* 0, IFlag and other feature-flags enabled
* 1, IFlag is the only feature-flag enabled
* : trinary variable, modified using IFLAGMOD()
*/
int Iflag_only = -1;
extern char *optarg;
extern int optind;
char *default_ip_str = NULL;
if (v4compat == DEFAULT_PROT_BAD_VALUE)
switch ((char)c) {
case 'a': /* all connections */
break;
case 'd': /* turn on debugging */
break;
break;
case 'm': /* streams msg report */
break;
case 'n': /* numeric format */
break;
case 'r': /* route tables */
break;
case 'R': /* security attributes */
break;
case 's': /* per-protocol statistics */
break;
break;
case 'M': /* multicast routing tables */
break;
case 'g': /* multicast group membership */
break;
case 'v': /* verbose output format */
break;
case 'f':
break;
case 'P':
proto = IPPROTO_IP;
v4compat = 0; /* Overridden */
v4compat = 0; /* Overridden */
proto = IPPROTO_UDP;
proto = IPPROTO_TCP;
proto = IPPROTO_RAW;
} else {
}
break;
case 'I':
break;
case 'D':
Iflag_only = 0;
break;
case '?':
default:
}
}
/*
* Make sure -R option is set only on a labeled system.
*/
if (RSECflag && !is_system_labeled()) {
}
/*
* Handle other arguments: find interval, count; the
* flags that accept 'interval' and 'count' are OR'd
* in the outermost 'if'; more flags may be added as
* required
*/
if (d + 1 < argc &&
optind++;
}
optind++;
break;
}
}
}
if (count == 0)
optind++;
}
}
"%s: extra arguments\n", name);
}
if (interval)
if (DHCPflag) {
exit(0);
}
/* Get data structures: priming before iteration */
if (sd == -1)
}
/* Extract constant sizes - need do once only */
}
}
if (interval <= 0) {
count = 1;
}
/* 'for' loop 1: */
for (;;) {
/* netstat: AF_INET[6] behaviour */
if (Sflag) {
"out of memory\n");
}
if (protocol_selected(IPPROTO_UDP))
if (protocol_selected(IPPROTO_TCP))
}
if (Iflag)
if (Mflag)
m_report();
if (Rflag)
} else {
if (Sflag)
if (MMflag)
}
if (Gflag)
if (Pflag) {
if (family_selected(AF_INET))
if (family_selected(AF_INET6))
}
}
/* netstat: AF_UNIX behaviour */
if (family_selected(AF_UNIX) &&
(void) kstat_close(kc);
/* iteration handling code */
break;
/* re-populating of data structures */
if (Sflag) {
/* previtem is a cut-down list */
"out of memory\n");
}
}
}
} /* 'for' loop 1 ends */
return (0);
}
static int
isnum(char *p)
{
int len;
int i;
for (i = 0; i < len; i++)
if (!isdigit(p[i]))
return (0);
return (1);
}
/* --------------------------------- MIBGET -------------------------------- */
static mib_item_t *
{
/*
* buf is an automatic for this function, so the
* compiler has complete control over its alignment;
* it is assumed this alignment is satisfactory for
* it to be casted to certain other struct pointers
* here, such as struct T_optmgmt_ack * .
*/
int flags;
int i, j, getcode;
/*
* Note: we use the special level value below so that IP will return
* us information concerning IRE_MARK_TESTHIDDEN routes.
*/
flags = 0;
perror("mibget: putmsg(ctl) failed");
goto error_exit;
}
/*
* Each reply consists of a ctl part for one fixed structure
* or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
* len is the size of the data part of the message.
*/
j = 1;
for (;;) {
flags = 0;
if (getcode == -1) {
perror("mibget getmsg(ctl) failed");
if (Dflag) {
(void) fputs("# level name len\n",
stderr);
i = 0;
(void) printf("%d %4d %5d %d\n",
++i,
}
goto error_exit;
}
if (getcode == 0 &&
if (Dflag)
(void) printf("mibget getmsg() %d returned "
"EOD (level %ld, name %ld)\n",
return (first_item); /* this is EOD msg */
}
"mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, "
"UNIX_error = 0x%lx\n",
goto error_exit;
}
(void) printf("mibget getmsg(ctl) %d returned %d, "
"ctlbuf.len = %d, PRIM_type = %ld\n",
(void) printf("T_OPTMGMT_ACK: "
"MGMT_flags = 0x%lx, req->len = %ld\n",
goto error_exit;
}
perror("mibget malloc failed");
goto error_exit;
}
else
first_item = temp;
goto error_exit;
if (Dflag)
(void) printf("msg %d: group = %4d mib_id = %5d"
"length = %d\n",
flags = 0;
if (getcode == -1) {
perror("mibget getmsg(data) failed");
goto error_exit;
} else if (getcode != 0) {
(void) printf("mibget getmsg(data) returned %d, "
"databuf.maxlen = %d, databuf.len = %d\n",
goto error_exit;
}
j++;
}
/* NOTREACHED */
return (NULL);
}
/*
* mibfree: frees a linked list of type (mib_item_t *)
* returned by mibget(); this is NOT THE SAME AS
* mib_item_destroy(), so should be used for objects
* returned by mibget() only
*/
static void
{
}
}
static int
mibopen(void)
{
int sd;
if (sd == -1) {
perror("arp open");
return (-1);
}
perror("tcp I_PUSH");
return (-1);
}
perror("udp I_PUSH");
return (-1);
}
perror("icmp I_PUSH");
return (-1);
}
return (sd);
}
/*
* mib_item_dup: returns a clean mib_item_t * linked
* list, so that for every element item->mib_id is 0;
* to deallocate this linked list, use mib_item_destroy
*/
static mib_item_t *
{
int c = 0;
c++;
return (NULL);
c = 0;
/* Replicate item in localp */
return (NULL);
}
if (c > 0)
c++;
}
}
return (localp);
}
/*
* mib_item_diff: takes two (mib_item_t *) linked lists
* item1 and item2 and computes the difference between
* differentiable values in item2 against item1 for every
* given member of item2; returns an mib_item_t * linked
* list of diff's, or a copy of item2 if item1 is NULL;
* will return NULL if system out of memory; works only
* for item->mib_id == 0
*/
static mib_item_t *
int nitems = 0; /* no. of items in item2 */
return (diffp);
}
/*
* upon adding a case here, the same
* must also be added in the next
* switch statement, alongwith
* appropriate code
*/
case MIB2_IP:
case MIB2_IP6:
case EXPER_DVMRP:
case EXPER_IGMP:
case MIB2_ICMP:
case MIB2_ICMP6:
case MIB2_TCP:
case MIB2_UDP:
case MIB2_SCTP:
case EXPER_RAWIP:
nitems++;
}
}
if (nitems == 0) {
return (diffp);
}
return (NULL);
/* 'for' loop 1: */
continue; /* 'for' loop 1 */
/* 'for' loop 2: */
continue; /* 'for' loop 2 */
/* found comparable data sets */
/*
* Indenting note: Because of long variable names
* in cases MIB2_IP6 and MIB2_ICMP6, their contents
* have been indented by one tab space only
*/
case MIB2_IP: {
mib2_ip_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_IP6: {
d = (mib2_ipv6IfStatsEntry_t *)calloc(
if (d == NULL)
goto mibdiff_out_of_memory;
d->ipv6DefaultHopLimit =
break;
}
case EXPER_DVMRP: {
struct mrtstat *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case EXPER_IGMP: {
struct igmpstat *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_ICMP: {
mib2_icmp_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_ICMP6: {
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_TCP: {
mib2_tcp_t *t2;
mib2_tcp_t *t1;
mib2_tcp_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_UDP: {
mib2_udp_t *u2;
mib2_udp_t *u1;
mib2_udp_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case MIB2_SCTP: {
mib2_sctp_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
case EXPER_RAWIP: {
mib2_rawip_t *d;
if (d == NULL)
goto mibdiff_out_of_memory;
break;
}
/*
* there are more "group" types but they aren't
* required for the -s and -Ms options
*/
}
} /* 'for' loop 2 ends */
} /* 'for' loop 1 ends */
diffptr--;
return (diffp);
return (NULL);
}
/*
* mib_item_destroy: cleans up a mib_item_t *
* that was created by calling mib_item_dup or
* mib_item_diff
*/
static void
int nitems = 0;
int c = 0;
return;
nitems++;
else
return; /* cannot destroy! */
if (nitems == 0)
return; /* cannot destroy! */
for (c = nitems - 1; c >= 0; c--) {
}
}
/* Compare two Octet_ts. Return B_TRUE if they match, B_FALSE if not. */
static boolean_t
{
return (B_FALSE);
return (B_FALSE);
}
/* If octetstr() changes make an appropriate change to STR_EXPAND */
static char *
{
int i;
char *cp;
if (op) {
switch (code) {
case 'd':
*cp = '\0';
return (dst);
}
break;
case 'a':
*cp = '\0';
return (dst);
}
break;
case 'h':
default:
*cp = '\0';
return (dst);
}
cp += 3;
break;
}
}
}
cp--;
*cp = '\0';
return (dst);
}
static const char *
{
static char tcpsbuf[50];
const char *cp;
switch (state) {
case TCPS_CLOSED:
cp = "CLOSED";
break;
case TCPS_IDLE:
cp = "IDLE";
break;
case TCPS_BOUND:
cp = "BOUND";
break;
case TCPS_LISTEN:
cp = "LISTEN";
break;
case TCPS_SYN_SENT:
cp = "SYN_SENT";
break;
case TCPS_SYN_RCVD:
cp = "SYN_RCVD";
break;
case TCPS_ESTABLISHED:
cp = "ESTABLISHED";
break;
case TCPS_CLOSE_WAIT:
cp = "CLOSE_WAIT";
break;
case TCPS_FIN_WAIT_1:
cp = "FIN_WAIT_1";
break;
case TCPS_CLOSING:
cp = "CLOSING";
break;
case TCPS_LAST_ACK:
cp = "LAST_ACK";
break;
case TCPS_FIN_WAIT_2:
cp = "FIN_WAIT_2";
break;
case TCPS_TIME_WAIT:
cp = "TIME_WAIT";
break;
default:
"UnknownState(%d)", state);
break;
}
}
}
return (cp);
}
static const char *
{
static char udpsbuf[50];
const char *cp;
switch (state) {
case MIB2_UDP_unbound:
cp = "Unbound";
break;
case MIB2_UDP_idle:
cp = "Idle";
break;
case MIB2_UDP_connected:
cp = "Connected";
break;
default:
"Unknown State(%d)", state);
break;
}
}
}
return (cp);
}
static int odd;
static void
prval_init(void)
{
odd = 0;
}
static void
{
if (odd++ & 1)
(void) putchar('\n');
}
static void
{
if (odd++ & 1)
(void) putchar('\n');
}
static void
{
if (odd++ & 1)
(void) putchar('\n');
}
static void
{
switch (val) {
case MIB2_SCTP_RTOALGO_OTHER:
break;
case MIB2_SCTP_RTOALGO_VANJ:
break;
default:
break;
}
if (odd++ & 1)
(void) putchar('\n');
}
static void
prval_end(void)
{
if (odd++ & 1)
(void) putchar('\n');
}
/* Extract constant sizes */
static void
{
/* 'for' loop 1: */
continue; /* 'for' loop 1 */
case MIB2_IP: {
sizeof (mib2_ipAddrEntry_t *)));
sizeof (mib2_ipRouteEntry_t *)));
sizeof (mib2_ipNetToMediaEntry_t *)));
sizeof (ip_member_t *)));
sizeof (ip_grpsrc_t *)));
sizeof (mib2_ipAttributeEntry_t *)));
sizeof (mib2_transportMLPEntry_t *)));
break;
}
case EXPER_DVMRP: {
sizeof (struct vifclt *)));
sizeof (struct mfcctl *)));
break;
}
case MIB2_IP6: {
/* Just use the first entry */
sizeof (mib2_ipv6IfStatsEntry_t *)));
sizeof (mib2_ipv6AddrEntry_t *)));
sizeof (mib2_ipv6RouteEntry_t *)));
sizeof (mib2_ipv6NetToMediaEntry_t *)));
sizeof (ipv6_member_t *)));
sizeof (ipv6_grpsrc_t *)));
break;
}
case MIB2_ICMP6: {
/* Just use the first entry */
sizeof (mib2_ipv6IfIcmpEntry_t *)));
break;
}
case MIB2_TCP: {
sizeof (mib2_tcpConnEntry_t *)));
sizeof (mib2_tcp6ConnEntry_t *)));
break;
}
case MIB2_UDP: {
sizeof (mib2_udpEntry_t *)));
sizeof (mib2_udp6Entry_t *)));
break;
}
case MIB2_SCTP: {
break;
}
}
} /* 'for' loop 1 ends */
if (Dflag) {
(void) puts("mib_get_constants:");
(void) printf("\tipv6IfStatsEntrySize %d\n",
(void) printf("\tipNetToMediaEntrySize %d\n",
(void) printf("\tipRouteAttributeSize %d\n",
(void) printf("\tipv6NetToMediaEntrySize %d\n",
(void) printf("\tipv6MemberEntrySize %d\n",
(void) printf("\tipv6IfIcmpEntrySize %d\n",
(void) printf("\tsctpRemoteEntrySize %d\n",
}
}
/* ----------------------------- STAT_REPORT ------------------------------- */
static void
{
int jtemp = 0;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
case MIB2_IP: {
if (protocol_selected(IPPROTO_IP) &&
stdout);
}
break;
}
case MIB2_ICMP: {
mib2_icmp_t *icmp =
if (protocol_selected(IPPROTO_ICMP) &&
stdout);
}
break;
}
case MIB2_IP6: {
if (!(protocol_selected(IPPROTO_IPV6)) ||
!(family_selected(AF_INET6)))
break;
/* 'for' loop 2a: */
/* LINTED: (note 1) */
if (ip6->ipv6IfIndex == 0) {
/*
* The "unknown interface" ip6
* mib. Just add to the sum.
*/
continue; /* 'for' loop 2a */
}
if (Aflag) {
(void) printf("\nIPv6 for %s\n",
ifname));
}
} /* 'for' loop 2a ends */
break;
}
case MIB2_ICMP6: {
if (!(protocol_selected(IPPROTO_ICMPV6)) ||
!(family_selected(AF_INET6)))
break;
/* 'for' loop 2b: */
if (icmp6->ipv6IfIcmpIfIndex == 0) {
/*
* The "unknown interface" icmp6
* mib. Just add to the sum.
*/
continue; /* 'for' loop 2b: */
}
if (Aflag) {
(void) printf("\nICMPv6 for %s\n",
}
} /* 'for' loop 2b ends */
break;
}
case MIB2_TCP: {
if (protocol_selected(IPPROTO_TCP) &&
(family_selected(AF_INET) ||
family_selected(AF_INET6))) {
}
break;
}
case MIB2_UDP: {
if (protocol_selected(IPPROTO_UDP) &&
(family_selected(AF_INET) ||
family_selected(AF_INET6))) {
}
break;
}
case MIB2_SCTP: {
if (protocol_selected(IPPROTO_SCTP) &&
(family_selected(AF_INET) ||
family_selected(AF_INET6))) {
}
break;
}
case EXPER_RAWIP: {
if (protocol_selected(IPPROTO_RAW) &&
(family_selected(AF_INET) ||
family_selected(AF_INET6))) {
}
break;
}
case EXPER_IGMP: {
if (protocol_selected(IPPROTO_IGMP) &&
(family_selected(AF_INET))) {
}
break;
}
}
} /* 'for' loop 1 ends */
(void) putchar('\n');
}
static void
{
prval_init();
prval_end();
}
static void
{
prval_init();
prval_end();
}
static void
{
prval_init();
prval_end();
}
static void
{
prval_init();
prval("icmp6InRouterAds",
prval("icmp6InNeighborAds",
prval_end();
prval_init();
prval("icmp6OutRouterAds",
prval("icmp6OutNeighborAds",
prval("icmp6OutGroupResps",
prval("icmp6OutGroupReds",
prval_end();
}
static void
{
prval_init();
prval_end();
}
static void
{
prval_init();
prval_end();
prval_end();
}
static void
{
prval_init();
prval_end();
}
static void
{
prval_init();
prval_end();
}
void
{
(void) printf(" %10u message%s received\n",
(void) printf(" %10u message%s received with too few bytes\n",
(void) printf(" %10u message%s received with bad checksum\n",
(void) printf(" %10u membership quer%s received\n",
(void) printf(" %10u membership quer%s received with invalid "
"field(s)\n",
(void) printf(" %10u membership report%s received\n",
(void) printf(" %10u membership report%s received with invalid "
"field(s)\n",
(void) printf(" %10u membership report%s received for groups to "
"which we belong\n",
(void) printf(" %10u membership report%s sent\n",
}
static void
{
(void) puts("DVMRP multicast routing:");
(void) printf(" %10u hit%s - kernel forwarding cache hits\n",
(void) printf(" %10u miss%s - kernel forwarding cache misses\n",
(void) printf(" %10u packet%s potentially forwarded\n",
(void) printf(" %10u packet%s actually sent out\n",
(void) printf(" %10u upcall%s - upcalls made to mrouted\n",
(void) printf(" %10u packet%s not sent out due to lack of resources\n",
(void) printf(" %10u datagram%s with malformed tunnel options\n",
(void) printf(" %10u datagram%s with no room for tunnel options\n",
(void) printf(" %10u datagram%s arrived on wrong interface\n",
(void) printf(" %10u datagram%s dropped due to upcall Q overflow\n",
(void) printf(" %10u datagram%s cleaned up by the cache\n",
(void) printf(" %10u datagram%s dropped selectively by ratelimiter\n",
(void) printf(" %10u datagram%s dropped - bucket Q overflow\n",
(void) printf(" %10u datagram%s dropped - larger than bkt size\n",
(void) printf("\nPIM multicast routing:\n");
(void) printf(" %10u datagram%s dropped - bad version number\n",
(void) printf(" %10u datagram%s dropped - bad checksum\n",
(void) printf(" %10u datagram%s dropped - bad register packets\n",
(void) printf(
" %10u datagram%s potentially forwarded - register packets\n",
(void) printf(" %10u datagram%s dropped - register send drops\n",
(void) printf(" %10u datagram%s dropped - packet malformed\n",
(void) printf(" %10u datagram%s dropped - no memory to forward\n",
}
static void
{
/* First few are not additive */
}
static void
{
}
/* ----------------------------- MRT_STAT_REPORT --------------------------- */
static void
{
int jtemp = 0;
if (!(family_selected(AF_INET)))
return;
(void) putchar('\n');
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
case EXPER_DVMRP: {
if (!(family_selected(AF_INET)))
continue; /* 'for' loop 1 */
break;
}
}
}
} /* 'for' loop 1 ends */
(void) putchar('\n');
}
/*
* if_stat_total() - Computes totals for interface statistics
* and returns result by updating sumstats.
*/
static void
{
}
/* --------------------- IF_REPORT (netstat -i) -------------------------- */
};
static void
{
int jtemp = 0;
uint32_t ifindex_v4 = 0;
uint32_t ifindex_v6 = 0;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
case MIB2_IP:
continue; /* 'for' loop 1 */
{
if (once_only) {
if (Dflag)
(void) printf("if_report: %d items\n",
/ sizeof (mib2_ipAddrEntry_t));
/* 'for' loop 2a: */
ap++) {
'a', logintname,
sizeof (logintname));
continue; /* 'for' loop 2a */
/*
* First lookup the "link" kstats in
* case the link is renamed. Then
* fallback to the legacy kstats for
* those non-GLDv3 links.
*/
if (new_ifindex != ifindex_v4 &&
NULL);
"ipackets");
"ierrors");
"opackets");
"oerrors");
"collisions");
if (first) {
if (!first_header)
(void) putchar('\n');
(void) printf(
"%-5.5s %-5.5s%-13.13s "
"%-14.14s %-6.6s %-5.5s "
"%-6.6s %-5.5s %-6.6s "
"%-6.6s\n",
"Address", "Ipkts",
"Ierrs", "Opkts", "Oerrs",
"Collis", "Queue");
}
} else {
}
} /* 'for' loop 2a ends */
} else if (!alreadydone) {
struct ifstat t;
/*
* Check if there is anything to do.
*/
sizeof (mib2_ipAddrEntry_t)) {
fail(0, "No compatible interfaces");
}
/*
* 'for' loop 2b: find the "right" entry:
* If an interface name to match has been
* supplied then try and find it, otherwise
* match the first non-loopback interface found.
* Use lo0 if all else fails.
*/
ap++) {
if (matchname) {
ifname) == 0) {
/* 'for' loop 2b */
break;
}
break; /* 'for' loop 2b */
} /* 'for' loop 2b ends */
} else {
if (!found_if)
fail(0, "-I: %s no such "
"interface.", matchname);
}
if (Iflag_only == 0 || !reentry) {
(void) printf(" input %-6.6s "
"output ",
(void) printf(" input (Total) "
"output\n");
(void) printf("%-7.7s %-5.5s %-7.7s "
"%-5.5s %-6.6s ",
"packets", "errs", "packets",
"errs", "colls");
(void) printf("%-7.7s %-5.5s %-7.7s "
"%-5.5s %-6.6s\n",
"packets", "errs", "packets",
"errs", "colls");
}
/* 'for' loop 2c: */
ap++) {
/*
* We have reduced the IP interface
* name, which could have been a
* logical, down to a name suitable
* for use with kstats.
* We treat this name as unique and
* only collate statistics for it once
* per pass. This is to avoid falsely
* amplifying these statistics by the
* the number of logical instances.
*/
continue;
}
/*
* First lookup the "link" kstats in
* case the link is renamed. Then
* fallback to the legacy kstats for
* those non-GLDv3 links.
*/
KSTAT_TYPE_NAMED)) {
NULL);
}
"ipackets");
"ierrors");
"opackets");
"oerrors");
"collisions");
new = t;
/* Build the interface list */
/*
* First time through.
* Just add up the interface stats.
*/
&t, &sum);
continue;
}
/*
* Walk old list for the interface.
*
* If found, add difference to total.
*
* If not, an interface has been plumbed
* up. In this case, we will simply
* ignore the new interface until the
* next interval; as there's no easy way
* to acquire statistics between time
* of the plumb and the next interval
* boundary. This results in inaccurate
* total values for current interval.
*
* Note the case when an interface is
* unplumbed; as similar problems exist.
* The unplumbed interface is not in the
* current list, and there's no easy way
* to account for the statistics between
* the previous interval and time of the
* unplumb. Therefore, we (in a sense)
* ignore the removed interface by only
* involving "current" interfaces when
* computing the total statistics.
* Unfortunately, this also results in
* inaccurate values for interval total.
*/
buf) == 0) {
&t, &sum);
break;
}
}
} /* 'for' loop 2c ends */
(void) printf("%-7llu %-5llu %-7llu "
"%-5llu %-6llu ",
(void) printf("%-7llu %-5llu %-7llu "
/*
* Tidy things up once finished.
*/
}
}
break;
}
case MIB2_IP6:
continue; /* 'for' loop 1 */
{
if (once_only) {
if (Dflag)
(void) printf("if_report: %d items\n",
/ sizeof (mib2_ipv6AddrEntry_t));
/* 'for' loop 2d: */
ap6++) {
'a', logintname,
sizeof (logintname));
continue; /* 'for' loop 2d */
/*
* First lookup the "link" kstats in
* case the link is renamed. Then
* fallback to the legacy kstats for
* those non-GLDv3 links.
*/
if (new_ifindex != ifindex_v6 &&
NULL);
"ipackets");
"ierrors");
"opackets");
"oerrors");
"collisions");
if (first) {
if (!first_header)
(void) putchar('\n');
(void) printf(
"%-5.5s %-5.5s%"
"-27.27s %-27.27s "
"%-6.6s %-5.5s "
"%-6.6s %-5.5s "
"%-6.6s\n",
"Name", "Mtu",
"Address", "Ipkts",
"Ierrs", "Opkts",
"Oerrs", "Collis");
}
} else {
}
} /* 'for' loop 2d ends */
} else if (!alreadydone) {
struct ifstat t;
/*
* Check if there is anything to do.
*/
sizeof (mib2_ipv6AddrEntry_t)) {
fail(0, "No compatible interfaces");
}
/*
* 'for' loop 2e: find the "right" entry:
* If an interface name to match has been
* supplied then try and find it, otherwise
* match the first non-loopback interface found.
* Use lo0 if all else fails.
*/
ap6++) {
if (matchname) {
ifname) == 0) {
/* 'for' loop 2e */
break;
}
break; /* 'for' loop 2e */
} /* 'for' loop 2e ends */
} else {
if (!found_if)
fail(0, "-I: %s no such "
"interface.", matchname);
}
if (Iflag_only == 0 || !reentry) {
(void) printf(
" input %-6.6s"
" output ",
(void) printf(" input (Total)"
" output\n");
(void) printf("%-7.7s %-5.5s %-7.7s "
"%-5.5s %-6.6s ",
"packets", "errs", "packets",
"errs", "colls");
(void) printf("%-7.7s %-5.5s %-7.7s "
"%-5.5s %-6.6s\n",
"packets", "errs", "packets",
"errs", "colls");
}
/* 'for' loop 2f: */
ap6++) {
/*
* We have reduced the IP interface
* name, which could have been a
* logical, down to a name suitable
* for use with kstats.
* We treat this name as unique and
* only collate statistics for it once
* per pass. This is to avoid falsely
* amplifying these statistics by the
* the number of logical instances.
*/
continue;
}
/*
* First lookup the "link" kstats in
* case the link is renamed. Then
* fallback to the legacy kstats for
* those non-GLDv3 links.
*/
KSTAT_TYPE_NAMED)) {
(void) safe_kstat_read(kc,
}
"ipackets");
"ierrors");
"opackets");
"oerrors");
"collisions");
new6 = t;
/* Build the interface list */
/*
* First time through.
* Just add up the interface stats.
*/
&t, &sum6);
continue;
}
/*
* Walk old list for the interface.
*
* If found, add difference to total.
*
* If not, an interface has been plumbed
* up. In this case, we will simply
* ignore the new interface until the
* next interval; as there's no easy way
* to acquire statistics between time
* of the plumb and the next interval
* boundary. This results in inaccurate
* total values for current interval.
*
* Note the case when an interface is
* unplumbed; as similar problems exist.
* The unplumbed interface is not in the
* current list, and there's no easy way
* to account for the statistics between
* the previous interval and time of the
* unplumb. Therefore, we (in a sense)
* ignore the removed interface by only
* involving "current" interfaces when
* computing the total statistics.
* Unfortunately, this also results in
* inaccurate values for interval total.
*/
buf) == 0) {
&t, &sum6);
break;
}
}
} /* 'for' loop 2f ends */
(void) printf("%-7llu %-5llu %-7llu "
"%-5llu %-6llu ",
(void) printf("%-7llu %-5llu %-7llu "
/*
* Tidy things up once finished.
*/
}
}
break;
}
}
} /* 'for' loop 1 ends */
if ((Iflag_only == 0) && (!once_only))
(void) putchar('\n');
}
static void
if (ksp_not_null) {
(void) printf("%-5s %-5u",
else
(void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
"%-6llu %-6llu\n",
}
/*
* Print logical interface info if Aflag set (including logical unit 0)
*/
if (Aflag) {
sizeof (abuf));
else
(void) printf("%-13s %-14s %-6llu %-5s %-6llu "
"%-5s %-6s %-6llu\n", abuf,
0LL);
}
}
static void
if (ksp_not_null) {
} else {
sizeof (abuf));
}
(void) printf("%-27s %-27s %-6llu %-5llu "
"%-6llu %-5llu %-6llu\n",
sizeof (dstbuf)),
}
/*
* Print logical interface info if Aflag set (including logical unit 0)
*/
if (Aflag) {
else
(void) printf("%-27s %-27s %-6llu %-5s %-6llu %-5s %-6s\n",
sizeof (dstbuf)),
}
}
/* --------------------- DHCP_REPORT (netstat -D) ------------------------- */
static boolean_t
{
int error;
fail(0, "dhcp_do_ipc: out of memory");
if (error != 0) {
}
if (error == DHCP_IPC_E_UNKIF) {
return (printed_one);
}
if (error != 0) {
}
if (!printed_one)
return (B_TRUE);
}
/*
* dhcp_walk_interfaces: walk the list of interfaces that have a given set of
* flags turned on (flags_on) and a given set turned off (flags_off) for a
* given address family (af). For each, print out the DHCP status using
* dhcp_do_ipc.
*/
static boolean_t
{
if (sock_fd == -1)
return (printed_one);
/*
* SIOCGLIFNUM is just an estimate. If the ioctl fails, we don't care;
* just drive on and use SIOCGLIFCONF with increasing buffer sizes, as
* is traditional.
*/
else
return (NULL);
}
for (i = 0; i < n_ifs; i++) {
continue;
}
}
return (printed_one);
}
static void
dhcp_report(char *ifname)
{
return;
if (family_selected(AF_INET)) {
}
if (family_selected(AF_INET6)) {
}
if (!printed_one) {
}
} else {
if (family_selected(AF_INET)) {
0, AF_INET, printed_one);
}
if (family_selected(AF_INET6)) {
(void) dhcp_walk_interfaces(IFF_DHCPRUNNING,
}
}
}
/* --------------------- GROUP_REPORT (netstat -g) ------------------------- */
static void
{
int jtemp = 0;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
if (Dflag)
(void) printf("item is v4grp info\n");
break;
case EXPER_IP_GROUP_SOURCES:
if (Dflag)
(void) printf("item is v4src info\n");
break;
default:
continue;
}
continue;
}
if (Dflag)
(void) printf("item is v6grp info\n");
break;
case EXPER_IP6_GROUP_SOURCES:
if (Dflag)
(void) printf("item is v6src info\n");
break;
default:
continue;
}
}
}
if (Dflag)
(void) printf("%u records for ipGroupMember:\n",
/* LINTED: (note 1) */
if (first) {
"Group Memberships" :
"Group Memberships: IPv4");
(void) puts("Interface "
"Group RefCnt");
(void) puts("--------- "
"-------------------- ------");
}
(void) printf("%-9s %-20s %6u\n",
continue;
if (Dflag)
(void) printf("scanning %u ipGroupSource "
"records...\n",
/* LINTED: (note 1) */
/*
* We assume that all source addrs for a given
* the first non-match after we've found at
* least one, we bail.
*/
if ((ipmp->ipGroupMemberAddress !=
ips->ipGroupSourceGroup) ||
&ips->ipGroupSourceIfIndex))) {
if (first_src)
continue;
else
break;
}
if (first_src) {
(void) printf("\t%s: %s\n",
continue;
}
(void) printf("\t %s\n",
sizeof (abuf)));
}
}
(void) putchar('\n');
}
if (Dflag)
(void) printf("%u records for ipv6GroupMember:\n",
/* LINTED: (note 1) */
if (first) {
(void) puts("Group Memberships: "
"IPv6");
(void) puts(" If "
"Group RefCnt");
(void) puts("----- "
"--------------------------- ------");
}
(void) printf("%-5s %-27s %5u\n",
continue;
if (Dflag)
(void) printf("scanning %u ipv6GroupSource "
"records...\n",
/* LINTED: (note 1) */
/* same assumption as in the v4 case above */
if ((ipmp6->ipv6GroupMemberIfIndex !=
&ips6->ipv6GroupSourceGroup))) {
if (first_src)
continue;
else
break;
}
if (first_src) {
(void) printf("\t%s: %s\n",
continue;
}
(void) printf("\t %s\n",
}
}
(void) putchar('\n');
}
(void) putchar('\n');
}
/* --------------------- ARP_REPORT (netstat -p) -------------------------- */
static void
{
int jtemp = 0;
int flags;
if (!(family_selected(AF_INET)))
return;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
if (Dflag)
(void) printf("%u records for "
"ipNetToMediaEntryTable:\n",
/* 'for' loop 2: */
/* LINTED: (note 1) */
if (first) {
"Net to Media Table" :
"Net to Media Table: IPv4");
(void) puts("Device "
" IP Address Mask "
"Flags Phys Addr");
(void) puts("------ "
"-------------------- --------------- "
"-------- ---------------");
}
flbuf[0] = '\0';
/*
* Note that not all flags are possible at the same
* time. Patterns: SPLAy DUo
*/
if (flags & ACE_F_PERMANENT)
if (flags & ACE_F_PUBLISH)
if (flags & ACE_F_DYING)
if (!(flags & ACE_F_RESOLVED))
if (flags & ACE_F_MAPPING)
if (flags & ACE_F_MYADDR)
if (flags & ACE_F_UNVERIFIED)
if (flags & ACE_F_AUTHORITY)
if (flags & ACE_F_DELAYED)
(void) printf("%-6s %-20s %-15s %-8s %s\n",
} /* 'for' loop 2 ends */
} /* 'for' loop 1 ends */
}
/* --------------------- NDP_REPORT (netstat -p) -------------------------- */
static void
{
int jtemp = 0;
char *state;
char *type;
if (!(family_selected(AF_INET6)))
return;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
/* 'for' loop 2: */
/* LINTED: (note 1) */
if (first) {
(void) puts("\nNet to Media Table: IPv6");
(void) puts(" If Physical Address "
" Type State Destination/Mask");
(void) puts("----- ----------------- "
"------- ------------ "
"---------------------------");
}
switch (np6->ipv6NetToMediaState) {
case ND_INCOMPLETE:
state = "INCOMPLETE";
break;
case ND_REACHABLE:
state = "REACHABLE";
break;
case ND_STALE:
state = "STALE";
break;
case ND_DELAY:
state = "DELAY";
break;
case ND_PROBE:
state = "PROBE";
break;
case ND_UNREACHABLE:
state = "UNREACHABLE";
break;
default:
state = "UNKNOWN";
}
switch (np6->ipv6NetToMediaType) {
case 1:
type = "other";
break;
case 2:
type = "dynamic";
break;
case 3:
type = "static";
break;
case 4:
type = "local";
break;
}
(void) printf("%-5s %-17s %-7s %-12s %-27s\n",
type,
} /* 'for' loop 2 ends */
} /* 'for' loop 1 ends */
(void) putchar('\n');
}
/* ------------------------- ire_report (netstat -r) ------------------------ */
typedef struct sec_attr_list_s {
struct sec_attr_list_s *sal_next;
const mib2_ipAttributeEntry_t *sal_attr;
const sec_attr_list_t *);
const sec_attr_list_t *);
static const char *pr_secattr(const sec_attr_list_t *);
static void
{
int jtemp = 0;
const mib_item_t *iptr;
int route_attrs_count;
/*
* Preparation pass: the kernel returns separate entries for IP routing
* table entries and security attributes. We loop through the
* attributes first and link them into lists.
*/
}
perror("ire_report calloc v4_attrs failed");
return;
}
}
perror("ire_report calloc v6_attrs failed");
goto ire_report_done;
}
}
if (route_attrs_count > 0) {
perror("ire_report malloc all_attrs failed");
goto ire_report_done;
}
}
} else {
continue;
}
/* LINTED: (note 1) */
}
}
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
if (Dflag) {
(void) printf("%u records for "
"ipRouteEntryTable:\n",
} else {
(void) printf("%u records for "
"ipv6RouteEntryTable:\n",
sizeof (mib2_ipv6RouteEntry_t));
}
}
/* LINTED: (note 1) */
ipRouteEntrySize)) {
}
} else {
/* LINTED: (note 1) */
}
}
} /* 'for' loop 1 ends */
}
/*
* Match a user-supplied device name. We do this by string because
* the MIB2 interface gives us interface name strings rather than
* ifIndex numbers. The "none" rule matches only routes with no
* interface. The "any" rule matches routes with any non-blank
* interface. A base name ("hme0") matches all aliases as well
* ("hme0:1").
*/
static boolean_t
{
int iflen;
if (*ifname == '\0')
/* The check for ':' here supports interface aliases. */
return (B_FALSE);
}
/*
* Match a user-supplied IP address list. The "any" rule matches any
* non-zero address. The "none" rule matches only the zero address.
* IPv6 addresses supplied by the user are ignored. If the user
* supplies a subnet mask, then match routes that are at least that
* specific (use the user's mask). If the user supplies only an
* address, then select any routes that would match (use the route's
* mask).
*/
static boolean_t
{
char **app;
char *aptr;
else
}
return (B_FALSE);
if (fmask != IP_HOST_MASK) {
return (B_FALSE);
}
/* LINTED: (note 1) */
/* LINTED: (note 1) */
return (B_TRUE);
}
return (B_FALSE);
}
/*
* Run through the filter list for an IPv4 MIB2 route entry. If all
* filters of a given type fail to match, then the route is filtered
* out (not displayed). If no filter is given or at least one filter
* of each type matches, then display the route.
*/
static boolean_t
{
int idx;
/* 'for' loop 1: */
/* 'for' loop 2: */
switch (idx) {
case FK_AF:
continue; /* 'for' loop 2 */
break;
case FK_OUTIF:
continue; /* 'for' loop 2 */
break;
case FK_DST:
continue; /* 'for' loop 2 */
break;
case FK_FLAGS:
continue; /* 'for' loop 2 */
break;
}
break;
} /* 'for' loop 2 ends */
return (B_FALSE);
}
/* 'for' loop 1 ends */
return (B_TRUE);
}
/*
* Given an IPv4 MIB2 route entry, form the list of flags for the
* route.
*/
static uint_t
{
}
}
}
/* Address resolution */
}
}
}
}
}
return (flag_b);
}
static const char ire_hdr_v4[] =
"\n%s Table: IPv4\n";
static const char ire_hdr_v4_compat[] =
"\n%s Table:\n";
static const char ire_hdr_v4_verbose[] =
" Destination Mask Gateway Device Mxfrg "
"-------------------- --------------- -------------------- ------ ----- "
"----- --- --- ----- ------ %s\n";
static const char ire_hdr_v4_normal[] =
" Destination Gateway Flags Ref Use Interface"
" %s\n-------------------- -------------------- ----- ----- ---------- "
"--------- %s\n";
static boolean_t
const sec_attr_list_t *attrs)
{
return (first);
}
return (first);
if (first) {
}
} else {
}
if (Vflag) {
(void) printf("%-20s %-15s %-20s %-6s %5u%c %4u %3u "
"%-4s%6u %6u %s\n",
pr_secattr(attrs));
} else {
(void) printf("%-20s %-20s %-5s %4u %10u %-9s %s\n",
pr_secattr(attrs));
}
return (first);
}
/*
* Match a user-supplied IP address list against an IPv6 route entry.
* If the user specified "any," then any non-zero address matches. If
* the user specified "none," then only the zero address matches. If
* the user specified a subnet mask length, then use that in matching
* routes (select routes that are at least as specific). If the user
* specified only an address, then use the route's mask (select routes
* that would match that address). IPv4 addresses are ignored.
*/
static boolean_t
{
int fmasklen;
int i;
char **app;
char *aptr;
return (!IN6_IS_ADDR_UNSPECIFIED(addr));
}
fmasklen = 0;
/* 'for' loop 1a: */
ucp++) {
if (*ucp != 0xff) {
if (*ucp != 0)
break; /* 'for' loop 1a */
}
fmasklen += 8;
} /* 'for' loop 1a ends */
if (fmasklen != IPV6_ABITS) {
return (B_FALSE);
}
/* 'for' loop 1b: */
app++) {
/* LINTED: (note 1) */
continue; /* 'for' loop 1b */
break; /* 'for' loop 1b */
if (i == 0 ||
return (B_TRUE);
} /* 'for' loop 1b ends */
return (B_FALSE);
}
/*
* Run through the filter list for an IPv6 MIB2 IRE. For a given
* type, if there's at least one filter and all filters of that type
* fail to match, then the route doesn't match and isn't displayed.
* If at least one matches, or none are specified, for each of the
* types, then the route is selected and displayed.
*/
static boolean_t
{
int idx;
/* 'for' loop 1: */
/* 'for' loop 2: */
switch (idx) {
case FK_AF:
/* 'for' loop 2 */
continue;
break;
case FK_OUTIF:
if (!dev_name_match(&rp6->
/* 'for' loop 2 */
continue;
break;
case FK_DST:
/* 'for' loop 2 */
continue;
break;
case FK_FLAGS:
/* 'for' loop 2 */
continue;
break;
}
break;
} /* 'for' loop 2 ends */
return (B_FALSE);
}
/* 'for' loop 1 ends */
return (B_TRUE);
}
static const char ire_hdr_v6[] =
"\n%s Table: IPv6\n";
static const char ire_hdr_v6_verbose[] =
" Destination/Mask Gateway If PMTU Rtt "
"--------------------------- --------------------------- ----- ------ ----- "
"--- ----- ------ ------ %s\n";
static const char ire_hdr_v6_normal[] =
" Destination/Mask Gateway Flags Ref Use "
" If %s\n"
"--------------------------- --------------------------- ----- --- ------- "
"----- %s\n";
static boolean_t
const sec_attr_list_t *attrs)
{
return (first);
}
}
}
}
/* Address resolution */
}
}
}
}
return (first);
if (first) {
}
if (Vflag) {
(void) printf("%-27s %-27s %-5s %5u%c %5u %3u "
"%-5s %6u %6u %s\n",
" --" :
pr_secattr(attrs));
} else {
(void) printf("%-27s %-27s %-5s %3u %7u %-5s %s\n",
" --" :
pr_secattr(attrs));
}
return (first);
}
/*
* Common attribute-gathering routine for all transports.
*/
static mib2_transportMLPEntry_t **
{
int transport_count = 0;
const mib_item_t *iptr;
}
if (transport_count <= 0)
return (NULL);
perror("gather_attrs calloc failed");
return (NULL);
}
/* LINTED: (note 1) */
transportMLPSize)) {
}
}
}
return (attrs);
}
static void
{
return;
(void) printf(" INVALID\n");
else
}
/* ------------------------------ TCP_REPORT------------------------------- */
static const char tcp_hdr_v4[] =
"\nTCP: IPv4\n";
static const char tcp_hdr_v4_compat[] =
"\nTCP\n";
static const char tcp_hdr_v4_verbose[] =
" Rto Mss State\n"
"-------------------- ----- -------- -------- ----- -------- -------- "
"----- ----- -----------\n";
static const char tcp_hdr_v4_normal[] =
" Local Address Remote Address Swind Send-Q Rwind Recv-Q "
" State\n"
"-------------------- -------------------- ----- ------ ----- ------ "
"-----------\n";
static const char tcp_hdr_v6[] =
"\nTCP: IPv6\n";
static const char tcp_hdr_v6_verbose[] =
" Rack Rto Mss State If\n"
"--------------------------------- ----- -------- -------- ----- -------- "
"-------- ----- ----- ----------- -----\n";
static const char tcp_hdr_v6_normal[] =
" Local Address Remote Address "
"Swind Send-Q Rwind Recv-Q State If\n"
"--------------------------------- --------------------------------- "
"----- ------ ----- ------ ----------- -----\n";
static void
{
int jtemp = 0;
if (!protocol_selected(IPPROTO_TCP))
return;
/*
* Preparation pass: the kernel returns separate entries for TCP
* connection table entries and Multilevel Port attributes. We loop
* through the attributes first and set up an array for each address
* family.
*/
NULL;
NULL;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
/* LINTED: (note 1) */
tcpConnEntrySize)) {
}
} else {
/* LINTED: (note 1) */
}
}
} /* 'for' loop 1 ends */
}
static boolean_t
const mib2_transportMLPEntry_t *attr)
{
/*
* lname and fname below are for the hostname as well as the portname
* There is no limit on portname length so we assume MAXHOSTNAMELEN
* as the limit
*/
return (first); /* Nothing to print */
if (first) {
}
if (Vflag) {
(void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
"%5u %5u %s\n",
} else {
(void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
}
return (B_FALSE);
}
static boolean_t
const mib2_transportMLPEntry_t *attr)
{
/*
* lname and fname below are for the hostname as well as the portname
* There is no limit on portname length so we assume MAXHOSTNAMELEN
* as the limit
*/
char *ifnamep;
return (first); /* Nothing to print */
if (first) {
(void) printf(tcp_hdr_v6);
}
ifnamep = "";
if (Vflag) {
(void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
"%5u %5u %-11s %s\n",
ifnamep);
} else {
(void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
ifnamep);
}
return (B_FALSE);
}
/* ------------------------------- UDP_REPORT------------------------------- */
static const char udp_hdr_v4[] =
" Local Address Remote Address State\n"
"-------------------- -------------------- ----------\n";
static const char udp_hdr_v6[] =
" Local Address Remote Address "
" State If\n"
"--------------------------------- --------------------------------- "
"---------- -----\n";
static void
{
int jtemp = 0;
if (!protocol_selected(IPPROTO_UDP))
return;
/*
* Preparation pass: the kernel returns separate entries for UDP
* connection table entries and Multilevel Port attributes. We loop
* through the attributes first and set up an array for each address
* family.
*/
NULL;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
continue; /* 'for' loop 1 */
/* xxx.xxx.xxx.xxx,pppp sss... */
/* LINTED: (note 1) */
udpEntrySize)) {
}
} else {
/* LINTED: (note 1) */
udp6EntrySize)) {
}
}
} /* 'for' loop 1 ends */
}
static boolean_t
const mib2_transportMLPEntry_t *attr)
{
/* hostname + portname */
return (first); /* Nothing to print */
if (first) {
(void) printf(udp_hdr_v4);
}
(void) printf("%-20s ",
(void) printf("%-20s %s\n",
"",
/*
* UDP sockets don't have remote attributes, so there's no need to
* print them here.
*/
return (first);
}
static boolean_t
const mib2_transportMLPEntry_t *attr)
{
/* hostname + portname */
const char *ifnamep;
return (first); /* Nothing to print */
if (first) {
(void) printf("\nUDP: IPv6\n");
(void) printf(udp_hdr_v6);
}
(void) printf("%-33s ",
(void) printf("%-33s %-10s %s\n",
"",
/*
* UDP sockets don't have remote attributes, so there's no need to
* print them here.
*/
return (first);
}
/* ------------------------------ SCTP_REPORT------------------------------- */
static const char sctp_hdr[] =
"\nSCTP:";
static const char sctp_hdr_normal[] =
" Local Address Remote Address "
"Swind Send-Q Rwind Recv-Q StrsI/O State\n"
"------------------------------- ------------------------------- "
"------ ------ ------ ------ ------- -----------";
static const char *
{
static char sctpsbuf[50];
const char *cp;
switch (state) {
case MIB2_SCTP_closed:
cp = "CLOSED";
break;
case MIB2_SCTP_cookieWait:
cp = "COOKIE_WAIT";
break;
case MIB2_SCTP_cookieEchoed:
cp = "COOKIE_ECHOED";
break;
case MIB2_SCTP_established:
cp = "ESTABLISHED";
break;
cp = "SHUTDOWN_PENDING";
break;
case MIB2_SCTP_shutdownSent:
cp = "SHUTDOWN_SENT";
break;
cp = "SHUTDOWN_RECEIVED";
break;
cp = "SHUTDOWN_ACK_SENT";
break;
case MIB2_SCTP_listen:
cp = "LISTEN";
break;
default:
"UNKNOWN STATE(%d)", state);
break;
}
}
}
return (cp);
}
static const mib2_sctpConnRemoteEntry_t *
{
const mib2_sctpConnRemoteEntry_t *sre;
continue;
}
/* LINTED: (note 1) */
sre = (const mib2_sctpConnRemoteEntry_t *)
((const char *)current + sctpRemoteEntrySize);
} else {
}
/* LINTED: (note 1) */
sre = (const mib2_sctpConnRemoteEntry_t *)
((const char *)sre + sctpRemoteEntrySize)) {
continue;
}
return (sre);
}
}
return (NULL);
}
static const mib2_sctpConnLocalEntry_t *
{
const mib2_sctpConnLocalEntry_t *sle;
continue;
}
/* LINTED: (note 1) */
sle = (const mib2_sctpConnLocalEntry_t *)
((const char *)current + sctpLocalEntrySize);
} else {
}
/* LINTED: (note 1) */
sle = (const mib2_sctpConnLocalEntry_t *)
((const char *)sle + sctpLocalEntrySize)) {
continue;
}
return (sle);
}
}
return (NULL);
}
static void
int port)
{
/*
* Address is either a v4 mapped or v6 addr. If
* it's a v4 mapped, convert to v4 before
* displaying.
*/
switch (type) {
case MIB2_SCTP_ADDR_V4:
/* v4 */
if (port > 0) {
} else {
}
break;
case MIB2_SCTP_ADDR_V6:
/* v6 */
if (port > 0) {
} else {
}
break;
default:
break;
}
}
static void
const mib2_transportMLPEntry_t *attr)
{
(void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
if (!Vflag) {
return;
}
&sp->sctpAssocRemPrimAddr)) {
if (printfirst == B_TRUE) {
} else {
}
} else {
}
}
}
if (printfirst == B_FALSE) {
(void) puts(">");
printfirst = B_TRUE;
}
&sp->sctpAssocLocPrimAddr)) {
if (printfirst == B_TRUE) {
} else {
}
}
}
if (printfirst == B_FALSE) {
(void) puts(">");
}
}
static void
{
const mib_item_t *head;
const mib2_sctpConnEntry_t *sp;
/*
* Preparation pass: the kernel returns separate entries for SCTP
* connection table entries and Multilevel Port attributes. We loop
* through the attributes first and set up an array for each address
* family.
*/
NULL;
continue;
/* LINTED: (note 1) */
if (Aflag ||
(void) puts(sctp_hdr_normal);
}
}
}
}
}
static char *
plural(int n)
{
return (n != 1 ? "s" : "");
}
static char *
pluraly(int n)
{
return (n != 1 ? "ies" : "y");
}
static char *
plurales(int n)
{
return (n != 1 ? "es" : "");
}
static char *
pktscale(n)
int n;
{
static char buf[6];
char t;
if (n < 1024) {
t = ' ';
} else if (n < 1024 * 1024) {
t = 'k';
n /= 1024;
} else if (n < 1024 * 1024 * 1024) {
t = 'm';
n /= 1024 * 1024;
} else {
t = 'g';
n /= 1024 * 1024 * 1024;
}
return (buf);
}
/* --------------------- mrt_report (netstat -m) -------------------------- */
static void
{
int jtemp = 0;
int numvifs = 0;
int nmfc = 0;
if (!(family_selected(AF_INET)))
return;
/* 'for' loop 1: */
if (Dflag) {
(void) printf("Group = %d, mib_id = %d, "
"length = %d, valp = 0x%p\n",
}
continue; /* 'for' loop 1 */
case EXPER_DVMRP_VIF:
if (Dflag)
(void) printf("%u records for ipVifTable:\n",
(void) puts("\nVirtual Interface Table is "
"empty");
break;
}
(void) puts("\nVirtual Interface Table\n"
" Vif Threshold Rate_Limit Local-Address"
" Remote-Address Pkt_in Pkt_out");
/* 'for' loop 2: */
/* LINTED: (note 1) */
vifctlSize)) {
continue; /* 'for' loop 2 */
/* numvifs = vip->vifc_vifi; */
numvifs++;
(void) printf(" %2u %3u "
"%4u %-15.15s",
(void) printf(" %-15.15s %8u %8u\n",
vip->vifc_pkt_out);
} /* 'for' loop 2 ends */
break;
case EXPER_DVMRP_MRT:
if (Dflag)
(void) printf("%u records for ipMfcTable:\n",
(void) puts("\nMulticast Forwarding Cache is "
"empty");
break;
}
(void) puts("\nMulticast Forwarding Cache\n"
" Origin-Subnet Mcastgroup "
/* LINTED: (note 1) */
mfcctlSize)) {
nmfc++;
(void) printf(" %-30.15s",
(void) printf("%-15.15s %6s %3u ",
mfccp->mfcc_parent);
(void) printf(" %u (%u)",
vifi,
}
}
(void) putchar('\n');
}
(void) printf("\nTotal no. of entries in cache: %d\n",
nmfc);
break;
}
} /* 'for' loop 1 ends */
(void) putchar('\n');
}
/*
* Get the stats for the cache named 'name'. If prefix != 0, then
* interpret the name as a prefix, and sum up stats for all caches
* named 'name*'.
*/
static void
{
int len;
int alloc;
int64_t total_alloc = 0;
int alloc_fail, total_alloc_fail = 0;
int buf_size = 0;
int buf_avail;
int buf_total;
int buf_max, total_buf_max = 0;
int buf_inuse, total_buf_inuse = 0;
char buf[256];
/* 'for' loop 1: */
continue; /* 'for' loop 1 */
/*
* Hack alert: because of the way streams messages are
* allocated, every constructed free dblk has an associated
* mblk. From the allocator's viewpoint those mblks are
* allocated (because they haven't been freed), but from
* our viewpoint they're actually free (because they're
* not currently in use). To account for this caching
* effect we subtract the total constructed free dblks
* from the total allocated mblks to derive mblks in use.
*/
continue; /* 'for' loop 1 */
}
continue; /* 'for' loop 1 */
(void) printf(" %-18s %6u %9u %11u %11u\n",
}
total_alloc += alloc;
total_buf_max += buf_max;
} /* 'for' loop 1 ends */
if (buf_size == 0) {
(void) printf("%-22s [couldn't find statistics for %s]\n",
return;
}
else
}
static void
m_report(void)
{
int64_t total_bytes = 0;
(void) puts("streams allocation:");
(void) printf("%63s\n",
"current maximum total failures");
kmem_cache_stats("streams",
"stream_head_cache", 0, &total_bytes);
(void) printf("\n%lld Kbytes allocated for streams data\n",
total_bytes / 1024);
(void) putchar('\n');
}
/* --------------------------------- */
/*
* Print an IPv4 address. Remove the matching part of the domain name
* from the returned name.
*/
static char *
{
char *cp;
int error_num;
if (first) {
} else
domain[0] = 0;
}
if (!Nflag) {
&error_num);
if (hp) {
*cp = 0;
}
}
} else {
}
return (dst);
}
/*
* Print a non-zero IPv4 address. Print " --" if the address is zero.
*/
static char *
{
if (addr == INADDR_ANY) {
return (dst);
}
}
/*
* Print an IPv6 address. Remove the matching part of the domain name
* from the returned name.
*/
static char *
{
char *cp;
int error_num;
if (first) {
} else
domain[0] = 0;
}
if (!Nflag) {
if (hp) {
*cp = 0;
}
}
} else {
}
return (dst);
}
/* For IPv4 masks */
static char *
{
return (dst);
}
/*
* Does not print /128 to save space in printout. H flag carries this notion.
*/
static char *
{
char *cp;
return (dst);
}
if (prefixlen != IPV6_ABITS) {
/* How much room is left? */
}
}
return (dst);
}
/* Print IPv4 address and port */
static char *
{
char *cp;
if (addr == INADDR_ANY) {
} else {
}
/* How much room is left? */
*cp++ = '.';
dstlen--;
}
return (dst);
}
/* Print IPv6 address and port */
static char *
{
char *cp;
if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
} else {
}
/* How much room is left? */
*cp++ = '.';
dstlen--;
}
return (dst);
}
/*
* Return the name of the network whose address is given. The address is
* assumed to be that of a net or subnet, not a host.
*/
static char *
{
int subnetshift;
int error_num;
return (dst);
}
if (mask == 0) {
subnetshift = 8;
subnetshift = 8;
} else {
subnetshift = 4;
}
/*
* If there are more bits than the standard mask
* would suggest, subnets must be in use. Guess at
* the subnet mask, assuming reasonable width subnet
* fields.
*/
/* compiler doesn't sign extend! */
}
while ((mask & 1) == 0)
else {
/*
* Look for subnets in hosts map.
*/
if (hp)
}
}
} else {
}
return (dst);
}
/*
* Return the name of the network whose address is given.
* The address is assumed to be a host address.
*/
static char *
{
int subnetshift;
int error_num;
return (dst);
}
/* Figure out network portion of address (with host portion = 0) */
if (addr) {
/* Try figuring out mask if unknown (all 0s). */
if (mask == 0) {
subnetshift = 8;
subnetshift = 8;
} else {
subnetshift = 4;
}
/*
* If there are more bits than the standard mask
* would suggest, subnets must be in use. Guess at
* the subnet mask, assuming reasonable width subnet
* fields.
*/
/* compiler doesn't sign extend! */
}
while ((mask & 1) == 0)
}
else
net = netshifted = 0;
/* Try looking up name unless -n was specified. */
if (!Nflag) {
else {
/*
* Look for subnets in hosts map.
*/
if (hp)
}
return (dst);
}
/*
* No name found for net: fallthru and return in decimal
* dot notation.
*/
}
return (dst);
}
/*
* Return the filter mode as a string:
* 1 => "INCLUDE"
* 2 => "EXCLUDE"
* otherwise "<unknown>"
*/
static char *
{
switch (fmode) {
case 1:
return ("INCLUDE");
case 2:
return ("EXCLUDE");
default:
return ("<unknown>");
}
}
#define MAX_STRING_SIZE 256
static const char *
{
int i;
static char *sbuf;
const sec_attr_list_t *aptr;
return ("");
i += MAX_STRING_SIZE;
if (i > sbuf_len) {
perror("realloc security attribute buffer");
return ("");
}
sbuf_len = i;
}
/* note: effectively hard-coded in rtsa_keyword */
}
*cp = '\0';
return (sbuf);
}
/*
* Pretty print a port number. If the Nflag was
* specified, use numbers instead of names.
*/
static char *
{
else
return (dst);
}
/*PRINTFLIKE2*/
void
{
if (do_perror)
exit(2);
}
/*
* Return value of named statistic for given kstat_named kstat;
* return 0LL if named statistic is not in list (use "ll" as a
* type qualifier when printing 64-bit int's with printf() )
*/
static uint64_t
{
return (0LL);
return (0LL);
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
break;
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
break;
default:
break;
}
return (value);
}
{
if (kstat_chain_id == -1)
return (kstat_chain_id);
}
/*
* Parse a list of IRE flag characters into a bit field.
*/
static uint_t
{
const char *cp;
if (*arg == '\0')
val = 0;
while (*arg != '\0') {
arg++;
}
return (val);
}
/*
* Handle -f argument. Validate input format, sort by keyword, and
* save off digested results.
*/
static void
process_filter(char *arg)
{
int idx;
int klen = 0;
int val;
int error_num;
int maxv;
/* Look up the keyword first */
} else {
break;
}
if (idx >= NFILTERKEYS)
/* Advance past keyword and separator. */
}
perror("filter");
exit(1);
}
switch (idx) {
case FK_AF:
} else {
}
break;
case FK_OUTIF:
break;
}
break;
}
exit(1);
}
}
break;
case FK_DST:
/* Special semantics; any address *but* zero */
break;
}
break;
}
*cp++ = '\0';
&error_num);
} else {
/*
* If decode as "/n" works, then translate
* into a mask.
*/
/* LINTED: (note 1) */
hp->h_addr_list[0])) {
} else {
maxv = IPV6_ABITS;
}
while (val >= 8)
*ucp++ = 0;
/* Otherwise, try as numeric address */
}
}
break;
case FK_FLAGS:
if (*arg == '+') {
newf->u.f.f_flagclear = 0;
} else if (*arg == '-') {
} else {
}
break;
default:
assert(0);
}
}
/* Determine if user wants this address family printed. */
static boolean_t
family_selected(int family)
{
return (B_FALSE);
return (B_TRUE);
return (B_TRUE);
}
return (B_FALSE);
}
/*
* Convert the interface index to a string using the buffer `ifname', which
* must be at least LIFNAMSIZ bytes. We first try to map it to name. If that
* fails (e.g., because we're inside a zone and it does not have access to
* interface for the index in question), just return "if#<num>".
*/
static char *
{
return (ifname);
}
/*
* print the usage line
*/
static void
{
cmdname);
"[-P protocol] [-g | -p | -s [interval [count]]]\n", cmdname);
"[interval [count]]\n", cmdname);
"[-f address_family] [interval [count]]\n", cmdname);
"[-f address_family|filter]\n", cmdname);
cmdname);
"[-f address_family]\n", cmdname);
}
/*
* fatal: print error message to stderr and
* call exit(errcode)
*/
/*PRINTFLIKE2*/
static void
{
return;
}