diff options
| author | Tim Foster <tim.foster@joyent.com> | 2019-10-25 13:00:51 +0000 |
|---|---|---|
| committer | Tim Foster <tim.foster@joyent.com> | 2019-10-25 14:03:36 +0000 |
| commit | f4b6c0de737058d0e1624e50536bcbe149b3206c (patch) | |
| tree | 402b11d0a54882c7d5e7daffc1087fe620104f41 /usr/src/cmd | |
| parent | 29de67cafe15bb9e2c61bd58e6183182a7735036 (diff) | |
| parent | 7284664a1faa361af4ff33ba5435d43d3ee07bf2 (diff) | |
| download | illumos-joyent-merge-20191025T123815.tar.gz | |
[illumos-gate merge]merge-20191025T123815
commit 7284664a1faa361af4ff33ba5435d43d3ee07bf2
11816 iscsi initiator gets confused if attached before root file system mount
commit 55908bd733fe029d49237b91c700655997242419
11843 update Intel microcode to 20190918
commit b9c9c3595312927fb362936529c5679117843b93
11826 Buffer overflow and memory leak in "libbsm"
commit 78a2e113edb6fe0a0382b403b55d92e8f0bba78f
9531 Want netstat -u to show PIDs associated with sockets
11707 provide 64-bit libdhcpagent
11708 netstat should be smatch and CERRWARN clean
Conflicts:
usr/src/data/ucode/Makefile
usr/src/data/ucode/README.ucode
In addition, this change makes all of
usr/src/data/ucode/intel and corresponding
usr/src/data/ucode/Makefile[.links] match upstream,
with corresponding manifest changes.
Diffstat (limited to 'usr/src/cmd')
| -rw-r--r-- | usr/src/cmd/cmd-inet/common/compat.c | 6 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile | 19 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c | 2171 | ||||
| -rw-r--r-- | usr/src/cmd/cmd-inet/usr.bin/netstat/unix.c | 243 | ||||
| -rw-r--r-- | usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs | 5 | ||||
| -rw-r--r-- | usr/src/cmd/stat/common/statcommon.h | 8 |
6 files changed, 1789 insertions, 663 deletions
diff --git a/usr/src/cmd/cmd-inet/common/compat.c b/usr/src/cmd/cmd-inet/common/compat.c index ec055db910..7041762a87 100644 --- a/usr/src/cmd/cmd-inet/common/compat.c +++ b/usr/src/cmd/cmd-inet/common/compat.c @@ -22,10 +22,10 @@ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <deflt.h> #include <string.h> #include <stddef.h> @@ -58,7 +58,7 @@ get_compat_flag(char **value) TURNOFF(flags, DC_CASE); (void) defcntl(DC_SETFLAGS, flags); - if (cp = defread(DEFAULT_IP_LINE)) + if ((cp = defread(DEFAULT_IP_LINE)) != NULL) *value = strdup(cp); /* close */ diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile b/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile index 9c2565656f..c3051e7ef8 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile +++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile @@ -25,13 +25,19 @@ # Copyright (c) 1990 Mentat Inc. # # Copyright (c) 2018, Joyent, Inc. +# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. PROG= netstat -LOCALOBJS= netstat.o unix.o +LOCALOBJS= netstat.o COMMONOBJS= compat.o include ../../../Makefile.cmd +# netstat uses libproc to grab processes and extract information about their +# sockets. In order to be able to grab 64-bit processes, netstat itself must +# be built 64-bit. +$(BUILD64) include ../../../Makefile.cmd.64 + include ../../Makefile.cmd-inet LOCALSRCS= $(LOCALOBJS:%.o=%.c) @@ -46,12 +52,9 @@ OBJS= $(LOCALOBJS) $(COMMONOBJS) $(STAT_COMMON_OBJS) SRCS= $(LOCALSRCS) $(COMMONSRCS) $(STAT_COMMON_SRCS) CPPFLAGS += -DNDEBUG -I$(CMDINETCOMMONDIR) -I$(STATCOMMONDIR) -CERRWARN += $(CNOWARN_UNINIT) -CERRWARN += -_gcc=-Wno-parentheses -LDLIBS += -ldhcpagent -lsocket -lnsl -lkstat -ltsnet -ltsol +LDLIBS += -ldhcpagent -lsocket -lnsl -lkstat -ltsnet -ltsol -lproc -# not linted -SMATCH=off +CSTD= $(CSTD_GNU99) .KEEP_STATE: @@ -67,12 +70,10 @@ $(PROG): $(OBJS) $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) -install: all $(ROOTPROG) +install: all $(ROOTPROG) clean: $(RM) $(OBJS) -lint: lint_SRCS - include ../../../Makefile.targ diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c index 223e582072..a6249ae566 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c +++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c @@ -24,22 +24,12 @@ * netstat.c 2.2, last change 9/9/91 * MROUTING Revision 3.5 * Copyright 2018, Joyent, Inc. + * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. */ /* * simple netstat based on snmp/mib-2 interface to the TCP/IP stack * - * 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) @@ -58,14 +48,21 @@ #include <locale.h> #include <synch.h> #include <thread.h> +#include <pwd.h> +#include <limits.h> +#include <sys/ccompile.h> #include <sys/types.h> +#include <sys/stat.h> #include <sys/stream.h> #include <stropts.h> #include <sys/strstat.h> #include <sys/tihdr.h> +#include <procfs.h> +#include <dirent.h> #include <sys/socket.h> +#include <sys/socketvar.h> #include <sys/sockio.h> #include <netinet/in.h> #include <net/if.h> @@ -88,13 +85,14 @@ #include <dhcpagent_ipc.h> #include <dhcpagent_util.h> #include <compat.h> +#include <sys/mkdev.h> #include <libtsnet.h> #include <tsol/label.h> -#include "statcommon.h" +#include <libproc.h> -extern void unixpr(kstat_ctl_t *kc); +#include "statcommon.h" #define STR_EXPAND 4 @@ -138,25 +136,24 @@ struct iflist { struct ifstat tot; }; +static void fatal(int, char *, ...) __NORETURN; + static mib_item_t *mibget(int sd); static void mibfree(mib_item_t *firstitem); static int mibopen(void); static void mib_get_constants(mib_item_t *item); static mib_item_t *mib_item_dup(mib_item_t *item); -static mib_item_t *mib_item_diff(mib_item_t *item1, - mib_item_t *item2); +static mib_item_t *mib_item_diff(mib_item_t *item1, mib_item_t *item2); static void mib_item_destroy(mib_item_t **item); static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b); static char *octetstr(const Octet_t *op, int code, char *dst, uint_t dstlen); -static char *pr_addr(uint_t addr, - char *dst, uint_t dstlen); +static char *pr_addr(uint_t addr, char *dst, uint_t dstlen); static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen); static char *pr_addr6(const in6_addr_t *addr, char *dst, uint_t dstlen); -static char *pr_mask(uint_t addr, - char *dst, uint_t dstlen); +static char *pr_mask(uint_t addr, char *dst, uint_t dstlen); static char *pr_prefix6(const struct in6_addr *addr, uint_t prefixlen, char *dst, uint_t dstlen); static char *pr_ap(uint_t addr, uint_t port, @@ -194,6 +191,7 @@ static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6, static void ire_report(const mib_item_t *item); static void tcp_report(const mib_item_t *item); static void udp_report(const mib_item_t *item); +static void uds_report(kstat_ctl_t *); static void group_report(mib_item_t *item); static void dce_report(mib_item_t *item); static void print_ip_stats(mib2_ip_t *ip); @@ -225,7 +223,10 @@ static char *ifindex2str(uint_t, char *); static boolean_t family_selected(int family); static void usage(char *); -static void fatal(int errcode, char *str1, ...); +static char *get_username(uid_t); + +static void process_hash_build(void); +static void process_hash_free(void); #define PLURAL(n) plural((int)n) #define PLURALY(n) pluraly((int)n) @@ -234,7 +235,6 @@ static void fatal(int errcode, char *str1, ...); #define MDIFF(diff, elem2, elem1, member) (diff)->member = \ (elem2)->member - (elem1)->member - static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */ static boolean_t CIDRflag = B_FALSE; /* CIDR for IPv4 -i/-r addrs */ static boolean_t Dflag = B_FALSE; /* DCE info */ @@ -245,6 +245,7 @@ static boolean_t Rflag = B_FALSE; /* Routing Tables */ static boolean_t RSECflag = B_FALSE; /* Security attributes */ static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */ static boolean_t Vflag = B_FALSE; /* Verbose */ +static boolean_t Uflag = B_FALSE; /* Show PID and UID info. */ static boolean_t Pflag = B_FALSE; /* Net to Media Tables */ static boolean_t Gflag = B_FALSE; /* Multicast group membership */ static boolean_t MMflag = B_FALSE; /* Multicast routing table */ @@ -406,11 +407,9 @@ ns_warning_thr(void *unsued) mutex_exit(&ns_lock); } - /* LINTED: E_STMT_NOT_REACHED */ return (NULL); } - int main(int argc, char **argv) { @@ -447,7 +446,7 @@ main(int argc, char **argv) (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); - while ((c = getopt(argc, argv, "acdimnrspMgvxf:P:I:DRT:")) != -1) { + while ((c = getopt(argc, argv, "acdimnrspMguvxf:P:I:DRT:")) != -1) { switch ((char)c) { case 'a': /* all connections */ Aflag = B_TRUE; @@ -511,6 +510,10 @@ main(int argc, char **argv) IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ break; + case 'u': /* show pid and uid information */ + Uflag = B_TRUE; + break; + case 'x': /* turn on debugging */ Xflag = B_TRUE; break; @@ -617,8 +620,7 @@ main(int argc, char **argv) } } if (optind < argc) { - (void) fprintf(stderr, - "%s: extra arguments\n", name); + (void) fprintf(stderr, "%s: extra arguments\n", name); usage(name); } if (interval) @@ -638,6 +640,9 @@ main(int argc, char **argv) exit(0); } + if (Uflag) + process_hash_build(); + /* * Get this process's security label if the -R switch is set. * We use this label as the current zone's security label. @@ -672,7 +677,6 @@ main(int argc, char **argv) count = 1; once_only = B_TRUE; } - /* 'for' loop 1: */ for (;;) { mib_item_t *curritem = NULL; /* only for -[M]s */ @@ -729,7 +733,7 @@ main(int argc, char **argv) if (family_selected(AF_UNIX) && (!(Dflag || Iflag || Rflag || Sflag || Mflag || MMflag || Pflag || Gflag))) - unixpr(kc); + uds_report(kc); (void) kstat_close(kc); /* iteration handling code */ @@ -758,16 +762,18 @@ main(int argc, char **argv) if ((kc = kstat_open()) == NULL) fail(1, "kstat_open(): can't open /dev/kstat"); - } /* 'for' loop 1 ends */ + } mibfree(item); (void) close(sd); if (zone_security_label != NULL) m_label_free(zone_security_label); + if (Uflag) + process_hash_free(); + return (0); } - static int isnum(char *p) { @@ -781,6 +787,427 @@ isnum(char *p) return (1); } +/* + * ------------------------------ Process Hash ----------------------------- + * + * When passed the -u option, netstat presents additional information against + * each socket showing the associated process ID(s), user(s) and command(s). + * + * The kernel provides some additional information for each socket, namely: + * - inode; + * - address family; + * - socket type; + * - major number; + * - flags. + * + * Netstat must correlate this information against processes running on the + * system and the files which they have open. + * + * It does this by traversing /proc and checking each process' open files, + * looking for BSD sockets or file descriptors relating to TLI/XTI sockets. + * When it finds one, it retrieves information and records it in the + * 'process_table' hash table with the entry hashed by its inode. + * + * For a BSD socket, libproc is used to grab the process and retrieve + * further information. This is not necessary for TLI/XTI sockets since the + * information can be derived directly via stat(). + * + * Note that each socket can be associated with more than one process. + */ + +/* + * The size of the hash table for recording sockets found under /proc. + * This should be a prime number. The value below was chosen after testing + * on a busy web server to reduce the number of hash table collisions to + * fewer than five per slot. + */ +#define PROC_HASH_SIZE 2003 +/* Maximum length of a username - anything larger will be truncated */ +#define PROC_USERNAME_SIZE 128 +/* Maximum length of the string representation of a process ID */ +#define PROC_PID_SIZE 15 + +#define PROC_HASH(k) ((k) % PROC_HASH_SIZE) + +typedef struct proc_fdinfo { + uint64_t ph_inode; + uint64_t ph_fd; + mode_t ph_mode; + major_t ph_major; + int ph_family; + int ph_type; + + char ph_fname[PRFNSZ]; + char ph_psargs[PRARGSZ]; + char ph_username[PROC_USERNAME_SIZE]; + pid_t ph_pid; + char ph_pidstr[PROC_PID_SIZE]; + + struct proc_fdinfo *ph_next; /* Next (for collisions) */ + struct proc_fdinfo *ph_next_proc; /* Next process with this inode */ +} proc_fdinfo_t; + +static proc_fdinfo_t *process_table[PROC_HASH_SIZE]; + +static proc_fdinfo_t unknown_proc = { + .ph_pid = 0, + .ph_pidstr = "", + .ph_username = "", + .ph_fname = "", + .ph_psargs = "", + .ph_next_proc = NULL +}; + +/* + * Gets username given uid. It doesn't return NULL. + */ +static char * +get_username(uid_t u) +{ + static uid_t saved_uid = UID_MAX; + static char saved_username[PROC_USERNAME_SIZE]; + struct passwd *pw = NULL; + + if (u == UID_MAX) + return ("<unknown>"); + + if (u == saved_uid && saved_username[0] != '\0') + return (saved_username); + + setpwent(); + + if ((pw = getpwuid(u)) != NULL) { + (void) strlcpy(saved_username, pw->pw_name, + sizeof (saved_username)); + } else { + (void) snprintf(saved_username, sizeof (saved_username), + "(%u)", u); + } + + saved_uid = u; + return (saved_username); +} + +static proc_fdinfo_t * +process_hash_find(const mib2_socketInfoEntry_t *sie, int type, int family) +{ + proc_fdinfo_t *ph; + uint_t idx = PROC_HASH(sie->sie_inode); + + for (ph = process_table[idx]; ph != NULL; ph = ph->ph_next) { + if (ph->ph_inode != sie->sie_inode) + continue; + if ((sie->sie_flags & MIB2_SOCKINFO_STREAM)) { + /* TLI/XTI socket */ + if (S_ISCHR(ph->ph_mode) && + major(sie->sie_dev) == ph->ph_major) { + return (ph); + } + } else { + if (S_ISSOCK(ph->ph_mode) && ph->ph_type == type && + ph->ph_family == family) { + return (ph); + } + } + } + + return (NULL); +} + +static proc_fdinfo_t * +process_hash_get(const mib2_socketInfoEntry_t *sie, int type, int family) +{ + proc_fdinfo_t *ph; + + if (sie != NULL && sie->sie_inode > 0 && + (ph = process_hash_find(sie, type, family)) != NULL) { + return (ph); + } + + return (&unknown_proc); +} + +static void +process_hash_insert(proc_fdinfo_t *ph) +{ + uint_t idx = PROC_HASH(ph->ph_inode); + proc_fdinfo_t *slotp; + + mib2_socketInfoEntry_t sie = { + .sie_inode = ph->ph_inode, + .sie_dev = makedev(ph->ph_major, 0), + .sie_flags = S_ISCHR(ph->ph_mode) ? MIB2_SOCKINFO_STREAM : 0 + }; + + slotp = process_hash_find(&sie, ph->ph_type, ph->ph_family); + + if (slotp == NULL) { + ph->ph_next = process_table[idx]; + process_table[idx] = ph; + } else { + ph->ph_next_proc = slotp->ph_next_proc; + slotp->ph_next_proc = ph; + } +} + +static void +process_hash_dump(void) +{ + unsigned int i; + + (void) printf("--- Process hash table\n"); + for (i = 0; i < PROC_HASH_SIZE; i++) { + proc_fdinfo_t *ph; + + if (process_table[i] == NULL) + continue; + + (void) printf("Slot %d\n", i); + + for (ph = process_table[i]; ph != NULL; ph = ph->ph_next) { + proc_fdinfo_t *ph2; + + (void) printf(" -> Inode %" PRIu64 "\n", + ph->ph_inode); + + for (ph2 = ph; ph2 != NULL; ph2 = ph2->ph_next_proc) { + (void) printf(" -> " + "/proc/%ld/fd/%" PRIu64 " %s - " + "fname %s - " + "psargs %s - " + "major %" PRIx32 " - " + "type/fam %d/%d\n", + ph2->ph_pid, ph2->ph_fd, + S_ISCHR(ph2->ph_mode) ? "CHR" : "SOCK", + ph2->ph_fname, ph2->ph_psargs, + ph2->ph_major, + ph2->ph_type, ph2->ph_family); + } + } + } +} + +static int +process_hash_iter(const psinfo_t *psinfo, const prfdinfo_t *pr, + struct ps_prochandle *Pr) +{ + proc_fdinfo_t *ph; + + /* + * We are interested both in sockets and in descriptors linked to + * network STREAMS character devices. + */ + if (S_ISCHR(pr->pr_mode)) { + /* + * There's no elegant way to determine if a character device + * supports TLI, so just check a hardcoded list of known TLI + * devices. + */ + const char *tlidevs[] = { + "tcp", "tcp6", "udp", "udp6", NULL + }; + boolean_t istli = B_FALSE; + char *dev; + int i; + + /* global zone: /devices paths */ + dev = strrchr(pr->pr_path, ':'); + /* also check the /dev path for zones */ + if (dev == NULL) + dev = strrchr(pr->pr_path, '/'); + if (dev == NULL) + return (0); + dev++; /* skip past the `:' or '/' */ + + for (i = 0; tlidevs[i] != NULL; i++) { + if (strcmp(dev, tlidevs[i]) == 0) { + istli = B_TRUE; + break; + } + } + if (!istli) + return (0); + } else if (!S_ISSOCK(pr->pr_mode)) { + return (0); + } + + if ((ph = calloc(1, sizeof (proc_fdinfo_t))) == NULL) + fatal(1, "out of memory\n"); + + ph->ph_pid = psinfo->pr_pid; + if (ph->ph_pid > 0) + (void) snprintf(ph->ph_pidstr, PROC_PID_SIZE, "%" PRIu64, + ph->ph_pid); + ph->ph_inode = pr->pr_ino; + ph->ph_fd = pr->pr_fd; + ph->ph_major = pr->pr_rmajor; + ph->ph_mode = pr->pr_mode; + (void) strlcpy(ph->ph_fname, psinfo->pr_fname, sizeof (ph->ph_fname)); + (void) strlcpy(ph->ph_psargs, psinfo->pr_psargs, + sizeof (ph->ph_psargs)); + (void) strlcpy(ph->ph_username, get_username(psinfo->pr_uid), + sizeof (ph->ph_username)); + + if (S_ISSOCK(pr->pr_mode) && Pr != NULL) { + struct sockaddr sa; + socklen_t slen; + int type, tlen; + + /* Determine the socket type */ + tlen = sizeof (type); + if (pr_getsockopt(Pr, pr->pr_fd, SOL_SOCKET, SO_TYPE, &type, + &tlen) == 0) + ph->ph_type = type; + + /* Determine the protocol family */ + slen = sizeof (sa); + if (pr_getsockname(Pr, pr->pr_fd, &sa, &slen) == 0) + ph->ph_family = sa.sa_family; + } + + process_hash_insert(ph); + + return (0); +} + +static void +process_hash_iterate(psinfo_t *psinfo) +{ + char dir_name[PATH_MAX]; + struct dirent *ent; + struct ps_prochandle *ph = NULL; + int err; + + DIR *dirp; + + if (snprintf(dir_name, sizeof (dir_name), "/proc/%d/path", + psinfo->pr_pid) >= sizeof (dir_name)) + return; + dirp = opendir(dir_name); + if (dirp == NULL) + return; + while ((ent = readdir(dirp)) != NULL) { + char path[PATH_MAX]; + struct stat st; + prfdinfo_t info; + int fd, len; + + if (!isdigit(ent->d_name[0])) + continue; + + fd = atoi(ent->d_name); + + if (snprintf(path, sizeof (path), "/proc/%d/fd/%d", + psinfo->pr_pid, fd) >= sizeof (path)) + continue; + if (stat(path, &st) != 0) + continue; + bzero(&info, sizeof (info)); + info.pr_fd = fd; + info.pr_mode = st.st_mode; + info.pr_uid = st.st_uid; + info.pr_gid = st.st_gid; + info.pr_major = major(st.st_dev); + info.pr_minor = minor(st.st_dev); + info.pr_rmajor = major(st.st_rdev); + info.pr_rminor = minor(st.st_rdev); + info.pr_size = st.st_size; + info.pr_ino = st.st_ino; + + len = -1; + switch (info.pr_mode & S_IFMT) { + case S_IFDOOR: + break; + case S_IFSOCK: + /* + * Grab the process so that we can interrogate it + * for further details on the socket. + */ + if (ph == NULL && + (ph = Pgrab(psinfo->pr_pid, + PGRAB_RETAIN | PGRAB_NOSTOP, &err)) == NULL) { + /* unreadable or SYS process */ + if (Xflag) { + printf("Could not grab %d - %s\n", + psinfo->pr_pid, Pgrab_error(err)); + } + } + break; + default: + /* attempt to determine the path */ + if (snprintf(path, sizeof (path), "%s/%d", + dir_name, fd) < sizeof (path)) { + len = readlink(path, info.pr_path, + sizeof (info.pr_path) - 1); + } + break; + } + + if (len <= 0) + len = 0; + info.pr_path[len] = '\0'; + + if (process_hash_iter(psinfo, &info, ph) != 0) + break; + } + (void) closedir(dirp); + + if (ph != NULL) + Prelease(ph, PRELEASE_RETAIN); +} + +static void +process_hash_build(void) +{ + struct dirent *proce; + DIR *proc; + int err; + pid_t me = getpid(); + + if ((proc = opendir("/proc")) == NULL) + return; + + while ((proce = readdir(proc)) != NULL) { + psinfo_t psinfo; + pid_t pid; + + if (!isdigit(proce->d_name[0])) + continue; + + pid = proc_arg_psinfo(proce->d_name, PR_ARG_PIDS, &psinfo, + &err); + if (pid < 0 || pid == me) + continue; + + /* + * We do not use libproc's Pfdinfo_iter() here as it requires + * grabbing the process in read/write mode. Instead, the + * process is grabbed if (and only if) details about an open + * socket need to be retrieved. + */ + process_hash_iterate(&psinfo); + } + (void) closedir(proc); + + if (Xflag) + process_hash_dump(); +} + +static void +process_hash_free(void) +{ + unsigned int i; + + for (i = 0; i < PROC_HASH_SIZE; i++) { + proc_fdinfo_t *ph, *ph_next; + + for (ph = process_table[i]; ph != NULL; ph = ph_next) { + ph_next = ph->ph_next; + free(ph); + } + process_table[i] = NULL; + } +} /* --------------------------------- MIBGET -------------------------------- */ @@ -811,7 +1238,6 @@ mibget(int sd) tor->OPT_length = sizeof (struct opthdr); tor->MGMT_flags = T_CURRENT; - /* * Note: we use the special level value below so that IP will return * us information concerning IRE_MARK_TESTHIDDEN routes. @@ -915,7 +1341,7 @@ mibget(int sd) if (last_item->valp == NULL) goto error_exit; if (Xflag) - (void) printf("msg %d: group = %4d mib_id = %5d" + (void) printf("msg %4d: group = %-4d mib_id = %-5d " "length = %d\n", j, last_item->group, last_item->mib_id, last_item->length); @@ -1091,21 +1517,19 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) return (diffp); } - diffp = (mib_item_t *)calloc(nitems, sizeof (mib_item_t)); + diffp = calloc(nitems, sizeof (mib_item_t)); if (diffp == NULL) return (NULL); diffptr = diffp; - /* 'for' loop 1: */ for (tempp2 = item2; tempp2 != NULL; tempp2 = tempp2->next_item) { if (tempp2->mib_id != 0) - continue; /* 'for' loop 1 */ - /* 'for' loop 2: */ + continue; for (tempp1 = item1; tempp1 != NULL; tempp1 = tempp1->next_item) { if (!(tempp1->mib_id == 0 && tempp1->group == tempp2->group && tempp1->mib_id == tempp2->mib_id)) - continue; /* 'for' loop 2 */ + continue; /* found comparable data sets */ if (prevp != NULL) prevp->next_item = diffptr; @@ -1123,7 +1547,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_ip_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1174,8 +1598,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_ipv6IfStatsEntry_t *)calloc( - tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1226,7 +1649,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (struct mrtstat *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1264,8 +1687,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (struct igmpstat *)calloc( - tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1291,7 +1713,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_icmp_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1340,7 +1762,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_ipv6IfIcmpEntry_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1393,7 +1815,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_tcp_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1460,7 +1882,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_udp_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1481,7 +1903,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_sctp_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1538,7 +1960,7 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) diffptr->group = tempp2->group; diffptr->mib_id = tempp2->mib_id; diffptr->length = tempp2->length; - d = (mib2_rawip_t *)calloc(tempp2->length, 1); + d = calloc(1, tempp2->length); if (d == NULL) goto mibdiff_out_of_memory; diffptr->valp = d; @@ -1555,9 +1977,9 @@ mib_item_diff(mib_item_t *item1, mib_item_t *item2) * required for the -s and -Ms options */ } - } /* 'for' loop 2 ends */ + } tempp1 = NULL; - } /* 'for' loop 1 ends */ + } tempp2 = NULL; diffptr--; diffptr->next_item = NULL; @@ -1828,10 +2250,9 @@ prval_end(void) static void mib_get_constants(mib_item_t *item) { - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (item->mib_id != 0) - continue; /* 'for' loop 1 */ + continue; switch (item->group) { case MIB2_IP: { @@ -1939,7 +2360,7 @@ mib_get_constants(mib_item_t *item) break; } } - } /* 'for' loop 1 ends */ + } if (Xflag) { (void) puts("mib_get_constants:"); @@ -1976,7 +2397,6 @@ mib_get_constants(mib_item_t *item) } } - /* ----------------------------- STAT_REPORT ------------------------------- */ static void @@ -1985,17 +2405,15 @@ stat_report(mib_item_t *item) int jtemp = 0; char ifname[LIFNAMSIZ + 1]; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " + (void) printf("[%4d] Group = %d, mib_id = %d, " "length = %d, valp = 0x%p\n", - item->group, item->mib_id, + jtemp++, item->group, item->mib_id, item->length, item->valp); } if (item->mib_id != 0) - continue; /* 'for' loop 1 */ + continue; switch (item->group) { case MIB2_IP: { @@ -2029,10 +2447,8 @@ stat_report(mib_item_t *item) !(family_selected(AF_INET6))) break; bzero(&sum6, sizeof (sum6)); - /* 'for' loop 2a: */ for (ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp; (char *)ip6 < (char *)item->valp + item->length; - /* LINTED: (note 1) */ ip6 = (mib2_ipv6IfStatsEntry_t *)((char *)ip6 + ipv6IfStatsEntrySize)) { if (ip6->ipv6IfIndex == 0) { @@ -2041,7 +2457,7 @@ stat_report(mib_item_t *item) * mib. Just add to the sum. */ sum_ip6_stats(ip6, &sum6); - continue; /* 'for' loop 2a */ + continue; } if (Aflag) { (void) printf("\nIPv6 for %s\n", @@ -2050,7 +2466,7 @@ stat_report(mib_item_t *item) print_ip6_stats(ip6); } sum_ip6_stats(ip6, &sum6); - } /* 'for' loop 2a ends */ + } (void) fputs("\nIPv6", stdout); print_ip6_stats(&sum6); break; @@ -2063,7 +2479,6 @@ stat_report(mib_item_t *item) !(family_selected(AF_INET6))) break; bzero(&sum6, sizeof (sum6)); - /* 'for' loop 2b: */ for (icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp; (char *)icmp6 < (char *)item->valp + item->length; icmp6 = (void *)((char *)icmp6 + @@ -2074,7 +2489,7 @@ stat_report(mib_item_t *item) * mib. Just add to the sum. */ sum_icmp6_stats(icmp6, &sum6); - continue; /* 'for' loop 2b: */ + continue; } if (Aflag) { (void) printf("\nICMPv6 for %s\n", @@ -2083,7 +2498,7 @@ stat_report(mib_item_t *item) print_icmp6_stats(icmp6); } sum_icmp6_stats(icmp6, &sum6); - } /* 'for' loop 2b ends */ + } (void) fputs("\nICMPv6", stdout); print_icmp6_stats(&sum6); break; @@ -2145,7 +2560,7 @@ stat_report(mib_item_t *item) break; } } - } /* 'for' loop 1 ends */ + } (void) putchar('\n'); (void) fflush(stdout); } @@ -2630,15 +3045,13 @@ mrt_stat_report(mib_item_t *curritem) return; (void) putchar('\n'); - /* 'for' loop 1: */ for (tempitem = curritem; tempitem; tempitem = tempitem->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " + (void) printf("[%4d] Group = %d, mib_id = %d, " "length = %d, valp = 0x%p\n", - tempitem->group, tempitem->mib_id, + jtemp++, tempitem->group, tempitem->mib_id, tempitem->length, tempitem->valp); } @@ -2649,14 +3062,14 @@ mrt_stat_report(mib_item_t *curritem) mrts = (struct mrtstat *)tempitem->valp; if (!(family_selected(AF_INET))) - continue; /* 'for' loop 1 */ + continue; print_mrt_stats(mrts); break; } } } - } /* 'for' loop 1 ends */ + } (void) putchar('\n'); (void) fflush(stdout); } @@ -2693,12 +3106,10 @@ if_report(mib_item_t *item, char *matchname, uint32_t ifindex_v6 = 0; boolean_t first_header = B_TRUE; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } @@ -2707,7 +3118,7 @@ if_report(mib_item_t *item, char *matchname, case MIB2_IP: if (item->mib_id != MIB2_IP_ADDR || !family_selected(AF_INET)) - continue; /* 'for' loop 1 */ + continue; { static struct ifstat old = {0L, 0L, 0L, 0L, 0L}; static struct ifstat new = {0L, 0L, 0L, 0L, 0L}; @@ -2729,7 +3140,6 @@ if_report(mib_item_t *item, char *matchname, (item->length) / sizeof (mib2_ipAddrEntry_t)); - /* 'for' loop 2a: */ for (ap = (mib2_ipAddrEntry_t *)item->valp; (char *)ap < (char *)item->valp + item->length; @@ -2742,7 +3152,7 @@ if_report(mib_item_t *item, char *matchname, if (matchname != NULL && strcmp(matchname, ifname) != 0 && strcmp(matchname, logintname) != 0) - continue; /* 'for' loop 2a */ + continue; new_ifindex = if_nametoindex(logintname); /* @@ -2775,19 +3185,22 @@ if_report(mib_item_t *item, char *matchname, "collisions"); if (first) { if (!first_header) - (void) putchar('\n'); + (void) putchar( + '\n'); first_header = B_FALSE; - (void) printf( - "%-5.5s %-5.5s%-13.13s " - "%-14.14s %-6.6s %-5.5s " - "%-6.6s %-5.5s %-6.6s " - "%-6.6s\n", - "Name", "Mtu", "Net/Dest", - "Address", "Ipkts", - "Ierrs", "Opkts", "Oerrs", - "Collis", "Queue"); - - first = B_FALSE; + (void) printf( + "%-5.5s %-5.5s" + "%-13.13s %-14.14s " + "%-6.6s %-5.5s " + "%-6.6s %-5.5s " + "%-6.6s %-6.6s\n", + "Name", "Mtu", + "Net/Dest", + "Address", "Ipkts", + "Ierrs", "Opkts", + "Oerrs", "Collis", + "Queue"); + first = B_FALSE; } if_report_ip4(ap, ifname, logintname, &stat, B_TRUE); @@ -2796,7 +3209,7 @@ if_report(mib_item_t *item, char *matchname, if_report_ip4(ap, ifname, logintname, &stat, B_FALSE); } - } /* 'for' loop 2a ends */ + } } else if (!alreadydone) { char ifname[LIFNAMSIZ + 1]; char buf[LIFNAMSIZ + 1]; @@ -2819,7 +3232,7 @@ if_report(mib_item_t *item, char *matchname, } /* - * 'for' loop 2b: find the "right" entry: + * 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. @@ -2836,13 +3249,12 @@ if_report(mib_item_t *item, char *matchname, if (matchname) { if (strcmp(matchname, ifname) == 0) { - /* 'for' loop 2b */ found_if = B_TRUE; break; } } else if (strcmp(ifname, "lo0") != 0) - break; /* 'for' loop 2b */ - } /* 'for' loop 2b ends */ + break; + } if (matchname == NULL) { matchname = ifname; @@ -2870,7 +3282,6 @@ if_report(mib_item_t *item, char *matchname, sum = zerostat; - /* 'for' loop 2c: */ for (ap = (mib2_ipAddrEntry_t *)item->valp; (char *)ap < (char *)item->valp + item->length; @@ -2984,7 +3395,7 @@ if_report(mib_item_t *item, char *matchname, } } - } /* 'for' loop 2c ends */ + } *nextnew = NULL; @@ -3019,7 +3430,7 @@ if_report(mib_item_t *item, char *matchname, case MIB2_IP6: if (item->mib_id != MIB2_IP6_ADDR || !family_selected(AF_INET6)) - continue; /* 'for' loop 1 */ + continue; { static struct ifstat old6 = {0L, 0L, 0L, 0L, 0L}; static struct ifstat new6 = {0L, 0L, 0L, 0L, 0L}; @@ -3040,7 +3451,6 @@ if_report(mib_item_t *item, char *matchname, (void) printf("if_report: %d items\n", (item->length) / sizeof (mib2_ipv6AddrEntry_t)); - /* 'for' loop 2d: */ for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp; (char *)ap6 < (char *)item->valp + item->length; @@ -3053,7 +3463,7 @@ if_report(mib_item_t *item, char *matchname, if (matchname != NULL && strcmp(matchname, ifname) != 0 && strcmp(matchname, logintname) != 0) - continue; /* 'for' loop 2d */ + continue; new_ifindex = if_nametoindex(logintname); @@ -3087,7 +3497,8 @@ if_report(mib_item_t *item, char *matchname, "collisions"); if (first) { if (!first_header) - (void) putchar('\n'); + (void) putchar( + '\n'); first_header = B_FALSE; (void) printf( "%-5.5s %-5.5s%" @@ -3109,7 +3520,7 @@ if_report(mib_item_t *item, char *matchname, if_report_ip6(ap6, ifname, logintname, &stat, B_FALSE); } - } /* 'for' loop 2d ends */ + } } else if (!alreadydone) { char ifname[LIFNAMSIZ + 1]; char buf[IFNAMSIZ + 1]; @@ -3132,7 +3543,7 @@ if_report(mib_item_t *item, char *matchname, } /* - * 'for' loop 2e: find the "right" entry: + * 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. @@ -3149,13 +3560,12 @@ if_report(mib_item_t *item, char *matchname, if (matchname) { if (strcmp(matchname, ifname) == 0) { - /* 'for' loop 2e */ found_if = B_TRUE; break; } } else if (strcmp(ifname, "lo0") != 0) - break; /* 'for' loop 2e */ - } /* 'for' loop 2e ends */ + break; + } if (matchname == NULL) { matchname = ifname; @@ -3184,7 +3594,6 @@ if_report(mib_item_t *item, char *matchname, sum6 = zerostat; - /* 'for' loop 2f: */ for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp; (char *)ap6 < (char *)item->valp + item->length; @@ -3299,7 +3708,7 @@ if_report(mib_item_t *item, char *matchname, } } - } /* 'for' loop 2f ends */ + } *nextnew = NULL; @@ -3333,7 +3742,7 @@ if_report(mib_item_t *item, char *matchname, } } (void) fflush(stdout); - } /* 'for' loop 1 ends */ + } if ((Iflag_only == 0) && (!once_only)) (void) putchar('\n'); reentry = B_TRUE; @@ -3581,13 +3990,11 @@ group_report(mib_item_t *item) ipv6_grpsrc_t *ips6; boolean_t first, first_src; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " + (void) printf("[%4d] Group = %d, mib_id = %d, " "length = %d, valp = 0x%p\n", - item->group, item->mib_id, item->length, + jtemp++, item->group, item->mib_id, item->length, item->valp); } if (item->group == MIB2_IP && family_selected(AF_INET)) { @@ -3633,7 +4040,6 @@ group_report(mib_item_t *item) first = B_TRUE; for (ipmp = (ip_member_t *)v4grp->valp; (char *)ipmp < (char *)v4grp->valp + v4grp->length; - /* LINTED: (note 1) */ ipmp = (ip_member_t *)((char *)ipmp + ipMemberEntrySize)) { if (first) { (void) puts(v4compat ? @@ -3653,7 +4059,6 @@ group_report(mib_item_t *item) abuf, sizeof (abuf)), ipmp->ipGroupMemberRefCnt); - if (!Vflag || v4src == NULL) continue; @@ -3665,7 +4070,6 @@ group_report(mib_item_t *item) first_src = B_TRUE; for (ips = (ip_grpsrc_t *)v4src->valp; (char *)ips < (char *)v4src->valp + v4src->length; - /* LINTED: (note 1) */ ips = (ip_grpsrc_t *)((char *)ips + ipGroupSourceEntrySize)) { /* @@ -3709,7 +4113,6 @@ group_report(mib_item_t *item) first = B_TRUE; for (ipmp6 = (ipv6_member_t *)v6grp->valp; (char *)ipmp6 < (char *)v6grp->valp + v6grp->length; - /* LINTED: (note 1) */ ipmp6 = (ipv6_member_t *)((char *)ipmp6 + ipv6MemberEntrySize)) { if (first) { @@ -3739,7 +4142,6 @@ group_report(mib_item_t *item) first_src = B_TRUE; for (ips6 = (ipv6_grpsrc_t *)v6src->valp; (char *)ips6 < (char *)v6src->valp + v6src->length; - /* LINTED: (note 1) */ ips6 = (ipv6_grpsrc_t *)((char *)ips6 + ipv6GroupSourceEntrySize)) { /* same assumption as in the v4 case above */ @@ -3810,12 +4212,10 @@ dce_report(mib_item_t *item) boolean_t first; dest_cache_entry_t *dce; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } @@ -3841,7 +4241,6 @@ dce_report(mib_item_t *item) first = B_TRUE; for (dce = (dest_cache_entry_t *)v4dce->valp; (char *)dce < (char *)v4dce->valp + v4dce->length; - /* LINTED: (note 1) */ dce = (dest_cache_entry_t *)((char *)dce + ipDestEntrySize)) { if (first) { @@ -3869,7 +4268,6 @@ dce_report(mib_item_t *item) first = B_TRUE; for (dce = (dest_cache_entry_t *)v6dce->valp; (char *)dce < (char *)v6dce->valp + v6dce->length; - /* LINTED: (note 1) */ dce = (dest_cache_entry_t *)((char *)dce + ipDestEntrySize)) { if (first) { @@ -3914,17 +4312,15 @@ arp_report(mib_item_t *item) if (!(family_selected(AF_INET))) return; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } if (!(item->group == MIB2_IP && item->mib_id == MIB2_IP_MEDIA)) - continue; /* 'for' loop 1 */ + continue; if (Xflag) (void) printf("%u records for " @@ -3932,10 +4328,8 @@ arp_report(mib_item_t *item) item->length/sizeof (mib2_ipNetToMediaEntry_t)); first = B_TRUE; - /* 'for' loop 2: */ for (np = (mib2_ipNetToMediaEntry_t *)item->valp; (char *)np < (char *)item->valp + item->length; - /* LINTED: (note 1) */ np = (mib2_ipNetToMediaEntry_t *)((char *)np + ipNetToMediaEntrySize)) { if (first) { @@ -3987,8 +4381,8 @@ arp_report(mib_item_t *item) flbuf, octetstr(&np->ipNetToMediaPhysAddress, 'h', xbuf, sizeof (xbuf))); - } /* 'for' loop 2 ends */ - } /* 'for' loop 1 ends */ + } + } (void) fflush(stdout); } @@ -4009,7 +4403,6 @@ ndp_report(mib_item_t *item) if (!(family_selected(AF_INET6))) return; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { (void) printf("\n--- Entry %d ---\n", ++jtemp); @@ -4020,13 +4413,11 @@ ndp_report(mib_item_t *item) } if (!(item->group == MIB2_IP6 && item->mib_id == MIB2_IP6_MEDIA)) - continue; /* 'for' loop 1 */ + continue; first = B_TRUE; - /* 'for' loop 2: */ for (np6 = (mib2_ipv6NetToMediaEntry_t *)item->valp; (char *)np6 < (char *)item->valp + item->length; - /* LINTED: (note 1) */ np6 = (mib2_ipv6NetToMediaEntry_t *)((char *)np6 + ipv6NetToMediaEntrySize)) { if (first) { @@ -4075,6 +4466,8 @@ ndp_report(mib_item_t *item) case 4: type = "local"; break; + default: + type = "UNKNOWN"; } (void) printf("%-5s %-17s %-7s %-12s %-27s\n", ifindex2str(np6->ipv6NetToMediaIfIndex, ifname), @@ -4084,8 +4477,8 @@ ndp_report(mib_item_t *item) state, pr_addr6(&np6->ipv6NetToMediaNetAddress, abuf, sizeof (abuf))); - } /* 'for' loop 2 ends */ - } /* 'for' loop 1 ends */ + } + } (void) putchar('\n'); (void) fflush(stdout); } @@ -4173,7 +4566,6 @@ ire_report(const mib_item_t *item) } for (iae = iptr->valp; (char *)iae < (char *)iptr->valp + iptr->length; - /* LINTED: (note 1) */ iae = (mib2_ipAttributeEntry_t *)((char *)iae + ipRouteAttributeSize)) { aptr->sal_next = alp[iae->iae_routeidx]; @@ -4182,14 +4574,12 @@ ire_report(const mib_item_t *item) } } - /* 'for' loop 1: */ v4a = v4_attrs; v6a = v6_attrs; for (; item != NULL; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } @@ -4197,12 +4587,12 @@ ire_report(const mib_item_t *item) item->mib_id == MIB2_IP_ROUTE) || (item->group == MIB2_IP6 && item->mib_id == MIB2_IP6_ROUTE))) - continue; /* 'for' loop 1 */ + continue; if (item->group == MIB2_IP && !family_selected(AF_INET)) - continue; /* 'for' loop 1 */ + continue; else if (item->group == MIB2_IP6 && !family_selected(AF_INET6)) - continue; /* 'for' loop 1 */ + continue; if (Xflag) { if (item->group == MIB2_IP) { @@ -4220,7 +4610,6 @@ ire_report(const mib_item_t *item) if (item->group == MIB2_IP) { for (rp = (mib2_ipRouteEntry_t *)item->valp; (char *)rp < (char *)item->valp + item->length; - /* LINTED: (note 1) */ rp = (mib2_ipRouteEntry_t *)((char *)rp + ipRouteEntrySize)) { aptr = v4a == NULL ? NULL : *v4a++; @@ -4230,7 +4619,6 @@ ire_report(const mib_item_t *item) } else { for (rp6 = (mib2_ipv6RouteEntry_t *)item->valp; (char *)rp6 < (char *)item->valp + item->length; - /* LINTED: (note 1) */ rp6 = (mib2_ipv6RouteEntry_t *)((char *)rp6 + ipv6RouteEntrySize)) { aptr = v6a == NULL ? NULL : *v6a++; @@ -4238,7 +4626,7 @@ ire_report(const mib_item_t *item) print_hdr_once_v6, aptr); } } - } /* 'for' loop 1 ends */ + } (void) fflush(stdout); ire_report_done: if (v4_attrs != NULL) @@ -4305,9 +4693,7 @@ v4_addr_match(IpAddress addr, IpAddress mask, const filter_t *fp) mask = fmask; } for (app = fp->u.a.f_address->h_addr_list; (aptr = *app) != NULL; app++) - /* LINTED: (note 1) */ if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) { - /* LINTED: (note 1) */ IN6_V4MAPPED_TO_IPADDR((in6_addr_t *)aptr, faddr); if (((faddr ^ addr) & mask) == 0) return (B_TRUE); @@ -4327,39 +4713,36 @@ ire_filter_match_v4(const mib2_ipRouteEntry_t *rp, uint_t flag_b) filter_t *fp; int idx; - /* 'for' loop 1: */ for (idx = 0; idx < NFILTERKEYS; idx++) if ((fp = filters[idx]) != NULL) { - /* 'for' loop 2: */ for (; fp != NULL; fp = fp->f_next) { switch (idx) { case FK_AF: if (fp->u.f_family != AF_INET) - continue; /* 'for' loop 2 */ + continue; break; case FK_OUTIF: if (!dev_name_match(&rp->ipRouteIfIndex, fp->u.f_ifname)) - continue; /* 'for' loop 2 */ + continue; break; case FK_DST: if (!v4_addr_match(rp->ipRouteDest, rp->ipRouteMask, fp)) - continue; /* 'for' loop 2 */ + continue; break; case FK_FLAGS: if ((flag_b & fp->u.f.f_flagset) != fp->u.f.f_flagset || (flag_b & fp->u.f.f_flagclear)) - continue; /* 'for' loop 2 */ + continue; break; } break; - } /* 'for' loop 2 ends */ + } if (fp == NULL) return (B_FALSE); } - /* 'for' loop 1 ends */ return (B_TRUE); } @@ -4425,20 +4808,74 @@ form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags) return (flag_b); } +/* + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define IRE_V4_DEST " Destination " +#define IRE_V4_DEST_ "--------------------" +#define IRE_V4_DEST_F "%-20s" +#define IRE_V4_MASK " Mask " +#define IRE_V4_MASK_ "---------------" +#define IRE_V4_MASK_F "%-15s" +#define IRE_V4_GATEWAY " Gateway " +#define IRE_V4_GATEWAY_ "--------------------" +#define IRE_V4_GATEWAY_F "%-20s" +#define IRE_V4_DEVICE "Device" +#define IRE_V4_DEVICE_ "------" +#define IRE_V4_DEVICE_F "%-6s" +#define IRE_V4_MTU " MTU " +#define IRE_V4_MTU_ "-----" +#define IRE_V4_MTU_F "%5u" +#define IRE_V4_REF "Ref" +#define IRE_V4_REF_ "---" +#define IRE_V4_REF_F "%3u" +#define IRE_V4_FLAGS "Flg" +#define IRE_V4_FLAGS_ "---" +#define IRE_V4_FLAGS_F "%-4s" +#define IRE_V4_OUT " Out " +#define IRE_V4_OUT_ "------" +#define IRE_V4_OUT_F "%-6s" +#define IRE_V4_INFWD "In/Fwd" +#define IRE_V4_INFWD_ "------" +#define IRE_V4_INFWD_F "%6u" +#define IRE_V4_LFLAGS "Flags" +#define IRE_V4_LFLAGS_ "-----" +#define IRE_V4_LFLAGS_F "%-5s" +#define IRE_V4_LREF " Ref " +#define IRE_V4_LREF_ "-----" +#define IRE_V4_LREF_F " %4u" +#define IRE_V4_USE " Use " +#define IRE_V4_USE_ "----------" +#define IRE_V4_USE_F "%10u" +#define IRE_V4_INTERFACE "Interface" +#define IRE_V4_INTERFACE_ "---------" +#define IRE_V4_INTERFACE_F "%-9s" + 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 " -" MTU Ref Flg Out In/Fwd %s\n" -"-------------------- --------------- -------------------- ------ " -"----- --- --- ----- ------ %s\n"; + IRE_V4_DEST " " IRE_V4_MASK " " IRE_V4_GATEWAY " " IRE_V4_DEVICE " " + IRE_V4_MTU " " IRE_V4_REF " " IRE_V4_FLAGS " " + IRE_V4_OUT " " IRE_V4_INFWD " %s\n" + IRE_V4_DEST_" " IRE_V4_MASK_" " IRE_V4_GATEWAY_" " IRE_V4_DEVICE_" " + IRE_V4_MTU_" " IRE_V4_REF_" " IRE_V4_FLAGS_" " + IRE_V4_OUT_" " IRE_V4_INFWD_" %s\n"; static const char ire_hdr_v4_normal[] = -" Destination Gateway Flags Ref Use Interface" -" %s\n-------------------- -------------------- ----- ----- ---------- " -"--------- %s\n"; + IRE_V4_DEST " " IRE_V4_GATEWAY " " + IRE_V4_LFLAGS " " IRE_V4_LREF " " IRE_V4_USE " " + IRE_V4_INTERFACE " %s\n" + IRE_V4_DEST_" " IRE_V4_GATEWAY_" " + IRE_V4_LFLAGS_" " IRE_V4_LREF_" " IRE_V4_USE_" " + IRE_V4_INTERFACE_" %s\n"; static boolean_t ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first, @@ -4480,8 +4917,10 @@ ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first, dstbuf, sizeof (dstbuf)); } if (Vflag) { - (void) printf("%-20s %-15s %-20s %-6s %5u %3u " - "%-4s%6u %6u %s\n", + (void) printf( + IRE_V4_DEST_F " " IRE_V4_MASK_F " " IRE_V4_GATEWAY_F " " + IRE_V4_DEVICE_F " " IRE_V4_MTU_F " " IRE_V4_REF_F " " + IRE_V4_FLAGS_F IRE_V4_INFWD_F " " IRE_V4_INFWD_F " %s\n", dstbuf, pr_mask(rp->ipRouteMask, maskbuf, sizeof (maskbuf)), pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)), @@ -4493,7 +4932,10 @@ ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first, rp->ipRouteInfo.re_ibpkt, pr_secattr(attrs)); } else { - (void) printf("%-20s %-20s %-5s %4u %10u %-9s %s\n", + (void) printf( + IRE_V4_DEST_F " " IRE_V4_GATEWAY_F " " + IRE_V4_LFLAGS_F " " IRE_V4_LREF_F " " + IRE_V4_USE_F " " IRE_V4_INTERFACE_F " %s\n", dstbuf, pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)), flags, @@ -4530,36 +4972,33 @@ v6_addr_match(const Ip6Address *addr, int masklen, const filter_t *fp) return (IN6_IS_ADDR_UNSPECIFIED(addr)); /* "none" */ } fmasklen = 0; - /* 'for' loop 1a: */ for (ucp = fp->u.a.f_mask.s6_addr; ucp < fp->u.a.f_mask.s6_addr + sizeof (fp->u.a.f_mask.s6_addr); ucp++) { if (*ucp != 0xff) { if (*ucp != 0) fmasklen += 9 - ffs(*ucp); - break; /* 'for' loop 1a */ + break; } fmasklen += 8; - } /* 'for' loop 1a ends */ + } if (fmasklen != IPV6_ABITS) { if (fmasklen > masklen) return (B_FALSE); masklen = fmasklen; } - /* 'for' loop 1b: */ for (app = fp->u.a.f_address->h_addr_list; (aptr = (uint8_t *)*app) != NULL; app++) { - /* LINTED: (note 1) */ if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) - continue; /* 'for' loop 1b */ + continue; ucp = addr->s6_addr; for (i = masklen; i >= 8; i -= 8) if (*ucp++ != *aptr++) - break; /* 'for' loop 1b */ + break; if (i == 0 || (i < 8 && ((*ucp ^ *aptr) & ~(0xff >> i)) == 0)) return (B_TRUE); - } /* 'for' loop 1b ends */ + } return (B_FALSE); } @@ -4576,43 +5015,36 @@ ire_filter_match_v6(const mib2_ipv6RouteEntry_t *rp6, uint_t flag_b) filter_t *fp; int idx; - /* 'for' loop 1: */ for (idx = 0; idx < NFILTERKEYS; idx++) if ((fp = filters[idx]) != NULL) { - /* 'for' loop 2: */ for (; fp != NULL; fp = fp->f_next) { switch (idx) { case FK_AF: if (fp->u.f_family != AF_INET6) - /* 'for' loop 2 */ continue; break; case FK_OUTIF: if (!dev_name_match(&rp6-> ipv6RouteIfIndex, fp->u.f_ifname)) - /* 'for' loop 2 */ continue; break; case FK_DST: if (!v6_addr_match(&rp6->ipv6RouteDest, rp6->ipv6RoutePfxLength, fp)) - /* 'for' loop 2 */ continue; break; case FK_FLAGS: if ((flag_b & fp->u.f.f_flagset) != fp->u.f.f_flagset || (flag_b & fp->u.f.f_flagclear)) - /* 'for' loop 2 */ continue; break; } break; - } /* 'for' loop 2 ends */ + } if (fp == NULL) return (B_FALSE); } - /* 'for' loop 1 ends */ return (B_TRUE); } @@ -4676,18 +5108,54 @@ form_v6_route_flags(const mib2_ipv6RouteEntry_t *rp6, char *flags) return (flag_b); } +/* + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define IRE_V6_DEST " Destination/Mask " +#define IRE_V6_DEST_ "---------------------------" +#define IRE_V6_DEST_F "%-27s" +#define IRE_V6_GATEWAY " Gateway " +#define IRE_V6_GATEWAY_ "---------------------------" +#define IRE_V6_GATEWAY_F "%-27s" +#define IRE_V6_IF " If " +#define IRE_V6_IF_ "-----" +#define IRE_V6_IF_F "%-5s" +#define IRE_V6_MTU " MTU " +#define IRE_V6_MTU_ "-----" +#define IRE_V6_MTU_F "%5u" +#define IRE_V6_REF "Ref" +#define IRE_V6_REF_ "---" +#define IRE_V6_REF_F "%3u" +#define IRE_V6_USE " Use " +#define IRE_V6_USE_ "-------" +#define IRE_V6_USE_F "%7u" +#define IRE_V6_FLAGS "Flags" +#define IRE_V6_FLAGS_ "-----" +#define IRE_V6_FLAGS_F "%-5s" +#define IRE_V6_OUT " Out " +#define IRE_V6_OUT_ "------" +#define IRE_V6_OUT_F "%6u" +#define IRE_V6_INFWD "In/Fwd" +#define IRE_V6_INFWD_ "------" +#define IRE_V6_INFWD_F "%6u" + static const char ire_hdr_v6[] = "\n%s Table: IPv6\n"; static const char ire_hdr_v6_verbose[] = -" Destination/Mask Gateway If MTU " -"Ref Flags Out In/Fwd %s\n" -"--------------------------- --------------------------- ----- ----- " -"--- ----- ------ ------ %s\n"; + IRE_V6_DEST " " IRE_V6_GATEWAY " " IRE_V6_IF " " IRE_V6_MTU " " + IRE_V6_REF " " IRE_V6_FLAGS " " IRE_V6_OUT " " IRE_V6_INFWD " %s\n" + IRE_V6_DEST_" " IRE_V6_GATEWAY_" " IRE_V6_IF_" " IRE_V6_MTU_" " + IRE_V6_REF_" " IRE_V6_FLAGS_" " IRE_V6_OUT_" " IRE_V6_INFWD_" %s\n"; static const char ire_hdr_v6_normal[] = -" Destination/Mask Gateway Flags Ref Use " -" If %s\n" -"--------------------------- --------------------------- ----- --- ------- " -"----- %s\n"; + IRE_V6_DEST " " IRE_V6_GATEWAY " " + IRE_V6_FLAGS " " IRE_V6_REF " " IRE_V6_USE " " IRE_V6_IF " %s\n" + IRE_V6_DEST_" " IRE_V6_GATEWAY_" " + IRE_V6_FLAGS_" " IRE_V6_REF_" " IRE_V6_USE_" " IRE_V6_IF_" %s\n"; static boolean_t ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first, @@ -4720,8 +5188,10 @@ ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first, } if (Vflag) { - (void) printf("%-27s %-27s %-5s %5u %3u " - "%-5s %6u %6u %s\n", + (void) printf( + IRE_V6_DEST_F " " IRE_V6_GATEWAY_F " " + IRE_V6_IF_F " " IRE_V6_MTU_F " " IRE_V6_REF_F " " + IRE_V6_FLAGS_F " " IRE_V6_OUT_F " " IRE_V6_INFWD_F " %s\n", pr_prefix6(&rp6->ipv6RouteDest, rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)), IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ? @@ -4736,7 +5206,10 @@ ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first, rp6->ipv6RouteInfo.re_ibpkt, pr_secattr(attrs)); } else { - (void) printf("%-27s %-27s %-5s %3u %7u %-5s %s\n", + (void) printf( + IRE_V6_DEST_F " " IRE_V6_GATEWAY_F " " + IRE_V6_FLAGS_F " " IRE_V6_REF_F " " + IRE_V6_USE_F " " IRE_V6_IF_F " %s\n", pr_prefix6(&rp6->ipv6RouteDest, rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)), IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ? @@ -4758,26 +5231,36 @@ ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first, static mib2_transportMLPEntry_t ** gather_attrs(const mib_item_t *item, int group, int mib_id, int esize) { - int transport_count = 0; + size_t transport_count = 0; const mib_item_t *iptr; mib2_transportMLPEntry_t **attrs, *tme; for (iptr = item; iptr != NULL; iptr = iptr->next_item) { - if (iptr->group == group && iptr->mib_id == mib_id) - transport_count += iptr->length / esize; + if (iptr->group == group && iptr->mib_id == mib_id) { + size_t els = iptr->length / esize; + if (transport_count > SIZE_MAX - els) { + fprintf(stderr, "Connection table too large\n"); + return (NULL); + } else { + transport_count += els; + } + } } - if (transport_count <= 0) + + if (transport_count == 0) return (NULL); - attrs = calloc(transport_count, sizeof (*attrs)); + + attrs = recallocarray(NULL, 0, transport_count, sizeof (*attrs)); + if (attrs == NULL) { - perror("gather_attrs calloc failed"); + perror("gather_attrs allocation failed"); return (NULL); } + for (iptr = item; iptr != NULL; iptr = iptr->next_item) { if (iptr->group == group && iptr->mib_id == EXPER_XPORT_MLP) { for (tme = iptr->valp; (char *)tme < (char *)iptr->valp + iptr->length; - /* LINTED: (note 1) */ tme = (mib2_transportMLPEntry_t *)((char *)tme + transportMLPSize)) { attrs[tme->tme_connidx] = tme; @@ -4788,6 +5271,89 @@ gather_attrs(const mib_item_t *item, int group, int mib_id, int esize) } static void +sie_report(const mib2_socketInfoEntry_t *sie) +{ + if (sie == NULL) + return; + + (void) printf("INFO[%" PRIu64 "] = " + "inode %" PRIu64 ", " + "major %" PRIx32 ", " + "flags %#" PRIx64 "\n", + sie->sie_connidx, sie->sie_inode, + major((dev_t)sie->sie_dev), sie->sie_flags); +} + +/* + * Common info-gathering routine for all transports. + * + * The linked list of MIB data pointed to by item consists of a number of + * tables covering several protocol families and socket types, one after + * another. These are generally tables containing information about network + * connections, such as mib2_tcpConnEntry, as defined in RFC 1213/4022. + * + * There are also ancilliary tables which contain optional additional + * information about each socket. The data in these ancilliary tables is + * indexed by the table position of the connection to which it relates, and + * data may not be available for all connections. + * + * The code here determines the size of the connection table, allocates an + * array of that size to hold the ancilliary data and then fills that in + * if data is present. + * + * As an example, if the data contains a mib2_tcpConnEntry table containing + * three connections, but there is no ancilliary data for the second, then + * the accompanying mib2_socketInfoEntry table will only contain two entries. + * However, the first entry is tagged as referring to connection slot 0, and + * the second is tagged with connection slot 2. + * This function would return an array with: + * { <data for conn0>, NULL, <data for conn2> } + * + */ +static mib2_socketInfoEntry_t ** +gather_info(const mib_item_t *item, int group, int mib_id, int esize) +{ + size_t transport_count = 0; + const mib_item_t *iptr; + mib2_socketInfoEntry_t **info, *sie; + + for (iptr = item; iptr != NULL; iptr = iptr->next_item) { + if (iptr->group == group && iptr->mib_id == mib_id) { + size_t els = iptr->length / esize; + if (transport_count > SIZE_MAX - els) { + fprintf(stderr, "Connection table too large\n"); + return (NULL); + } else { + transport_count += els; + } + } + } + + if (transport_count == 0) + return (NULL); + + info = recallocarray(NULL, 0, transport_count, sizeof (*info)); + + if (info == NULL) { + perror("gather_info allocation failed"); + return (NULL); + } + + for (iptr = item; iptr != NULL; iptr = iptr->next_item) { + if (iptr->group != group || iptr->mib_id != EXPER_SOCK_INFO) + continue; + + for (sie = (mib2_socketInfoEntry_t *)iptr->valp; + (uintptr_t)sie < (uintptr_t)iptr->valp + iptr->length; + sie++) { + assert(sie->sie_connidx < transport_count); + info[sie->sie_connidx] = sie; + } + } + return (info); +} + +static void print_transport_label(const mib2_transportMLPEntry_t *attr) { if (!RSECflag || attr == NULL || @@ -4811,55 +5377,226 @@ 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[] = -"Local/Remote Address Swind Snext Suna Rwind Rnext Rack " -" Rto Mss State\n" -"-------------------- ----- -------- -------- ----- -------- -------- " -"----- ----- -----------\n"; + +/* + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define TCP_V4_LOCAL " Local Address " +#define TCP_V4_LOCAL_ "--------------------" +#define TCP_V4_LOCAL_F "%-20s" +#define TCP_V4_REMOTE " Remote Address " +#define TCP_V4_REMOTE_ "--------------------" +#define TCP_V4_REMOTE_F "%-20s" +#define TCP_V4_ADDRESS "Local/Remote Address" +#define TCP_V4_ADDRESS_ "--------------------" +#define TCP_V4_ADDRESS_F "%-20s" +#define TCP_V4_SWIND "Swind " +#define TCP_V4_SWIND_ "------" +#define TCP_V4_SWIND_F "%6u" +#define TCP_V4_SENDQ "Send-Q" +#define TCP_V4_SENDQ_ "------" +#define TCP_V4_SENDQ_F "%6" PRId64 +#define TCP_V4_RWIND "Rwind " +#define TCP_V4_RWIND_ "------" +#define TCP_V4_RWIND_F "%6u" +#define TCP_V4_RECVQ "Recv-Q" +#define TCP_V4_RECVQ_ "------" +#define TCP_V4_RECVQ_F "%6" PRId64 +#define TCP_V4_SNEXT " Snext " +#define TCP_V4_SNEXT_ "--------" +#define TCP_V4_SNEXT_F "%08x" +#define TCP_V4_SUNA " Suna " +#define TCP_V4_SUNA_ "--------" +#define TCP_V4_SUNA_F "%08x" +#define TCP_V4_RNEXT " Rnext " +#define TCP_V4_RNEXT_ "--------" +#define TCP_V4_RNEXT_F "%08x" +#define TCP_V4_RACK " Rack " +#define TCP_V4_RACK_ "--------" +#define TCP_V4_RACK_F "%08x" +#define TCP_V4_RTO " Rto " +#define TCP_V4_RTO_ "-----" +#define TCP_V4_RTO_F "%5u" +#define TCP_V4_MSS " Mss " +#define TCP_V4_MSS_ "-----" +#define TCP_V4_MSS_F "%5u" +#define TCP_V4_STATE " State " +#define TCP_V4_STATE_ "-----------" +#define TCP_V4_STATE_F "%-11s" +#define TCP_V4_USER " User " +#define TCP_V4_USER_ "--------" +#define TCP_V4_USER_F "%-8.8s" +#define TCP_V4_PID " Pid " +#define TCP_V4_PID_ "------" +#define TCP_V4_PID_F "%6s" +#define TCP_V4_COMMAND " Command " +#define TCP_V4_COMMAND_ "--------------" +#define TCP_V4_COMMAND_F "%-14.14s" + static const char tcp_hdr_v4_normal[] = -" Local Address Remote Address Swind Send-Q Rwind Recv-Q " -" State\n" -"-------------------- -------------------- ----- ------ ----- ------ " -"-----------\n"; + TCP_V4_LOCAL " " TCP_V4_REMOTE " " + TCP_V4_SWIND " " TCP_V4_SENDQ " " TCP_V4_RWIND " " TCP_V4_RECVQ " " + TCP_V4_STATE "\n" + TCP_V4_LOCAL_" " TCP_V4_REMOTE_" " + TCP_V4_SWIND_" " TCP_V4_SENDQ_" " TCP_V4_RWIND_" " TCP_V4_RECVQ_" " + TCP_V4_STATE_"\n"; +static const char tcp_hdr_v4_normal_pid[] = + TCP_V4_LOCAL " " TCP_V4_REMOTE " " + TCP_V4_USER " " TCP_V4_PID " " TCP_V4_COMMAND " " + TCP_V4_SWIND " " TCP_V4_SENDQ " " TCP_V4_RWIND " " TCP_V4_RECVQ " " + TCP_V4_STATE "\n" + TCP_V4_LOCAL_" " TCP_V4_REMOTE_" " + TCP_V4_USER_" " TCP_V4_PID_" " TCP_V4_COMMAND_" " + TCP_V4_SWIND_" " TCP_V4_SENDQ_" " TCP_V4_RWIND_" " TCP_V4_RECVQ_" " + TCP_V4_STATE_"\n"; +static const char tcp_hdr_v4_verbose[] = + TCP_V4_ADDRESS " " + TCP_V4_SWIND " " TCP_V4_SNEXT " " TCP_V4_SUNA " " + TCP_V4_RWIND " " TCP_V4_RNEXT " " TCP_V4_RACK " " + TCP_V4_RTO " " TCP_V4_MSS " " TCP_V4_STATE "\n" + TCP_V4_ADDRESS_" " + TCP_V4_SWIND_" " TCP_V4_SNEXT_" " TCP_V4_SUNA_" " + TCP_V4_RWIND_" " TCP_V4_RNEXT_" " TCP_V4_RACK_" " + TCP_V4_RTO_" " TCP_V4_MSS_" " TCP_V4_STATE_"\n"; +static const char tcp_hdr_v4_verbose_pid[] = + TCP_V4_ADDRESS " " + TCP_V4_SWIND " " TCP_V4_SNEXT " " TCP_V4_SUNA " " + TCP_V4_RWIND " " TCP_V4_RNEXT " " TCP_V4_RACK " " + TCP_V4_RTO " " TCP_V4_MSS " " TCP_V4_STATE " " + TCP_V4_USER " " TCP_V4_PID " " TCP_V4_COMMAND "\n" + TCP_V4_ADDRESS_" " + TCP_V4_SWIND_" " TCP_V4_SNEXT_" " TCP_V4_SUNA_" " + TCP_V4_RWIND_" " TCP_V4_RNEXT_" " TCP_V4_RACK_" " + TCP_V4_RTO_" " TCP_V4_MSS_" " TCP_V4_STATE_" " + TCP_V4_USER_" " TCP_V4_PID_" " TCP_V4_COMMAND_"\n"; + +#define TCP_V6_LOCAL " Local Address " +#define TCP_V6_LOCAL_ "---------------------------------" +#define TCP_V6_LOCAL_F "%-33s" +#define TCP_V6_REMOTE " Remote Address " +#define TCP_V6_REMOTE_ "---------------------------------" +#define TCP_V6_REMOTE_F "%-33s" +#define TCP_V6_ADDRESS "Local/Remote Address " +#define TCP_V6_ADDRESS_ "---------------------------------" +#define TCP_V6_ADDRESS_F "%-33s" +#define TCP_V6_IF " If " +#define TCP_V6_IF_ "-----" +#define TCP_V6_IF_F "%-5.5s" +#define TCP_V6_SWIND TCP_V4_SWIND +#define TCP_V6_SWIND_ TCP_V4_SWIND_ +#define TCP_V6_SWIND_F TCP_V4_SWIND_F +#define TCP_V6_SENDQ TCP_V4_SENDQ +#define TCP_V6_SENDQ_ TCP_V4_SENDQ_ +#define TCP_V6_SENDQ_F TCP_V4_SENDQ_F +#define TCP_V6_RWIND TCP_V4_RWIND +#define TCP_V6_RWIND_ TCP_V4_RWIND_ +#define TCP_V6_RWIND_F TCP_V4_RWIND_F +#define TCP_V6_RECVQ TCP_V4_RECVQ +#define TCP_V6_RECVQ_ TCP_V4_RECVQ_ +#define TCP_V6_RECVQ_F TCP_V4_RECVQ_F +#define TCP_V6_SNEXT TCP_V4_SNEXT +#define TCP_V6_SNEXT_ TCP_V4_SNEXT_ +#define TCP_V6_SNEXT_F TCP_V4_SNEXT_F +#define TCP_V6_SUNA TCP_V4_SUNA +#define TCP_V6_SUNA_ TCP_V4_SUNA_ +#define TCP_V6_SUNA_F TCP_V4_SUNA_F +#define TCP_V6_RNEXT TCP_V4_RNEXT +#define TCP_V6_RNEXT_ TCP_V4_RNEXT_ +#define TCP_V6_RNEXT_F TCP_V4_RNEXT_F +#define TCP_V6_RACK TCP_V4_RACK +#define TCP_V6_RACK_ TCP_V4_RACK_ +#define TCP_V6_RACK_F TCP_V4_RACK_F +#define TCP_V6_RTO TCP_V4_RTO +#define TCP_V6_RTO_ TCP_V4_RTO_ +#define TCP_V6_RTO_F TCP_V4_RTO_F +#define TCP_V6_MSS TCP_V4_MSS +#define TCP_V6_MSS_ TCP_V4_MSS_ +#define TCP_V6_MSS_F TCP_V4_MSS_F +#define TCP_V6_STATE TCP_V4_STATE +#define TCP_V6_STATE_ TCP_V4_STATE_ +#define TCP_V6_STATE_F TCP_V4_STATE_F +#define TCP_V6_USER TCP_V4_USER +#define TCP_V6_USER_ TCP_V4_USER_ +#define TCP_V6_USER_F TCP_V4_USER_F +#define TCP_V6_PID TCP_V4_PID +#define TCP_V6_PID_ TCP_V4_PID_ +#define TCP_V6_PID_F TCP_V4_PID_F +#define TCP_V6_COMMAND TCP_V4_COMMAND +#define TCP_V6_COMMAND_ TCP_V4_COMMAND_ +#define TCP_V6_COMMAND_F TCP_V4_COMMAND_F static const char tcp_hdr_v6[] = "\nTCP: IPv6\n"; -static const char tcp_hdr_v6_verbose[] = -"Local/Remote Address Swind Snext Suna Rwind Rnext " -" 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"; + TCP_V6_LOCAL " " TCP_V6_REMOTE " " + TCP_V6_SWIND " " TCP_V6_SENDQ " " TCP_V6_RWIND " " TCP_V6_RECVQ " " + TCP_V6_STATE " " TCP_V6_IF "\n" + TCP_V6_LOCAL_" " TCP_V6_REMOTE_" " + TCP_V6_SWIND_" " TCP_V6_SENDQ_" " TCP_V6_RWIND_" " TCP_V6_RECVQ_" " + TCP_V6_STATE_" " TCP_V6_IF_"\n"; +static const char tcp_hdr_v6_normal_pid[] = + TCP_V6_LOCAL " " TCP_V6_REMOTE " " + TCP_V6_USER " " TCP_V6_PID " " TCP_V6_COMMAND " " + TCP_V6_SWIND " " TCP_V6_SENDQ " " TCP_V6_RWIND " " TCP_V6_RECVQ " " + TCP_V6_STATE " " TCP_V6_IF "\n" + TCP_V6_LOCAL_" " TCP_V6_REMOTE_" " + TCP_V6_USER_" " TCP_V6_PID_" " TCP_V6_COMMAND_" " + TCP_V6_SWIND_" " TCP_V6_SENDQ_" " TCP_V6_RWIND_" " TCP_V6_RECVQ_" " + TCP_V6_STATE_" " TCP_V6_IF_"\n"; +static const char tcp_hdr_v6_verbose[] = + TCP_V6_ADDRESS " " + TCP_V6_SWIND " " TCP_V6_SNEXT " " TCP_V6_SUNA " " + TCP_V6_RWIND " " TCP_V6_RNEXT " " TCP_V6_RACK " " + TCP_V6_RTO " " TCP_V6_MSS " " TCP_V6_STATE " " TCP_V6_IF "\n" + TCP_V6_ADDRESS_" " + TCP_V6_SWIND_" " TCP_V6_SNEXT_" " TCP_V6_SUNA_" " + TCP_V6_RWIND_" " TCP_V6_RNEXT_" " TCP_V6_RACK_" " + TCP_V6_RTO_" " TCP_V6_MSS_" " TCP_V6_STATE_" " TCP_V6_IF_"\n"; +static const char tcp_hdr_v6_verbose_pid[] = + TCP_V6_ADDRESS " " + TCP_V6_SWIND " " TCP_V6_SNEXT " " TCP_V6_SUNA " " + TCP_V6_RWIND " " TCP_V6_RNEXT " " TCP_V6_RACK " " + TCP_V6_RTO " " TCP_V6_MSS " " TCP_V6_STATE " " TCP_V6_IF " " + TCP_V6_USER " " TCP_V6_PID " " TCP_V6_COMMAND "\n" + TCP_V6_ADDRESS_" " + TCP_V6_SWIND_" " TCP_V6_SNEXT_" " TCP_V6_SUNA_" " + TCP_V6_RWIND_" " TCP_V6_RNEXT_" " TCP_V6_RACK_" " + TCP_V6_RTO_" " TCP_V6_MSS_" " TCP_V6_STATE_" " TCP_V6_IF_" " + TCP_V6_USER_" " TCP_V6_PID_" " TCP_V6_COMMAND_"\n"; static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *, - boolean_t first, const mib2_transportMLPEntry_t *); + boolean_t first, const mib2_transportMLPEntry_t *, + const mib2_socketInfoEntry_t *); static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *, - boolean_t first, const mib2_transportMLPEntry_t *); + boolean_t first, const mib2_transportMLPEntry_t *, + const mib2_socketInfoEntry_t *); static void tcp_report(const mib_item_t *item) { - int jtemp = 0; - boolean_t print_hdr_once_v4 = B_TRUE; - boolean_t print_hdr_once_v6 = B_TRUE; - mib2_tcpConnEntry_t *tp; - mib2_tcp6ConnEntry_t *tp6; - mib2_transportMLPEntry_t **v4_attrs, **v6_attrs; - mib2_transportMLPEntry_t **v4a, **v6a; - mib2_transportMLPEntry_t *aptr; + int jtemp = 0; + boolean_t print_hdr_once_v4 = B_TRUE; + boolean_t print_hdr_once_v6 = B_TRUE; + mib2_tcpConnEntry_t *tp; + mib2_tcp6ConnEntry_t *tp6; + mib2_transportMLPEntry_t **v4_attrs, **v6_attrs, **v4a, **v6a; + mib2_transportMLPEntry_t *aptr; + mib2_socketInfoEntry_t **v4_info, **v6_info, **v4i, **v6i; + mib2_socketInfoEntry_t *iptr; 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. + * connection table entries, Multilevel Port attributes and extra + * socket information. We loop through the attributes first and set up + * an array for each address family. */ v4_attrs = family_selected(AF_INET) && RSECflag ? gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) : @@ -4868,14 +5605,21 @@ tcp_report(const mib_item_t *item) gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) : NULL; - /* 'for' loop 1: */ + v4_info = Uflag && family_selected(AF_INET) ? + gather_info(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) : + NULL; + v6_info = Uflag && family_selected(AF_INET6) ? + gather_info(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) : + NULL; + v4a = v4_attrs; v6a = v6_attrs; + v4i = v4_info; + v6i = v6_info; for (; item != NULL; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } @@ -4884,46 +5628,46 @@ tcp_report(const mib_item_t *item) item->mib_id == MIB2_TCP_CONN) || (item->group == MIB2_TCP6 && item->mib_id == MIB2_TCP6_CONN))) - continue; /* 'for' loop 1 */ + continue; if (item->group == MIB2_TCP && !family_selected(AF_INET)) - continue; /* 'for' loop 1 */ - else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6)) - continue; /* 'for' loop 1 */ + continue; + if (item->group == MIB2_TCP6 && !family_selected(AF_INET6)) + continue; if (item->group == MIB2_TCP) { for (tp = (mib2_tcpConnEntry_t *)item->valp; (char *)tp < (char *)item->valp + item->length; - /* LINTED: (note 1) */ tp = (mib2_tcpConnEntry_t *)((char *)tp + tcpConnEntrySize)) { aptr = v4a == NULL ? NULL : *v4a++; + iptr = v4i == NULL ? NULL : *v4i++; print_hdr_once_v4 = tcp_report_item_v4(tp, - print_hdr_once_v4, aptr); + print_hdr_once_v4, aptr, iptr); } } else { for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp; (char *)tp6 < (char *)item->valp + item->length; - /* LINTED: (note 1) */ tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 + tcp6ConnEntrySize)) { aptr = v6a == NULL ? NULL : *v6a++; + iptr = v6i == NULL ? NULL : *v6i++; print_hdr_once_v6 = tcp_report_item_v6(tp6, - print_hdr_once_v6, aptr); + print_hdr_once_v6, aptr, iptr); } } - } /* 'for' loop 1 ends */ + } (void) fflush(stdout); - if (v4_attrs != NULL) - free(v4_attrs); - if (v6_attrs != NULL) - free(v6_attrs); + free(v4_attrs); + free(v6_attrs); + free(v4_info); + free(v6_info); } static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first, - const mib2_transportMLPEntry_t *attr) + const mib2_transportMLPEntry_t *attr, const mib2_socketInfoEntry_t *sie) { /* * lname and fname below are for the hostname as well as the portname @@ -4932,18 +5676,44 @@ tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first, */ char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; + proc_fdinfo_t *ph; if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED)) return (first); /* Nothing to print */ if (first) { (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4); - (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal); + if (Vflag) + (void) printf(Uflag ? tcp_hdr_v4_verbose_pid : + tcp_hdr_v4_verbose); + else + (void) printf(Uflag ? tcp_hdr_v4_normal_pid : + tcp_hdr_v4_normal); } - if (Vflag) { - (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x " - "%5u %5u %s\n", + int64_t sq = (int64_t)tp->tcpConnEntryInfo.ce_snxt - + (int64_t)tp->tcpConnEntryInfo.ce_suna - 1; + int64_t rq = (int64_t)tp->tcpConnEntryInfo.ce_rnxt - + (int64_t)tp->tcpConnEntryInfo.ce_rack; + + if (Xflag) + sie_report(sie); + + if (Uflag) { + ph = process_hash_get(sie, SOCK_STREAM, AF_INET); + if (ph->ph_pid == 0 && sie != NULL && + (sie->sie_flags & MIB2_SOCKINFO_IPV6)) { + ph = process_hash_get(sie, SOCK_STREAM, AF_INET6); + } + } + + if (!Uflag && Vflag) { + (void) printf( + TCP_V4_LOCAL_F "\n" TCP_V4_REMOTE_F " " + TCP_V4_SWIND_F " " TCP_V4_SNEXT_F " " + TCP_V4_SUNA_F " " TCP_V4_RWIND_F " " + TCP_V4_RNEXT_F " " TCP_V4_RACK_F " " + TCP_V4_RTO_F " " TCP_V4_MSS_F " %s\n", pr_ap(tp->tcpConnLocalAddress, tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), pr_ap(tp->tcpConnRemAddress, @@ -4957,13 +5727,11 @@ tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first, tp->tcpConnEntryInfo.ce_rto, tp->tcpConnEntryInfo.ce_mss, mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); - } else { - int sq = (int)tp->tcpConnEntryInfo.ce_snxt - - (int)tp->tcpConnEntryInfo.ce_suna - 1; - int rq = (int)tp->tcpConnEntryInfo.ce_rnxt - - (int)tp->tcpConnEntryInfo.ce_rack; - - (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n", + } else if (!Uflag) { + (void) printf( + TCP_V4_LOCAL_F " " TCP_V4_REMOTE_F " " + TCP_V4_SWIND_F " " TCP_V4_SENDQ_F " " + TCP_V4_RWIND_F " " TCP_V4_RECVQ_F " %s\n", pr_ap(tp->tcpConnLocalAddress, tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), pr_ap(tp->tcpConnRemAddress, @@ -4973,6 +5741,50 @@ tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first, tp->tcpConnEntryInfo.ce_rwnd, (rq >= 0) ? rq : 0, mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); + } else if (Uflag && Vflag) { + for (; ph != NULL; ph = ph->ph_next_proc) { + (void) printf( + TCP_V4_LOCAL_F "\n" TCP_V4_REMOTE_F " " + TCP_V4_SWIND_F " " TCP_V4_SNEXT_F " " + TCP_V4_SUNA_F " " TCP_V4_RWIND_F " " + TCP_V4_RNEXT_F " " TCP_V4_RACK_F " " + TCP_V4_RTO_F " " TCP_V4_MSS_F " " + TCP_V4_STATE_F " " TCP_V4_USER_F " " + TCP_V4_PID_F " %s\n", + pr_ap(tp->tcpConnLocalAddress, + tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), + pr_ap(tp->tcpConnRemAddress, + tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), + tp->tcpConnEntryInfo.ce_swnd, + tp->tcpConnEntryInfo.ce_snxt, + tp->tcpConnEntryInfo.ce_suna, + tp->tcpConnEntryInfo.ce_rwnd, + tp->tcpConnEntryInfo.ce_rnxt, + tp->tcpConnEntryInfo.ce_rack, + tp->tcpConnEntryInfo.ce_rto, + tp->tcpConnEntryInfo.ce_mss, + mitcp_state(tp->tcpConnEntryInfo.ce_state, attr), + ph->ph_username, ph->ph_pidstr, ph->ph_psargs); + } + } else if (Uflag) { + for (; ph != NULL; ph = ph->ph_next_proc) { + (void) printf( + TCP_V4_LOCAL_F " " TCP_V4_REMOTE_F " " + TCP_V4_USER_F " "TCP_V4_PID_F " " + TCP_V4_COMMAND_F " " + TCP_V4_SWIND_F " " TCP_V4_SENDQ_F " " + TCP_V4_RWIND_F " " TCP_V4_RECVQ_F " %s\n", + pr_ap(tp->tcpConnLocalAddress, + tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), + pr_ap(tp->tcpConnRemAddress, + tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), + ph->ph_username, ph->ph_pidstr, ph->ph_fname, + tp->tcpConnEntryInfo.ce_swnd, + (sq >= 0) ? sq : 0, + tp->tcpConnEntryInfo.ce_rwnd, + (rq >= 0) ? rq : 0, + mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); + } } print_transport_label(attr); @@ -4982,7 +5794,7 @@ tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first, static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, - const mib2_transportMLPEntry_t *attr) + const mib2_transportMLPEntry_t *attr, const mib2_socketInfoEntry_t *sie) { /* * lname and fname below are for the hostname as well as the portname @@ -4993,13 +5805,19 @@ tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; char ifname[LIFNAMSIZ + 1]; char *ifnamep; + proc_fdinfo_t *ph; if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED)) return (first); /* Nothing to print */ if (first) { (void) printf(tcp_hdr_v6); - (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal); + if (Vflag) + (void) printf(Uflag ? tcp_hdr_v6_verbose_pid : + tcp_hdr_v6_verbose); + else + (void) printf(Uflag ? tcp_hdr_v6_normal_pid : + tcp_hdr_v6_normal); } ifnamep = (tp6->tcp6ConnIfIndex != 0) ? @@ -5007,9 +5825,22 @@ tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, if (ifnamep == NULL) ifnamep = ""; - if (Vflag) { - (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x " - "%5u %5u %-11s %s\n", + int64_t sq = (int64_t)tp6->tcp6ConnEntryInfo.ce_snxt - + (int64_t)tp6->tcp6ConnEntryInfo.ce_suna - 1; + int64_t rq = (int64_t)tp6->tcp6ConnEntryInfo.ce_rnxt - + (int64_t)tp6->tcp6ConnEntryInfo.ce_rack; + + if (Xflag) + sie_report(sie); + + if (!Uflag && Vflag) { + (void) printf( + TCP_V6_LOCAL_F "\n" TCP_V6_REMOTE_F " " + TCP_V6_SWIND_F " " TCP_V6_SNEXT_F " " + TCP_V6_SUNA_F " " TCP_V6_RWIND_F " " + TCP_V6_RNEXT_F " " TCP_V6_RACK_F " " + TCP_V6_RTO_F " " TCP_V6_MSS_F " " + TCP_V6_STATE_F " %s\n", pr_ap6(&tp6->tcp6ConnLocalAddress, tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)), pr_ap6(&tp6->tcp6ConnRemAddress, @@ -5024,13 +5855,12 @@ tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, tp6->tcp6ConnEntryInfo.ce_mss, mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), ifnamep); - } else { - int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt - - (int)tp6->tcp6ConnEntryInfo.ce_suna - 1; - int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt - - (int)tp6->tcp6ConnEntryInfo.ce_rack; - - (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n", + } else if (!Uflag) { + (void) printf( + TCP_V6_LOCAL_F " " TCP_V6_REMOTE_F " " + TCP_V6_SWIND_F " " TCP_V6_SENDQ_F " " + TCP_V6_RWIND_F " " TCP_V6_RECVQ_F " " + TCP_V6_STATE_F " %s\n", pr_ap6(&tp6->tcp6ConnLocalAddress, tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)), pr_ap6(&tp6->tcp6ConnRemAddress, @@ -5041,6 +5871,58 @@ tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, (rq >= 0) ? rq : 0, mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), ifnamep); + } else if (Uflag && Vflag) { + for (ph = process_hash_get(sie, SOCK_STREAM, AF_INET6); + ph != NULL; ph = ph->ph_next_proc) { + (void) printf( + TCP_V6_LOCAL_F "\n" TCP_V6_REMOTE_F " " + TCP_V6_SWIND_F " " TCP_V6_SNEXT_F " " + TCP_V6_SUNA_F " " TCP_V6_RWIND_F " " + TCP_V6_RNEXT_F " " TCP_V6_RACK_F " " + TCP_V6_RTO_F " " TCP_V6_MSS_F " " + TCP_V6_STATE_F " " TCP_V6_IF_F " " + TCP_V6_USER_F " " TCP_V6_PID_F " %s\n", + pr_ap6(&tp6->tcp6ConnLocalAddress, + tp6->tcp6ConnLocalPort, "tcp", lname, + sizeof (lname)), + pr_ap6(&tp6->tcp6ConnRemAddress, + tp6->tcp6ConnRemPort, "tcp", fname, + sizeof (fname)), + tp6->tcp6ConnEntryInfo.ce_swnd, + tp6->tcp6ConnEntryInfo.ce_snxt, + tp6->tcp6ConnEntryInfo.ce_suna, + tp6->tcp6ConnEntryInfo.ce_rwnd, + tp6->tcp6ConnEntryInfo.ce_rnxt, + tp6->tcp6ConnEntryInfo.ce_rack, + tp6->tcp6ConnEntryInfo.ce_rto, + tp6->tcp6ConnEntryInfo.ce_mss, + mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), + ifnamep, + ph->ph_username, ph->ph_pidstr, ph->ph_psargs); + } + } else if (Uflag) { + for (ph = process_hash_get(sie, SOCK_STREAM, AF_INET6); + ph != NULL; ph = ph->ph_next_proc) { + (void) printf( + TCP_V6_LOCAL_F " " TCP_V6_REMOTE_F " " + TCP_V6_USER_F " " TCP_V6_PID_F " " + TCP_V6_COMMAND_F " " + TCP_V6_SWIND_F " " TCP_V6_SENDQ_F " " + TCP_V6_RWIND_F " " TCP_V6_RECVQ_F " " + TCP_V6_STATE_F " %s\n", + pr_ap6(&tp6->tcp6ConnLocalAddress, + tp6->tcp6ConnLocalPort, "tcp", lname, + sizeof (lname)), + pr_ap6(&tp6->tcp6ConnRemAddress, + tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)), + ph->ph_username, ph->ph_pidstr, ph->ph_fname, + tp6->tcp6ConnEntryInfo.ce_swnd, + (sq >= 0) ? sq : 0, + tp6->tcp6ConnEntryInfo.ce_rwnd, + (rq >= 0) ? rq : 0, + mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), + ifnamep); + } } print_transport_label(attr); @@ -5050,32 +5932,109 @@ tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first, /* ------------------------------- UDP_REPORT------------------------------- */ -static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude, - boolean_t first, const mib2_transportMLPEntry_t *attr); -static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6, - boolean_t first, const mib2_transportMLPEntry_t *attr); +static boolean_t udp_report_item_v4(const mib2_udpEntry_t *, boolean_t, + const mib2_transportMLPEntry_t *, const mib2_socketInfoEntry_t *); +static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *, boolean_t, + const mib2_transportMLPEntry_t *, const mib2_socketInfoEntry_t *); + +/* + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define UDP_V4_LOCAL " Local Address " +#define UDP_V4_LOCAL_ "--------------------" +#define UDP_V4_LOCAL_F "%-20s" +#define UDP_V4_REMOTE " Remote Address " +#define UDP_V4_REMOTE_ "--------------------" +#define UDP_V4_REMOTE_F "%-20s" +#define UDP_V4_STATE " State " +#define UDP_V4_STATE_ "----------" +#define UDP_V4_STATE_F "%-10.10s" +#define UDP_V4_USER " User " +#define UDP_V4_USER_ "--------" +#define UDP_V4_USER_F "%-8.8s" +#define UDP_V4_PID " Pid " +#define UDP_V4_PID_ "------" +#define UDP_V4_PID_F "%6s" +#define UDP_V4_COMMAND " Command " +#define UDP_V4_COMMAND_ "--------------" +#define UDP_V4_COMMAND_F "%-14.14s" static const char udp_hdr_v4[] = -" Local Address Remote Address State\n" -"-------------------- -------------------- ----------\n"; + UDP_V4_LOCAL " " UDP_V4_REMOTE " " UDP_V4_STATE "\n" + UDP_V4_LOCAL_" " UDP_V4_REMOTE_" " UDP_V4_STATE_"\n"; + +static const char udp_hdr_v4_pid[] = + UDP_V4_LOCAL " " UDP_V4_REMOTE " " + UDP_V4_USER " " UDP_V4_PID " " UDP_V4_COMMAND " " UDP_V4_STATE "\n" + UDP_V4_LOCAL_" " UDP_V4_REMOTE_" " + UDP_V4_USER_" " UDP_V4_PID_" " UDP_V4_COMMAND_" " UDP_V4_STATE_"\n"; +static const char udp_hdr_v4_pid_verbose[] = + UDP_V4_LOCAL " " UDP_V4_REMOTE " " + UDP_V4_USER " " UDP_V4_PID " " UDP_V4_STATE " " UDP_V4_COMMAND "\n" + UDP_V4_LOCAL_" " UDP_V4_REMOTE_" " + UDP_V4_USER_" " UDP_V4_PID_" " UDP_V4_STATE_" " UDP_V4_COMMAND_"\n"; + +#define UDP_V6_LOCAL " Local Address " +#define UDP_V6_LOCAL_ "---------------------------------" +#define UDP_V6_LOCAL_F "%-33s" +#define UDP_V6_REMOTE " Remote Address " +#define UDP_V6_REMOTE_ "---------------------------------" +#define UDP_V6_REMOTE_F "%-33s" +#define UDP_V6_STATE UDP_V4_STATE +#define UDP_V6_STATE_ UDP_V4_STATE_ +#define UDP_V6_STATE_F UDP_V4_STATE_F +#define UDP_V6_USER UDP_V4_USER +#define UDP_V6_USER_ UDP_V4_USER_ +#define UDP_V6_USER_F UDP_V4_USER_F +#define UDP_V6_PID UDP_V4_PID +#define UDP_V6_PID_ UDP_V4_PID_ +#define UDP_V6_PID_F UDP_V4_PID_F +#define UDP_V6_COMMAND UDP_V4_COMMAND +#define UDP_V6_COMMAND_ UDP_V4_COMMAND_ +#define UDP_V6_COMMAND_F UDP_V4_COMMAND_F +#define UDP_V6_IF " If " +#define UDP_V6_IF_ "-----" +#define UDP_V6_IF_F "%-5.5s" static const char udp_hdr_v6[] = -" Local Address Remote Address " -" State If\n" -"--------------------------------- --------------------------------- " -"---------- -----\n"; + UDP_V6_LOCAL " " UDP_V6_REMOTE " " UDP_V6_STATE " " + UDP_V6_IF "\n" + UDP_V6_LOCAL_" " UDP_V6_REMOTE_" " UDP_V6_STATE_" " + UDP_V6_IF_"\n"; + +static const char udp_hdr_v6_pid[] = + UDP_V6_LOCAL " " UDP_V6_REMOTE " " + UDP_V6_USER " " UDP_V6_PID " " UDP_V6_COMMAND " " + UDP_V6_STATE " " UDP_V6_IF "\n" + UDP_V6_LOCAL_" " UDP_V6_REMOTE_" " + UDP_V6_USER_" " UDP_V6_PID_" " UDP_V6_COMMAND_" " + UDP_V6_STATE_" " UDP_V6_IF_"\n"; + +static const char udp_hdr_v6_pid_verbose[] = + UDP_V6_LOCAL " " UDP_V6_REMOTE " " + UDP_V6_USER " " UDP_V6_PID " " UDP_V6_STATE " " + UDP_V6_IF " " UDP_V6_COMMAND "\n" + UDP_V6_LOCAL_" " UDP_V6_REMOTE_" " + UDP_V6_USER_" " UDP_V6_PID_" " UDP_V6_STATE_" " + UDP_V6_IF_" " UDP_V6_COMMAND_ "\n"; static void udp_report(const mib_item_t *item) { - int jtemp = 0; - boolean_t print_hdr_once_v4 = B_TRUE; - boolean_t print_hdr_once_v6 = B_TRUE; - mib2_udpEntry_t *ude; - mib2_udp6Entry_t *ude6; - mib2_transportMLPEntry_t **v4_attrs, **v6_attrs; - mib2_transportMLPEntry_t **v4a, **v6a; - mib2_transportMLPEntry_t *aptr; + int jtemp = 0; + boolean_t print_hdr_once_v4 = B_TRUE; + boolean_t print_hdr_once_v6 = B_TRUE; + mib2_udpEntry_t *ude; + mib2_udp6Entry_t *ude6; + mib2_transportMLPEntry_t **v4_attrs, **v6_attrs, **v4a, **v6a; + mib2_transportMLPEntry_t *aptr; + mib2_socketInfoEntry_t **v4_info, **v6_info, **v4i, **v6i; + mib2_socketInfoEntry_t *iptr; if (!protocol_selected(IPPROTO_UDP)) return; @@ -5092,14 +6051,21 @@ udp_report(const mib_item_t *item) gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) : NULL; + v4_info = Uflag && family_selected(AF_INET) ? + gather_info(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : + NULL; + v6_info = Uflag && family_selected(AF_INET6) ? + gather_info(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) : + NULL; + v4a = v4_attrs; v6a = v6_attrs; - /* 'for' loop 1: */ + v4i = v4_info; + v6i = v6_info; for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } @@ -5107,121 +6073,263 @@ udp_report(const mib_item_t *item) item->mib_id == MIB2_UDP_ENTRY) || (item->group == MIB2_UDP6 && item->mib_id == MIB2_UDP6_ENTRY))) - continue; /* 'for' loop 1 */ + continue; if (item->group == MIB2_UDP && !family_selected(AF_INET)) - continue; /* 'for' loop 1 */ + continue; else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6)) - continue; /* 'for' loop 1 */ + continue; - /* xxx.xxx.xxx.xxx,pppp sss... */ if (item->group == MIB2_UDP) { for (ude = (mib2_udpEntry_t *)item->valp; (char *)ude < (char *)item->valp + item->length; - /* LINTED: (note 1) */ ude = (mib2_udpEntry_t *)((char *)ude + udpEntrySize)) { aptr = v4a == NULL ? NULL : *v4a++; + iptr = v4i == NULL ? NULL : *v4i++; print_hdr_once_v4 = udp_report_item_v4(ude, - print_hdr_once_v4, aptr); + print_hdr_once_v4, aptr, iptr); } } else { for (ude6 = (mib2_udp6Entry_t *)item->valp; (char *)ude6 < (char *)item->valp + item->length; - /* LINTED: (note 1) */ ude6 = (mib2_udp6Entry_t *)((char *)ude6 + udp6EntrySize)) { aptr = v6a == NULL ? NULL : *v6a++; + iptr = v6i == NULL ? NULL : *v6i++; print_hdr_once_v6 = udp_report_item_v6(ude6, - print_hdr_once_v6, aptr); + print_hdr_once_v6, aptr, iptr); } } - } /* 'for' loop 1 ends */ + + } (void) fflush(stdout); - if (v4_attrs != NULL) - free(v4_attrs); - if (v6_attrs != NULL) - free(v6_attrs); + free(v4_attrs); + free(v6_attrs); + free(v4_info); + free(v6_info); } static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first, - const mib2_transportMLPEntry_t *attr) + const mib2_transportMLPEntry_t *attr, const mib2_socketInfoEntry_t *sie) { + char *leadin; char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; /* hostname + portname */ + proc_fdinfo_t *ph; if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected)) return (first); /* Nothing to print */ if (first) { (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n"); - (void) printf(udp_hdr_v4); + + if (Uflag) + (void) printf(Vflag ? udp_hdr_v4_pid_verbose : + udp_hdr_v4_pid); + else + (void) printf(udp_hdr_v4); + first = B_FALSE; } - (void) printf("%-20s ", + if (Xflag) + sie_report(sie); + + if (asprintf(&leadin, + UDP_V4_LOCAL_F " " UDP_V4_REMOTE_F " ", pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp", - lname, sizeof (lname))); - (void) printf("%-20s %s\n", + lname, sizeof (lname)), ude->udpEntryInfo.ue_state == MIB2_UDP_connected ? pr_ap(ude->udpEntryInfo.ue_RemoteAddress, ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) : - "", - miudp_state(ude->udpEntryInfo.ue_state, attr)); + "") == -1) { + fatal(1, "Out of memory"); + } + if (!Uflag) { + (void) printf("%s%s\n", + leadin, miudp_state(ude->udpEntryInfo.ue_state, attr)); + } else { + ph = process_hash_get(sie, SOCK_DGRAM, AF_INET); + if (ph->ph_pid == 0 && sie != NULL && + (sie->sie_flags & MIB2_SOCKINFO_IPV6)) + ph = process_hash_get(sie, SOCK_DGRAM, AF_INET6); + for (; ph != NULL; ph = ph->ph_next_proc) { + (void) printf("%s" UDP_V4_USER_F " " UDP_V4_PID_F " ", + leadin, ph->ph_username, ph->ph_pidstr); + if (Vflag) { + (void) printf(UDP_V4_STATE_F " %s\n", + miudp_state(ude->udpEntryInfo.ue_state, + attr), + ph->ph_psargs); + } else { + (void) printf(UDP_V4_COMMAND_F " %s\n", + ph->ph_fname, + miudp_state(ude->udpEntryInfo.ue_state, + attr)); + } + } + } print_transport_label(attr); + free(leadin); + return (first); } static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first, - const mib2_transportMLPEntry_t *attr) + const mib2_transportMLPEntry_t *attr, const mib2_socketInfoEntry_t *sie) { - char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; + char *leadin; + char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; /* hostname + portname */ - char ifname[LIFNAMSIZ + 1]; - const char *ifnamep; + char ifname[LIFNAMSIZ + 1]; + const char *ifnamep; + proc_fdinfo_t *ph; if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected)) return (first); /* Nothing to print */ if (first) { (void) printf("\nUDP: IPv6\n"); - (void) printf(udp_hdr_v6); + + if (Uflag) + (void) printf(Vflag ? udp_hdr_v6_pid_verbose : + udp_hdr_v6_pid); + else + (void) printf(udp_hdr_v6); + first = B_FALSE; } ifnamep = (ude6->udp6IfIndex != 0) ? if_indextoname(ude6->udp6IfIndex, ifname) : NULL; - (void) printf("%-33s ", + if (Xflag) + sie_report(sie); + + if (asprintf(&leadin, + UDP_V6_LOCAL_F " " UDP_V6_REMOTE_F " ", pr_ap6(&ude6->udp6LocalAddress, - ude6->udp6LocalPort, "udp", lname, sizeof (lname))); - (void) printf("%-33s %-10s %s\n", + ude6->udp6LocalPort, "udp", lname, sizeof (lname)), ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ? pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress, ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) : - "", - miudp_state(ude6->udp6EntryInfo.ue_state, attr), - ifnamep == NULL ? "" : ifnamep); + "") == -1) { + fatal(1, "Out of memory"); + } + if (!Uflag) { + (void) printf("%s" UDP_V6_STATE_F " %s\n", leadin, + miudp_state(ude6->udp6EntryInfo.ue_state, attr), + ifnamep == NULL ? "" : ifnamep); + } else { + for (ph = process_hash_get(sie, SOCK_DGRAM, AF_INET6); + ph != NULL; ph = ph->ph_next_proc) { + (void) printf("%s" UDP_V6_USER_F " " UDP_V6_PID_F " ", + leadin, ph->ph_username, ph->ph_pidstr); + if (Vflag) { + (void) printf( + UDP_V6_STATE_F " " UDP_V6_IF_F " %s\n", + miudp_state(ude6->udp6EntryInfo.ue_state, + attr), + ifnamep == NULL ? "" : ifnamep, + ph->ph_psargs); + } else { + (void) printf( + UDP_V6_COMMAND_F " " UDP_V6_STATE_F " %s\n", + ph->ph_fname, + miudp_state(ude6->udp6EntryInfo.ue_state, + attr), + ifnamep == NULL ? "" : ifnamep); + } + } + } print_transport_label(attr); + free(leadin); + return (first); } /* ------------------------------ SCTP_REPORT------------------------------- */ +/* + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define SCTP_LOCAL " Local Address " +#define SCTP_LOCAL_ "-------------------------------" +#define SCTP_LOCAL_F "%-31s" +#define SCTP_REMOTE " Remote Address " +#define SCTP_REMOTE_ "-------------------------------" +#define SCTP_REMOTE_F "%-31s" +#define SCTP_SWIND "Swind " +#define SCTP_SWIND_ "------" +#define SCTP_SWIND_F "%6u" +#define SCTP_SENDQ "Send-Q" +#define SCTP_SENDQ_ "------" +#define SCTP_SENDQ_F "%6d" +#define SCTP_RWIND "Rwind " +#define SCTP_RWIND_ "------" +#define SCTP_RWIND_F "%6d" +#define SCTP_RECVQ "Recv-Q" +#define SCTP_RECVQ_ "------" +#define SCTP_RECVQ_F "%6u" +#define SCTP_STRS "StrsI/O" +#define SCTP_STRS_ "-------" +#define SCTP_STRS_FI "%3d" +#define SCTP_STRS_FO "%-3d" +#define SCTP_STATE " State " +#define SCTP_STATE_ "-----------" +#define SCTP_STATE_F "%-11.11s" +#define SCTP_USER " User " +#define SCTP_USER_ "--------" +#define SCTP_USER_F "%-8.8s" +#define SCTP_PID " Pid " +#define SCTP_PID_ "------" +#define SCTP_PID_F "%6s" +#define SCTP_COMMAND " Command " +#define SCTP_COMMAND_ "--------------" +#define SCTP_COMMAND_F "%-14.14s" + 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" -"------------------------------- ------------------------------- " -"------ ------ ------ ------ ------- -----------"; + SCTP_LOCAL " " SCTP_REMOTE " " + SCTP_SWIND " " SCTP_SENDQ " " SCTP_RWIND " " SCTP_RECVQ " " + SCTP_STRS " " SCTP_STATE "\n" + SCTP_LOCAL_" " SCTP_REMOTE_" " + SCTP_SWIND_" " SCTP_SENDQ_" " SCTP_RWIND_" " SCTP_RECVQ_" " + SCTP_STRS_" " SCTP_STATE_"\n"; + +static const char sctp_hdr_pid[] = + SCTP_LOCAL " " SCTP_REMOTE " " + SCTP_SWIND " " SCTP_SENDQ " " SCTP_RWIND " " SCTP_RECVQ " " + SCTP_STRS " " + SCTP_USER " " SCTP_PID " " SCTP_COMMAND " " SCTP_STATE "\n" + SCTP_LOCAL_" " SCTP_REMOTE_" " + SCTP_SWIND_" " SCTP_SENDQ_" " SCTP_RWIND_" " SCTP_RECVQ_" " + SCTP_STRS_" " + SCTP_USER_" " SCTP_PID_" " SCTP_COMMAND_" " SCTP_STATE_"\n"; + +static const char sctp_hdr_pid_verbose[] = + SCTP_LOCAL " " SCTP_REMOTE " " + SCTP_SWIND " " SCTP_SENDQ " " SCTP_RWIND " " SCTP_RECVQ " " + SCTP_STRS_" " + SCTP_USER " " SCTP_PID " " SCTP_STATE " " SCTP_COMMAND "\n" + SCTP_LOCAL_" " SCTP_REMOTE_" " + SCTP_SWIND_" " SCTP_SENDQ_" " SCTP_RWIND_" " SCTP_RECVQ_" " + SCTP_STRS_" " + SCTP_USER_" " SCTP_PID_" " SCTP_STATE_" " SCTP_COMMAND_"\n"; static const char * nssctp_state(int state, const mib2_transportMLPEntry_t *attr) @@ -5292,14 +6400,12 @@ sctp_getnext_rem(const mib_item_t **itemp, } if (current != NULL) { - /* LINTED: (note 1) */ sre = (const mib2_sctpConnRemoteEntry_t *) ((const char *)current + sctpRemoteEntrySize); } else { sre = item->valp; } for (; (char *)sre < (char *)item->valp + item->length; - /* LINTED: (note 1) */ sre = (const mib2_sctpConnRemoteEntry_t *) ((const char *)sre + sctpRemoteEntrySize)) { if (sre->sctpAssocId != associd) { @@ -5327,14 +6433,12 @@ sctp_getnext_local(const mib_item_t **itemp, } if (current != NULL) { - /* LINTED: (note 1) */ sle = (const mib2_sctpConnLocalEntry_t *) ((const char *)current + sctpLocalEntrySize); } else { sle = item->valp; } for (; (char *)sle < (char *)item->valp + item->length; - /* LINTED: (note 1) */ sle = (const mib2_sctpConnLocalEntry_t *) ((const char *)sle + sctpLocalEntrySize)) { if (sle->sctpAssocId != associd) { @@ -5388,9 +6492,10 @@ sctp_pr_addr(int type, char *name, int namelen, const in6_addr_t *addr, } } -static void -sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp, - const mib2_transportMLPEntry_t *attr) +static boolean_t +sctp_conn_report_item(const mib_item_t *head, boolean_t print_sctp_hdr, + const mib2_sctpConnEntry_t *sp, const mib2_transportMLPEntry_t *attr, + const mib2_socketInfoEntry_t *sie) { char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; @@ -5400,26 +6505,72 @@ sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp, const mib_item_t *remote = head; uint32_t id = sp->sctpAssocId; boolean_t printfirst = B_TRUE; + proc_fdinfo_t *ph; + + if (print_sctp_hdr == B_TRUE) { + (void) puts(sctp_hdr); + if (Uflag) + (void) puts(Vflag ? sctp_hdr_pid_verbose: sctp_hdr_pid); + else + (void) puts(sctp_hdr_normal); + + print_sctp_hdr = B_FALSE; + } sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname), &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort); sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname), &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort); - (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n", - lname, fname, - sp->sctpConnEntryInfo.ce_swnd, - sp->sctpConnEntryInfo.ce_sendq, - sp->sctpConnEntryInfo.ce_rwnd, - sp->sctpConnEntryInfo.ce_recvq, - sp->sctpAssocInStreams, sp->sctpAssocOutStreams, - nssctp_state(sp->sctpAssocState, attr)); + if (Xflag) + sie_report(sie); + + if (Uflag) { + for (ph = process_hash_get(sie, SOCK_STREAM, AF_INET); + ph != NULL; ph = ph->ph_next_proc) { + (void) printf( + SCTP_LOCAL_F " " SCTP_REMOTE_F " " + SCTP_SWIND_F " " SCTP_SENDQ_F " " + SCTP_RWIND_F " " SCTP_RECVQ_F " " + SCTP_STRS_FI "/" SCTP_STRS_FO " " + SCTP_USER_F " " SCTP_PID_F " ", + lname, fname, + sp->sctpConnEntryInfo.ce_swnd, + sp->sctpConnEntryInfo.ce_sendq, + sp->sctpConnEntryInfo.ce_rwnd, + sp->sctpConnEntryInfo.ce_recvq, + sp->sctpAssocInStreams, + sp->sctpAssocOutStreams, + ph->ph_username, ph->ph_pidstr); + if (Vflag) { + (void) printf(SCTP_STATE_F " %s\n", + nssctp_state(sp->sctpAssocState, attr), + ph->ph_psargs); + } else { + (void) printf(SCTP_COMMAND_F " %s\n", + ph->ph_fname, + nssctp_state(sp->sctpAssocState, attr)); + } + } + } else { + (void) printf( + SCTP_LOCAL_F " " SCTP_REMOTE_F " " + SCTP_SWIND_F " " SCTP_SENDQ_F " " + SCTP_RWIND_F " " SCTP_RECVQ_F " " + SCTP_STRS_FI "/" SCTP_STRS_FO " %s\n", + lname, fname, + sp->sctpConnEntryInfo.ce_swnd, + sp->sctpConnEntryInfo.ce_sendq, + sp->sctpConnEntryInfo.ce_rwnd, + sp->sctpConnEntryInfo.ce_recvq, + sp->sctpAssocInStreams, sp->sctpAssocOutStreams, + nssctp_state(sp->sctpAssocState, attr)); + } print_transport_label(attr); - if (!Vflag) { - return; - } + if (!Vflag) + return (print_sctp_hdr); /* Print remote addresses/local addresses on following lines */ while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) { @@ -5461,16 +6612,17 @@ sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp, if (printfirst == B_FALSE) { (void) puts(">"); } + + return (print_sctp_hdr); } static void sctp_report(const mib_item_t *item) { - const mib_item_t *head; const mib2_sctpConnEntry_t *sp; - boolean_t first = B_TRUE; - mib2_transportMLPEntry_t **attrs, **aptr; - mib2_transportMLPEntry_t *attr; + boolean_t print_sctp_hdr_once = B_TRUE; + mib2_transportMLPEntry_t **attrs, **a, *aptr; + mib2_socketInfoEntry_t **info, **i, *iptr; /* * Preparation pass: the kernel returns separate entries for SCTP @@ -5481,9 +6633,12 @@ sctp_report(const mib_item_t *item) attrs = RSECflag ? gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) : NULL; + info = Uflag ? + gather_info(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) : + NULL; - aptr = attrs; - head = item; + a = attrs; + i = info; for (; item != NULL; item = item->next_item) { if (!(item->group == MIB2_SCTP && @@ -5492,22 +6647,18 @@ sctp_report(const mib_item_t *item) for (sp = item->valp; (char *)sp < (char *)item->valp + item->length; - /* LINTED: (note 1) */ sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) { - attr = aptr == NULL ? NULL : *aptr++; - if (Aflag || - sp->sctpAssocState >= MIB2_SCTP_established) { - if (first == B_TRUE) { - (void) puts(sctp_hdr); - (void) puts(sctp_hdr_normal); - first = B_FALSE; - } - sctp_conn_report_item(head, sp, attr); - } + if (!(Aflag || + sp->sctpAssocState >= MIB2_SCTP_established)) + continue; + aptr = a == NULL ? NULL : *a++; + iptr = i == NULL ? NULL : *i++; + print_sctp_hdr_once = sctp_conn_report_item( + item, print_sctp_hdr_once, sp, aptr, iptr); } } - if (attrs != NULL) - free(attrs); + free(attrs); + free(info); } static char * @@ -5567,17 +6718,15 @@ mrt_report(mib_item_t *item) if (!(family_selected(AF_INET))) return; - /* 'for' loop 1: */ for (; item; item = item->next_item) { if (Xflag) { - (void) printf("\n--- Entry %d ---\n", ++jtemp); - (void) printf("Group = %d, mib_id = %d, " - "length = %d, valp = 0x%p\n", + (void) printf("[%4d] Group = %d, mib_id = %d, " + "length = %d, valp = 0x%p\n", jtemp++, item->group, item->mib_id, item->length, item->valp); } if (item->group != EXPER_DVMRP) - continue; /* 'for' loop 1 */ + continue; switch (item->mib_id) { @@ -5595,14 +6744,12 @@ mrt_report(mib_item_t *item) " Vif Threshold Rate_Limit Local-Address" " Remote-Address Pkt_in Pkt_out"); - /* 'for' loop 2: */ for (vip = (struct vifctl *)item->valp; (char *)vip < (char *)item->valp + item->length; - /* LINTED: (note 1) */ vip = (struct vifctl *)((char *)vip + vifctlSize)) { if (vip->vifc_lcl_addr.s_addr == 0) - continue; /* 'for' loop 2 */ + continue; /* numvifs = vip->vifc_vifi; */ numvifs++; @@ -5619,7 +6766,7 @@ mrt_report(mib_item_t *item) abuf, sizeof (abuf)) : "", vip->vifc_pkt_in, vip->vifc_pkt_out); - } /* 'for' loop 2 ends */ + } (void) printf("Numvifs: %d\n", numvifs); break; @@ -5640,7 +6787,6 @@ mrt_report(mib_item_t *item) for (mfccp = (struct mfcctl *)item->valp; (char *)mfccp < (char *)item->valp + item->length; - /* LINTED: (note 1) */ mfccp = (struct mfcctl *)((char *)mfccp + mfcctlSize)) { @@ -5669,7 +6815,7 @@ mrt_report(mib_item_t *item) nmfc); break; } - } /* 'for' loop 1 ends */ + } (void) putchar('\n'); (void) fflush(stdout); } @@ -5696,11 +6842,10 @@ kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes) len = prefix ? strlen(name) : 256; - /* 'for' loop 1: */ for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { if (strcmp(ksp->ks_class, "kmem_cache") != 0) - continue; /* 'for' loop 1 */ + continue; /* * Hack alert: because of the way streams messages are @@ -5717,11 +6862,11 @@ kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes) (void) safe_kstat_read(kc, ksp, NULL); total_buf_inuse -= kstat_named_value(ksp, "buf_constructed"); - continue; /* 'for' loop 1 */ + continue; } if (strncmp(ksp->ks_name, name, len) != 0) - continue; /* 'for' loop 1 */ + continue; (void) safe_kstat_read(kc, ksp, NULL); @@ -5745,7 +6890,7 @@ kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes) total_buf_max += buf_max; total_buf_inuse += buf_inuse; *total_bytes += (int64_t)buf_inuse * buf_size; - } /* 'for' loop 1 ends */ + } if (buf_size == 0) { (void) printf("%-22s [couldn't find statistics for %s]\n", @@ -6303,7 +7448,6 @@ portname(uint_t port, char *proto, char *dst, uint_t dstlen) return (dst); } -/*PRINTFLIKE2*/ void fail(int do_perror, char *message, ...) { @@ -6320,6 +7464,25 @@ fail(int do_perror, char *message, ...) } /* + * fatal: print error message to stderr and + * call exit(errcode) + */ +static void +fatal(int errcode, char *format, ...) +{ + if (format != NULL) { + va_list argp; + + va_start(argp, format); + (void) vfprintf(stderr, format, argp); + va_end(argp); + } + + exit(errcode); +} + + +/* * 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() ) @@ -6489,7 +7652,6 @@ process_filter(char *arg) * into a mask. */ if (hp->h_addr_list[0] != NULL && - /* LINTED: (note 1) */ IN6_IS_ADDR_V4MAPPED((in6_addr_t *) hp->h_addr_list[0])) { maxv = IP_ABITS; @@ -6575,7 +7737,7 @@ ifindex2str(uint_t ifindex, char *ifname) static void usage(char *cmdname) { - (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] " + (void) fprintf(stderr, "usage: %s [-anuv] [-f address_family] " "[-T d|u]\n", cmdname); (void) fprintf(stderr, " %s [-n] [-f address_family] " "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n", @@ -6593,22 +7755,225 @@ usage(char *cmdname) exit(EXIT_FAILURE); } +/* -------------------UNIX Domain Sockets Report---------------------------- */ + +#define UDS_SO_PAIR "(socketpair)" + +static char *typetoname(t_scalar_t); +static boolean_t uds_report_item(struct sockinfo *, boolean_t); + /* - * fatal: print error message to stderr and - * call exit(errcode) + * Central definitions for the columns used in the reports. + * For each column, there's a definition for the heading, the underline and + * the formatted value. + * Since most reports select different columns depending on command line + * options, defining everything here avoids duplication in the report + * format strings and makes it easy to make changes as necessary. + */ +#define UDS_ADDRESS "Address " +#define UDS_ADDRESS_ "----------------" +#define UDS_ADDRESS_F "%-16.16s" +#define UDS_TYPE "Type " +#define UDS_TYPE_ "----------" +#define UDS_TYPE_F "%-10.10s" +#define UDS_VNODE "Vnode " +#define UDS_VNODE_ "----------------" +#define UDS_VNODE_F "%-16.16s" +#define UDS_CONN "Conn " +#define UDS_CONN_ "----------------" +#define UDS_CONN_F "%-16.16s" +#define UDS_LOCAL "Local Address " +#define UDS_LOCAL_ "---------------------------------------" +#define UDS_LOCAL_F "%-39.39s" +#define UDS_REMOTE "Remote Address " +#define UDS_REMOTE_ "---------------------------------------" +#define UDS_REMOTE_F "%-39.39s" +#define UDS_USER "User " +#define UDS_USER_ "--------" +#define UDS_USER_F "%-8.8s" +#define UDS_PID "Pid " +#define UDS_PID_ "------" +#define UDS_PID_F "%6s" +#define UDS_COMMAND "Command " +#define UDS_COMMAND_ "--------------" +#define UDS_COMMAND_F "%-14.14s" + +static const char uds_hdr[] = "\nActive UNIX domain sockets\n"; + +static const char uds_hdr_normal[] = + UDS_ADDRESS " " UDS_TYPE " " UDS_VNODE " " UDS_CONN " " + UDS_LOCAL " " UDS_REMOTE "\n" + UDS_ADDRESS_" " UDS_TYPE_" " UDS_VNODE_" " UDS_CONN_" " + UDS_LOCAL_" " UDS_REMOTE_"\n"; + +static const char uds_hdr_pid[] = + UDS_ADDRESS " " UDS_TYPE " " UDS_USER " " UDS_PID " " UDS_COMMAND " " + UDS_LOCAL " " UDS_REMOTE "\n" + UDS_ADDRESS_ " " UDS_TYPE_" " UDS_USER_" " UDS_PID_" " UDS_COMMAND_" " + UDS_LOCAL_" " UDS_REMOTE_"\n"; + +static const char uds_hdr_pid_verbose[] = + UDS_ADDRESS " " UDS_TYPE " " UDS_USER " " UDS_PID " " + UDS_LOCAL " " UDS_REMOTE " " UDS_COMMAND "\n" + UDS_ADDRESS_ " " UDS_TYPE_" " UDS_USER_" " UDS_PID_" " + UDS_LOCAL_" " UDS_REMOTE_" " UDS_COMMAND_"\n"; + +/* + * Print a summary of connections related to unix protocols. */ -/*PRINTFLIKE2*/ static void -fatal(int errcode, char *format, ...) +uds_report(kstat_ctl_t *kc) { - va_list argp; + uint32_t i; + kstat_t *ksp; + struct sockinfo *psi; + boolean_t print_uds_hdr_once = B_TRUE; - if (format == NULL) - return; + if (kc == NULL) { + fail(0, "uds_report: No kstat"); + exit(3); + } - va_start(argp, format); - (void) vfprintf(stderr, format, argp); - va_end(argp); + if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) == NULL) + fail(0, "kstat_data_lookup failed\n"); - exit(errcode); + if (kstat_read(kc, ksp, NULL) == -1) + fail(0, "kstat_read failed for sock_unix_list\n"); + + if (ksp->ks_ndata == 0) + return; /* no AF_UNIX sockets found */ + + /* + * Having ks_data set with ks_data == NULL shouldn't happen; + * If it does, the sockfs kstat is seriously broken. + */ + if ((psi = ksp->ks_data) == NULL) + fail(0, "uds_report: no kstat data\n"); + + for (i = 0; i < ksp->ks_ndata; i++) { + + print_uds_hdr_once = uds_report_item(psi, print_uds_hdr_once); + + /* If si_size didn't get filled in, then we're done */ + if (psi->si_size == 0 || + !IS_P2ALIGNED(psi->si_size, sizeof (psi))) + break; + + /* Point to the next sockinfo in the array */ + psi = (struct sockinfo *)(((char *)psi) + psi->si_size); + } +} + +static boolean_t +uds_report_item(struct sockinfo *psi, boolean_t first) +{ + char *laddr, *raddr; + proc_fdinfo_t *ph; + + if (first) { + (void) printf("%s", uds_hdr); + if (Uflag) + (void) printf("%s", + Vflag ? uds_hdr_pid_verbose : uds_hdr_pid); + else + (void) printf("%s", uds_hdr_normal); + + first = B_FALSE; + } + + raddr = laddr = ""; + + if ((psi->si_state & SS_ISBOUND) && + strlen(psi->si_laddr_sun_path) != 0 && + psi->si_laddr_soa_len != 0) { + if (psi->si_faddr_noxlate) { + laddr = UDS_SO_PAIR; + } else { + if (psi->si_laddr_soa_len > + sizeof (psi->si_laddr_family)) + laddr = psi->si_laddr_sun_path; + } + } + + if ((psi->si_state & SS_ISCONNECTED) && + strlen(psi->si_faddr_sun_path) != 0 && + psi->si_faddr_soa_len != 0) { + if (psi->si_faddr_noxlate) { + raddr = UDS_SO_PAIR; + } else { + if (psi->si_faddr_soa_len > + sizeof (psi->si_faddr_family)) + raddr = psi->si_faddr_sun_path; + } + } + + /* Traditional output */ + if (!Uflag) { + (void) printf( + UDS_ADDRESS_F " " UDS_TYPE_F " " UDS_VNODE_F " " + UDS_CONN_F " " UDS_LOCAL_F " " UDS_REMOTE_F "\n", + psi->si_son_straddr, + typetoname(psi->si_serv_type), + (psi->si_state & SS_ISBOUND) && + psi->si_ux_laddr_sou_magic == SOU_MAGIC_EXPLICIT ? + psi->si_lvn_straddr : "0000000", + (psi->si_state & SS_ISCONNECTED) && + psi->si_ux_faddr_sou_magic == SOU_MAGIC_EXPLICIT ? + psi->si_fvn_straddr : "0000000", + laddr, raddr); + return (first); + } + + mib2_socketInfoEntry_t sie = { + .sie_inode = psi->si_inode, + .sie_flags = 0 + }; + + if (Xflag) + sie_report(&sie); + + for (ph = process_hash_get(&sie, + psi->si_serv_type == T_CLTS ? SOCK_DGRAM : SOCK_STREAM, AF_UNIX); + ph != NULL; ph = ph->ph_next_proc) { + if (Vflag) { + (void) printf( + UDS_ADDRESS_F " " UDS_TYPE_F " " + UDS_USER_F " " UDS_PID_F " " + UDS_LOCAL_F " " UDS_REMOTE_F " %s\n", + psi->si_son_straddr, + typetoname(psi->si_serv_type), + ph->ph_username, ph->ph_pidstr, + laddr, raddr, ph->ph_psargs); + } else { + (void) printf( + UDS_ADDRESS_F " " UDS_TYPE_F " " + UDS_USER_F " " UDS_PID_F " " UDS_COMMAND_F " " + UDS_LOCAL_F " " UDS_REMOTE_F "\n", + psi->si_son_straddr, + typetoname(psi->si_serv_type), + ph->ph_username, ph->ph_pidstr, ph->ph_fname, + laddr, raddr); + } + + } + + return (first); +} + +static char * +typetoname(t_scalar_t type) +{ + switch (type) { + case T_CLTS: + return ("dgram"); + + case T_COTS: + return ("stream"); + + case T_COTS_ORD: + return ("stream-ord"); + + default: + return (""); + } } diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/unix.c b/usr/src/cmd/cmd-inet/usr.bin/netstat/unix.c deleted file mode 100644 index 1a6364c00f..0000000000 --- a/usr/src/cmd/cmd-inet/usr.bin/netstat/unix.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ - -/* - * University Copyright- Copyright (c) 1982, 1986, 1988 - * The Regents of the University of California - * All Rights Reserved - * - * University Acknowledgment- Portions of this document are derived from - * software developed by the University of California, Berkeley, and its - * contributors. - */ - -/* - * code for netstat's -k option - * - * 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <strings.h> -#include <string.h> -#include <kstat.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stream.h> -#include <sys/tiuser.h> -#include <sys/socketvar.h> -#include <sys/sysmacros.h> - -static char *typetoname(t_scalar_t); -static void print_kn(kstat_t *); -static char *nextstr(char *); -extern void fail(int, char *, ...); - -#define NALEN 8 /* nulladdress string length */ - -/* - * Print a summary of connections related to a unix protocol. - */ -void -unixpr(kstat_ctl_t *kc) -{ - kstat_t *ksp; - - if (kc == NULL) { /* sanity check. */ - fail(0, "unixpr: No kstat"); - exit(3); - } - - /* find the sockfs kstat: */ - if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) == - (kstat_t *)NULL) { - fail(0, "kstat_data_lookup failed\n"); - } - - if (kstat_read(kc, ksp, NULL) == -1) { - fail(0, "kstat_read failed for sock_unix_list\n"); - } - - print_kn(ksp); -} - -static void -print_kn(kstat_t *ksp) -{ - int i; - struct sockinfo *psi; /* ptr to current sockinfo */ - char *pas; /* ptr to string-format addrs */ - char *nullstr; /* ptr to null string */ - char *conn_vp; - char *local_vp; - - if (ksp->ks_ndata == 0) { - return; /* no AF_UNIX sockets found */ - } - - /* - * Having ks_data set with ks_data == NULL shouldn't happen; - * If it does, the sockfs kstat is seriously broken. - */ - if ((psi = ksp->ks_data) == NULL) { - fail(0, "print_kn: no kstat data\n"); - } - - /* set pas to the address strings which are after the sockinfo */ - pas = &((char *)psi)[sizeof (struct sockinfo)]; - - /* Create a string of NALEN "0"'s for NULL addresses. */ - if ((nullstr = calloc(1, NALEN)) == NULL) { - fail(0, "print_kn: out of memory\n"); - } - (void) memset((void *)nullstr, '0', NALEN); - - (void) printf("\nActive UNIX domain sockets\n"); - (void) printf("%-8.8s %-10.10s %8.8s %8.8s " - "Local Addr Remote Addr\n", - "Address", "Type", "Vnode", "Conn"); - - /* for each sockinfo structure, display what we need: */ - for (i = 0; i < ksp->ks_ndata; i++) { - /* display sonode's address. 1st string after sockinfo: */ - pas = &(((char *)psi)[sizeof (struct sockinfo)]); - (void) printf("%s ", pas); - - (void) printf("%-10.10s ", typetoname(psi->si_serv_type)); - - /* laddr.sou_vp: 2nd string after sockinfo: */ - pas = nextstr(pas); - - local_vp = conn_vp = nullstr; - - if ((psi->si_state & SS_ISBOUND) && - (psi->si_ux_laddr_sou_magic == SOU_MAGIC_EXPLICIT)) { - local_vp = pas; - } - - /* faddr.sou_vp: 3rd string after sockinfo: */ - pas = nextstr(pas); - if ((psi->si_state & SS_ISCONNECTED) && - (psi->si_ux_faddr_sou_magic == SOU_MAGIC_EXPLICIT)) { - conn_vp = pas; - } - - (void) printf("%s %s ", local_vp, conn_vp); - - /* laddr.soa_sa: */ - if ((psi->si_state & SS_ISBOUND) && - strlen(psi->si_laddr_sun_path) != 0 && - psi->si_laddr_soa_len != 0) { - if (psi->si_faddr_noxlate) { - (void) printf(" (socketpair) "); - } else { - if (psi->si_laddr_soa_len > - sizeof (psi->si_laddr_family)) - (void) printf("%s ", - psi->si_laddr_sun_path); - else - (void) printf(" "); - } - } else - (void) printf(" "); - - /* faddr.soa_sa: */ - if ((psi->si_state & SS_ISCONNECTED) && - strlen(psi->si_faddr_sun_path) != 0 && - psi->si_faddr_soa_len != 0) { - - if (psi->si_faddr_noxlate) { - (void) printf(" (socketpair) "); - } else { - if (psi->si_faddr_soa_len > - sizeof (psi->si_faddr_family)) - (void) printf("%s ", - psi->si_faddr_sun_path); - else - (void) printf(" "); - } - } else - (void) printf(" "); - - (void) printf("\n"); - - /* if si_size didn't get filled in, then we're done */ - if (psi->si_size == 0 || - !IS_P2ALIGNED(psi->si_size, sizeof (psi))) { - break; - } - - /* LINTED: (note 1) */ - psi = (struct sockinfo *)&(((char *)psi)[psi->si_size]); - } -} - -static char * -typetoname(t_scalar_t type) -{ - switch (type) { - case T_CLTS: - return ("dgram"); - - case T_COTS: - return ("stream"); - - case T_COTS_ORD: - return ("stream-ord"); - - default: - return (""); - } -} - -/* - * nextstr(): find the beginning of a next string. - * The sockfs kstat left-justifies each address string, leaving - * null's between the strings. Since we don't necessarily know - * the sizes of pointers in the kernel, we need to skip over these - * nulls in order to get to the start of the next string. - */ -static char * -nextstr(char *pas) -{ - char *next; - - for (next = &pas[strlen(pas) + 1]; *next == '\0'; ) { - next++; - } - - return (next); -} diff --git a/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs b/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs index 58dcfe2a46..e93076d9ce 100644 --- a/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs +++ b/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs @@ -22,6 +22,7 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014 Racktop Systems. + * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -62,8 +63,8 @@ * * sockfs:*:sock_unix_list * This is stored as an array with one entry per active socket. Each element - * is of type struct k_sockinfo. The ks_ndata and ks_data_size fields are both - * zero. + * is of type struct sockinfo. ks_ndata is the number of elements of that + * array and ks_data_size is the total size of the array. * * Note that the ks_ndata and ks_data_size of many non-array raw kstats are * also incorrect. The relevant assertions are therefore commented out in the diff --git a/usr/src/cmd/stat/common/statcommon.h b/usr/src/cmd/stat/common/statcommon.h index fd3e9d2d9b..d39aee8687 100644 --- a/usr/src/cmd/stat/common/statcommon.h +++ b/usr/src/cmd/stat/common/statcommon.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -45,6 +46,7 @@ extern "C" { #include <sys/processor.h> #include <sys/pset.h> #include <sys/avl.h> +#include <sys/ccompile.h> /* No CPU present at this CPU position */ #define ID_NO_CPU -1 @@ -66,13 +68,13 @@ extern "C" { enum snapshot_types { /* All CPUs separately */ - SNAP_CPUS = 1 << 0, + SNAP_CPUS = 1 << 0, /* Aggregated processor sets */ SNAP_PSETS = 1 << 1, /* sys-wide stats including aggregated CPU stats */ SNAP_SYSTEM = 1 << 2, /* interrupt sources and counts */ - SNAP_INTERRUPTS = 1 << 3, + SNAP_INTERRUPTS = 1 << 3, /* disk etc. stats */ SNAP_IODEVS = 1 << 4, /* disk controller aggregates */ @@ -228,7 +230,7 @@ struct snapshot { }; /* print a message and exit with failure */ -void fail(int do_perror, char *message, ...); +void fail(int do_perror, char *message, ...) __NORETURN; /* strdup str, or exit with failure */ char *safe_strdup(char *str); |
