1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 1990 Mentat Inc. 24 * netstat.c 2.2, last change 9/9/91 25 * MROUTING Revision 3.5 26 */ 27 28 /* 29 * simple netstat based on snmp/mib-2 interface to the TCP/IP stack 30 * 31 * NOTES: 32 * 1. A comment "LINTED: (note 1)" appears before certain lines where 33 * lint would have complained, "pointer cast may result in improper 34 * alignment". These are lines where lint had suspected potential 35 * improper alignment of a data structure; in each such situation 36 * we have relied on the kernel guaranteeing proper alignment. 37 * 2. Some 'for' loops have been commented as "'for' loop 1", etc 38 * because they have 'continue' or 'break' statements in their 39 * bodies. 'continue' statements have been used inside some loops 40 * where avoiding them would have led to deep levels of indentation. 41 * 42 * TODO: 43 * Add ability to request subsets from kernel (with level = MIB2_IP; 44 * name = 0 meaning everything for compatibility) 45 */ 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <stdarg.h> 50 #include <unistd.h> 51 #include <strings.h> 52 #include <string.h> 53 #include <errno.h> 54 #include <ctype.h> 55 #include <kstat.h> 56 #include <assert.h> 57 #include <locale.h> 58 #include <pwd.h> 59 #include <limits.h> 60 61 #include <sys/types.h> 62 #include <sys/stat.h> 63 #include <sys/stream.h> 64 #include <stropts.h> 65 #include <sys/strstat.h> 66 #include <sys/tihdr.h> 67 #include <procfs.h> 68 69 #include <sys/socket.h> 70 #include <sys/socketvar.h> 71 #include <sys/sockio.h> 72 #include <netinet/in.h> 73 #include <net/if.h> 74 #include <net/route.h> 75 76 #include <inet/mib2.h> 77 #include <inet/ip.h> 78 #include <inet/arp.h> 79 #include <inet/tcp.h> 80 #include <netinet/igmp_var.h> 81 #include <netinet/ip_mroute.h> 82 83 #include <arpa/inet.h> 84 #include <netdb.h> 85 #include <fcntl.h> 86 #include <sys/systeminfo.h> 87 #include <arpa/inet.h> 88 89 #include <netinet/dhcp.h> 90 #include <dhcpagent_ipc.h> 91 #include <dhcpagent_util.h> 92 #include <compat.h> 93 94 #include <libtsnet.h> 95 #include <tsol/label.h> 96 97 #include "statcommon.h" 98 99 100 #define STR_EXPAND 4 101 102 #define V4MASK_TO_V6(v4, v6) ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \ 103 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \ 104 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \ 105 (v6)._S6_un._S6_u32[3] = (v4)) 106 107 #define IN6_IS_V4MASK(v6) ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \ 108 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \ 109 (v6)._S6_un._S6_u32[2] == 0xfffffffful) 110 111 /* 112 * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM. 113 * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's 114 * possible for an administrator to plumb new interfaces between those two 115 * calls, resulting in the failure of the latter. This addition makes that 116 * less likely. 117 */ 118 #define LIFN_GUARD_VALUE 10 119 120 typedef struct mib_item_s { 121 struct mib_item_s *next_item; 122 int group; 123 int mib_id; 124 int length; 125 void *valp; 126 } mib_item_t; 127 128 struct ifstat { 129 uint64_t ipackets; 130 uint64_t ierrors; 131 uint64_t opackets; 132 uint64_t oerrors; 133 uint64_t collisions; 134 }; 135 136 struct iflist { 137 struct iflist *next_if; 138 char ifname[LIFNAMSIZ]; 139 struct ifstat tot; 140 }; 141 142 typedef struct proc_info { 143 char *pr_user; 144 char *pr_fname; 145 char *pr_psargs; 146 } proc_info_t; 147 148 static mib_item_t *mibget(int sd); 149 static void mibfree(mib_item_t *firstitem); 150 static int mibopen(void); 151 static void mib_get_constants(mib_item_t *item); 152 static mib_item_t *mib_item_dup(mib_item_t *item); 153 static mib_item_t *mib_item_diff(mib_item_t *item1, 154 mib_item_t *item2); 155 static void mib_item_destroy(mib_item_t **item); 156 157 static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b); 158 static char *octetstr(const Octet_t *op, int code, 159 char *dst, uint_t dstlen); 160 static char *pr_addr(uint_t addr, 161 char *dst, uint_t dstlen); 162 static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen); 163 static char *pr_addr6(const in6_addr_t *addr, 164 char *dst, uint_t dstlen); 165 static char *pr_mask(uint_t addr, 166 char *dst, uint_t dstlen); 167 static char *pr_prefix6(const struct in6_addr *addr, 168 uint_t prefixlen, char *dst, uint_t dstlen); 169 static char *pr_ap(uint_t addr, uint_t port, 170 char *proto, char *dst, uint_t dstlen); 171 static char *pr_ap6(const in6_addr_t *addr, uint_t port, 172 char *proto, char *dst, uint_t dstlen); 173 static char *pr_net(uint_t addr, uint_t mask, 174 char *dst, uint_t dstlen); 175 static char *pr_netaddr(uint_t addr, uint_t mask, 176 char *dst, uint_t dstlen); 177 static char *fmodestr(uint_t fmode); 178 static char *portname(uint_t port, char *proto, 179 char *dst, uint_t dstlen); 180 181 static const char *mitcp_state(int code, 182 const mib2_transportMLPEntry_t *attr); 183 static const char *miudp_state(int code, 184 const mib2_transportMLPEntry_t *attr); 185 186 static void stat_report(mib_item_t *item); 187 static void mrt_stat_report(mib_item_t *item); 188 static void arp_report(mib_item_t *item); 189 static void ndp_report(mib_item_t *item); 190 static void mrt_report(mib_item_t *item); 191 static void if_stat_total(struct ifstat *oldstats, 192 struct ifstat *newstats, struct ifstat *sumstats); 193 static void if_report(mib_item_t *item, char *ifname, 194 int Iflag_only, boolean_t once_only); 195 static void if_report_ip4(mib2_ipAddrEntry_t *ap, 196 char ifname[], char logintname[], 197 struct ifstat *statptr, boolean_t ksp_not_null); 198 static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6, 199 char ifname[], char logintname[], 200 struct ifstat *statptr, boolean_t ksp_not_null); 201 static void ire_report(const mib_item_t *item); 202 static void tcp_report(const mib_item_t *item); 203 static void udp_report(const mib_item_t *item); 204 static void uds_report(kstat_ctl_t *); 205 static void group_report(mib_item_t *item); 206 static void dce_report(mib_item_t *item); 207 static void print_ip_stats(mib2_ip_t *ip); 208 static void print_icmp_stats(mib2_icmp_t *icmp); 209 static void print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6); 210 static void print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6); 211 static void print_sctp_stats(mib2_sctp_t *tcp); 212 static void print_tcp_stats(mib2_tcp_t *tcp); 213 static void print_udp_stats(mib2_udp_t *udp); 214 static void print_rawip_stats(mib2_rawip_t *rawip); 215 static void print_igmp_stats(struct igmpstat *igps); 216 static void print_mrt_stats(struct mrtstat *mrts); 217 static void sctp_report(const mib_item_t *item); 218 static void sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6, 219 mib2_ipv6IfStatsEntry_t *sum6); 220 static void sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6, 221 mib2_ipv6IfIcmpEntry_t *sum6); 222 static void m_report(void); 223 static void dhcp_report(char *); 224 225 static uint64_t kstat_named_value(kstat_t *, char *); 226 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *); 227 static int isnum(char *); 228 static char *plural(int n); 229 static char *pluraly(int n); 230 static char *plurales(int n); 231 static void process_filter(char *arg); 232 static char *ifindex2str(uint_t, char *); 233 static boolean_t family_selected(int family); 234 235 static void usage(char *); 236 static char *get_username(uid_t); 237 proc_info_t *get_proc_info(pid_t); 238 static void fatal(int errcode, char *str1, ...); 239 240 #define PLURAL(n) plural((int)n) 241 #define PLURALY(n) pluraly((int)n) 242 #define PLURALES(n) plurales((int)n) 243 #define IFLAGMOD(flg, val1, val2) if (flg == val1) flg = val2 244 #define MDIFF(diff, elem2, elem1, member) (diff)->member = \ 245 (elem2)->member - (elem1)->member 246 247 248 static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */ 249 static boolean_t Dflag = B_FALSE; /* DCE info */ 250 static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */ 251 static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */ 252 static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */ 253 static boolean_t Rflag = B_FALSE; /* Routing Tables */ 254 static boolean_t RSECflag = B_FALSE; /* Security attributes */ 255 static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */ 256 static boolean_t Vflag = B_FALSE; /* Verbose */ 257 static boolean_t Uflag = B_FALSE; /* Show PID and UID info. */ 258 static boolean_t Pflag = B_FALSE; /* Net to Media Tables */ 259 static boolean_t Gflag = B_FALSE; /* Multicast group membership */ 260 static boolean_t MMflag = B_FALSE; /* Multicast routing table */ 261 static boolean_t DHCPflag = B_FALSE; /* DHCP statistics */ 262 static boolean_t Xflag = B_FALSE; /* Debug Info */ 263 264 static int v4compat = 0; /* Compatible printing format for status */ 265 266 static int proto = IPPROTO_MAX; /* all protocols */ 267 kstat_ctl_t *kc = NULL; 268 269 /* 270 * Sizes of data structures extracted from the base mib. 271 * This allows the size of the tables entries to grow while preserving 272 * binary compatibility. 273 */ 274 static int ipAddrEntrySize; 275 static int ipRouteEntrySize; 276 static int ipNetToMediaEntrySize; 277 static int ipMemberEntrySize; 278 static int ipGroupSourceEntrySize; 279 static int ipRouteAttributeSize; 280 static int vifctlSize; 281 static int mfcctlSize; 282 283 static int ipv6IfStatsEntrySize; 284 static int ipv6IfIcmpEntrySize; 285 static int ipv6AddrEntrySize; 286 static int ipv6RouteEntrySize; 287 static int ipv6NetToMediaEntrySize; 288 static int ipv6MemberEntrySize; 289 static int ipv6GroupSourceEntrySize; 290 291 static int ipDestEntrySize; 292 293 static int transportMLPSize; 294 static int tcpConnEntrySize; 295 static int tcp6ConnEntrySize; 296 static int udpEntrySize; 297 static int udp6EntrySize; 298 static int sctpEntrySize; 299 static int sctpLocalEntrySize; 300 static int sctpRemoteEntrySize; 301 302 #define protocol_selected(p) (proto == IPPROTO_MAX || proto == (p)) 303 304 /* Machinery used for -f (filter) option */ 305 enum { FK_AF = 0, FK_OUTIF, FK_DST, FK_FLAGS, NFILTERKEYS }; 306 307 static const char *filter_keys[NFILTERKEYS] = { 308 "af", "outif", "dst", "flags" 309 }; 310 311 static m_label_t *zone_security_label = NULL; 312 313 /* Flags on routes */ 314 #define FLF_A 0x00000001 315 #define FLF_b 0x00000002 316 #define FLF_D 0x00000004 317 #define FLF_G 0x00000008 318 #define FLF_H 0x00000010 319 #define FLF_L 0x00000020 320 #define FLF_U 0x00000040 321 #define FLF_M 0x00000080 322 #define FLF_S 0x00000100 323 #define FLF_C 0x00000200 /* IRE_IF_CLONE */ 324 #define FLF_I 0x00000400 /* RTF_INDIRECT */ 325 #define FLF_R 0x00000800 /* RTF_REJECT */ 326 #define FLF_B 0x00001000 /* RTF_BLACKHOLE */ 327 #define FLF_Z 0x00100000 /* RTF_ZONE */ 328 329 static const char flag_list[] = "AbDGHLUMSCIRBZ"; 330 331 typedef struct filter_rule filter_t; 332 333 struct filter_rule { 334 filter_t *f_next; 335 union { 336 int f_family; 337 const char *f_ifname; 338 struct { 339 struct hostent *f_address; 340 in6_addr_t f_mask; 341 } a; 342 struct { 343 uint_t f_flagset; 344 uint_t f_flagclear; 345 } f; 346 } u; 347 }; 348 349 /* 350 * The user-specified filters are linked into lists separated by 351 * keyword (type of filter). Thus, the matching algorithm is: 352 * For each non-empty filter list 353 * If no filters in the list match 354 * then stop here; route doesn't match 355 * If loop above completes, then route does match and will be 356 * displayed. 357 */ 358 static filter_t *filters[NFILTERKEYS]; 359 360 static uint_t timestamp_fmt = NODATE; 361 362 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 363 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't */ 364 #endif 365 366 int 367 main(int argc, char **argv) 368 { 369 char *name; 370 mib_item_t *item = NULL; 371 mib_item_t *previtem = NULL; 372 int sd = -1; 373 char *ifname = NULL; 374 int interval = 0; /* Single time by default */ 375 int count = -1; /* Forever */ 376 int c; 377 int d; 378 /* 379 * Possible values of 'Iflag_only': 380 * -1, no feature-flags; 381 * 0, IFlag and other feature-flags enabled 382 * 1, IFlag is the only feature-flag enabled 383 * : trinary variable, modified using IFLAGMOD() 384 */ 385 int Iflag_only = -1; 386 boolean_t once_only = B_FALSE; /* '-i' with count > 1 */ 387 extern char *optarg; 388 extern int optind; 389 char *default_ip_str = NULL; 390 391 name = argv[0]; 392 393 v4compat = get_compat_flag(&default_ip_str); 394 if (v4compat == DEFAULT_PROT_BAD_VALUE) 395 fatal(2, "%s: %s: Bad value for %s in %s\n", name, 396 default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE); 397 free(default_ip_str); 398 399 (void) setlocale(LC_ALL, ""); 400 (void) textdomain(TEXT_DOMAIN); 401 402 while ((c = getopt(argc, argv, "adimnrspMgvuxf:P:I:DRT:")) != -1) { 403 switch ((char)c) { 404 case 'a': /* all connections */ 405 Aflag = B_TRUE; 406 break; 407 408 case 'd': /* DCE info */ 409 Dflag = B_TRUE; 410 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 411 break; 412 413 case 'i': /* interface (ill/ipif report) */ 414 Iflag = B_TRUE; 415 IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */ 416 break; 417 418 case 'm': /* streams msg report */ 419 Mflag = B_TRUE; 420 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 421 break; 422 423 case 'n': /* numeric format */ 424 Nflag = B_TRUE; 425 break; 426 427 case 'r': /* route tables */ 428 Rflag = B_TRUE; 429 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 430 break; 431 432 case 'R': /* security attributes */ 433 RSECflag = B_TRUE; 434 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 435 break; 436 437 case 's': /* per-protocol statistics */ 438 Sflag = B_TRUE; 439 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 440 break; 441 442 case 'p': /* arp/ndp table */ 443 Pflag = B_TRUE; 444 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 445 break; 446 447 case 'M': /* multicast routing tables */ 448 MMflag = B_TRUE; 449 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 450 break; 451 452 case 'g': /* multicast group membership */ 453 Gflag = B_TRUE; 454 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 455 break; 456 457 case 'v': /* verbose output format */ 458 Vflag = B_TRUE; 459 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */ 460 break; 461 462 case 'u': /* show pid and uid information */ 463 Uflag = B_TRUE; 464 break; 465 466 case 'x': /* turn on debugging */ 467 Xflag = B_TRUE; 468 break; 469 470 case 'f': 471 process_filter(optarg); 472 break; 473 474 case 'P': 475 if (strcmp(optarg, "ip") == 0) { 476 proto = IPPROTO_IP; 477 } else if (strcmp(optarg, "ipv6") == 0 || 478 strcmp(optarg, "ip6") == 0) { 479 v4compat = 0; /* Overridden */ 480 proto = IPPROTO_IPV6; 481 } else if (strcmp(optarg, "icmp") == 0) { 482 proto = IPPROTO_ICMP; 483 } else if (strcmp(optarg, "icmpv6") == 0 || 484 strcmp(optarg, "icmp6") == 0) { 485 v4compat = 0; /* Overridden */ 486 proto = IPPROTO_ICMPV6; 487 } else if (strcmp(optarg, "igmp") == 0) { 488 proto = IPPROTO_IGMP; 489 } else if (strcmp(optarg, "udp") == 0) { 490 proto = IPPROTO_UDP; 491 } else if (strcmp(optarg, "tcp") == 0) { 492 proto = IPPROTO_TCP; 493 } else if (strcmp(optarg, "sctp") == 0) { 494 proto = IPPROTO_SCTP; 495 } else if (strcmp(optarg, "raw") == 0 || 496 strcmp(optarg, "rawip") == 0) { 497 proto = IPPROTO_RAW; 498 } else { 499 fatal(1, "%s: unknown protocol.\n", optarg); 500 } 501 break; 502 503 case 'I': 504 ifname = optarg; 505 Iflag = B_TRUE; 506 IFLAGMOD(Iflag_only, -1, 1); /* see macro def'n */ 507 break; 508 509 case 'D': 510 DHCPflag = B_TRUE; 511 Iflag_only = 0; 512 break; 513 514 case 'T': 515 if (optarg) { 516 if (*optarg == 'u') 517 timestamp_fmt = UDATE; 518 else if (*optarg == 'd') 519 timestamp_fmt = DDATE; 520 else 521 usage(name); 522 } else { 523 usage(name); 524 } 525 break; 526 527 case '?': 528 default: 529 usage(name); 530 } 531 } 532 533 /* 534 * Make sure -R option is set only on a labeled system. 535 */ 536 if (RSECflag && !is_system_labeled()) { 537 (void) fprintf(stderr, "-R set but labeling is not enabled\n"); 538 usage(name); 539 } 540 541 /* 542 * Handle other arguments: find interval, count; the 543 * flags that accept 'interval' and 'count' are OR'd 544 * in the outermost 'if'; more flags may be added as 545 * required 546 */ 547 if (Iflag || Sflag || Mflag) { 548 for (d = optind; d < argc; d++) { 549 if (isnum(argv[d])) { 550 interval = atoi(argv[d]); 551 if (d + 1 < argc && 552 isnum(argv[d + 1])) { 553 count = atoi(argv[d + 1]); 554 optind++; 555 } 556 optind++; 557 if (interval == 0 || count == 0) 558 usage(name); 559 break; 560 } 561 } 562 } 563 if (optind < argc) { 564 if (Iflag && isnum(argv[optind])) { 565 count = atoi(argv[optind]); 566 if (count == 0) 567 usage(name); 568 optind++; 569 } 570 } 571 if (optind < argc) { 572 (void) fprintf(stderr, 573 "%s: extra arguments\n", name); 574 usage(name); 575 } 576 if (interval) 577 setbuf(stdout, NULL); 578 579 if (DHCPflag) { 580 dhcp_report(Iflag ? ifname : NULL); 581 exit(0); 582 } 583 584 /* 585 * Get this process's security label if the -R switch is set. 586 * We use this label as the current zone's security label. 587 */ 588 if (RSECflag) { 589 zone_security_label = m_label_alloc(MAC_LABEL); 590 if (zone_security_label == NULL) 591 fatal(errno, "m_label_alloc() failed"); 592 if (getplabel(zone_security_label) < 0) 593 fatal(errno, "getplabel() failed"); 594 } 595 596 /* Get data structures: priming before iteration */ 597 if (family_selected(AF_INET) || family_selected(AF_INET6)) { 598 sd = mibopen(); 599 if (sd == -1) 600 fatal(1, "can't open mib stream\n"); 601 if ((item = mibget(sd)) == NULL) { 602 (void) close(sd); 603 fatal(1, "mibget() failed\n"); 604 } 605 /* Extract constant sizes - need do once only */ 606 mib_get_constants(item); 607 } 608 if ((kc = kstat_open()) == NULL) { 609 mibfree(item); 610 (void) close(sd); 611 fail(1, "kstat_open(): can't open /dev/kstat"); 612 } 613 614 if (interval <= 0) { 615 count = 1; 616 once_only = B_TRUE; 617 } 618 /* 'for' loop 1: */ 619 for (;;) { 620 mib_item_t *curritem = NULL; /* only for -[M]s */ 621 622 if (timestamp_fmt != NODATE) 623 print_timestamp(timestamp_fmt); 624 625 /* netstat: AF_INET[6] behaviour */ 626 if (family_selected(AF_INET) || family_selected(AF_INET6)) { 627 if (Sflag) { 628 curritem = mib_item_diff(previtem, item); 629 if (curritem == NULL) 630 fatal(1, "can't process mib data, " 631 "out of memory\n"); 632 mib_item_destroy(&previtem); 633 } 634 635 if (!(Dflag || Iflag || Rflag || Sflag || Mflag || 636 MMflag || Pflag || Gflag || DHCPflag)) { 637 if (protocol_selected(IPPROTO_UDP)) 638 udp_report(item); 639 if (protocol_selected(IPPROTO_TCP)) 640 tcp_report(item); 641 if (protocol_selected(IPPROTO_SCTP)) 642 sctp_report(item); 643 } 644 if (Iflag) 645 if_report(item, ifname, Iflag_only, once_only); 646 if (Mflag) 647 m_report(); 648 if (Rflag) 649 ire_report(item); 650 if (Sflag && MMflag) { 651 mrt_stat_report(curritem); 652 } else { 653 if (Sflag) 654 stat_report(curritem); 655 if (MMflag) 656 mrt_report(item); 657 } 658 if (Gflag) 659 group_report(item); 660 if (Pflag) { 661 if (family_selected(AF_INET)) 662 arp_report(item); 663 if (family_selected(AF_INET6)) 664 ndp_report(item); 665 } 666 if (Dflag) 667 dce_report(item); 668 mib_item_destroy(&curritem); 669 } 670 671 /* netstat: AF_UNIX behaviour */ 672 if (family_selected(AF_UNIX) && 673 (!(Dflag || Iflag || Rflag || Sflag || Mflag || 674 MMflag || Pflag || Gflag))) 675 uds_report(kc); 676 (void) kstat_close(kc); 677 678 /* iteration handling code */ 679 if (count > 0 && --count == 0) 680 break; 681 (void) sleep(interval); 682 683 /* re-populating of data structures */ 684 if (family_selected(AF_INET) || family_selected(AF_INET6)) { 685 if (Sflag) { 686 /* previtem is a cut-down list */ 687 previtem = mib_item_dup(item); 688 if (previtem == NULL) 689 fatal(1, "can't process mib data, " 690 "out of memory\n"); 691 } 692 mibfree(item); 693 (void) close(sd); 694 if ((sd = mibopen()) == -1) 695 fatal(1, "can't open mib stream anymore\n"); 696 if ((item = mibget(sd)) == NULL) { 697 (void) close(sd); 698 fatal(1, "mibget() failed\n"); 699 } 700 } 701 if ((kc = kstat_open()) == NULL) 702 fail(1, "kstat_open(): can't open /dev/kstat"); 703 704 } /* 'for' loop 1 ends */ 705 mibfree(item); 706 (void) close(sd); 707 if (zone_security_label != NULL) 708 m_label_free(zone_security_label); 709 710 return (0); 711 } 712 713 714 static int 715 isnum(char *p) 716 { 717 int len; 718 int i; 719 720 len = strlen(p); 721 for (i = 0; i < len; i++) 722 if (!isdigit(p[i])) 723 return (0); 724 return (1); 725 } 726 727 728 /* --------------------------------- MIBGET -------------------------------- */ 729 730 static mib_item_t * 731 mibget(int sd) 732 { 733 /* 734 * buf is an automatic for this function, so the 735 * compiler has complete control over its alignment; 736 * it is assumed this alignment is satisfactory for 737 * it to be casted to certain other struct pointers 738 * here, such as struct T_optmgmt_ack * . 739 */ 740 uintptr_t buf[512 / sizeof (uintptr_t)]; 741 int flags; 742 int i, j, getcode; 743 struct strbuf ctlbuf, databuf; 744 struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf; 745 struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf; 746 struct T_error_ack *tea = (struct T_error_ack *)buf; 747 struct opthdr *req; 748 mib_item_t *first_item = NULL; 749 mib_item_t *last_item = NULL; 750 mib_item_t *temp; 751 752 tor->PRIM_type = T_SVR4_OPTMGMT_REQ; 753 tor->OPT_offset = sizeof (struct T_optmgmt_req); 754 tor->OPT_length = sizeof (struct opthdr); 755 tor->MGMT_flags = T_CURRENT; 756 757 758 /* 759 * Note: we use the special level value below so that IP will return 760 * us information concerning IRE_MARK_TESTHIDDEN routes. 761 */ 762 req = (struct opthdr *)&tor[1]; 763 req->level = EXPER_IP_AND_ALL_IRES; 764 req->name = 0; 765 req->len = 1; 766 767 ctlbuf.buf = (char *)buf; 768 ctlbuf.len = tor->OPT_length + tor->OPT_offset; 769 flags = 0; 770 if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) { 771 perror("mibget: putmsg(ctl) failed"); 772 goto error_exit; 773 } 774 775 /* 776 * Each reply consists of a ctl part for one fixed structure 777 * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK, 778 * containing an opthdr structure. level/name identify the entry, 779 * len is the size of the data part of the message. 780 */ 781 req = (struct opthdr *)&toa[1]; 782 ctlbuf.maxlen = sizeof (buf); 783 j = 1; 784 for (;;) { 785 flags = 0; 786 getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags); 787 if (getcode == -1) { 788 perror("mibget getmsg(ctl) failed"); 789 if (Xflag) { 790 (void) fputs("# level name len\n", 791 stderr); 792 i = 0; 793 for (last_item = first_item; last_item; 794 last_item = last_item->next_item) 795 (void) printf("%d %4d %5d %d\n", 796 ++i, 797 last_item->group, 798 last_item->mib_id, 799 last_item->length); 800 } 801 goto error_exit; 802 } 803 if (getcode == 0 && 804 ctlbuf.len >= sizeof (struct T_optmgmt_ack) && 805 toa->PRIM_type == T_OPTMGMT_ACK && 806 toa->MGMT_flags == T_SUCCESS && 807 req->len == 0) { 808 if (Xflag) 809 (void) printf("mibget getmsg() %d returned " 810 "EOD (level %ld, name %ld)\n", 811 j, req->level, req->name); 812 return (first_item); /* this is EOD msg */ 813 } 814 815 if (ctlbuf.len >= sizeof (struct T_error_ack) && 816 tea->PRIM_type == T_ERROR_ACK) { 817 (void) fprintf(stderr, 818 "mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, " 819 "UNIX_error = 0x%lx\n", 820 j, tea->TLI_error, tea->UNIX_error); 821 822 errno = (tea->TLI_error == TSYSERR) ? 823 tea->UNIX_error : EPROTO; 824 goto error_exit; 825 } 826 827 if (getcode != MOREDATA || 828 ctlbuf.len < sizeof (struct T_optmgmt_ack) || 829 toa->PRIM_type != T_OPTMGMT_ACK || 830 toa->MGMT_flags != T_SUCCESS) { 831 (void) printf("mibget getmsg(ctl) %d returned %d, " 832 "ctlbuf.len = %d, PRIM_type = %ld\n", 833 j, getcode, ctlbuf.len, toa->PRIM_type); 834 835 if (toa->PRIM_type == T_OPTMGMT_ACK) 836 (void) printf("T_OPTMGMT_ACK: " 837 "MGMT_flags = 0x%lx, req->len = %ld\n", 838 toa->MGMT_flags, req->len); 839 errno = ENOMSG; 840 goto error_exit; 841 } 842 843 temp = (mib_item_t *)malloc(sizeof (mib_item_t)); 844 if (temp == NULL) { 845 perror("mibget malloc failed"); 846 goto error_exit; 847 } 848 if (last_item != NULL) 849 last_item->next_item = temp; 850 else 851 first_item = temp; 852 last_item = temp; 853 last_item->next_item = NULL; 854 last_item->group = req->level; 855 last_item->mib_id = req->name; 856 last_item->length = req->len; 857 last_item->valp = malloc((int)req->len); 858 if (last_item->valp == NULL) 859 goto error_exit; 860 if (Xflag) 861 (void) printf("msg %d: group = %4d mib_id = %5d" 862 "length = %d\n", 863 j, last_item->group, last_item->mib_id, 864 last_item->length); 865 866 databuf.maxlen = last_item->length; 867 databuf.buf = (char *)last_item->valp; 868 databuf.len = 0; 869 flags = 0; 870 getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags); 871 if (getcode == -1) { 872 perror("mibget getmsg(data) failed"); 873 goto error_exit; 874 } else if (getcode != 0) { 875 (void) printf("mibget getmsg(data) returned %d, " 876 "databuf.maxlen = %d, databuf.len = %d\n", 877 getcode, databuf.maxlen, databuf.len); 878 goto error_exit; 879 } 880 j++; 881 } 882 /* NOTREACHED */ 883 884 error_exit:; 885 mibfree(first_item); 886 return (NULL); 887 } 888 889 /* 890 * mibfree: frees a linked list of type (mib_item_t *) 891 * returned by mibget(); this is NOT THE SAME AS 892 * mib_item_destroy(), so should be used for objects 893 * returned by mibget() only 894 */ 895 static void 896 mibfree(mib_item_t *firstitem) 897 { 898 mib_item_t *lastitem; 899 900 while (firstitem != NULL) { 901 lastitem = firstitem; 902 firstitem = firstitem->next_item; 903 if (lastitem->valp != NULL) 904 free(lastitem->valp); 905 free(lastitem); 906 } 907 } 908 909 static int 910 mibopen(void) 911 { 912 int sd; 913 914 sd = open("/dev/arp", O_RDWR); 915 if (sd == -1) { 916 perror("arp open"); 917 return (-1); 918 } 919 if (ioctl(sd, I_PUSH, "tcp") == -1) { 920 perror("tcp I_PUSH"); 921 (void) close(sd); 922 return (-1); 923 } 924 if (ioctl(sd, I_PUSH, "udp") == -1) { 925 perror("udp I_PUSH"); 926 (void) close(sd); 927 return (-1); 928 } 929 if (ioctl(sd, I_PUSH, "icmp") == -1) { 930 perror("icmp I_PUSH"); 931 (void) close(sd); 932 return (-1); 933 } 934 return (sd); 935 } 936 937 /* 938 * mib_item_dup: returns a clean mib_item_t * linked 939 * list, so that for every element item->mib_id is 0; 940 * to deallocate this linked list, use mib_item_destroy 941 */ 942 static mib_item_t * 943 mib_item_dup(mib_item_t *item) 944 { 945 int c = 0; 946 mib_item_t *localp; 947 mib_item_t *tempp; 948 949 for (tempp = item; tempp; tempp = tempp->next_item) 950 if (tempp->mib_id == 0) 951 c++; 952 tempp = NULL; 953 954 localp = (mib_item_t *)malloc(c * sizeof (mib_item_t)); 955 if (localp == NULL) 956 return (NULL); 957 c = 0; 958 for (; item; item = item->next_item) { 959 if (item->mib_id == 0) { 960 /* Replicate item in localp */ 961 (localp[c]).next_item = NULL; 962 (localp[c]).group = item->group; 963 (localp[c]).mib_id = item->mib_id; 964 (localp[c]).length = item->length; 965 (localp[c]).valp = (uintptr_t *)malloc( 966 item->length); 967 if ((localp[c]).valp == NULL) { 968 mib_item_destroy(&localp); 969 return (NULL); 970 } 971 (void *) memcpy((localp[c]).valp, 972 item->valp, 973 item->length); 974 tempp = &(localp[c]); 975 if (c > 0) 976 (localp[c - 1]).next_item = tempp; 977 c++; 978 } 979 } 980 return (localp); 981 } 982 983 /* 984 * mib_item_diff: takes two (mib_item_t *) linked lists 985 * item1 and item2 and computes the difference between 986 * differentiable values in item2 against item1 for every 987 * given member of item2; returns an mib_item_t * linked 988 * list of diff's, or a copy of item2 if item1 is NULL; 989 * will return NULL if system out of memory; works only 990 * for item->mib_id == 0 991 */ 992 static mib_item_t * 993 mib_item_diff(mib_item_t *item1, mib_item_t *item2) 994 { 995 int nitems = 0; /* no. of items in item2 */ 996 mib_item_t *tempp2; /* walking copy of item2 */ 997 mib_item_t *tempp1; /* walking copy of item1 */ 998 mib_item_t *diffp; 999 mib_item_t *diffptr; /* walking copy of diffp */ 1000 mib_item_t *prevp = NULL; 1001 1002 if (item1 == NULL) { 1003 diffp = mib_item_dup(item2); 1004 return (diffp); 1005 } 1006 1007 for (tempp2 = item2; 1008 tempp2; 1009 tempp2 = tempp2->next_item) { 1010 if (tempp2->mib_id == 0) 1011 switch (tempp2->group) { 1012 /* 1013 * upon adding a case here, the same 1014 * must also be added in the next 1015 * switch statement, alongwith 1016 * appropriate code 1017 */ 1018 case MIB2_IP: 1019 case MIB2_IP6: 1020 case EXPER_DVMRP: 1021 case EXPER_IGMP: 1022 case MIB2_ICMP: 1023 case MIB2_ICMP6: 1024 case MIB2_TCP: 1025 case MIB2_UDP: 1026 case MIB2_SCTP: 1027 case EXPER_RAWIP: 1028 nitems++; 1029 } 1030 } 1031 tempp2 = NULL; 1032 if (nitems == 0) { 1033 diffp = mib_item_dup(item2); 1034 return (diffp); 1035 } 1036 1037 diffp = (mib_item_t *)calloc(nitems, sizeof (mib_item_t)); 1038 if (diffp == NULL) 1039 return (NULL); 1040 diffptr = diffp; 1041 /* 'for' loop 1: */ 1042 for (tempp2 = item2; tempp2 != NULL; tempp2 = tempp2->next_item) { 1043 if (tempp2->mib_id != 0) 1044 continue; /* 'for' loop 1 */ 1045 /* 'for' loop 2: */ 1046 for (tempp1 = item1; tempp1 != NULL; 1047 tempp1 = tempp1->next_item) { 1048 if (!(tempp1->mib_id == 0 && 1049 tempp1->group == tempp2->group && 1050 tempp1->mib_id == tempp2->mib_id)) 1051 continue; /* 'for' loop 2 */ 1052 /* found comparable data sets */ 1053 if (prevp != NULL) 1054 prevp->next_item = diffptr; 1055 switch (tempp2->group) { 1056 /* 1057 * Indenting note: Because of long variable names 1058 * in cases MIB2_IP6 and MIB2_ICMP6, their contents 1059 * have been indented by one tab space only 1060 */ 1061 case MIB2_IP: { 1062 mib2_ip_t *i2 = (mib2_ip_t *)tempp2->valp; 1063 mib2_ip_t *i1 = (mib2_ip_t *)tempp1->valp; 1064 mib2_ip_t *d; 1065 1066 diffptr->group = tempp2->group; 1067 diffptr->mib_id = tempp2->mib_id; 1068 diffptr->length = tempp2->length; 1069 d = (mib2_ip_t *)calloc(tempp2->length, 1); 1070 if (d == NULL) 1071 goto mibdiff_out_of_memory; 1072 diffptr->valp = d; 1073 d->ipForwarding = i2->ipForwarding; 1074 d->ipDefaultTTL = i2->ipDefaultTTL; 1075 MDIFF(d, i2, i1, ipInReceives); 1076 MDIFF(d, i2, i1, ipInHdrErrors); 1077 MDIFF(d, i2, i1, ipInAddrErrors); 1078 MDIFF(d, i2, i1, ipInCksumErrs); 1079 MDIFF(d, i2, i1, ipForwDatagrams); 1080 MDIFF(d, i2, i1, ipForwProhibits); 1081 MDIFF(d, i2, i1, ipInUnknownProtos); 1082 MDIFF(d, i2, i1, ipInDiscards); 1083 MDIFF(d, i2, i1, ipInDelivers); 1084 MDIFF(d, i2, i1, ipOutRequests); 1085 MDIFF(d, i2, i1, ipOutDiscards); 1086 MDIFF(d, i2, i1, ipOutNoRoutes); 1087 MDIFF(d, i2, i1, ipReasmTimeout); 1088 MDIFF(d, i2, i1, ipReasmReqds); 1089 MDIFF(d, i2, i1, ipReasmOKs); 1090 MDIFF(d, i2, i1, ipReasmFails); 1091 MDIFF(d, i2, i1, ipReasmDuplicates); 1092 MDIFF(d, i2, i1, ipReasmPartDups); 1093 MDIFF(d, i2, i1, ipFragOKs); 1094 MDIFF(d, i2, i1, ipFragFails); 1095 MDIFF(d, i2, i1, ipFragCreates); 1096 MDIFF(d, i2, i1, ipRoutingDiscards); 1097 MDIFF(d, i2, i1, tcpInErrs); 1098 MDIFF(d, i2, i1, udpNoPorts); 1099 MDIFF(d, i2, i1, udpInCksumErrs); 1100 MDIFF(d, i2, i1, udpInOverflows); 1101 MDIFF(d, i2, i1, rawipInOverflows); 1102 MDIFF(d, i2, i1, ipsecInSucceeded); 1103 MDIFF(d, i2, i1, ipsecInFailed); 1104 MDIFF(d, i2, i1, ipInIPv6); 1105 MDIFF(d, i2, i1, ipOutIPv6); 1106 MDIFF(d, i2, i1, ipOutSwitchIPv6); 1107 prevp = diffptr++; 1108 break; 1109 } 1110 case MIB2_IP6: { 1111 mib2_ipv6IfStatsEntry_t *i2; 1112 mib2_ipv6IfStatsEntry_t *i1; 1113 mib2_ipv6IfStatsEntry_t *d; 1114 1115 i2 = (mib2_ipv6IfStatsEntry_t *)tempp2->valp; 1116 i1 = (mib2_ipv6IfStatsEntry_t *)tempp1->valp; 1117 diffptr->group = tempp2->group; 1118 diffptr->mib_id = tempp2->mib_id; 1119 diffptr->length = tempp2->length; 1120 d = (mib2_ipv6IfStatsEntry_t *)calloc( 1121 tempp2->length, 1); 1122 if (d == NULL) 1123 goto mibdiff_out_of_memory; 1124 diffptr->valp = d; 1125 d->ipv6Forwarding = i2->ipv6Forwarding; 1126 d->ipv6DefaultHopLimit = 1127 i2->ipv6DefaultHopLimit; 1128 1129 MDIFF(d, i2, i1, ipv6InReceives); 1130 MDIFF(d, i2, i1, ipv6InHdrErrors); 1131 MDIFF(d, i2, i1, ipv6InTooBigErrors); 1132 MDIFF(d, i2, i1, ipv6InNoRoutes); 1133 MDIFF(d, i2, i1, ipv6InAddrErrors); 1134 MDIFF(d, i2, i1, ipv6InUnknownProtos); 1135 MDIFF(d, i2, i1, ipv6InTruncatedPkts); 1136 MDIFF(d, i2, i1, ipv6InDiscards); 1137 MDIFF(d, i2, i1, ipv6InDelivers); 1138 MDIFF(d, i2, i1, ipv6OutForwDatagrams); 1139 MDIFF(d, i2, i1, ipv6OutRequests); 1140 MDIFF(d, i2, i1, ipv6OutDiscards); 1141 MDIFF(d, i2, i1, ipv6OutNoRoutes); 1142 MDIFF(d, i2, i1, ipv6OutFragOKs); 1143 MDIFF(d, i2, i1, ipv6OutFragFails); 1144 MDIFF(d, i2, i1, ipv6OutFragCreates); 1145 MDIFF(d, i2, i1, ipv6ReasmReqds); 1146 MDIFF(d, i2, i1, ipv6ReasmOKs); 1147 MDIFF(d, i2, i1, ipv6ReasmFails); 1148 MDIFF(d, i2, i1, ipv6InMcastPkts); 1149 MDIFF(d, i2, i1, ipv6OutMcastPkts); 1150 MDIFF(d, i2, i1, ipv6ReasmDuplicates); 1151 MDIFF(d, i2, i1, ipv6ReasmPartDups); 1152 MDIFF(d, i2, i1, ipv6ForwProhibits); 1153 MDIFF(d, i2, i1, udpInCksumErrs); 1154 MDIFF(d, i2, i1, udpInOverflows); 1155 MDIFF(d, i2, i1, rawipInOverflows); 1156 MDIFF(d, i2, i1, ipv6InIPv4); 1157 MDIFF(d, i2, i1, ipv6OutIPv4); 1158 MDIFF(d, i2, i1, ipv6OutSwitchIPv4); 1159 prevp = diffptr++; 1160 break; 1161 } 1162 case EXPER_DVMRP: { 1163 struct mrtstat *m2; 1164 struct mrtstat *m1; 1165 struct mrtstat *d; 1166 1167 m2 = (struct mrtstat *)tempp2->valp; 1168 m1 = (struct mrtstat *)tempp1->valp; 1169 diffptr->group = tempp2->group; 1170 diffptr->mib_id = tempp2->mib_id; 1171 diffptr->length = tempp2->length; 1172 d = (struct mrtstat *)calloc(tempp2->length, 1); 1173 if (d == NULL) 1174 goto mibdiff_out_of_memory; 1175 diffptr->valp = d; 1176 MDIFF(d, m2, m1, mrts_mfc_hits); 1177 MDIFF(d, m2, m1, mrts_mfc_misses); 1178 MDIFF(d, m2, m1, mrts_fwd_in); 1179 MDIFF(d, m2, m1, mrts_fwd_out); 1180 d->mrts_upcalls = m2->mrts_upcalls; 1181 MDIFF(d, m2, m1, mrts_fwd_drop); 1182 MDIFF(d, m2, m1, mrts_bad_tunnel); 1183 MDIFF(d, m2, m1, mrts_cant_tunnel); 1184 MDIFF(d, m2, m1, mrts_wrong_if); 1185 MDIFF(d, m2, m1, mrts_upq_ovflw); 1186 MDIFF(d, m2, m1, mrts_cache_cleanups); 1187 MDIFF(d, m2, m1, mrts_drop_sel); 1188 MDIFF(d, m2, m1, mrts_q_overflow); 1189 MDIFF(d, m2, m1, mrts_pkt2large); 1190 MDIFF(d, m2, m1, mrts_pim_badversion); 1191 MDIFF(d, m2, m1, mrts_pim_rcv_badcsum); 1192 MDIFF(d, m2, m1, mrts_pim_badregisters); 1193 MDIFF(d, m2, m1, mrts_pim_regforwards); 1194 MDIFF(d, m2, m1, mrts_pim_regsend_drops); 1195 MDIFF(d, m2, m1, mrts_pim_malformed); 1196 MDIFF(d, m2, m1, mrts_pim_nomemory); 1197 prevp = diffptr++; 1198 break; 1199 } 1200 case EXPER_IGMP: { 1201 struct igmpstat *i2; 1202 struct igmpstat *i1; 1203 struct igmpstat *d; 1204 1205 i2 = (struct igmpstat *)tempp2->valp; 1206 i1 = (struct igmpstat *)tempp1->valp; 1207 diffptr->group = tempp2->group; 1208 diffptr->mib_id = tempp2->mib_id; 1209 diffptr->length = tempp2->length; 1210 d = (struct igmpstat *)calloc( 1211 tempp2->length, 1); 1212 if (d == NULL) 1213 goto mibdiff_out_of_memory; 1214 diffptr->valp = d; 1215 MDIFF(d, i2, i1, igps_rcv_total); 1216 MDIFF(d, i2, i1, igps_rcv_tooshort); 1217 MDIFF(d, i2, i1, igps_rcv_badsum); 1218 MDIFF(d, i2, i1, igps_rcv_queries); 1219 MDIFF(d, i2, i1, igps_rcv_badqueries); 1220 MDIFF(d, i2, i1, igps_rcv_reports); 1221 MDIFF(d, i2, i1, igps_rcv_badreports); 1222 MDIFF(d, i2, i1, igps_rcv_ourreports); 1223 MDIFF(d, i2, i1, igps_snd_reports); 1224 prevp = diffptr++; 1225 break; 1226 } 1227 case MIB2_ICMP: { 1228 mib2_icmp_t *i2; 1229 mib2_icmp_t *i1; 1230 mib2_icmp_t *d; 1231 1232 i2 = (mib2_icmp_t *)tempp2->valp; 1233 i1 = (mib2_icmp_t *)tempp1->valp; 1234 diffptr->group = tempp2->group; 1235 diffptr->mib_id = tempp2->mib_id; 1236 diffptr->length = tempp2->length; 1237 d = (mib2_icmp_t *)calloc(tempp2->length, 1); 1238 if (d == NULL) 1239 goto mibdiff_out_of_memory; 1240 diffptr->valp = d; 1241 MDIFF(d, i2, i1, icmpInMsgs); 1242 MDIFF(d, i2, i1, icmpInErrors); 1243 MDIFF(d, i2, i1, icmpInCksumErrs); 1244 MDIFF(d, i2, i1, icmpInUnknowns); 1245 MDIFF(d, i2, i1, icmpInDestUnreachs); 1246 MDIFF(d, i2, i1, icmpInTimeExcds); 1247 MDIFF(d, i2, i1, icmpInParmProbs); 1248 MDIFF(d, i2, i1, icmpInSrcQuenchs); 1249 MDIFF(d, i2, i1, icmpInRedirects); 1250 MDIFF(d, i2, i1, icmpInBadRedirects); 1251 MDIFF(d, i2, i1, icmpInEchos); 1252 MDIFF(d, i2, i1, icmpInEchoReps); 1253 MDIFF(d, i2, i1, icmpInTimestamps); 1254 MDIFF(d, i2, i1, icmpInAddrMasks); 1255 MDIFF(d, i2, i1, icmpInAddrMaskReps); 1256 MDIFF(d, i2, i1, icmpInFragNeeded); 1257 MDIFF(d, i2, i1, icmpOutMsgs); 1258 MDIFF(d, i2, i1, icmpOutDrops); 1259 MDIFF(d, i2, i1, icmpOutErrors); 1260 MDIFF(d, i2, i1, icmpOutDestUnreachs); 1261 MDIFF(d, i2, i1, icmpOutTimeExcds); 1262 MDIFF(d, i2, i1, icmpOutParmProbs); 1263 MDIFF(d, i2, i1, icmpOutSrcQuenchs); 1264 MDIFF(d, i2, i1, icmpOutRedirects); 1265 MDIFF(d, i2, i1, icmpOutEchos); 1266 MDIFF(d, i2, i1, icmpOutEchoReps); 1267 MDIFF(d, i2, i1, icmpOutTimestamps); 1268 MDIFF(d, i2, i1, icmpOutTimestampReps); 1269 MDIFF(d, i2, i1, icmpOutAddrMasks); 1270 MDIFF(d, i2, i1, icmpOutAddrMaskReps); 1271 MDIFF(d, i2, i1, icmpOutFragNeeded); 1272 MDIFF(d, i2, i1, icmpInOverflows); 1273 prevp = diffptr++; 1274 break; 1275 } 1276 case MIB2_ICMP6: { 1277 mib2_ipv6IfIcmpEntry_t *i2; 1278 mib2_ipv6IfIcmpEntry_t *i1; 1279 mib2_ipv6IfIcmpEntry_t *d; 1280 1281 i2 = (mib2_ipv6IfIcmpEntry_t *)tempp2->valp; 1282 i1 = (mib2_ipv6IfIcmpEntry_t *)tempp1->valp; 1283 diffptr->group = tempp2->group; 1284 diffptr->mib_id = tempp2->mib_id; 1285 diffptr->length = tempp2->length; 1286 d = (mib2_ipv6IfIcmpEntry_t *)calloc(tempp2->length, 1); 1287 if (d == NULL) 1288 goto mibdiff_out_of_memory; 1289 diffptr->valp = d; 1290 MDIFF(d, i2, i1, ipv6IfIcmpInMsgs); 1291 MDIFF(d, i2, i1, ipv6IfIcmpInErrors); 1292 MDIFF(d, i2, i1, ipv6IfIcmpInDestUnreachs); 1293 MDIFF(d, i2, i1, ipv6IfIcmpInAdminProhibs); 1294 MDIFF(d, i2, i1, ipv6IfIcmpInTimeExcds); 1295 MDIFF(d, i2, i1, ipv6IfIcmpInParmProblems); 1296 MDIFF(d, i2, i1, ipv6IfIcmpInPktTooBigs); 1297 MDIFF(d, i2, i1, ipv6IfIcmpInEchos); 1298 MDIFF(d, i2, i1, ipv6IfIcmpInEchoReplies); 1299 MDIFF(d, i2, i1, ipv6IfIcmpInRouterSolicits); 1300 MDIFF(d, i2, i1, ipv6IfIcmpInRouterAdvertisements); 1301 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborSolicits); 1302 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborAdvertisements); 1303 MDIFF(d, i2, i1, ipv6IfIcmpInRedirects); 1304 MDIFF(d, i2, i1, ipv6IfIcmpInBadRedirects); 1305 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembQueries); 1306 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembResponses); 1307 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembReductions); 1308 MDIFF(d, i2, i1, ipv6IfIcmpInOverflows); 1309 MDIFF(d, i2, i1, ipv6IfIcmpOutMsgs); 1310 MDIFF(d, i2, i1, ipv6IfIcmpOutErrors); 1311 MDIFF(d, i2, i1, ipv6IfIcmpOutDestUnreachs); 1312 MDIFF(d, i2, i1, ipv6IfIcmpOutAdminProhibs); 1313 MDIFF(d, i2, i1, ipv6IfIcmpOutTimeExcds); 1314 MDIFF(d, i2, i1, ipv6IfIcmpOutParmProblems); 1315 MDIFF(d, i2, i1, ipv6IfIcmpOutPktTooBigs); 1316 MDIFF(d, i2, i1, ipv6IfIcmpOutEchos); 1317 MDIFF(d, i2, i1, ipv6IfIcmpOutEchoReplies); 1318 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterSolicits); 1319 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterAdvertisements); 1320 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborSolicits); 1321 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborAdvertisements); 1322 MDIFF(d, i2, i1, ipv6IfIcmpOutRedirects); 1323 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembQueries); 1324 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembResponses); 1325 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembReductions); 1326 prevp = diffptr++; 1327 break; 1328 } 1329 case MIB2_TCP: { 1330 mib2_tcp_t *t2; 1331 mib2_tcp_t *t1; 1332 mib2_tcp_t *d; 1333 1334 t2 = (mib2_tcp_t *)tempp2->valp; 1335 t1 = (mib2_tcp_t *)tempp1->valp; 1336 diffptr->group = tempp2->group; 1337 diffptr->mib_id = tempp2->mib_id; 1338 diffptr->length = tempp2->length; 1339 d = (mib2_tcp_t *)calloc(tempp2->length, 1); 1340 if (d == NULL) 1341 goto mibdiff_out_of_memory; 1342 diffptr->valp = d; 1343 d->tcpRtoMin = t2->tcpRtoMin; 1344 d->tcpRtoMax = t2->tcpRtoMax; 1345 d->tcpMaxConn = t2->tcpMaxConn; 1346 MDIFF(d, t2, t1, tcpActiveOpens); 1347 MDIFF(d, t2, t1, tcpPassiveOpens); 1348 MDIFF(d, t2, t1, tcpAttemptFails); 1349 MDIFF(d, t2, t1, tcpEstabResets); 1350 d->tcpCurrEstab = t2->tcpCurrEstab; 1351 MDIFF(d, t2, t1, tcpHCOutSegs); 1352 MDIFF(d, t2, t1, tcpOutDataSegs); 1353 MDIFF(d, t2, t1, tcpOutDataBytes); 1354 MDIFF(d, t2, t1, tcpRetransSegs); 1355 MDIFF(d, t2, t1, tcpRetransBytes); 1356 MDIFF(d, t2, t1, tcpOutAck); 1357 MDIFF(d, t2, t1, tcpOutAckDelayed); 1358 MDIFF(d, t2, t1, tcpOutUrg); 1359 MDIFF(d, t2, t1, tcpOutWinUpdate); 1360 MDIFF(d, t2, t1, tcpOutWinProbe); 1361 MDIFF(d, t2, t1, tcpOutControl); 1362 MDIFF(d, t2, t1, tcpOutRsts); 1363 MDIFF(d, t2, t1, tcpOutFastRetrans); 1364 MDIFF(d, t2, t1, tcpHCInSegs); 1365 MDIFF(d, t2, t1, tcpInAckSegs); 1366 MDIFF(d, t2, t1, tcpInAckBytes); 1367 MDIFF(d, t2, t1, tcpInDupAck); 1368 MDIFF(d, t2, t1, tcpInAckUnsent); 1369 MDIFF(d, t2, t1, tcpInDataInorderSegs); 1370 MDIFF(d, t2, t1, tcpInDataInorderBytes); 1371 MDIFF(d, t2, t1, tcpInDataUnorderSegs); 1372 MDIFF(d, t2, t1, tcpInDataUnorderBytes); 1373 MDIFF(d, t2, t1, tcpInDataDupSegs); 1374 MDIFF(d, t2, t1, tcpInDataDupBytes); 1375 MDIFF(d, t2, t1, tcpInDataPartDupSegs); 1376 MDIFF(d, t2, t1, tcpInDataPartDupBytes); 1377 MDIFF(d, t2, t1, tcpInDataPastWinSegs); 1378 MDIFF(d, t2, t1, tcpInDataPastWinBytes); 1379 MDIFF(d, t2, t1, tcpInWinProbe); 1380 MDIFF(d, t2, t1, tcpInWinUpdate); 1381 MDIFF(d, t2, t1, tcpInClosed); 1382 MDIFF(d, t2, t1, tcpRttNoUpdate); 1383 MDIFF(d, t2, t1, tcpRttUpdate); 1384 MDIFF(d, t2, t1, tcpTimRetrans); 1385 MDIFF(d, t2, t1, tcpTimRetransDrop); 1386 MDIFF(d, t2, t1, tcpTimKeepalive); 1387 MDIFF(d, t2, t1, tcpTimKeepaliveProbe); 1388 MDIFF(d, t2, t1, tcpTimKeepaliveDrop); 1389 MDIFF(d, t2, t1, tcpListenDrop); 1390 MDIFF(d, t2, t1, tcpListenDropQ0); 1391 MDIFF(d, t2, t1, tcpHalfOpenDrop); 1392 MDIFF(d, t2, t1, tcpOutSackRetransSegs); 1393 prevp = diffptr++; 1394 break; 1395 } 1396 case MIB2_UDP: { 1397 mib2_udp_t *u2; 1398 mib2_udp_t *u1; 1399 mib2_udp_t *d; 1400 1401 u2 = (mib2_udp_t *)tempp2->valp; 1402 u1 = (mib2_udp_t *)tempp1->valp; 1403 diffptr->group = tempp2->group; 1404 diffptr->mib_id = tempp2->mib_id; 1405 diffptr->length = tempp2->length; 1406 d = (mib2_udp_t *)calloc(tempp2->length, 1); 1407 if (d == NULL) 1408 goto mibdiff_out_of_memory; 1409 diffptr->valp = d; 1410 MDIFF(d, u2, u1, udpHCInDatagrams); 1411 MDIFF(d, u2, u1, udpInErrors); 1412 MDIFF(d, u2, u1, udpHCOutDatagrams); 1413 MDIFF(d, u2, u1, udpOutErrors); 1414 prevp = diffptr++; 1415 break; 1416 } 1417 case MIB2_SCTP: { 1418 mib2_sctp_t *s2; 1419 mib2_sctp_t *s1; 1420 mib2_sctp_t *d; 1421 1422 s2 = (mib2_sctp_t *)tempp2->valp; 1423 s1 = (mib2_sctp_t *)tempp1->valp; 1424 diffptr->group = tempp2->group; 1425 diffptr->mib_id = tempp2->mib_id; 1426 diffptr->length = tempp2->length; 1427 d = (mib2_sctp_t *)calloc(tempp2->length, 1); 1428 if (d == NULL) 1429 goto mibdiff_out_of_memory; 1430 diffptr->valp = d; 1431 d->sctpRtoAlgorithm = s2->sctpRtoAlgorithm; 1432 d->sctpRtoMin = s2->sctpRtoMin; 1433 d->sctpRtoMax = s2->sctpRtoMax; 1434 d->sctpRtoInitial = s2->sctpRtoInitial; 1435 d->sctpMaxAssocs = s2->sctpMaxAssocs; 1436 d->sctpValCookieLife = s2->sctpValCookieLife; 1437 d->sctpMaxInitRetr = s2->sctpMaxInitRetr; 1438 d->sctpCurrEstab = s2->sctpCurrEstab; 1439 MDIFF(d, s2, s1, sctpActiveEstab); 1440 MDIFF(d, s2, s1, sctpPassiveEstab); 1441 MDIFF(d, s2, s1, sctpAborted); 1442 MDIFF(d, s2, s1, sctpShutdowns); 1443 MDIFF(d, s2, s1, sctpOutOfBlue); 1444 MDIFF(d, s2, s1, sctpChecksumError); 1445 MDIFF(d, s2, s1, sctpOutCtrlChunks); 1446 MDIFF(d, s2, s1, sctpOutOrderChunks); 1447 MDIFF(d, s2, s1, sctpOutUnorderChunks); 1448 MDIFF(d, s2, s1, sctpRetransChunks); 1449 MDIFF(d, s2, s1, sctpOutAck); 1450 MDIFF(d, s2, s1, sctpOutAckDelayed); 1451 MDIFF(d, s2, s1, sctpOutWinUpdate); 1452 MDIFF(d, s2, s1, sctpOutFastRetrans); 1453 MDIFF(d, s2, s1, sctpOutWinProbe); 1454 MDIFF(d, s2, s1, sctpInCtrlChunks); 1455 MDIFF(d, s2, s1, sctpInOrderChunks); 1456 MDIFF(d, s2, s1, sctpInUnorderChunks); 1457 MDIFF(d, s2, s1, sctpInAck); 1458 MDIFF(d, s2, s1, sctpInDupAck); 1459 MDIFF(d, s2, s1, sctpInAckUnsent); 1460 MDIFF(d, s2, s1, sctpFragUsrMsgs); 1461 MDIFF(d, s2, s1, sctpReasmUsrMsgs); 1462 MDIFF(d, s2, s1, sctpOutSCTPPkts); 1463 MDIFF(d, s2, s1, sctpInSCTPPkts); 1464 MDIFF(d, s2, s1, sctpInInvalidCookie); 1465 MDIFF(d, s2, s1, sctpTimRetrans); 1466 MDIFF(d, s2, s1, sctpTimRetransDrop); 1467 MDIFF(d, s2, s1, sctpTimHeartBeatProbe); 1468 MDIFF(d, s2, s1, sctpTimHeartBeatDrop); 1469 MDIFF(d, s2, s1, sctpListenDrop); 1470 MDIFF(d, s2, s1, sctpInClosed); 1471 prevp = diffptr++; 1472 break; 1473 } 1474 case EXPER_RAWIP: { 1475 mib2_rawip_t *r2; 1476 mib2_rawip_t *r1; 1477 mib2_rawip_t *d; 1478 1479 r2 = (mib2_rawip_t *)tempp2->valp; 1480 r1 = (mib2_rawip_t *)tempp1->valp; 1481 diffptr->group = tempp2->group; 1482 diffptr->mib_id = tempp2->mib_id; 1483 diffptr->length = tempp2->length; 1484 d = (mib2_rawip_t *)calloc(tempp2->length, 1); 1485 if (d == NULL) 1486 goto mibdiff_out_of_memory; 1487 diffptr->valp = d; 1488 MDIFF(d, r2, r1, rawipInDatagrams); 1489 MDIFF(d, r2, r1, rawipInErrors); 1490 MDIFF(d, r2, r1, rawipInCksumErrs); 1491 MDIFF(d, r2, r1, rawipOutDatagrams); 1492 MDIFF(d, r2, r1, rawipOutErrors); 1493 prevp = diffptr++; 1494 break; 1495 } 1496 /* 1497 * there are more "group" types but they aren't 1498 * required for the -s and -Ms options 1499 */ 1500 } 1501 } /* 'for' loop 2 ends */ 1502 tempp1 = NULL; 1503 } /* 'for' loop 1 ends */ 1504 tempp2 = NULL; 1505 diffptr--; 1506 diffptr->next_item = NULL; 1507 return (diffp); 1508 1509 mibdiff_out_of_memory:; 1510 mib_item_destroy(&diffp); 1511 return (NULL); 1512 } 1513 1514 /* 1515 * mib_item_destroy: cleans up a mib_item_t * 1516 * that was created by calling mib_item_dup or 1517 * mib_item_diff 1518 */ 1519 static void 1520 mib_item_destroy(mib_item_t **itemp) 1521 { 1522 int nitems = 0; 1523 int c = 0; 1524 mib_item_t *tempp; 1525 1526 if (itemp == NULL || *itemp == NULL) 1527 return; 1528 1529 for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item) 1530 if (tempp->mib_id == 0) 1531 nitems++; 1532 else 1533 return; /* cannot destroy! */ 1534 1535 if (nitems == 0) 1536 return; /* cannot destroy! */ 1537 1538 for (c = nitems - 1; c >= 0; c--) { 1539 if ((itemp[0][c]).valp != NULL) 1540 free((itemp[0][c]).valp); 1541 } 1542 free(*itemp); 1543 1544 *itemp = NULL; 1545 } 1546 1547 /* Compare two Octet_ts. Return B_TRUE if they match, B_FALSE if not. */ 1548 static boolean_t 1549 octetstrmatch(const Octet_t *a, const Octet_t *b) 1550 { 1551 if (a == NULL || b == NULL) 1552 return (B_FALSE); 1553 1554 if (a->o_length != b->o_length) 1555 return (B_FALSE); 1556 1557 return (memcmp(a->o_bytes, b->o_bytes, a->o_length) == 0); 1558 } 1559 1560 /* If octetstr() changes make an appropriate change to STR_EXPAND */ 1561 static char * 1562 octetstr(const Octet_t *op, int code, char *dst, uint_t dstlen) 1563 { 1564 int i; 1565 char *cp; 1566 1567 cp = dst; 1568 if (op) { 1569 for (i = 0; i < op->o_length; i++) { 1570 switch (code) { 1571 case 'd': 1572 if (cp - dst + 4 > dstlen) { 1573 *cp = '\0'; 1574 return (dst); 1575 } 1576 (void) snprintf(cp, 5, "%d.", 1577 0xff & op->o_bytes[i]); 1578 cp = strchr(cp, '\0'); 1579 break; 1580 case 'a': 1581 if (cp - dst + 1 > dstlen) { 1582 *cp = '\0'; 1583 return (dst); 1584 } 1585 *cp++ = op->o_bytes[i]; 1586 break; 1587 case 'h': 1588 default: 1589 if (cp - dst + 3 > dstlen) { 1590 *cp = '\0'; 1591 return (dst); 1592 } 1593 (void) snprintf(cp, 4, "%02x:", 1594 0xff & op->o_bytes[i]); 1595 cp += 3; 1596 break; 1597 } 1598 } 1599 } 1600 if (code != 'a' && cp != dst) 1601 cp--; 1602 *cp = '\0'; 1603 return (dst); 1604 } 1605 1606 static const char * 1607 mitcp_state(int state, const mib2_transportMLPEntry_t *attr) 1608 { 1609 static char tcpsbuf[50]; 1610 const char *cp; 1611 1612 switch (state) { 1613 case TCPS_CLOSED: 1614 cp = "CLOSED"; 1615 break; 1616 case TCPS_IDLE: 1617 cp = "IDLE"; 1618 break; 1619 case TCPS_BOUND: 1620 cp = "BOUND"; 1621 break; 1622 case TCPS_LISTEN: 1623 cp = "LISTEN"; 1624 break; 1625 case TCPS_SYN_SENT: 1626 cp = "SYN_SENT"; 1627 break; 1628 case TCPS_SYN_RCVD: 1629 cp = "SYN_RCVD"; 1630 break; 1631 case TCPS_ESTABLISHED: 1632 cp = "ESTABLISHED"; 1633 break; 1634 case TCPS_CLOSE_WAIT: 1635 cp = "CLOSE_WAIT"; 1636 break; 1637 case TCPS_FIN_WAIT_1: 1638 cp = "FIN_WAIT_1"; 1639 break; 1640 case TCPS_CLOSING: 1641 cp = "CLOSING"; 1642 break; 1643 case TCPS_LAST_ACK: 1644 cp = "LAST_ACK"; 1645 break; 1646 case TCPS_FIN_WAIT_2: 1647 cp = "FIN_WAIT_2"; 1648 break; 1649 case TCPS_TIME_WAIT: 1650 cp = "TIME_WAIT"; 1651 break; 1652 default: 1653 (void) snprintf(tcpsbuf, sizeof (tcpsbuf), 1654 "UnknownState(%d)", state); 1655 cp = tcpsbuf; 1656 break; 1657 } 1658 1659 if (RSECflag && attr != NULL && attr->tme_flags != 0) { 1660 if (cp != tcpsbuf) { 1661 (void) strlcpy(tcpsbuf, cp, sizeof (tcpsbuf)); 1662 cp = tcpsbuf; 1663 } 1664 if (attr->tme_flags & MIB2_TMEF_PRIVATE) 1665 (void) strlcat(tcpsbuf, " P", sizeof (tcpsbuf)); 1666 if (attr->tme_flags & MIB2_TMEF_SHARED) 1667 (void) strlcat(tcpsbuf, " S", sizeof (tcpsbuf)); 1668 } 1669 1670 return (cp); 1671 } 1672 1673 static const char * 1674 miudp_state(int state, const mib2_transportMLPEntry_t *attr) 1675 { 1676 static char udpsbuf[50]; 1677 const char *cp; 1678 1679 switch (state) { 1680 case MIB2_UDP_unbound: 1681 cp = "Unbound"; 1682 break; 1683 case MIB2_UDP_idle: 1684 cp = "Idle"; 1685 break; 1686 case MIB2_UDP_connected: 1687 cp = "Connected"; 1688 break; 1689 default: 1690 (void) snprintf(udpsbuf, sizeof (udpsbuf), 1691 "Unknown State(%d)", state); 1692 cp = udpsbuf; 1693 break; 1694 } 1695 1696 if (RSECflag && attr != NULL && attr->tme_flags != 0) { 1697 if (cp != udpsbuf) { 1698 (void) strlcpy(udpsbuf, cp, sizeof (udpsbuf)); 1699 cp = udpsbuf; 1700 } 1701 if (attr->tme_flags & MIB2_TMEF_PRIVATE) 1702 (void) strlcat(udpsbuf, " P", sizeof (udpsbuf)); 1703 if (attr->tme_flags & MIB2_TMEF_SHARED) 1704 (void) strlcat(udpsbuf, " S", sizeof (udpsbuf)); 1705 } 1706 1707 return (cp); 1708 } 1709 1710 static int odd; 1711 1712 static void 1713 prval_init(void) 1714 { 1715 odd = 0; 1716 } 1717 1718 static void 1719 prval(char *str, Counter val) 1720 { 1721 (void) printf("\t%-20s=%6u", str, val); 1722 if (odd++ & 1) 1723 (void) putchar('\n'); 1724 } 1725 1726 static void 1727 prval64(char *str, Counter64 val) 1728 { 1729 (void) printf("\t%-20s=%6llu", str, val); 1730 if (odd++ & 1) 1731 (void) putchar('\n'); 1732 } 1733 1734 static void 1735 pr_int_val(char *str, int val) 1736 { 1737 (void) printf("\t%-20s=%6d", str, val); 1738 if (odd++ & 1) 1739 (void) putchar('\n'); 1740 } 1741 1742 static void 1743 pr_sctp_rtoalgo(char *str, int val) 1744 { 1745 (void) printf("\t%-20s=", str); 1746 switch (val) { 1747 case MIB2_SCTP_RTOALGO_OTHER: 1748 (void) printf("%6.6s", "other"); 1749 break; 1750 1751 case MIB2_SCTP_RTOALGO_VANJ: 1752 (void) printf("%6.6s", "vanj"); 1753 break; 1754 1755 default: 1756 (void) printf("%6d", val); 1757 break; 1758 } 1759 if (odd++ & 1) 1760 (void) putchar('\n'); 1761 } 1762 1763 static void 1764 prval_end(void) 1765 { 1766 if (odd++ & 1) 1767 (void) putchar('\n'); 1768 } 1769 1770 /* Extract constant sizes */ 1771 static void 1772 mib_get_constants(mib_item_t *item) 1773 { 1774 /* 'for' loop 1: */ 1775 for (; item; item = item->next_item) { 1776 if (item->mib_id != 0) 1777 continue; /* 'for' loop 1 */ 1778 1779 switch (item->group) { 1780 case MIB2_IP: { 1781 mib2_ip_t *ip = (mib2_ip_t *)item->valp; 1782 1783 ipAddrEntrySize = ip->ipAddrEntrySize; 1784 ipRouteEntrySize = ip->ipRouteEntrySize; 1785 ipNetToMediaEntrySize = ip->ipNetToMediaEntrySize; 1786 ipMemberEntrySize = ip->ipMemberEntrySize; 1787 ipGroupSourceEntrySize = ip->ipGroupSourceEntrySize; 1788 ipRouteAttributeSize = ip->ipRouteAttributeSize; 1789 transportMLPSize = ip->transportMLPSize; 1790 ipDestEntrySize = ip->ipDestEntrySize; 1791 assert(IS_P2ALIGNED(ipAddrEntrySize, 1792 sizeof (mib2_ipAddrEntry_t *))); 1793 assert(IS_P2ALIGNED(ipRouteEntrySize, 1794 sizeof (mib2_ipRouteEntry_t *))); 1795 assert(IS_P2ALIGNED(ipNetToMediaEntrySize, 1796 sizeof (mib2_ipNetToMediaEntry_t *))); 1797 assert(IS_P2ALIGNED(ipMemberEntrySize, 1798 sizeof (ip_member_t *))); 1799 assert(IS_P2ALIGNED(ipGroupSourceEntrySize, 1800 sizeof (ip_grpsrc_t *))); 1801 assert(IS_P2ALIGNED(ipRouteAttributeSize, 1802 sizeof (mib2_ipAttributeEntry_t *))); 1803 assert(IS_P2ALIGNED(transportMLPSize, 1804 sizeof (mib2_transportMLPEntry_t *))); 1805 break; 1806 } 1807 case EXPER_DVMRP: { 1808 struct mrtstat *mrts = (struct mrtstat *)item->valp; 1809 1810 vifctlSize = mrts->mrts_vifctlSize; 1811 mfcctlSize = mrts->mrts_mfcctlSize; 1812 assert(IS_P2ALIGNED(vifctlSize, 1813 sizeof (struct vifclt *))); 1814 assert(IS_P2ALIGNED(mfcctlSize, 1815 sizeof (struct mfcctl *))); 1816 break; 1817 } 1818 case MIB2_IP6: { 1819 mib2_ipv6IfStatsEntry_t *ip6; 1820 /* Just use the first entry */ 1821 1822 ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp; 1823 ipv6IfStatsEntrySize = ip6->ipv6IfStatsEntrySize; 1824 ipv6AddrEntrySize = ip6->ipv6AddrEntrySize; 1825 ipv6RouteEntrySize = ip6->ipv6RouteEntrySize; 1826 ipv6NetToMediaEntrySize = ip6->ipv6NetToMediaEntrySize; 1827 ipv6MemberEntrySize = ip6->ipv6MemberEntrySize; 1828 ipv6GroupSourceEntrySize = 1829 ip6->ipv6GroupSourceEntrySize; 1830 assert(IS_P2ALIGNED(ipv6IfStatsEntrySize, 1831 sizeof (mib2_ipv6IfStatsEntry_t *))); 1832 assert(IS_P2ALIGNED(ipv6AddrEntrySize, 1833 sizeof (mib2_ipv6AddrEntry_t *))); 1834 assert(IS_P2ALIGNED(ipv6RouteEntrySize, 1835 sizeof (mib2_ipv6RouteEntry_t *))); 1836 assert(IS_P2ALIGNED(ipv6NetToMediaEntrySize, 1837 sizeof (mib2_ipv6NetToMediaEntry_t *))); 1838 assert(IS_P2ALIGNED(ipv6MemberEntrySize, 1839 sizeof (ipv6_member_t *))); 1840 assert(IS_P2ALIGNED(ipv6GroupSourceEntrySize, 1841 sizeof (ipv6_grpsrc_t *))); 1842 break; 1843 } 1844 case MIB2_ICMP6: { 1845 mib2_ipv6IfIcmpEntry_t *icmp6; 1846 /* Just use the first entry */ 1847 1848 icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp; 1849 ipv6IfIcmpEntrySize = icmp6->ipv6IfIcmpEntrySize; 1850 assert(IS_P2ALIGNED(ipv6IfIcmpEntrySize, 1851 sizeof (mib2_ipv6IfIcmpEntry_t *))); 1852 break; 1853 } 1854 case MIB2_TCP: { 1855 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp; 1856 1857 tcpConnEntrySize = tcp->tcpConnTableSize; 1858 tcp6ConnEntrySize = tcp->tcp6ConnTableSize; 1859 assert(IS_P2ALIGNED(tcpConnEntrySize, 1860 sizeof (mib2_tcpConnEntry_t *))); 1861 assert(IS_P2ALIGNED(tcp6ConnEntrySize, 1862 sizeof (mib2_tcp6ConnEntry_t *))); 1863 break; 1864 } 1865 case MIB2_UDP: { 1866 mib2_udp_t *udp = (mib2_udp_t *)item->valp; 1867 1868 udpEntrySize = udp->udpEntrySize; 1869 udp6EntrySize = udp->udp6EntrySize; 1870 assert(IS_P2ALIGNED(udpEntrySize, 1871 sizeof (mib2_udpEntry_t *))); 1872 assert(IS_P2ALIGNED(udp6EntrySize, 1873 sizeof (mib2_udp6Entry_t *))); 1874 break; 1875 } 1876 case MIB2_SCTP: { 1877 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp; 1878 1879 sctpEntrySize = sctp->sctpEntrySize; 1880 sctpLocalEntrySize = sctp->sctpLocalEntrySize; 1881 sctpRemoteEntrySize = sctp->sctpRemoteEntrySize; 1882 break; 1883 } 1884 } 1885 } /* 'for' loop 1 ends */ 1886 1887 if (Xflag) { 1888 (void) puts("mib_get_constants:"); 1889 (void) printf("\tipv6IfStatsEntrySize %d\n", 1890 ipv6IfStatsEntrySize); 1891 (void) printf("\tipAddrEntrySize %d\n", ipAddrEntrySize); 1892 (void) printf("\tipRouteEntrySize %d\n", ipRouteEntrySize); 1893 (void) printf("\tipNetToMediaEntrySize %d\n", 1894 ipNetToMediaEntrySize); 1895 (void) printf("\tipMemberEntrySize %d\n", ipMemberEntrySize); 1896 (void) printf("\tipRouteAttributeSize %d\n", 1897 ipRouteAttributeSize); 1898 (void) printf("\tvifctlSize %d\n", vifctlSize); 1899 (void) printf("\tmfcctlSize %d\n", mfcctlSize); 1900 1901 (void) printf("\tipv6AddrEntrySize %d\n", ipv6AddrEntrySize); 1902 (void) printf("\tipv6RouteEntrySize %d\n", ipv6RouteEntrySize); 1903 (void) printf("\tipv6NetToMediaEntrySize %d\n", 1904 ipv6NetToMediaEntrySize); 1905 (void) printf("\tipv6MemberEntrySize %d\n", 1906 ipv6MemberEntrySize); 1907 (void) printf("\tipv6IfIcmpEntrySize %d\n", 1908 ipv6IfIcmpEntrySize); 1909 (void) printf("\tipDestEntrySize %d\n", ipDestEntrySize); 1910 (void) printf("\ttransportMLPSize %d\n", transportMLPSize); 1911 (void) printf("\ttcpConnEntrySize %d\n", tcpConnEntrySize); 1912 (void) printf("\ttcp6ConnEntrySize %d\n", tcp6ConnEntrySize); 1913 (void) printf("\tudpEntrySize %d\n", udpEntrySize); 1914 (void) printf("\tudp6EntrySize %d\n", udp6EntrySize); 1915 (void) printf("\tsctpEntrySize %d\n", sctpEntrySize); 1916 (void) printf("\tsctpLocalEntrySize %d\n", sctpLocalEntrySize); 1917 (void) printf("\tsctpRemoteEntrySize %d\n", 1918 sctpRemoteEntrySize); 1919 } 1920 } 1921 1922 1923 /* ----------------------------- STAT_REPORT ------------------------------- */ 1924 1925 static void 1926 stat_report(mib_item_t *item) 1927 { 1928 int jtemp = 0; 1929 char ifname[LIFNAMSIZ + 1]; 1930 1931 /* 'for' loop 1: */ 1932 for (; item; item = item->next_item) { 1933 if (Xflag) { 1934 (void) printf("\n--- Entry %d ---\n", ++jtemp); 1935 (void) printf("Group = %d, mib_id = %d, " 1936 "length = %d, valp = 0x%p\n", 1937 item->group, item->mib_id, 1938 item->length, item->valp); 1939 } 1940 if (item->mib_id != 0) 1941 continue; /* 'for' loop 1 */ 1942 1943 switch (item->group) { 1944 case MIB2_IP: { 1945 mib2_ip_t *ip = (mib2_ip_t *)item->valp; 1946 1947 if (protocol_selected(IPPROTO_IP) && 1948 family_selected(AF_INET)) { 1949 (void) fputs(v4compat ? "\nIP" : "\nIPv4", 1950 stdout); 1951 print_ip_stats(ip); 1952 } 1953 break; 1954 } 1955 case MIB2_ICMP: { 1956 mib2_icmp_t *icmp = 1957 (mib2_icmp_t *)item->valp; 1958 1959 if (protocol_selected(IPPROTO_ICMP) && 1960 family_selected(AF_INET)) { 1961 (void) fputs(v4compat ? "\nICMP" : "\nICMPv4", 1962 stdout); 1963 print_icmp_stats(icmp); 1964 } 1965 break; 1966 } 1967 case MIB2_IP6: { 1968 mib2_ipv6IfStatsEntry_t *ip6; 1969 mib2_ipv6IfStatsEntry_t sum6; 1970 1971 if (!(protocol_selected(IPPROTO_IPV6)) || 1972 !(family_selected(AF_INET6))) 1973 break; 1974 bzero(&sum6, sizeof (sum6)); 1975 /* 'for' loop 2a: */ 1976 for (ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp; 1977 (char *)ip6 < (char *)item->valp + item->length; 1978 /* LINTED: (note 1) */ 1979 ip6 = (mib2_ipv6IfStatsEntry_t *)((char *)ip6 + 1980 ipv6IfStatsEntrySize)) { 1981 if (ip6->ipv6IfIndex == 0) { 1982 /* 1983 * The "unknown interface" ip6 1984 * mib. Just add to the sum. 1985 */ 1986 sum_ip6_stats(ip6, &sum6); 1987 continue; /* 'for' loop 2a */ 1988 } 1989 if (Aflag) { 1990 (void) printf("\nIPv6 for %s\n", 1991 ifindex2str(ip6->ipv6IfIndex, 1992 ifname)); 1993 print_ip6_stats(ip6); 1994 } 1995 sum_ip6_stats(ip6, &sum6); 1996 } /* 'for' loop 2a ends */ 1997 (void) fputs("\nIPv6", stdout); 1998 print_ip6_stats(&sum6); 1999 break; 2000 } 2001 case MIB2_ICMP6: { 2002 mib2_ipv6IfIcmpEntry_t *icmp6; 2003 mib2_ipv6IfIcmpEntry_t sum6; 2004 2005 if (!(protocol_selected(IPPROTO_ICMPV6)) || 2006 !(family_selected(AF_INET6))) 2007 break; 2008 bzero(&sum6, sizeof (sum6)); 2009 /* 'for' loop 2b: */ 2010 for (icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp; 2011 (char *)icmp6 < (char *)item->valp + item->length; 2012 icmp6 = (void *)((char *)icmp6 + 2013 ipv6IfIcmpEntrySize)) { 2014 if (icmp6->ipv6IfIcmpIfIndex == 0) { 2015 /* 2016 * The "unknown interface" icmp6 2017 * mib. Just add to the sum. 2018 */ 2019 sum_icmp6_stats(icmp6, &sum6); 2020 continue; /* 'for' loop 2b: */ 2021 } 2022 if (Aflag) { 2023 (void) printf("\nICMPv6 for %s\n", 2024 ifindex2str( 2025 icmp6->ipv6IfIcmpIfIndex, ifname)); 2026 print_icmp6_stats(icmp6); 2027 } 2028 sum_icmp6_stats(icmp6, &sum6); 2029 } /* 'for' loop 2b ends */ 2030 (void) fputs("\nICMPv6", stdout); 2031 print_icmp6_stats(&sum6); 2032 break; 2033 } 2034 case MIB2_TCP: { 2035 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp; 2036 2037 if (protocol_selected(IPPROTO_TCP) && 2038 (family_selected(AF_INET) || 2039 family_selected(AF_INET6))) { 2040 (void) fputs("\nTCP", stdout); 2041 print_tcp_stats(tcp); 2042 } 2043 break; 2044 } 2045 case MIB2_UDP: { 2046 mib2_udp_t *udp = (mib2_udp_t *)item->valp; 2047 2048 if (protocol_selected(IPPROTO_UDP) && 2049 (family_selected(AF_INET) || 2050 family_selected(AF_INET6))) { 2051 (void) fputs("\nUDP", stdout); 2052 print_udp_stats(udp); 2053 } 2054 break; 2055 } 2056 case MIB2_SCTP: { 2057 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp; 2058 2059 if (protocol_selected(IPPROTO_SCTP) && 2060 (family_selected(AF_INET) || 2061 family_selected(AF_INET6))) { 2062 (void) fputs("\nSCTP", stdout); 2063 print_sctp_stats(sctp); 2064 } 2065 break; 2066 } 2067 case EXPER_RAWIP: { 2068 mib2_rawip_t *rawip = 2069 (mib2_rawip_t *)item->valp; 2070 2071 if (protocol_selected(IPPROTO_RAW) && 2072 (family_selected(AF_INET) || 2073 family_selected(AF_INET6))) { 2074 (void) fputs("\nRAWIP", stdout); 2075 print_rawip_stats(rawip); 2076 } 2077 break; 2078 } 2079 case EXPER_IGMP: { 2080 struct igmpstat *igps = 2081 (struct igmpstat *)item->valp; 2082 2083 if (protocol_selected(IPPROTO_IGMP) && 2084 (family_selected(AF_INET))) { 2085 (void) fputs("\nIGMP:\n", stdout); 2086 print_igmp_stats(igps); 2087 } 2088 break; 2089 } 2090 } 2091 } /* 'for' loop 1 ends */ 2092 (void) putchar('\n'); 2093 (void) fflush(stdout); 2094 } 2095 2096 static void 2097 print_ip_stats(mib2_ip_t *ip) 2098 { 2099 prval_init(); 2100 pr_int_val("ipForwarding", ip->ipForwarding); 2101 pr_int_val("ipDefaultTTL", ip->ipDefaultTTL); 2102 prval("ipInReceives", ip->ipInReceives); 2103 prval("ipInHdrErrors", ip->ipInHdrErrors); 2104 prval("ipInAddrErrors", ip->ipInAddrErrors); 2105 prval("ipInCksumErrs", ip->ipInCksumErrs); 2106 prval("ipForwDatagrams", ip->ipForwDatagrams); 2107 prval("ipForwProhibits", ip->ipForwProhibits); 2108 prval("ipInUnknownProtos", ip->ipInUnknownProtos); 2109 prval("ipInDiscards", ip->ipInDiscards); 2110 prval("ipInDelivers", ip->ipInDelivers); 2111 prval("ipOutRequests", ip->ipOutRequests); 2112 prval("ipOutDiscards", ip->ipOutDiscards); 2113 prval("ipOutNoRoutes", ip->ipOutNoRoutes); 2114 pr_int_val("ipReasmTimeout", ip->ipReasmTimeout); 2115 prval("ipReasmReqds", ip->ipReasmReqds); 2116 prval("ipReasmOKs", ip->ipReasmOKs); 2117 prval("ipReasmFails", ip->ipReasmFails); 2118 prval("ipReasmDuplicates", ip->ipReasmDuplicates); 2119 prval("ipReasmPartDups", ip->ipReasmPartDups); 2120 prval("ipFragOKs", ip->ipFragOKs); 2121 prval("ipFragFails", ip->ipFragFails); 2122 prval("ipFragCreates", ip->ipFragCreates); 2123 prval("ipRoutingDiscards", ip->ipRoutingDiscards); 2124 2125 prval("tcpInErrs", ip->tcpInErrs); 2126 prval("udpNoPorts", ip->udpNoPorts); 2127 prval("udpInCksumErrs", ip->udpInCksumErrs); 2128 prval("udpInOverflows", ip->udpInOverflows); 2129 prval("rawipInOverflows", ip->rawipInOverflows); 2130 prval("ipsecInSucceeded", ip->ipsecInSucceeded); 2131 prval("ipsecInFailed", ip->ipsecInFailed); 2132 prval("ipInIPv6", ip->ipInIPv6); 2133 prval("ipOutIPv6", ip->ipOutIPv6); 2134 prval("ipOutSwitchIPv6", ip->ipOutSwitchIPv6); 2135 prval_end(); 2136 } 2137 2138 static void 2139 print_icmp_stats(mib2_icmp_t *icmp) 2140 { 2141 prval_init(); 2142 prval("icmpInMsgs", icmp->icmpInMsgs); 2143 prval("icmpInErrors", icmp->icmpInErrors); 2144 prval("icmpInCksumErrs", icmp->icmpInCksumErrs); 2145 prval("icmpInUnknowns", icmp->icmpInUnknowns); 2146 prval("icmpInDestUnreachs", icmp->icmpInDestUnreachs); 2147 prval("icmpInTimeExcds", icmp->icmpInTimeExcds); 2148 prval("icmpInParmProbs", icmp->icmpInParmProbs); 2149 prval("icmpInSrcQuenchs", icmp->icmpInSrcQuenchs); 2150 prval("icmpInRedirects", icmp->icmpInRedirects); 2151 prval("icmpInBadRedirects", icmp->icmpInBadRedirects); 2152 prval("icmpInEchos", icmp->icmpInEchos); 2153 prval("icmpInEchoReps", icmp->icmpInEchoReps); 2154 prval("icmpInTimestamps", icmp->icmpInTimestamps); 2155 prval("icmpInTimestampReps", icmp->icmpInTimestampReps); 2156 prval("icmpInAddrMasks", icmp->icmpInAddrMasks); 2157 prval("icmpInAddrMaskReps", icmp->icmpInAddrMaskReps); 2158 prval("icmpInFragNeeded", icmp->icmpInFragNeeded); 2159 prval("icmpOutMsgs", icmp->icmpOutMsgs); 2160 prval("icmpOutDrops", icmp->icmpOutDrops); 2161 prval("icmpOutErrors", icmp->icmpOutErrors); 2162 prval("icmpOutDestUnreachs", icmp->icmpOutDestUnreachs); 2163 prval("icmpOutTimeExcds", icmp->icmpOutTimeExcds); 2164 prval("icmpOutParmProbs", icmp->icmpOutParmProbs); 2165 prval("icmpOutSrcQuenchs", icmp->icmpOutSrcQuenchs); 2166 prval("icmpOutRedirects", icmp->icmpOutRedirects); 2167 prval("icmpOutEchos", icmp->icmpOutEchos); 2168 prval("icmpOutEchoReps", icmp->icmpOutEchoReps); 2169 prval("icmpOutTimestamps", icmp->icmpOutTimestamps); 2170 prval("icmpOutTimestampReps", icmp->icmpOutTimestampReps); 2171 prval("icmpOutAddrMasks", icmp->icmpOutAddrMasks); 2172 prval("icmpOutAddrMaskReps", icmp->icmpOutAddrMaskReps); 2173 prval("icmpOutFragNeeded", icmp->icmpOutFragNeeded); 2174 prval("icmpInOverflows", icmp->icmpInOverflows); 2175 prval_end(); 2176 } 2177 2178 static void 2179 print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6) 2180 { 2181 prval_init(); 2182 prval("ipv6Forwarding", ip6->ipv6Forwarding); 2183 prval("ipv6DefaultHopLimit", ip6->ipv6DefaultHopLimit); 2184 2185 prval("ipv6InReceives", ip6->ipv6InReceives); 2186 prval("ipv6InHdrErrors", ip6->ipv6InHdrErrors); 2187 prval("ipv6InTooBigErrors", ip6->ipv6InTooBigErrors); 2188 prval("ipv6InNoRoutes", ip6->ipv6InNoRoutes); 2189 prval("ipv6InAddrErrors", ip6->ipv6InAddrErrors); 2190 prval("ipv6InUnknownProtos", ip6->ipv6InUnknownProtos); 2191 prval("ipv6InTruncatedPkts", ip6->ipv6InTruncatedPkts); 2192 prval("ipv6InDiscards", ip6->ipv6InDiscards); 2193 prval("ipv6InDelivers", ip6->ipv6InDelivers); 2194 prval("ipv6OutForwDatagrams", ip6->ipv6OutForwDatagrams); 2195 prval("ipv6OutRequests", ip6->ipv6OutRequests); 2196 prval("ipv6OutDiscards", ip6->ipv6OutDiscards); 2197 prval("ipv6OutNoRoutes", ip6->ipv6OutNoRoutes); 2198 prval("ipv6OutFragOKs", ip6->ipv6OutFragOKs); 2199 prval("ipv6OutFragFails", ip6->ipv6OutFragFails); 2200 prval("ipv6OutFragCreates", ip6->ipv6OutFragCreates); 2201 prval("ipv6ReasmReqds", ip6->ipv6ReasmReqds); 2202 prval("ipv6ReasmOKs", ip6->ipv6ReasmOKs); 2203 prval("ipv6ReasmFails", ip6->ipv6ReasmFails); 2204 prval("ipv6InMcastPkts", ip6->ipv6InMcastPkts); 2205 prval("ipv6OutMcastPkts", ip6->ipv6OutMcastPkts); 2206 prval("ipv6ReasmDuplicates", ip6->ipv6ReasmDuplicates); 2207 prval("ipv6ReasmPartDups", ip6->ipv6ReasmPartDups); 2208 prval("ipv6ForwProhibits", ip6->ipv6ForwProhibits); 2209 prval("udpInCksumErrs", ip6->udpInCksumErrs); 2210 prval("udpInOverflows", ip6->udpInOverflows); 2211 prval("rawipInOverflows", ip6->rawipInOverflows); 2212 prval("ipv6InIPv4", ip6->ipv6InIPv4); 2213 prval("ipv6OutIPv4", ip6->ipv6OutIPv4); 2214 prval("ipv6OutSwitchIPv4", ip6->ipv6OutSwitchIPv4); 2215 prval_end(); 2216 } 2217 2218 static void 2219 print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6) 2220 { 2221 prval_init(); 2222 prval("icmp6InMsgs", icmp6->ipv6IfIcmpInMsgs); 2223 prval("icmp6InErrors", icmp6->ipv6IfIcmpInErrors); 2224 prval("icmp6InDestUnreachs", icmp6->ipv6IfIcmpInDestUnreachs); 2225 prval("icmp6InAdminProhibs", icmp6->ipv6IfIcmpInAdminProhibs); 2226 prval("icmp6InTimeExcds", icmp6->ipv6IfIcmpInTimeExcds); 2227 prval("icmp6InParmProblems", icmp6->ipv6IfIcmpInParmProblems); 2228 prval("icmp6InPktTooBigs", icmp6->ipv6IfIcmpInPktTooBigs); 2229 prval("icmp6InEchos", icmp6->ipv6IfIcmpInEchos); 2230 prval("icmp6InEchoReplies", icmp6->ipv6IfIcmpInEchoReplies); 2231 prval("icmp6InRouterSols", icmp6->ipv6IfIcmpInRouterSolicits); 2232 prval("icmp6InRouterAds", 2233 icmp6->ipv6IfIcmpInRouterAdvertisements); 2234 prval("icmp6InNeighborSols", icmp6->ipv6IfIcmpInNeighborSolicits); 2235 prval("icmp6InNeighborAds", 2236 icmp6->ipv6IfIcmpInNeighborAdvertisements); 2237 prval("icmp6InRedirects", icmp6->ipv6IfIcmpInRedirects); 2238 prval("icmp6InBadRedirects", icmp6->ipv6IfIcmpInBadRedirects); 2239 prval("icmp6InGroupQueries", icmp6->ipv6IfIcmpInGroupMembQueries); 2240 prval("icmp6InGroupResps", icmp6->ipv6IfIcmpInGroupMembResponses); 2241 prval("icmp6InGroupReds", icmp6->ipv6IfIcmpInGroupMembReductions); 2242 prval("icmp6InOverflows", icmp6->ipv6IfIcmpInOverflows); 2243 prval_end(); 2244 prval_init(); 2245 prval("icmp6OutMsgs", icmp6->ipv6IfIcmpOutMsgs); 2246 prval("icmp6OutErrors", icmp6->ipv6IfIcmpOutErrors); 2247 prval("icmp6OutDestUnreachs", icmp6->ipv6IfIcmpOutDestUnreachs); 2248 prval("icmp6OutAdminProhibs", icmp6->ipv6IfIcmpOutAdminProhibs); 2249 prval("icmp6OutTimeExcds", icmp6->ipv6IfIcmpOutTimeExcds); 2250 prval("icmp6OutParmProblems", icmp6->ipv6IfIcmpOutParmProblems); 2251 prval("icmp6OutPktTooBigs", icmp6->ipv6IfIcmpOutPktTooBigs); 2252 prval("icmp6OutEchos", icmp6->ipv6IfIcmpOutEchos); 2253 prval("icmp6OutEchoReplies", icmp6->ipv6IfIcmpOutEchoReplies); 2254 prval("icmp6OutRouterSols", icmp6->ipv6IfIcmpOutRouterSolicits); 2255 prval("icmp6OutRouterAds", 2256 icmp6->ipv6IfIcmpOutRouterAdvertisements); 2257 prval("icmp6OutNeighborSols", icmp6->ipv6IfIcmpOutNeighborSolicits); 2258 prval("icmp6OutNeighborAds", 2259 icmp6->ipv6IfIcmpOutNeighborAdvertisements); 2260 prval("icmp6OutRedirects", icmp6->ipv6IfIcmpOutRedirects); 2261 prval("icmp6OutGroupQueries", icmp6->ipv6IfIcmpOutGroupMembQueries); 2262 prval("icmp6OutGroupResps", 2263 icmp6->ipv6IfIcmpOutGroupMembResponses); 2264 prval("icmp6OutGroupReds", 2265 icmp6->ipv6IfIcmpOutGroupMembReductions); 2266 prval_end(); 2267 } 2268 2269 static void 2270 print_sctp_stats(mib2_sctp_t *sctp) 2271 { 2272 prval_init(); 2273 pr_sctp_rtoalgo("sctpRtoAlgorithm", sctp->sctpRtoAlgorithm); 2274 prval("sctpRtoMin", sctp->sctpRtoMin); 2275 prval("sctpRtoMax", sctp->sctpRtoMax); 2276 prval("sctpRtoInitial", sctp->sctpRtoInitial); 2277 pr_int_val("sctpMaxAssocs", sctp->sctpMaxAssocs); 2278 prval("sctpValCookieLife", sctp->sctpValCookieLife); 2279 prval("sctpMaxInitRetr", sctp->sctpMaxInitRetr); 2280 prval("sctpCurrEstab", sctp->sctpCurrEstab); 2281 prval("sctpActiveEstab", sctp->sctpActiveEstab); 2282 prval("sctpPassiveEstab", sctp->sctpPassiveEstab); 2283 prval("sctpAborted", sctp->sctpAborted); 2284 prval("sctpShutdowns", sctp->sctpShutdowns); 2285 prval("sctpOutOfBlue", sctp->sctpOutOfBlue); 2286 prval("sctpChecksumError", sctp->sctpChecksumError); 2287 prval64("sctpOutCtrlChunks", sctp->sctpOutCtrlChunks); 2288 prval64("sctpOutOrderChunks", sctp->sctpOutOrderChunks); 2289 prval64("sctpOutUnorderChunks", sctp->sctpOutUnorderChunks); 2290 prval64("sctpRetransChunks", sctp->sctpRetransChunks); 2291 prval("sctpOutAck", sctp->sctpOutAck); 2292 prval("sctpOutAckDelayed", sctp->sctpOutAckDelayed); 2293 prval("sctpOutWinUpdate", sctp->sctpOutWinUpdate); 2294 prval("sctpOutFastRetrans", sctp->sctpOutFastRetrans); 2295 prval("sctpOutWinProbe", sctp->sctpOutWinProbe); 2296 prval64("sctpInCtrlChunks", sctp->sctpInCtrlChunks); 2297 prval64("sctpInOrderChunks", sctp->sctpInOrderChunks); 2298 prval64("sctpInUnorderChunks", sctp->sctpInUnorderChunks); 2299 prval("sctpInAck", sctp->sctpInAck); 2300 prval("sctpInDupAck", sctp->sctpInDupAck); 2301 prval("sctpInAckUnsent", sctp->sctpInAckUnsent); 2302 prval64("sctpFragUsrMsgs", sctp->sctpFragUsrMsgs); 2303 prval64("sctpReasmUsrMsgs", sctp->sctpReasmUsrMsgs); 2304 prval64("sctpOutSCTPPkts", sctp->sctpOutSCTPPkts); 2305 prval64("sctpInSCTPPkts", sctp->sctpInSCTPPkts); 2306 prval("sctpInInvalidCookie", sctp->sctpInInvalidCookie); 2307 prval("sctpTimRetrans", sctp->sctpTimRetrans); 2308 prval("sctpTimRetransDrop", sctp->sctpTimRetransDrop); 2309 prval("sctpTimHearBeatProbe", sctp->sctpTimHeartBeatProbe); 2310 prval("sctpTimHearBeatDrop", sctp->sctpTimHeartBeatDrop); 2311 prval("sctpListenDrop", sctp->sctpListenDrop); 2312 prval("sctpInClosed", sctp->sctpInClosed); 2313 prval_end(); 2314 } 2315 2316 static void 2317 print_tcp_stats(mib2_tcp_t *tcp) 2318 { 2319 prval_init(); 2320 pr_int_val("tcpRtoAlgorithm", tcp->tcpRtoAlgorithm); 2321 pr_int_val("tcpRtoMin", tcp->tcpRtoMin); 2322 pr_int_val("tcpRtoMax", tcp->tcpRtoMax); 2323 pr_int_val("tcpMaxConn", tcp->tcpMaxConn); 2324 prval("tcpActiveOpens", tcp->tcpActiveOpens); 2325 prval("tcpPassiveOpens", tcp->tcpPassiveOpens); 2326 prval("tcpAttemptFails", tcp->tcpAttemptFails); 2327 prval("tcpEstabResets", tcp->tcpEstabResets); 2328 prval("tcpCurrEstab", tcp->tcpCurrEstab); 2329 prval64("tcpOutSegs", tcp->tcpHCOutSegs); 2330 prval("tcpOutDataSegs", tcp->tcpOutDataSegs); 2331 prval("tcpOutDataBytes", tcp->tcpOutDataBytes); 2332 prval("tcpRetransSegs", tcp->tcpRetransSegs); 2333 prval("tcpRetransBytes", tcp->tcpRetransBytes); 2334 prval("tcpOutAck", tcp->tcpOutAck); 2335 prval("tcpOutAckDelayed", tcp->tcpOutAckDelayed); 2336 prval("tcpOutUrg", tcp->tcpOutUrg); 2337 prval("tcpOutWinUpdate", tcp->tcpOutWinUpdate); 2338 prval("tcpOutWinProbe", tcp->tcpOutWinProbe); 2339 prval("tcpOutControl", tcp->tcpOutControl); 2340 prval("tcpOutRsts", tcp->tcpOutRsts); 2341 prval("tcpOutFastRetrans", tcp->tcpOutFastRetrans); 2342 prval64("tcpInSegs", tcp->tcpHCInSegs); 2343 prval_end(); 2344 prval("tcpInAckSegs", tcp->tcpInAckSegs); 2345 prval("tcpInAckBytes", tcp->tcpInAckBytes); 2346 prval("tcpInDupAck", tcp->tcpInDupAck); 2347 prval("tcpInAckUnsent", tcp->tcpInAckUnsent); 2348 prval("tcpInInorderSegs", tcp->tcpInDataInorderSegs); 2349 prval("tcpInInorderBytes", tcp->tcpInDataInorderBytes); 2350 prval("tcpInUnorderSegs", tcp->tcpInDataUnorderSegs); 2351 prval("tcpInUnorderBytes", tcp->tcpInDataUnorderBytes); 2352 prval("tcpInDupSegs", tcp->tcpInDataDupSegs); 2353 prval("tcpInDupBytes", tcp->tcpInDataDupBytes); 2354 prval("tcpInPartDupSegs", tcp->tcpInDataPartDupSegs); 2355 prval("tcpInPartDupBytes", tcp->tcpInDataPartDupBytes); 2356 prval("tcpInPastWinSegs", tcp->tcpInDataPastWinSegs); 2357 prval("tcpInPastWinBytes", tcp->tcpInDataPastWinBytes); 2358 prval("tcpInWinProbe", tcp->tcpInWinProbe); 2359 prval("tcpInWinUpdate", tcp->tcpInWinUpdate); 2360 prval("tcpInClosed", tcp->tcpInClosed); 2361 prval("tcpRttNoUpdate", tcp->tcpRttNoUpdate); 2362 prval("tcpRttUpdate", tcp->tcpRttUpdate); 2363 prval("tcpTimRetrans", tcp->tcpTimRetrans); 2364 prval("tcpTimRetransDrop", tcp->tcpTimRetransDrop); 2365 prval("tcpTimKeepalive", tcp->tcpTimKeepalive); 2366 prval("tcpTimKeepaliveProbe", tcp->tcpTimKeepaliveProbe); 2367 prval("tcpTimKeepaliveDrop", tcp->tcpTimKeepaliveDrop); 2368 prval("tcpListenDrop", tcp->tcpListenDrop); 2369 prval("tcpListenDropQ0", tcp->tcpListenDropQ0); 2370 prval("tcpHalfOpenDrop", tcp->tcpHalfOpenDrop); 2371 prval("tcpOutSackRetrans", tcp->tcpOutSackRetransSegs); 2372 prval_end(); 2373 2374 } 2375 2376 static void 2377 print_udp_stats(mib2_udp_t *udp) 2378 { 2379 prval_init(); 2380 prval64("udpInDatagrams", udp->udpHCInDatagrams); 2381 prval("udpInErrors", udp->udpInErrors); 2382 prval64("udpOutDatagrams", udp->udpHCOutDatagrams); 2383 prval("udpOutErrors", udp->udpOutErrors); 2384 prval_end(); 2385 } 2386 2387 static void 2388 print_rawip_stats(mib2_rawip_t *rawip) 2389 { 2390 prval_init(); 2391 prval("rawipInDatagrams", rawip->rawipInDatagrams); 2392 prval("rawipInErrors", rawip->rawipInErrors); 2393 prval("rawipInCksumErrs", rawip->rawipInCksumErrs); 2394 prval("rawipOutDatagrams", rawip->rawipOutDatagrams); 2395 prval("rawipOutErrors", rawip->rawipOutErrors); 2396 prval_end(); 2397 } 2398 2399 void 2400 print_igmp_stats(struct igmpstat *igps) 2401 { 2402 (void) printf(" %10u message%s received\n", 2403 igps->igps_rcv_total, PLURAL(igps->igps_rcv_total)); 2404 (void) printf(" %10u message%s received with too few bytes\n", 2405 igps->igps_rcv_tooshort, PLURAL(igps->igps_rcv_tooshort)); 2406 (void) printf(" %10u message%s received with bad checksum\n", 2407 igps->igps_rcv_badsum, PLURAL(igps->igps_rcv_badsum)); 2408 (void) printf(" %10u membership quer%s received\n", 2409 igps->igps_rcv_queries, PLURALY(igps->igps_rcv_queries)); 2410 (void) printf(" %10u membership quer%s received with invalid " 2411 "field(s)\n", 2412 igps->igps_rcv_badqueries, PLURALY(igps->igps_rcv_badqueries)); 2413 (void) printf(" %10u membership report%s received\n", 2414 igps->igps_rcv_reports, PLURAL(igps->igps_rcv_reports)); 2415 (void) printf(" %10u membership report%s received with invalid " 2416 "field(s)\n", 2417 igps->igps_rcv_badreports, PLURAL(igps->igps_rcv_badreports)); 2418 (void) printf(" %10u membership report%s received for groups to " 2419 "which we belong\n", 2420 igps->igps_rcv_ourreports, PLURAL(igps->igps_rcv_ourreports)); 2421 (void) printf(" %10u membership report%s sent\n", 2422 igps->igps_snd_reports, PLURAL(igps->igps_snd_reports)); 2423 } 2424 2425 static void 2426 print_mrt_stats(struct mrtstat *mrts) 2427 { 2428 (void) puts("DVMRP multicast routing:"); 2429 (void) printf(" %10u hit%s - kernel forwarding cache hits\n", 2430 mrts->mrts_mfc_hits, PLURAL(mrts->mrts_mfc_hits)); 2431 (void) printf(" %10u miss%s - kernel forwarding cache misses\n", 2432 mrts->mrts_mfc_misses, PLURALES(mrts->mrts_mfc_misses)); 2433 (void) printf(" %10u packet%s potentially forwarded\n", 2434 mrts->mrts_fwd_in, PLURAL(mrts->mrts_fwd_in)); 2435 (void) printf(" %10u packet%s actually sent out\n", 2436 mrts->mrts_fwd_out, PLURAL(mrts->mrts_fwd_out)); 2437 (void) printf(" %10u upcall%s - upcalls made to mrouted\n", 2438 mrts->mrts_upcalls, PLURAL(mrts->mrts_upcalls)); 2439 (void) printf(" %10u packet%s not sent out due to lack of resources\n", 2440 mrts->mrts_fwd_drop, PLURAL(mrts->mrts_fwd_drop)); 2441 (void) printf(" %10u datagram%s with malformed tunnel options\n", 2442 mrts->mrts_bad_tunnel, PLURAL(mrts->mrts_bad_tunnel)); 2443 (void) printf(" %10u datagram%s with no room for tunnel options\n", 2444 mrts->mrts_cant_tunnel, PLURAL(mrts->mrts_cant_tunnel)); 2445 (void) printf(" %10u datagram%s arrived on wrong interface\n", 2446 mrts->mrts_wrong_if, PLURAL(mrts->mrts_wrong_if)); 2447 (void) printf(" %10u datagram%s dropped due to upcall Q overflow\n", 2448 mrts->mrts_upq_ovflw, PLURAL(mrts->mrts_upq_ovflw)); 2449 (void) printf(" %10u datagram%s cleaned up by the cache\n", 2450 mrts->mrts_cache_cleanups, PLURAL(mrts->mrts_cache_cleanups)); 2451 (void) printf(" %10u datagram%s dropped selectively by ratelimiter\n", 2452 mrts->mrts_drop_sel, PLURAL(mrts->mrts_drop_sel)); 2453 (void) printf(" %10u datagram%s dropped - bucket Q overflow\n", 2454 mrts->mrts_q_overflow, PLURAL(mrts->mrts_q_overflow)); 2455 (void) printf(" %10u datagram%s dropped - larger than bkt size\n", 2456 mrts->mrts_pkt2large, PLURAL(mrts->mrts_pkt2large)); 2457 (void) printf("\nPIM multicast routing:\n"); 2458 (void) printf(" %10u datagram%s dropped - bad version number\n", 2459 mrts->mrts_pim_badversion, PLURAL(mrts->mrts_pim_badversion)); 2460 (void) printf(" %10u datagram%s dropped - bad checksum\n", 2461 mrts->mrts_pim_rcv_badcsum, PLURAL(mrts->mrts_pim_rcv_badcsum)); 2462 (void) printf(" %10u datagram%s dropped - bad register packets\n", 2463 mrts->mrts_pim_badregisters, PLURAL(mrts->mrts_pim_badregisters)); 2464 (void) printf( 2465 " %10u datagram%s potentially forwarded - register packets\n", 2466 mrts->mrts_pim_regforwards, PLURAL(mrts->mrts_pim_regforwards)); 2467 (void) printf(" %10u datagram%s dropped - register send drops\n", 2468 mrts->mrts_pim_regsend_drops, PLURAL(mrts->mrts_pim_regsend_drops)); 2469 (void) printf(" %10u datagram%s dropped - packet malformed\n", 2470 mrts->mrts_pim_malformed, PLURAL(mrts->mrts_pim_malformed)); 2471 (void) printf(" %10u datagram%s dropped - no memory to forward\n", 2472 mrts->mrts_pim_nomemory, PLURAL(mrts->mrts_pim_nomemory)); 2473 } 2474 2475 static void 2476 sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6, mib2_ipv6IfStatsEntry_t *sum6) 2477 { 2478 /* First few are not additive */ 2479 sum6->ipv6Forwarding = ip6->ipv6Forwarding; 2480 sum6->ipv6DefaultHopLimit = ip6->ipv6DefaultHopLimit; 2481 2482 sum6->ipv6InReceives += ip6->ipv6InReceives; 2483 sum6->ipv6InHdrErrors += ip6->ipv6InHdrErrors; 2484 sum6->ipv6InTooBigErrors += ip6->ipv6InTooBigErrors; 2485 sum6->ipv6InNoRoutes += ip6->ipv6InNoRoutes; 2486 sum6->ipv6InAddrErrors += ip6->ipv6InAddrErrors; 2487 sum6->ipv6InUnknownProtos += ip6->ipv6InUnknownProtos; 2488 sum6->ipv6InTruncatedPkts += ip6->ipv6InTruncatedPkts; 2489 sum6->ipv6InDiscards += ip6->ipv6InDiscards; 2490 sum6->ipv6InDelivers += ip6->ipv6InDelivers; 2491 sum6->ipv6OutForwDatagrams += ip6->ipv6OutForwDatagrams; 2492 sum6->ipv6OutRequests += ip6->ipv6OutRequests; 2493 sum6->ipv6OutDiscards += ip6->ipv6OutDiscards; 2494 sum6->ipv6OutFragOKs += ip6->ipv6OutFragOKs; 2495 sum6->ipv6OutFragFails += ip6->ipv6OutFragFails; 2496 sum6->ipv6OutFragCreates += ip6->ipv6OutFragCreates; 2497 sum6->ipv6ReasmReqds += ip6->ipv6ReasmReqds; 2498 sum6->ipv6ReasmOKs += ip6->ipv6ReasmOKs; 2499 sum6->ipv6ReasmFails += ip6->ipv6ReasmFails; 2500 sum6->ipv6InMcastPkts += ip6->ipv6InMcastPkts; 2501 sum6->ipv6OutMcastPkts += ip6->ipv6OutMcastPkts; 2502 sum6->ipv6OutNoRoutes += ip6->ipv6OutNoRoutes; 2503 sum6->ipv6ReasmDuplicates += ip6->ipv6ReasmDuplicates; 2504 sum6->ipv6ReasmPartDups += ip6->ipv6ReasmPartDups; 2505 sum6->ipv6ForwProhibits += ip6->ipv6ForwProhibits; 2506 sum6->udpInCksumErrs += ip6->udpInCksumErrs; 2507 sum6->udpInOverflows += ip6->udpInOverflows; 2508 sum6->rawipInOverflows += ip6->rawipInOverflows; 2509 } 2510 2511 static void 2512 sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6, mib2_ipv6IfIcmpEntry_t *sum6) 2513 { 2514 sum6->ipv6IfIcmpInMsgs += icmp6->ipv6IfIcmpInMsgs; 2515 sum6->ipv6IfIcmpInErrors += icmp6->ipv6IfIcmpInErrors; 2516 sum6->ipv6IfIcmpInDestUnreachs += icmp6->ipv6IfIcmpInDestUnreachs; 2517 sum6->ipv6IfIcmpInAdminProhibs += icmp6->ipv6IfIcmpInAdminProhibs; 2518 sum6->ipv6IfIcmpInTimeExcds += icmp6->ipv6IfIcmpInTimeExcds; 2519 sum6->ipv6IfIcmpInParmProblems += icmp6->ipv6IfIcmpInParmProblems; 2520 sum6->ipv6IfIcmpInPktTooBigs += icmp6->ipv6IfIcmpInPktTooBigs; 2521 sum6->ipv6IfIcmpInEchos += icmp6->ipv6IfIcmpInEchos; 2522 sum6->ipv6IfIcmpInEchoReplies += icmp6->ipv6IfIcmpInEchoReplies; 2523 sum6->ipv6IfIcmpInRouterSolicits += icmp6->ipv6IfIcmpInRouterSolicits; 2524 sum6->ipv6IfIcmpInRouterAdvertisements += 2525 icmp6->ipv6IfIcmpInRouterAdvertisements; 2526 sum6->ipv6IfIcmpInNeighborSolicits += 2527 icmp6->ipv6IfIcmpInNeighborSolicits; 2528 sum6->ipv6IfIcmpInNeighborAdvertisements += 2529 icmp6->ipv6IfIcmpInNeighborAdvertisements; 2530 sum6->ipv6IfIcmpInRedirects += icmp6->ipv6IfIcmpInRedirects; 2531 sum6->ipv6IfIcmpInGroupMembQueries += 2532 icmp6->ipv6IfIcmpInGroupMembQueries; 2533 sum6->ipv6IfIcmpInGroupMembResponses += 2534 icmp6->ipv6IfIcmpInGroupMembResponses; 2535 sum6->ipv6IfIcmpInGroupMembReductions += 2536 icmp6->ipv6IfIcmpInGroupMembReductions; 2537 sum6->ipv6IfIcmpOutMsgs += icmp6->ipv6IfIcmpOutMsgs; 2538 sum6->ipv6IfIcmpOutErrors += icmp6->ipv6IfIcmpOutErrors; 2539 sum6->ipv6IfIcmpOutDestUnreachs += icmp6->ipv6IfIcmpOutDestUnreachs; 2540 sum6->ipv6IfIcmpOutAdminProhibs += icmp6->ipv6IfIcmpOutAdminProhibs; 2541 sum6->ipv6IfIcmpOutTimeExcds += icmp6->ipv6IfIcmpOutTimeExcds; 2542 sum6->ipv6IfIcmpOutParmProblems += icmp6->ipv6IfIcmpOutParmProblems; 2543 sum6->ipv6IfIcmpOutPktTooBigs += icmp6->ipv6IfIcmpOutPktTooBigs; 2544 sum6->ipv6IfIcmpOutEchos += icmp6->ipv6IfIcmpOutEchos; 2545 sum6->ipv6IfIcmpOutEchoReplies += icmp6->ipv6IfIcmpOutEchoReplies; 2546 sum6->ipv6IfIcmpOutRouterSolicits += 2547 icmp6->ipv6IfIcmpOutRouterSolicits; 2548 sum6->ipv6IfIcmpOutRouterAdvertisements += 2549 icmp6->ipv6IfIcmpOutRouterAdvertisements; 2550 sum6->ipv6IfIcmpOutNeighborSolicits += 2551 icmp6->ipv6IfIcmpOutNeighborSolicits; 2552 sum6->ipv6IfIcmpOutNeighborAdvertisements += 2553 icmp6->ipv6IfIcmpOutNeighborAdvertisements; 2554 sum6->ipv6IfIcmpOutRedirects += icmp6->ipv6IfIcmpOutRedirects; 2555 sum6->ipv6IfIcmpOutGroupMembQueries += 2556 icmp6->ipv6IfIcmpOutGroupMembQueries; 2557 sum6->ipv6IfIcmpOutGroupMembResponses += 2558 icmp6->ipv6IfIcmpOutGroupMembResponses; 2559 sum6->ipv6IfIcmpOutGroupMembReductions += 2560 icmp6->ipv6IfIcmpOutGroupMembReductions; 2561 sum6->ipv6IfIcmpInOverflows += icmp6->ipv6IfIcmpInOverflows; 2562 } 2563 2564 /* ----------------------------- MRT_STAT_REPORT --------------------------- */ 2565 2566 static void 2567 mrt_stat_report(mib_item_t *curritem) 2568 { 2569 int jtemp = 0; 2570 mib_item_t *tempitem; 2571 2572 if (!(family_selected(AF_INET))) 2573 return; 2574 2575 (void) putchar('\n'); 2576 /* 'for' loop 1: */ 2577 for (tempitem = curritem; 2578 tempitem; 2579 tempitem = tempitem->next_item) { 2580 if (Xflag) { 2581 (void) printf("\n--- Entry %d ---\n", ++jtemp); 2582 (void) printf("Group = %d, mib_id = %d, " 2583 "length = %d, valp = 0x%p\n", 2584 tempitem->group, tempitem->mib_id, 2585 tempitem->length, tempitem->valp); 2586 } 2587 2588 if (tempitem->mib_id == 0) { 2589 switch (tempitem->group) { 2590 case EXPER_DVMRP: { 2591 struct mrtstat *mrts; 2592 mrts = (struct mrtstat *)tempitem->valp; 2593 2594 if (!(family_selected(AF_INET))) 2595 continue; /* 'for' loop 1 */ 2596 2597 print_mrt_stats(mrts); 2598 break; 2599 } 2600 } 2601 } 2602 } /* 'for' loop 1 ends */ 2603 (void) putchar('\n'); 2604 (void) fflush(stdout); 2605 } 2606 2607 /* 2608 * if_stat_total() - Computes totals for interface statistics 2609 * and returns result by updating sumstats. 2610 */ 2611 static void 2612 if_stat_total(struct ifstat *oldstats, struct ifstat *newstats, 2613 struct ifstat *sumstats) 2614 { 2615 sumstats->ipackets += newstats->ipackets - oldstats->ipackets; 2616 sumstats->opackets += newstats->opackets - oldstats->opackets; 2617 sumstats->ierrors += newstats->ierrors - oldstats->ierrors; 2618 sumstats->oerrors += newstats->oerrors - oldstats->oerrors; 2619 sumstats->collisions += newstats->collisions - oldstats->collisions; 2620 } 2621 2622 /* --------------------- IF_REPORT (netstat -i) -------------------------- */ 2623 2624 static struct ifstat zerostat = { 2625 0LL, 0LL, 0LL, 0LL, 0LL 2626 }; 2627 2628 static void 2629 if_report(mib_item_t *item, char *matchname, 2630 int Iflag_only, boolean_t once_only) 2631 { 2632 static boolean_t reentry = B_FALSE; 2633 boolean_t alreadydone = B_FALSE; 2634 int jtemp = 0; 2635 uint32_t ifindex_v4 = 0; 2636 uint32_t ifindex_v6 = 0; 2637 boolean_t first_header = B_TRUE; 2638 2639 /* 'for' loop 1: */ 2640 for (; item; item = item->next_item) { 2641 if (Xflag) { 2642 (void) printf("\n--- Entry %d ---\n", ++jtemp); 2643 (void) printf("Group = %d, mib_id = %d, " 2644 "length = %d, valp = 0x%p\n", 2645 item->group, item->mib_id, item->length, 2646 item->valp); 2647 } 2648 2649 switch (item->group) { 2650 case MIB2_IP: 2651 if (item->mib_id != MIB2_IP_ADDR || 2652 !family_selected(AF_INET)) 2653 continue; /* 'for' loop 1 */ 2654 { 2655 static struct ifstat old = {0L, 0L, 0L, 0L, 0L}; 2656 static struct ifstat new = {0L, 0L, 0L, 0L, 0L}; 2657 struct ifstat sum; 2658 struct iflist *newlist = NULL; 2659 static struct iflist *oldlist = NULL; 2660 kstat_t *ksp; 2661 2662 if (once_only) { 2663 char ifname[LIFNAMSIZ + 1]; 2664 char logintname[LIFNAMSIZ + 1]; 2665 mib2_ipAddrEntry_t *ap; 2666 struct ifstat stat = {0L, 0L, 0L, 0L, 0L}; 2667 boolean_t first = B_TRUE; 2668 uint32_t new_ifindex; 2669 2670 if (Xflag) 2671 (void) printf("if_report: %d items\n", 2672 (item->length) 2673 / sizeof (mib2_ipAddrEntry_t)); 2674 2675 /* 'for' loop 2a: */ 2676 for (ap = (mib2_ipAddrEntry_t *)item->valp; 2677 (char *)ap < (char *)item->valp 2678 + item->length; 2679 ap++) { 2680 (void) octetstr(&ap->ipAdEntIfIndex, 2681 'a', logintname, 2682 sizeof (logintname)); 2683 (void) strcpy(ifname, logintname); 2684 (void) strtok(ifname, ":"); 2685 if (matchname != NULL && 2686 strcmp(matchname, ifname) != 0 && 2687 strcmp(matchname, logintname) != 0) 2688 continue; /* 'for' loop 2a */ 2689 new_ifindex = 2690 if_nametoindex(logintname); 2691 /* 2692 * First lookup the "link" kstats in 2693 * case the link is renamed. Then 2694 * fallback to the legacy kstats for 2695 * those non-GLDv3 links. 2696 */ 2697 if (new_ifindex != ifindex_v4 && 2698 (((ksp = kstat_lookup(kc, "link", 0, 2699 ifname)) != NULL) || 2700 ((ksp = kstat_lookup(kc, NULL, -1, 2701 ifname)) != NULL))) { 2702 (void) safe_kstat_read(kc, ksp, 2703 NULL); 2704 stat.ipackets = 2705 kstat_named_value(ksp, 2706 "ipackets"); 2707 stat.ierrors = 2708 kstat_named_value(ksp, 2709 "ierrors"); 2710 stat.opackets = 2711 kstat_named_value(ksp, 2712 "opackets"); 2713 stat.oerrors = 2714 kstat_named_value(ksp, 2715 "oerrors"); 2716 stat.collisions = 2717 kstat_named_value(ksp, 2718 "collisions"); 2719 if (first) { 2720 if (!first_header) 2721 (void) putchar('\n'); 2722 first_header = B_FALSE; 2723 (void) printf( 2724 "%-5.5s %-5.5s%-13.13s " 2725 "%-14.14s %-6.6s %-5.5s " 2726 "%-6.6s %-5.5s %-6.6s " 2727 "%-6.6s\n", 2728 "Name", "Mtu", "Net/Dest", 2729 "Address", "Ipkts", 2730 "Ierrs", "Opkts", "Oerrs", 2731 "Collis", "Queue"); 2732 2733 first = B_FALSE; 2734 } 2735 if_report_ip4(ap, ifname, 2736 logintname, &stat, B_TRUE); 2737 ifindex_v4 = new_ifindex; 2738 } else { 2739 if_report_ip4(ap, ifname, 2740 logintname, &stat, B_FALSE); 2741 } 2742 } /* 'for' loop 2a ends */ 2743 } else if (!alreadydone) { 2744 char ifname[LIFNAMSIZ + 1]; 2745 char buf[LIFNAMSIZ + 1]; 2746 mib2_ipAddrEntry_t *ap; 2747 struct ifstat t; 2748 struct iflist *tlp = NULL; 2749 struct iflist **nextnew = &newlist; 2750 struct iflist *walkold; 2751 struct iflist *cleanlist; 2752 boolean_t found_if = B_FALSE; 2753 2754 alreadydone = B_TRUE; /* ignore other case */ 2755 2756 /* 2757 * Check if there is anything to do. 2758 */ 2759 if (item->length < 2760 sizeof (mib2_ipAddrEntry_t)) { 2761 fail(0, "No compatible interfaces"); 2762 } 2763 2764 /* 2765 * 'for' loop 2b: find the "right" entry: 2766 * If an interface name to match has been 2767 * supplied then try and find it, otherwise 2768 * match the first non-loopback interface found. 2769 * Use lo0 if all else fails. 2770 */ 2771 for (ap = (mib2_ipAddrEntry_t *)item->valp; 2772 (char *)ap < (char *)item->valp 2773 + item->length; 2774 ap++) { 2775 (void) octetstr(&ap->ipAdEntIfIndex, 2776 'a', ifname, sizeof (ifname)); 2777 (void) strtok(ifname, ":"); 2778 2779 if (matchname) { 2780 if (strcmp(matchname, 2781 ifname) == 0) { 2782 /* 'for' loop 2b */ 2783 found_if = B_TRUE; 2784 break; 2785 } 2786 } else if (strcmp(ifname, "lo0") != 0) 2787 break; /* 'for' loop 2b */ 2788 } /* 'for' loop 2b ends */ 2789 2790 if (matchname == NULL) { 2791 matchname = ifname; 2792 } else { 2793 if (!found_if) 2794 fail(0, "-I: %s no such " 2795 "interface.", matchname); 2796 } 2797 2798 if (Iflag_only == 0 || !reentry) { 2799 (void) printf(" input %-6.6s " 2800 "output ", 2801 matchname); 2802 (void) printf(" input (Total) " 2803 "output\n"); 2804 (void) printf("%-7.7s %-5.5s %-7.7s " 2805 "%-5.5s %-6.6s ", 2806 "packets", "errs", "packets", 2807 "errs", "colls"); 2808 (void) printf("%-7.7s %-5.5s %-7.7s " 2809 "%-5.5s %-6.6s\n", 2810 "packets", "errs", "packets", 2811 "errs", "colls"); 2812 } 2813 2814 sum = zerostat; 2815 2816 /* 'for' loop 2c: */ 2817 for (ap = (mib2_ipAddrEntry_t *)item->valp; 2818 (char *)ap < (char *)item->valp 2819 + item->length; 2820 ap++) { 2821 (void) octetstr(&ap->ipAdEntIfIndex, 2822 'a', buf, sizeof (buf)); 2823 (void) strtok(buf, ":"); 2824 2825 /* 2826 * We have reduced the IP interface 2827 * name, which could have been a 2828 * logical, down to a name suitable 2829 * for use with kstats. 2830 * We treat this name as unique and 2831 * only collate statistics for it once 2832 * per pass. This is to avoid falsely 2833 * amplifying these statistics by the 2834 * the number of logical instances. 2835 */ 2836 if ((tlp != NULL) && 2837 ((strcmp(buf, tlp->ifname) == 0))) { 2838 continue; 2839 } 2840 2841 /* 2842 * First lookup the "link" kstats in 2843 * case the link is renamed. Then 2844 * fallback to the legacy kstats for 2845 * those non-GLDv3 links. 2846 */ 2847 if (((ksp = kstat_lookup(kc, "link", 2848 0, buf)) != NULL || 2849 (ksp = kstat_lookup(kc, NULL, -1, 2850 buf)) != NULL) && (ksp->ks_type == 2851 KSTAT_TYPE_NAMED)) { 2852 (void) safe_kstat_read(kc, ksp, 2853 NULL); 2854 } 2855 2856 t.ipackets = kstat_named_value(ksp, 2857 "ipackets"); 2858 t.ierrors = kstat_named_value(ksp, 2859 "ierrors"); 2860 t.opackets = kstat_named_value(ksp, 2861 "opackets"); 2862 t.oerrors = kstat_named_value(ksp, 2863 "oerrors"); 2864 t.collisions = kstat_named_value(ksp, 2865 "collisions"); 2866 2867 if (strcmp(buf, matchname) == 0) 2868 new = t; 2869 2870 /* Build the interface list */ 2871 2872 tlp = malloc(sizeof (struct iflist)); 2873 (void) strlcpy(tlp->ifname, buf, 2874 sizeof (tlp->ifname)); 2875 tlp->tot = t; 2876 *nextnew = tlp; 2877 nextnew = &tlp->next_if; 2878 2879 /* 2880 * First time through. 2881 * Just add up the interface stats. 2882 */ 2883 2884 if (oldlist == NULL) { 2885 if_stat_total(&zerostat, 2886 &t, &sum); 2887 continue; 2888 } 2889 2890 /* 2891 * Walk old list for the interface. 2892 * 2893 * If found, add difference to total. 2894 * 2895 * If not, an interface has been plumbed 2896 * up. In this case, we will simply 2897 * ignore the new interface until the 2898 * next interval; as there's no easy way 2899 * to acquire statistics between time 2900 * of the plumb and the next interval 2901 * boundary. This results in inaccurate 2902 * total values for current interval. 2903 * 2904 * Note the case when an interface is 2905 * unplumbed; as similar problems exist. 2906 * The unplumbed interface is not in the 2907 * current list, and there's no easy way 2908 * to account for the statistics between 2909 * the previous interval and time of the 2910 * unplumb. Therefore, we (in a sense) 2911 * ignore the removed interface by only 2912 * involving "current" interfaces when 2913 * computing the total statistics. 2914 * Unfortunately, this also results in 2915 * inaccurate values for interval total. 2916 */ 2917 2918 for (walkold = oldlist; 2919 walkold != NULL; 2920 walkold = walkold->next_if) { 2921 if (strcmp(walkold->ifname, 2922 buf) == 0) { 2923 if_stat_total( 2924 &walkold->tot, 2925 &t, &sum); 2926 break; 2927 } 2928 } 2929 2930 } /* 'for' loop 2c ends */ 2931 2932 *nextnew = NULL; 2933 2934 (void) printf("%-7llu %-5llu %-7llu " 2935 "%-5llu %-6llu ", 2936 new.ipackets - old.ipackets, 2937 new.ierrors - old.ierrors, 2938 new.opackets - old.opackets, 2939 new.oerrors - old.oerrors, 2940 new.collisions - old.collisions); 2941 2942 (void) printf("%-7llu %-5llu %-7llu " 2943 "%-5llu %-6llu\n", sum.ipackets, 2944 sum.ierrors, sum.opackets, 2945 sum.oerrors, sum.collisions); 2946 2947 /* 2948 * Tidy things up once finished. 2949 */ 2950 2951 old = new; 2952 cleanlist = oldlist; 2953 oldlist = newlist; 2954 while (cleanlist != NULL) { 2955 tlp = cleanlist->next_if; 2956 free(cleanlist); 2957 cleanlist = tlp; 2958 } 2959 } 2960 break; 2961 } 2962 case MIB2_IP6: 2963 if (item->mib_id != MIB2_IP6_ADDR || 2964 !family_selected(AF_INET6)) 2965 continue; /* 'for' loop 1 */ 2966 { 2967 static struct ifstat old6 = {0L, 0L, 0L, 0L, 0L}; 2968 static struct ifstat new6 = {0L, 0L, 0L, 0L, 0L}; 2969 struct ifstat sum6; 2970 struct iflist *newlist6 = NULL; 2971 static struct iflist *oldlist6 = NULL; 2972 kstat_t *ksp; 2973 2974 if (once_only) { 2975 char ifname[LIFNAMSIZ + 1]; 2976 char logintname[LIFNAMSIZ + 1]; 2977 mib2_ipv6AddrEntry_t *ap6; 2978 struct ifstat stat = {0L, 0L, 0L, 0L, 0L}; 2979 boolean_t first = B_TRUE; 2980 uint32_t new_ifindex; 2981 2982 if (Xflag) 2983 (void) printf("if_report: %d items\n", 2984 (item->length) 2985 / sizeof (mib2_ipv6AddrEntry_t)); 2986 /* 'for' loop 2d: */ 2987 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp; 2988 (char *)ap6 < (char *)item->valp 2989 + item->length; 2990 ap6++) { 2991 (void) octetstr(&ap6->ipv6AddrIfIndex, 2992 'a', logintname, 2993 sizeof (logintname)); 2994 (void) strcpy(ifname, logintname); 2995 (void) strtok(ifname, ":"); 2996 if (matchname != NULL && 2997 strcmp(matchname, ifname) != 0 && 2998 strcmp(matchname, logintname) != 0) 2999 continue; /* 'for' loop 2d */ 3000 new_ifindex = 3001 if_nametoindex(logintname); 3002 3003 /* 3004 * First lookup the "link" kstats in 3005 * case the link is renamed. Then 3006 * fallback to the legacy kstats for 3007 * those non-GLDv3 links. 3008 */ 3009 if (new_ifindex != ifindex_v6 && 3010 ((ksp = kstat_lookup(kc, "link", 0, 3011 ifname)) != NULL || 3012 (ksp = kstat_lookup(kc, NULL, -1, 3013 ifname)) != NULL)) { 3014 (void) safe_kstat_read(kc, ksp, 3015 NULL); 3016 stat.ipackets = 3017 kstat_named_value(ksp, 3018 "ipackets"); 3019 stat.ierrors = 3020 kstat_named_value(ksp, 3021 "ierrors"); 3022 stat.opackets = 3023 kstat_named_value(ksp, 3024 "opackets"); 3025 stat.oerrors = 3026 kstat_named_value(ksp, 3027 "oerrors"); 3028 stat.collisions = 3029 kstat_named_value(ksp, 3030 "collisions"); 3031 if (first) { 3032 if (!first_header) 3033 (void) putchar('\n'); 3034 first_header = B_FALSE; 3035 (void) printf( 3036 "%-5.5s %-5.5s%" 3037 "-27.27s %-27.27s " 3038 "%-6.6s %-5.5s " 3039 "%-6.6s %-5.5s " 3040 "%-6.6s\n", 3041 "Name", "Mtu", 3042 "Net/Dest", 3043 "Address", "Ipkts", 3044 "Ierrs", "Opkts", 3045 "Oerrs", "Collis"); 3046 first = B_FALSE; 3047 } 3048 if_report_ip6(ap6, ifname, 3049 logintname, &stat, B_TRUE); 3050 ifindex_v6 = new_ifindex; 3051 } else { 3052 if_report_ip6(ap6, ifname, 3053 logintname, &stat, B_FALSE); 3054 } 3055 } /* 'for' loop 2d ends */ 3056 } else if (!alreadydone) { 3057 char ifname[LIFNAMSIZ + 1]; 3058 char buf[IFNAMSIZ + 1]; 3059 mib2_ipv6AddrEntry_t *ap6; 3060 struct ifstat t; 3061 struct iflist *tlp = NULL; 3062 struct iflist **nextnew = &newlist6; 3063 struct iflist *walkold; 3064 struct iflist *cleanlist; 3065 boolean_t found_if = B_FALSE; 3066 3067 alreadydone = B_TRUE; /* ignore other case */ 3068 3069 /* 3070 * Check if there is anything to do. 3071 */ 3072 if (item->length < 3073 sizeof (mib2_ipv6AddrEntry_t)) { 3074 fail(0, "No compatible interfaces"); 3075 } 3076 3077 /* 3078 * 'for' loop 2e: find the "right" entry: 3079 * If an interface name to match has been 3080 * supplied then try and find it, otherwise 3081 * match the first non-loopback interface found. 3082 * Use lo0 if all else fails. 3083 */ 3084 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp; 3085 (char *)ap6 < (char *)item->valp 3086 + item->length; 3087 ap6++) { 3088 (void) octetstr(&ap6->ipv6AddrIfIndex, 3089 'a', ifname, sizeof (ifname)); 3090 (void) strtok(ifname, ":"); 3091 3092 if (matchname) { 3093 if (strcmp(matchname, 3094 ifname) == 0) { 3095 /* 'for' loop 2e */ 3096 found_if = B_TRUE; 3097 break; 3098 } 3099 } else if (strcmp(ifname, "lo0") != 0) 3100 break; /* 'for' loop 2e */ 3101 } /* 'for' loop 2e ends */ 3102 3103 if (matchname == NULL) { 3104 matchname = ifname; 3105 } else { 3106 if (!found_if) 3107 fail(0, "-I: %s no such " 3108 "interface.", matchname); 3109 } 3110 3111 if (Iflag_only == 0 || !reentry) { 3112 (void) printf( 3113 " input %-6.6s" 3114 " output ", 3115 matchname); 3116 (void) printf(" input (Total)" 3117 " output\n"); 3118 (void) printf("%-7.7s %-5.5s %-7.7s " 3119 "%-5.5s %-6.6s ", 3120 "packets", "errs", "packets", 3121 "errs", "colls"); 3122 (void) printf("%-7.7s %-5.5s %-7.7s " 3123 "%-5.5s %-6.6s\n", 3124 "packets", "errs", "packets", 3125 "errs", "colls"); 3126 } 3127 3128 sum6 = zerostat; 3129 3130 /* 'for' loop 2f: */ 3131 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp; 3132 (char *)ap6 < (char *)item->valp 3133 + item->length; 3134 ap6++) { 3135 (void) octetstr(&ap6->ipv6AddrIfIndex, 3136 'a', buf, sizeof (buf)); 3137 (void) strtok(buf, ":"); 3138 3139 /* 3140 * We have reduced the IP interface 3141 * name, which could have been a 3142 * logical, down to a name suitable 3143 * for use with kstats. 3144 * We treat this name as unique and 3145 * only collate statistics for it once 3146 * per pass. This is to avoid falsely 3147 * amplifying these statistics by the 3148 * the number of logical instances. 3149 */ 3150 3151 if ((tlp != NULL) && 3152 ((strcmp(buf, tlp->ifname) == 0))) { 3153 continue; 3154 } 3155 3156 /* 3157 * First lookup the "link" kstats in 3158 * case the link is renamed. Then 3159 * fallback to the legacy kstats for 3160 * those non-GLDv3 links. 3161 */ 3162 if (((ksp = kstat_lookup(kc, "link", 3163 0, buf)) != NULL || 3164 (ksp = kstat_lookup(kc, NULL, -1, 3165 buf)) != NULL) && (ksp->ks_type == 3166 KSTAT_TYPE_NAMED)) { 3167 (void) safe_kstat_read(kc, 3168 ksp, NULL); 3169 } 3170 3171 t.ipackets = kstat_named_value(ksp, 3172 "ipackets"); 3173 t.ierrors = kstat_named_value(ksp, 3174 "ierrors"); 3175 t.opackets = kstat_named_value(ksp, 3176 "opackets"); 3177 t.oerrors = kstat_named_value(ksp, 3178 "oerrors"); 3179 t.collisions = kstat_named_value(ksp, 3180 "collisions"); 3181 3182 if (strcmp(buf, matchname) == 0) 3183 new6 = t; 3184 3185 /* Build the interface list */ 3186 3187 tlp = malloc(sizeof (struct iflist)); 3188 (void) strlcpy(tlp->ifname, buf, 3189 sizeof (tlp->ifname)); 3190 tlp->tot = t; 3191 *nextnew = tlp; 3192 nextnew = &tlp->next_if; 3193 3194 /* 3195 * First time through. 3196 * Just add up the interface stats. 3197 */ 3198 3199 if (oldlist6 == NULL) { 3200 if_stat_total(&zerostat, 3201 &t, &sum6); 3202 continue; 3203 } 3204 3205 /* 3206 * Walk old list for the interface. 3207 * 3208 * If found, add difference to total. 3209 * 3210 * If not, an interface has been plumbed 3211 * up. In this case, we will simply 3212 * ignore the new interface until the 3213 * next interval; as there's no easy way 3214 * to acquire statistics between time 3215 * of the plumb and the next interval 3216 * boundary. This results in inaccurate 3217 * total values for current interval. 3218 * 3219 * Note the case when an interface is 3220 * unplumbed; as similar problems exist. 3221 * The unplumbed interface is not in the 3222 * current list, and there's no easy way 3223 * to account for the statistics between 3224 * the previous interval and time of the 3225 * unplumb. Therefore, we (in a sense) 3226 * ignore the removed interface by only 3227 * involving "current" interfaces when 3228 * computing the total statistics. 3229 * Unfortunately, this also results in 3230 * inaccurate values for interval total. 3231 */ 3232 3233 for (walkold = oldlist6; 3234 walkold != NULL; 3235 walkold = walkold->next_if) { 3236 if (strcmp(walkold->ifname, 3237 buf) == 0) { 3238 if_stat_total( 3239 &walkold->tot, 3240 &t, &sum6); 3241 break; 3242 } 3243 } 3244 3245 } /* 'for' loop 2f ends */ 3246 3247 *nextnew = NULL; 3248 3249 (void) printf("%-7llu %-5llu %-7llu " 3250 "%-5llu %-6llu ", 3251 new6.ipackets - old6.ipackets, 3252 new6.ierrors - old6.ierrors, 3253 new6.opackets - old6.opackets, 3254 new6.oerrors - old6.oerrors, 3255 new6.collisions - old6.collisions); 3256 3257 (void) printf("%-7llu %-5llu %-7llu " 3258 "%-5llu %-6llu\n", sum6.ipackets, 3259 sum6.ierrors, sum6.opackets, 3260 sum6.oerrors, sum6.collisions); 3261 3262 /* 3263 * Tidy things up once finished. 3264 */ 3265 3266 old6 = new6; 3267 cleanlist = oldlist6; 3268 oldlist6 = newlist6; 3269 while (cleanlist != NULL) { 3270 tlp = cleanlist->next_if; 3271 free(cleanlist); 3272 cleanlist = tlp; 3273 } 3274 } 3275 break; 3276 } 3277 } 3278 (void) fflush(stdout); 3279 } /* 'for' loop 1 ends */ 3280 if ((Iflag_only == 0) && (!once_only)) 3281 (void) putchar('\n'); 3282 reentry = B_TRUE; 3283 } 3284 3285 static void 3286 if_report_ip4(mib2_ipAddrEntry_t *ap, char ifname[], char logintname[], 3287 struct ifstat *statptr, boolean_t ksp_not_null) 3288 { 3289 3290 char abuf[MAXHOSTNAMELEN + 1]; 3291 char dstbuf[MAXHOSTNAMELEN + 1]; 3292 3293 if (ksp_not_null) { 3294 (void) printf("%-5s %-4u ", 3295 ifname, ap->ipAdEntInfo.ae_mtu); 3296 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT) 3297 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, 3298 abuf, sizeof (abuf)); 3299 else 3300 (void) pr_netaddr(ap->ipAdEntAddr, 3301 ap->ipAdEntNetMask, abuf, sizeof (abuf)); 3302 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu " 3303 "%-6llu %-6llu\n", 3304 abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)), 3305 statptr->ipackets, statptr->ierrors, 3306 statptr->opackets, statptr->oerrors, 3307 statptr->collisions, 0LL); 3308 } 3309 /* 3310 * Print logical interface info if Aflag set (including logical unit 0) 3311 */ 3312 if (Aflag) { 3313 *statptr = zerostat; 3314 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt; 3315 statptr->opackets = ap->ipAdEntInfo.ae_obcnt; 3316 3317 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu); 3318 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT) 3319 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf, 3320 sizeof (abuf)); 3321 else 3322 (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask, 3323 abuf, sizeof (abuf)); 3324 3325 (void) printf("%-13s %-14s %-6llu %-5s %-6s " 3326 "%-5s %-6s %-6llu\n", abuf, 3327 pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)), 3328 statptr->ipackets, "N/A", "N/A", "N/A", "N/A", 3329 0LL); 3330 } 3331 } 3332 3333 static void 3334 if_report_ip6(mib2_ipv6AddrEntry_t *ap6, char ifname[], char logintname[], 3335 struct ifstat *statptr, boolean_t ksp_not_null) 3336 { 3337 3338 char abuf[MAXHOSTNAMELEN + 1]; 3339 char dstbuf[MAXHOSTNAMELEN + 1]; 3340 3341 if (ksp_not_null) { 3342 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu); 3343 if (ap6->ipv6AddrInfo.ae_flags & 3344 IFF_POINTOPOINT) { 3345 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr, 3346 abuf, sizeof (abuf)); 3347 } else { 3348 (void) pr_prefix6(&ap6->ipv6AddrAddress, 3349 ap6->ipv6AddrPfxLength, abuf, 3350 sizeof (abuf)); 3351 } 3352 (void) printf("%-27s %-27s %-6llu %-5llu " 3353 "%-6llu %-5llu %-6llu\n", 3354 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf, 3355 sizeof (dstbuf)), 3356 statptr->ipackets, statptr->ierrors, statptr->opackets, 3357 statptr->oerrors, statptr->collisions); 3358 } 3359 /* 3360 * Print logical interface info if Aflag set (including logical unit 0) 3361 */ 3362 if (Aflag) { 3363 *statptr = zerostat; 3364 statptr->ipackets = ap6->ipv6AddrInfo.ae_ibcnt; 3365 statptr->opackets = ap6->ipv6AddrInfo.ae_obcnt; 3366 3367 (void) printf("%-5s %-4u ", logintname, 3368 ap6->ipv6AddrInfo.ae_mtu); 3369 if (ap6->ipv6AddrInfo.ae_flags & IFF_POINTOPOINT) 3370 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr, 3371 abuf, sizeof (abuf)); 3372 else 3373 (void) pr_prefix6(&ap6->ipv6AddrAddress, 3374 ap6->ipv6AddrPfxLength, abuf, sizeof (abuf)); 3375 (void) printf("%-27s %-27s %-6llu %-5s %-6s %-5s %-6s\n", 3376 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf, 3377 sizeof (dstbuf)), 3378 statptr->ipackets, "N/A", "N/A", "N/A", "N/A"); 3379 } 3380 } 3381 3382 /* --------------------- DHCP_REPORT (netstat -D) ------------------------- */ 3383 3384 static boolean_t 3385 dhcp_do_ipc(dhcp_ipc_type_t type, const char *ifname, boolean_t printed_one) 3386 { 3387 dhcp_ipc_request_t *request; 3388 dhcp_ipc_reply_t *reply; 3389 int error; 3390 3391 request = dhcp_ipc_alloc_request(type, ifname, NULL, 0, DHCP_TYPE_NONE); 3392 if (request == NULL) 3393 fail(0, "dhcp_do_ipc: out of memory"); 3394 3395 error = dhcp_ipc_make_request(request, &reply, DHCP_IPC_WAIT_DEFAULT); 3396 if (error != 0) { 3397 free(request); 3398 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error)); 3399 } 3400 3401 free(request); 3402 error = reply->return_code; 3403 if (error == DHCP_IPC_E_UNKIF) { 3404 free(reply); 3405 return (printed_one); 3406 } 3407 if (error != 0) { 3408 free(reply); 3409 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error)); 3410 } 3411 3412 if (timestamp_fmt != NODATE) 3413 print_timestamp(timestamp_fmt); 3414 3415 if (!printed_one) 3416 (void) printf("%s", dhcp_status_hdr_string()); 3417 3418 (void) printf("%s", dhcp_status_reply_to_string(reply)); 3419 free(reply); 3420 return (B_TRUE); 3421 } 3422 3423 /* 3424 * dhcp_walk_interfaces: walk the list of interfaces for a given address 3425 * family (af). For each, print out the DHCP status using dhcp_do_ipc. 3426 */ 3427 static boolean_t 3428 dhcp_walk_interfaces(int af, boolean_t printed_one) 3429 { 3430 struct lifnum lifn; 3431 struct lifconf lifc; 3432 int n_ifs, i, sock_fd; 3433 3434 sock_fd = socket(af, SOCK_DGRAM, 0); 3435 if (sock_fd == -1) 3436 return (printed_one); 3437 3438 /* 3439 * SIOCGLIFNUM is just an estimate. If the ioctl fails, we don't care; 3440 * just drive on and use SIOCGLIFCONF with increasing buffer sizes, as 3441 * is traditional. 3442 */ 3443 (void) memset(&lifn, 0, sizeof (lifn)); 3444 lifn.lifn_family = af; 3445 lifn.lifn_flags = LIFC_ALLZONES | LIFC_NOXMIT | LIFC_UNDER_IPMP; 3446 if (ioctl(sock_fd, SIOCGLIFNUM, &lifn) == -1) 3447 n_ifs = LIFN_GUARD_VALUE; 3448 else 3449 n_ifs = lifn.lifn_count + LIFN_GUARD_VALUE; 3450 3451 (void) memset(&lifc, 0, sizeof (lifc)); 3452 lifc.lifc_family = af; 3453 lifc.lifc_flags = lifn.lifn_flags; 3454 lifc.lifc_len = n_ifs * sizeof (struct lifreq); 3455 lifc.lifc_buf = malloc(lifc.lifc_len); 3456 if (lifc.lifc_buf != NULL) { 3457 3458 if (ioctl(sock_fd, SIOCGLIFCONF, &lifc) == -1) { 3459 (void) close(sock_fd); 3460 free(lifc.lifc_buf); 3461 return (NULL); 3462 } 3463 3464 n_ifs = lifc.lifc_len / sizeof (struct lifreq); 3465 3466 for (i = 0; i < n_ifs; i++) { 3467 printed_one = dhcp_do_ipc(DHCP_STATUS | 3468 (af == AF_INET6 ? DHCP_V6 : 0), 3469 lifc.lifc_req[i].lifr_name, printed_one); 3470 } 3471 } 3472 (void) close(sock_fd); 3473 free(lifc.lifc_buf); 3474 return (printed_one); 3475 } 3476 3477 static void 3478 dhcp_report(char *ifname) 3479 { 3480 boolean_t printed_one; 3481 3482 if (!family_selected(AF_INET) && !family_selected(AF_INET6)) 3483 return; 3484 3485 printed_one = B_FALSE; 3486 if (ifname != NULL) { 3487 if (family_selected(AF_INET)) { 3488 printed_one = dhcp_do_ipc(DHCP_STATUS, ifname, 3489 printed_one); 3490 } 3491 if (family_selected(AF_INET6)) { 3492 printed_one = dhcp_do_ipc(DHCP_STATUS | DHCP_V6, 3493 ifname, printed_one); 3494 } 3495 if (!printed_one) { 3496 fail(0, "%s: %s", ifname, 3497 dhcp_ipc_strerror(DHCP_IPC_E_UNKIF)); 3498 } 3499 } else { 3500 if (family_selected(AF_INET)) { 3501 printed_one = dhcp_walk_interfaces(AF_INET, 3502 printed_one); 3503 } 3504 if (family_selected(AF_INET6)) 3505 (void) dhcp_walk_interfaces(AF_INET6, printed_one); 3506 } 3507 } 3508 3509 /* --------------------- GROUP_REPORT (netstat -g) ------------------------- */ 3510 3511 static void 3512 group_report(mib_item_t *item) 3513 { 3514 mib_item_t *v4grp = NULL, *v4src = NULL; 3515 mib_item_t *v6grp = NULL, *v6src = NULL; 3516 int jtemp = 0; 3517 char ifname[LIFNAMSIZ + 1]; 3518 char abuf[MAXHOSTNAMELEN + 1]; 3519 ip_member_t *ipmp; 3520 ip_grpsrc_t *ips; 3521 ipv6_member_t *ipmp6; 3522 ipv6_grpsrc_t *ips6; 3523 boolean_t first, first_src; 3524 3525 /* 'for' loop 1: */ 3526 for (; item; item = item->next_item) { 3527 if (Xflag) { 3528 (void) printf("\n--- Entry %d ---\n", ++jtemp); 3529 (void) printf("Group = %d, mib_id = %d, " 3530 "length = %d, valp = 0x%p\n", 3531 item->group, item->mib_id, item->length, 3532 item->valp); 3533 } 3534 if (item->group == MIB2_IP && family_selected(AF_INET)) { 3535 switch (item->mib_id) { 3536 case EXPER_IP_GROUP_MEMBERSHIP: 3537 v4grp = item; 3538 if (Xflag) 3539 (void) printf("item is v4grp info\n"); 3540 break; 3541 case EXPER_IP_GROUP_SOURCES: 3542 v4src = item; 3543 if (Xflag) 3544 (void) printf("item is v4src info\n"); 3545 break; 3546 default: 3547 continue; 3548 } 3549 continue; 3550 } 3551 if (item->group == MIB2_IP6 && family_selected(AF_INET6)) { 3552 switch (item->mib_id) { 3553 case EXPER_IP6_GROUP_MEMBERSHIP: 3554 v6grp = item; 3555 if (Xflag) 3556 (void) printf("item is v6grp info\n"); 3557 break; 3558 case EXPER_IP6_GROUP_SOURCES: 3559 v6src = item; 3560 if (Xflag) 3561 (void) printf("item is v6src info\n"); 3562 break; 3563 default: 3564 continue; 3565 } 3566 } 3567 } 3568 3569 if (family_selected(AF_INET) && v4grp != NULL) { 3570 if (Xflag) 3571 (void) printf("%u records for ipGroupMember:\n", 3572 v4grp->length / sizeof (ip_member_t)); 3573 3574 first = B_TRUE; 3575 for (ipmp = (ip_member_t *)v4grp->valp; 3576 (char *)ipmp < (char *)v4grp->valp + v4grp->length; 3577 /* LINTED: (note 1) */ 3578 ipmp = (ip_member_t *)((char *)ipmp + ipMemberEntrySize)) { 3579 if (first) { 3580 (void) puts(v4compat ? 3581 "Group Memberships" : 3582 "Group Memberships: IPv4"); 3583 (void) puts("Interface " 3584 "Group RefCnt"); 3585 (void) puts("--------- " 3586 "-------------------- ------"); 3587 first = B_FALSE; 3588 } 3589 3590 (void) printf("%-9s %-20s %6u\n", 3591 octetstr(&ipmp->ipGroupMemberIfIndex, 'a', 3592 ifname, sizeof (ifname)), 3593 pr_addr(ipmp->ipGroupMemberAddress, 3594 abuf, sizeof (abuf)), 3595 ipmp->ipGroupMemberRefCnt); 3596 3597 3598 if (!Vflag || v4src == NULL) 3599 continue; 3600 3601 if (Xflag) 3602 (void) printf("scanning %u ipGroupSource " 3603 "records...\n", 3604 v4src->length/sizeof (ip_grpsrc_t)); 3605 3606 first_src = B_TRUE; 3607 for (ips = (ip_grpsrc_t *)v4src->valp; 3608 (char *)ips < (char *)v4src->valp + v4src->length; 3609 /* LINTED: (note 1) */ 3610 ips = (ip_grpsrc_t *)((char *)ips + 3611 ipGroupSourceEntrySize)) { 3612 /* 3613 * We assume that all source addrs for a given 3614 * interface/group pair are contiguous, so on 3615 * the first non-match after we've found at 3616 * least one, we bail. 3617 */ 3618 if ((ipmp->ipGroupMemberAddress != 3619 ips->ipGroupSourceGroup) || 3620 (!octetstrmatch(&ipmp->ipGroupMemberIfIndex, 3621 &ips->ipGroupSourceIfIndex))) { 3622 if (first_src) 3623 continue; 3624 else 3625 break; 3626 } 3627 if (first_src) { 3628 (void) printf("\t%s: %s\n", 3629 fmodestr( 3630 ipmp->ipGroupMemberFilterMode), 3631 pr_addr(ips->ipGroupSourceAddress, 3632 abuf, sizeof (abuf))); 3633 first_src = B_FALSE; 3634 continue; 3635 } 3636 3637 (void) printf("\t %s\n", 3638 pr_addr(ips->ipGroupSourceAddress, abuf, 3639 sizeof (abuf))); 3640 } 3641 } 3642 (void) putchar('\n'); 3643 } 3644 3645 if (family_selected(AF_INET6) && v6grp != NULL) { 3646 if (Xflag) 3647 (void) printf("%u records for ipv6GroupMember:\n", 3648 v6grp->length / sizeof (ipv6_member_t)); 3649 3650 first = B_TRUE; 3651 for (ipmp6 = (ipv6_member_t *)v6grp->valp; 3652 (char *)ipmp6 < (char *)v6grp->valp + v6grp->length; 3653 /* LINTED: (note 1) */ 3654 ipmp6 = (ipv6_member_t *)((char *)ipmp6 + 3655 ipv6MemberEntrySize)) { 3656 if (first) { 3657 (void) puts("Group Memberships: " 3658 "IPv6"); 3659 (void) puts(" If " 3660 "Group RefCnt"); 3661 (void) puts("----- " 3662 "--------------------------- ------"); 3663 first = B_FALSE; 3664 } 3665 3666 (void) printf("%-5s %-27s %5u\n", 3667 ifindex2str(ipmp6->ipv6GroupMemberIfIndex, ifname), 3668 pr_addr6(&ipmp6->ipv6GroupMemberAddress, 3669 abuf, sizeof (abuf)), 3670 ipmp6->ipv6GroupMemberRefCnt); 3671 3672 if (!Vflag || v6src == NULL) 3673 continue; 3674 3675 if (Xflag) 3676 (void) printf("scanning %u ipv6GroupSource " 3677 "records...\n", 3678 v6src->length/sizeof (ipv6_grpsrc_t)); 3679 3680 first_src = B_TRUE; 3681 for (ips6 = (ipv6_grpsrc_t *)v6src->valp; 3682 (char *)ips6 < (char *)v6src->valp + v6src->length; 3683 /* LINTED: (note 1) */ 3684 ips6 = (ipv6_grpsrc_t *)((char *)ips6 + 3685 ipv6GroupSourceEntrySize)) { 3686 /* same assumption as in the v4 case above */ 3687 if ((ipmp6->ipv6GroupMemberIfIndex != 3688 ips6->ipv6GroupSourceIfIndex) || 3689 (!IN6_ARE_ADDR_EQUAL( 3690 &ipmp6->ipv6GroupMemberAddress, 3691 &ips6->ipv6GroupSourceGroup))) { 3692 if (first_src) 3693 continue; 3694 else 3695 break; 3696 } 3697 if (first_src) { 3698 (void) printf("\t%s: %s\n", 3699 fmodestr( 3700 ipmp6->ipv6GroupMemberFilterMode), 3701 pr_addr6( 3702 &ips6->ipv6GroupSourceAddress, 3703 abuf, sizeof (abuf))); 3704 first_src = B_FALSE; 3705 continue; 3706 } 3707 3708 (void) printf("\t %s\n", 3709 pr_addr6(&ips6->ipv6GroupSourceAddress, 3710 abuf, sizeof (abuf))); 3711 } 3712 } 3713 (void) putchar('\n'); 3714 } 3715 3716 (void) putchar('\n'); 3717 (void) fflush(stdout); 3718 } 3719 3720 /* --------------------- DCE_REPORT (netstat -d) ------------------------- */ 3721 3722 #define FLBUFSIZE 8 3723 3724 /* Assumes flbuf is at least 5 characters; callers use FLBUFSIZE */ 3725 static char * 3726 dceflags2str(uint32_t flags, char *flbuf) 3727 { 3728 char *str = flbuf; 3729 3730 if (flags & DCEF_DEFAULT) 3731 *str++ = 'D'; 3732 if (flags & DCEF_PMTU) 3733 *str++ = 'P'; 3734 if (flags & DCEF_UINFO) 3735 *str++ = 'U'; 3736 if (flags & DCEF_TOO_SMALL_PMTU) 3737 *str++ = 'S'; 3738 *str++ = '\0'; 3739 return (flbuf); 3740 } 3741 3742 static void 3743 dce_report(mib_item_t *item) 3744 { 3745 mib_item_t *v4dce = NULL; 3746 mib_item_t *v6dce = NULL; 3747 int jtemp = 0; 3748 char ifname[LIFNAMSIZ + 1]; 3749 char abuf[MAXHOSTNAMELEN + 1]; 3750 char flbuf[FLBUFSIZE]; 3751 boolean_t first; 3752 dest_cache_entry_t *dce; 3753 3754 /* 'for' loop 1: */ 3755 for (; item; item = item->next_item) { 3756 if (Xflag) { 3757 (void) printf("\n--- Entry %d ---\n", ++jtemp); 3758 (void) printf("Group = %d, mib_id = %d, " 3759 "length = %d, valp = 0x%p\n", 3760 item->group, item->mib_id, item->length, 3761 item->valp); 3762 } 3763 if (item->group == MIB2_IP && family_selected(AF_INET) && 3764 item->mib_id == EXPER_IP_DCE) { 3765 v4dce = item; 3766 if (Xflag) 3767 (void) printf("item is v4dce info\n"); 3768 } 3769 if (item->group == MIB2_IP6 && family_selected(AF_INET6) && 3770 item->mib_id == EXPER_IP_DCE) { 3771 v6dce = item; 3772 if (Xflag) 3773 (void) printf("item is v6dce info\n"); 3774 } 3775 } 3776 3777 if (family_selected(AF_INET) && v4dce != NULL) { 3778 if (Xflag) 3779 (void) printf("%u records for DestCacheEntry:\n", 3780 v4dce->length / ipDestEntrySize); 3781 3782 first = B_TRUE; 3783 for (dce = (dest_cache_entry_t *)v4dce->valp; 3784 (char *)dce < (char *)v4dce->valp + v4dce->length; 3785 /* LINTED: (note 1) */ 3786 dce = (dest_cache_entry_t *)((char *)dce + 3787 ipDestEntrySize)) { 3788 if (first) { 3789 (void) putchar('\n'); 3790 (void) puts("Destination Cache Entries: IPv4"); 3791 (void) puts( 3792 "Address PMTU Age Flags"); 3793 (void) puts( 3794 "-------------------- ------ ----- -----"); 3795 first = B_FALSE; 3796 } 3797 3798 (void) printf("%-20s %6u %5u %-5s\n", 3799 pr_addr(dce->DestIpv4Address, abuf, sizeof (abuf)), 3800 dce->DestPmtu, dce->DestAge, 3801 dceflags2str(dce->DestFlags, flbuf)); 3802 } 3803 } 3804 3805 if (family_selected(AF_INET6) && v6dce != NULL) { 3806 if (Xflag) 3807 (void) printf("%u records for DestCacheEntry:\n", 3808 v6dce->length / ipDestEntrySize); 3809 3810 first = B_TRUE; 3811 for (dce = (dest_cache_entry_t *)v6dce->valp; 3812 (char *)dce < (char *)v6dce->valp + v6dce->length; 3813 /* LINTED: (note 1) */ 3814 dce = (dest_cache_entry_t *)((char *)dce + 3815 ipDestEntrySize)) { 3816 if (first) { 3817 (void) putchar('\n'); 3818 (void) puts("Destination Cache Entries: IPv6"); 3819 (void) puts( 3820 "Address PMTU " 3821 " Age Flags If "); 3822 (void) puts( 3823 "--------------------------- ------ " 3824 "----- ----- ---"); 3825 first = B_FALSE; 3826 } 3827 3828 (void) printf("%-27s %6u %5u %-5s %s\n", 3829 pr_addr6(&dce->DestIpv6Address, abuf, 3830 sizeof (abuf)), 3831 dce->DestPmtu, dce->DestAge, 3832 dceflags2str(dce->DestFlags, flbuf), 3833 dce->DestIfindex == 0 ? "" : 3834 ifindex2str(dce->DestIfindex, ifname)); 3835 } 3836 } 3837 (void) fflush(stdout); 3838 } 3839 3840 /* --------------------- ARP_REPORT (netstat -p) -------------------------- */ 3841 3842 static void 3843 arp_report(mib_item_t *item) 3844 { 3845 int jtemp = 0; 3846 char ifname[LIFNAMSIZ + 1]; 3847 char abuf[MAXHOSTNAMELEN + 1]; 3848 char maskbuf[STR_EXPAND * OCTET_LENGTH + 1]; 3849 char flbuf[32]; /* ACE_F_ flags */ 3850 char xbuf[STR_EXPAND * OCTET_LENGTH + 1]; 3851 mib2_ipNetToMediaEntry_t *np; 3852 int flags; 3853 boolean_t first; 3854 3855 if (!(family_selected(AF_INET))) 3856 return; 3857 3858 /* 'for' loop 1: */ 3859 for (; item; item = item->next_item) { 3860 if (Xflag) { 3861 (void) printf("\n--- Entry %d ---\n", ++jtemp); 3862 (void) printf("Group = %d, mib_id = %d, " 3863 "length = %d, valp = 0x%p\n", 3864 item->group, item->mib_id, item->length, 3865 item->valp); 3866 } 3867 if (!(item->group == MIB2_IP && item->mib_id == MIB2_IP_MEDIA)) 3868 continue; /* 'for' loop 1 */ 3869 3870 if (Xflag) 3871 (void) printf("%u records for " 3872 "ipNetToMediaEntryTable:\n", 3873 item->length/sizeof (mib2_ipNetToMediaEntry_t)); 3874 3875 first = B_TRUE; 3876 /* 'for' loop 2: */ 3877 for (np = (mib2_ipNetToMediaEntry_t *)item->valp; 3878 (char *)np < (char *)item->valp + item->length; 3879 /* LINTED: (note 1) */ 3880 np = (mib2_ipNetToMediaEntry_t *)((char *)np + 3881 ipNetToMediaEntrySize)) { 3882 if (first) { 3883 (void) puts(v4compat ? 3884 "Net to Media Table" : 3885 "Net to Media Table: IPv4"); 3886 (void) puts("Device " 3887 " IP Address Mask " 3888 "Flags Phys Addr"); 3889 (void) puts("------ " 3890 "-------------------- --------------- " 3891 "-------- ---------------"); 3892 first = B_FALSE; 3893 } 3894 3895 flbuf[0] = '\0'; 3896 flags = np->ipNetToMediaInfo.ntm_flags; 3897 /* 3898 * Note that not all flags are possible at the same 3899 * time. Patterns: SPLAy DUo 3900 */ 3901 if (flags & ACE_F_PERMANENT) 3902 (void) strcat(flbuf, "S"); 3903 if (flags & ACE_F_PUBLISH) 3904 (void) strcat(flbuf, "P"); 3905 if (flags & ACE_F_DYING) 3906 (void) strcat(flbuf, "D"); 3907 if (!(flags & ACE_F_RESOLVED)) 3908 (void) strcat(flbuf, "U"); 3909 if (flags & ACE_F_MAPPING) 3910 (void) strcat(flbuf, "M"); 3911 if (flags & ACE_F_MYADDR) 3912 (void) strcat(flbuf, "L"); 3913 if (flags & ACE_F_UNVERIFIED) 3914 (void) strcat(flbuf, "d"); 3915 if (flags & ACE_F_AUTHORITY) 3916 (void) strcat(flbuf, "A"); 3917 if (flags & ACE_F_OLD) 3918 (void) strcat(flbuf, "o"); 3919 if (flags & ACE_F_DELAYED) 3920 (void) strcat(flbuf, "y"); 3921 (void) printf("%-6s %-20s %-15s %-8s %s\n", 3922 octetstr(&np->ipNetToMediaIfIndex, 'a', 3923 ifname, sizeof (ifname)), 3924 pr_addr(np->ipNetToMediaNetAddress, 3925 abuf, sizeof (abuf)), 3926 octetstr(&np->ipNetToMediaInfo.ntm_mask, 'd', 3927 maskbuf, sizeof (maskbuf)), 3928 flbuf, 3929 octetstr(&np->ipNetToMediaPhysAddress, 'h', 3930 xbuf, sizeof (xbuf))); 3931 } /* 'for' loop 2 ends */ 3932 } /* 'for' loop 1 ends */ 3933 (void) fflush(stdout); 3934 } 3935 3936 /* --------------------- NDP_REPORT (netstat -p) -------------------------- */ 3937 3938 static void 3939 ndp_report(mib_item_t *item) 3940 { 3941 int jtemp = 0; 3942 char abuf[MAXHOSTNAMELEN + 1]; 3943 char *state; 3944 char *type; 3945 char xbuf[STR_EXPAND * OCTET_LENGTH + 1]; 3946 mib2_ipv6NetToMediaEntry_t *np6; 3947 char ifname[LIFNAMSIZ + 1]; 3948 boolean_t first; 3949 3950 if (!(family_selected(AF_INET6))) 3951 return; 3952 3953 /* 'for' loop 1: */ 3954 for (; item; item = item->next_item) { 3955 if (Xflag) { 3956 (void) printf("\n--- Entry %d ---\n", ++jtemp); 3957 (void) printf("Group = %d, mib_id = %d, " 3958 "length = %d, valp = 0x%p\n", 3959 item->group, item->mib_id, item->length, 3960 item->valp); 3961 } 3962 if (!(item->group == MIB2_IP6 && 3963 item->mib_id == MIB2_IP6_MEDIA)) 3964 continue; /* 'for' loop 1 */ 3965 3966 first = B_TRUE; 3967 /* 'for' loop 2: */ 3968 for (np6 = (mib2_ipv6NetToMediaEntry_t *)item->valp; 3969 (char *)np6 < (char *)item->valp + item->length; 3970 /* LINTED: (note 1) */ 3971 np6 = (mib2_ipv6NetToMediaEntry_t *)((char *)np6 + 3972 ipv6NetToMediaEntrySize)) { 3973 if (first) { 3974 (void) puts("\nNet to Media Table: IPv6"); 3975 (void) puts(" If Physical Address " 3976 " Type State Destination/Mask"); 3977 (void) puts("----- ----------------- " 3978 "------- ------------ " 3979 "---------------------------"); 3980 first = B_FALSE; 3981 } 3982 3983 switch (np6->ipv6NetToMediaState) { 3984 case ND_INCOMPLETE: 3985 state = "INCOMPLETE"; 3986 break; 3987 case ND_REACHABLE: 3988 state = "REACHABLE"; 3989 break; 3990 case ND_STALE: 3991 state = "STALE"; 3992 break; 3993 case ND_DELAY: 3994 state = "DELAY"; 3995 break; 3996 case ND_PROBE: 3997 state = "PROBE"; 3998 break; 3999 case ND_UNREACHABLE: 4000 state = "UNREACHABLE"; 4001 break; 4002 default: 4003 state = "UNKNOWN"; 4004 } 4005 4006 switch (np6->ipv6NetToMediaType) { 4007 case 1: 4008 type = "other"; 4009 break; 4010 case 2: 4011 type = "dynamic"; 4012 break; 4013 case 3: 4014 type = "static"; 4015 break; 4016 case 4: 4017 type = "local"; 4018 break; 4019 } 4020 (void) printf("%-5s %-17s %-7s %-12s %-27s\n", 4021 ifindex2str(np6->ipv6NetToMediaIfIndex, ifname), 4022 octetstr(&np6->ipv6NetToMediaPhysAddress, 'h', 4023 xbuf, sizeof (xbuf)), 4024 type, 4025 state, 4026 pr_addr6(&np6->ipv6NetToMediaNetAddress, 4027 abuf, sizeof (abuf))); 4028 } /* 'for' loop 2 ends */ 4029 } /* 'for' loop 1 ends */ 4030 (void) putchar('\n'); 4031 (void) fflush(stdout); 4032 } 4033 4034 /* ------------------------- ire_report (netstat -r) ------------------------ */ 4035 4036 typedef struct sec_attr_list_s { 4037 struct sec_attr_list_s *sal_next; 4038 const mib2_ipAttributeEntry_t *sal_attr; 4039 } sec_attr_list_t; 4040 4041 static boolean_t ire_report_item_v4(const mib2_ipRouteEntry_t *, boolean_t, 4042 const sec_attr_list_t *); 4043 static boolean_t ire_report_item_v6(const mib2_ipv6RouteEntry_t *, boolean_t, 4044 const sec_attr_list_t *); 4045 static const char *pr_secattr(const sec_attr_list_t *); 4046 4047 static void 4048 ire_report(const mib_item_t *item) 4049 { 4050 int jtemp = 0; 4051 boolean_t print_hdr_once_v4 = B_TRUE; 4052 boolean_t print_hdr_once_v6 = B_TRUE; 4053 mib2_ipRouteEntry_t *rp; 4054 mib2_ipv6RouteEntry_t *rp6; 4055 sec_attr_list_t **v4_attrs, **v4a; 4056 sec_attr_list_t **v6_attrs, **v6a; 4057 sec_attr_list_t *all_attrs, *aptr; 4058 const mib_item_t *iptr; 4059 int ipv4_route_count, ipv6_route_count; 4060 int route_attrs_count; 4061 4062 /* 4063 * Preparation pass: the kernel returns separate entries for IP routing 4064 * table entries and security attributes. We loop through the 4065 * attributes first and link them into lists. 4066 */ 4067 ipv4_route_count = ipv6_route_count = route_attrs_count = 0; 4068 for (iptr = item; iptr != NULL; iptr = iptr->next_item) { 4069 if (iptr->group == MIB2_IP6 && iptr->mib_id == MIB2_IP6_ROUTE) 4070 ipv6_route_count += iptr->length / ipv6RouteEntrySize; 4071 if (iptr->group == MIB2_IP && iptr->mib_id == MIB2_IP_ROUTE) 4072 ipv4_route_count += iptr->length / ipRouteEntrySize; 4073 if ((iptr->group == MIB2_IP || iptr->group == MIB2_IP6) && 4074 iptr->mib_id == EXPER_IP_RTATTR) 4075 route_attrs_count += iptr->length / 4076 ipRouteAttributeSize; 4077 } 4078 v4_attrs = v6_attrs = NULL; 4079 all_attrs = NULL; 4080 if (family_selected(AF_INET) && ipv4_route_count > 0) { 4081 v4_attrs = calloc(ipv4_route_count, sizeof (*v4_attrs)); 4082 if (v4_attrs == NULL) { 4083 perror("ire_report calloc v4_attrs failed"); 4084 return; 4085 } 4086 } 4087 if (family_selected(AF_INET6) && ipv6_route_count > 0) { 4088 v6_attrs = calloc(ipv6_route_count, sizeof (*v6_attrs)); 4089 if (v6_attrs == NULL) { 4090 perror("ire_report calloc v6_attrs failed"); 4091 goto ire_report_done; 4092 } 4093 } 4094 if (route_attrs_count > 0) { 4095 all_attrs = malloc(route_attrs_count * sizeof (*all_attrs)); 4096 if (all_attrs == NULL) { 4097 perror("ire_report malloc all_attrs failed"); 4098 goto ire_report_done; 4099 } 4100 } 4101 aptr = all_attrs; 4102 for (iptr = item; iptr != NULL; iptr = iptr->next_item) { 4103 mib2_ipAttributeEntry_t *iae; 4104 sec_attr_list_t **alp; 4105 4106 if (v4_attrs != NULL && iptr->group == MIB2_IP && 4107 iptr->mib_id == EXPER_IP_RTATTR) { 4108 alp = v4_attrs; 4109 } else if (v6_attrs != NULL && iptr->group == MIB2_IP6 && 4110 iptr->mib_id == EXPER_IP_RTATTR) { 4111 alp = v6_attrs; 4112 } else { 4113 continue; 4114 } 4115 for (iae = iptr->valp; 4116 (char *)iae < (char *)iptr->valp + iptr->length; 4117 /* LINTED: (note 1) */ 4118 iae = (mib2_ipAttributeEntry_t *)((char *)iae + 4119 ipRouteAttributeSize)) { 4120 aptr->sal_next = alp[iae->iae_routeidx]; 4121 aptr->sal_attr = iae; 4122 alp[iae->iae_routeidx] = aptr++; 4123 } 4124 } 4125 4126 /* 'for' loop 1: */ 4127 v4a = v4_attrs; 4128 v6a = v6_attrs; 4129 for (; item != NULL; item = item->next_item) { 4130 if (Xflag) { 4131 (void) printf("\n--- Entry %d ---\n", ++jtemp); 4132 (void) printf("Group = %d, mib_id = %d, " 4133 "length = %d, valp = 0x%p\n", 4134 item->group, item->mib_id, 4135 item->length, item->valp); 4136 } 4137 if (!((item->group == MIB2_IP && 4138 item->mib_id == MIB2_IP_ROUTE) || 4139 (item->group == MIB2_IP6 && 4140 item->mib_id == MIB2_IP6_ROUTE))) 4141 continue; /* 'for' loop 1 */ 4142 4143 if (item->group == MIB2_IP && !family_selected(AF_INET)) 4144 continue; /* 'for' loop 1 */ 4145 else if (item->group == MIB2_IP6 && !family_selected(AF_INET6)) 4146 continue; /* 'for' loop 1 */ 4147 4148 if (Xflag) { 4149 if (item->group == MIB2_IP) { 4150 (void) printf("%u records for " 4151 "ipRouteEntryTable:\n", 4152 item->length/sizeof (mib2_ipRouteEntry_t)); 4153 } else { 4154 (void) printf("%u records for " 4155 "ipv6RouteEntryTable:\n", 4156 item->length/ 4157 sizeof (mib2_ipv6RouteEntry_t)); 4158 } 4159 } 4160 4161 if (item->group == MIB2_IP) { 4162 for (rp = (mib2_ipRouteEntry_t *)item->valp; 4163 (char *)rp < (char *)item->valp + item->length; 4164 /* LINTED: (note 1) */ 4165 rp = (mib2_ipRouteEntry_t *)((char *)rp + 4166 ipRouteEntrySize)) { 4167 aptr = v4a == NULL ? NULL : *v4a++; 4168 print_hdr_once_v4 = ire_report_item_v4(rp, 4169 print_hdr_once_v4, aptr); 4170 } 4171 } else { 4172 for (rp6 = (mib2_ipv6RouteEntry_t *)item->valp; 4173 (char *)rp6 < (char *)item->valp + item->length; 4174 /* LINTED: (note 1) */ 4175 rp6 = (mib2_ipv6RouteEntry_t *)((char *)rp6 + 4176 ipv6RouteEntrySize)) { 4177 aptr = v6a == NULL ? NULL : *v6a++; 4178 print_hdr_once_v6 = ire_report_item_v6(rp6, 4179 print_hdr_once_v6, aptr); 4180 } 4181 } 4182 } /* 'for' loop 1 ends */ 4183 (void) fflush(stdout); 4184 ire_report_done: 4185 if (v4_attrs != NULL) 4186 free(v4_attrs); 4187 if (v6_attrs != NULL) 4188 free(v6_attrs); 4189 if (all_attrs != NULL) 4190 free(all_attrs); 4191 } 4192 4193 /* 4194 * Match a user-supplied device name. We do this by string because 4195 * the MIB2 interface gives us interface name strings rather than 4196 * ifIndex numbers. The "none" rule matches only routes with no 4197 * interface. The "any" rule matches routes with any non-blank 4198 * interface. A base name ("hme0") matches all aliases as well 4199 * ("hme0:1"). 4200 */ 4201 static boolean_t 4202 dev_name_match(const DeviceName *devnam, const char *ifname) 4203 { 4204 int iflen; 4205 4206 if (ifname == NULL) 4207 return (devnam->o_length == 0); /* "none" */ 4208 if (*ifname == '\0') 4209 return (devnam->o_length != 0); /* "any" */ 4210 iflen = strlen(ifname); 4211 /* The check for ':' here supports interface aliases. */ 4212 if (iflen > devnam->o_length || 4213 (iflen < devnam->o_length && devnam->o_bytes[iflen] != ':')) 4214 return (B_FALSE); 4215 return (strncmp(ifname, devnam->o_bytes, iflen) == 0); 4216 } 4217 4218 /* 4219 * Match a user-supplied IP address list. The "any" rule matches any 4220 * non-zero address. The "none" rule matches only the zero address. 4221 * IPv6 addresses supplied by the user are ignored. If the user 4222 * supplies a subnet mask, then match routes that are at least that 4223 * specific (use the user's mask). If the user supplies only an 4224 * address, then select any routes that would match (use the route's 4225 * mask). 4226 */ 4227 static boolean_t 4228 v4_addr_match(IpAddress addr, IpAddress mask, const filter_t *fp) 4229 { 4230 char **app; 4231 char *aptr; 4232 in_addr_t faddr, fmask; 4233 4234 if (fp->u.a.f_address == NULL) { 4235 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask)) 4236 return (addr != INADDR_ANY); /* "any" */ 4237 else 4238 return (addr == INADDR_ANY); /* "none" */ 4239 } 4240 if (!IN6_IS_V4MASK(fp->u.a.f_mask)) 4241 return (B_FALSE); 4242 IN6_V4MAPPED_TO_IPADDR(&fp->u.a.f_mask, fmask); 4243 if (fmask != IP_HOST_MASK) { 4244 if (fmask > mask) 4245 return (B_FALSE); 4246 mask = fmask; 4247 } 4248 for (app = fp->u.a.f_address->h_addr_list; (aptr = *app) != NULL; app++) 4249 /* LINTED: (note 1) */ 4250 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) { 4251 /* LINTED: (note 1) */ 4252 IN6_V4MAPPED_TO_IPADDR((in6_addr_t *)aptr, faddr); 4253 if (((faddr ^ addr) & mask) == 0) 4254 return (B_TRUE); 4255 } 4256 return (B_FALSE); 4257 } 4258 4259 /* 4260 * Run through the filter list for an IPv4 MIB2 route entry. If all 4261 * filters of a given type fail to match, then the route is filtered 4262 * out (not displayed). If no filter is given or at least one filter 4263 * of each type matches, then display the route. 4264 */ 4265 static boolean_t 4266 ire_filter_match_v4(const mib2_ipRouteEntry_t *rp, uint_t flag_b) 4267 { 4268 filter_t *fp; 4269 int idx; 4270 4271 /* 'for' loop 1: */ 4272 for (idx = 0; idx < NFILTERKEYS; idx++) 4273 if ((fp = filters[idx]) != NULL) { 4274 /* 'for' loop 2: */ 4275 for (; fp != NULL; fp = fp->f_next) { 4276 switch (idx) { 4277 case FK_AF: 4278 if (fp->u.f_family != AF_INET) 4279 continue; /* 'for' loop 2 */ 4280 break; 4281 case FK_OUTIF: 4282 if (!dev_name_match(&rp->ipRouteIfIndex, 4283 fp->u.f_ifname)) 4284 continue; /* 'for' loop 2 */ 4285 break; 4286 case FK_DST: 4287 if (!v4_addr_match(rp->ipRouteDest, 4288 rp->ipRouteMask, fp)) 4289 continue; /* 'for' loop 2 */ 4290 break; 4291 case FK_FLAGS: 4292 if ((flag_b & fp->u.f.f_flagset) != 4293 fp->u.f.f_flagset || 4294 (flag_b & fp->u.f.f_flagclear)) 4295 continue; /* 'for' loop 2 */ 4296 break; 4297 } 4298 break; 4299 } /* 'for' loop 2 ends */ 4300 if (fp == NULL) 4301 return (B_FALSE); 4302 } 4303 /* 'for' loop 1 ends */ 4304 return (B_TRUE); 4305 } 4306 4307 /* 4308 * Given an IPv4 MIB2 route entry, form the list of flags for the 4309 * route. 4310 */ 4311 static uint_t 4312 form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags) 4313 { 4314 uint_t flag_b; 4315 4316 flag_b = FLF_U; 4317 (void) strcpy(flags, "U"); 4318 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */ 4319 if (rp->ipRouteInfo.re_flags & RTF_INDIRECT) { 4320 (void) strcat(flags, "I"); 4321 flag_b |= FLF_I; 4322 } else if (rp->ipRouteInfo.re_ire_type & IRE_OFFLINK) { 4323 (void) strcat(flags, "G"); 4324 flag_b |= FLF_G; 4325 } 4326 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */ 4327 if (rp->ipRouteInfo.re_ire_type & IRE_IF_CLONE) { 4328 (void) strcat(flags, "C"); 4329 flag_b |= FLF_C; 4330 } else if (rp->ipRouteMask == IP_HOST_MASK) { 4331 (void) strcat(flags, "H"); 4332 flag_b |= FLF_H; 4333 } 4334 if (rp->ipRouteInfo.re_flags & RTF_DYNAMIC) { 4335 (void) strcat(flags, "D"); 4336 flag_b |= FLF_D; 4337 } 4338 if (rp->ipRouteInfo.re_ire_type == IRE_BROADCAST) { /* Broadcast */ 4339 (void) strcat(flags, "b"); 4340 flag_b |= FLF_b; 4341 } 4342 if (rp->ipRouteInfo.re_ire_type == IRE_LOCAL) { /* Local */ 4343 (void) strcat(flags, "L"); 4344 flag_b |= FLF_L; 4345 } 4346 if (rp->ipRouteInfo.re_flags & RTF_MULTIRT) { 4347 (void) strcat(flags, "M"); /* Multiroute */ 4348 flag_b |= FLF_M; 4349 } 4350 if (rp->ipRouteInfo.re_flags & RTF_SETSRC) { 4351 (void) strcat(flags, "S"); /* Setsrc */ 4352 flag_b |= FLF_S; 4353 } 4354 if (rp->ipRouteInfo.re_flags & RTF_REJECT) { 4355 (void) strcat(flags, "R"); 4356 flag_b |= FLF_R; 4357 } 4358 if (rp->ipRouteInfo.re_flags & RTF_BLACKHOLE) { 4359 (void) strcat(flags, "B"); 4360 flag_b |= FLF_B; 4361 } 4362 if (rp->ipRouteInfo.re_flags & RTF_ZONE) { 4363 (void) strcat(flags, "Z"); 4364 flag_b |= FLF_Z; 4365 } 4366 return (flag_b); 4367 } 4368 4369 static const char ire_hdr_v4[] = 4370 "\n%s Table: IPv4\n"; 4371 static const char ire_hdr_v4_compat[] = 4372 "\n%s Table:\n"; 4373 static const char ire_hdr_v4_verbose[] = 4374 " Destination Mask Gateway Device " 4375 " MTU Ref Flg Out In/Fwd %s\n" 4376 "-------------------- --------------- -------------------- ------ " 4377 "----- --- --- ----- ------ %s\n"; 4378 4379 static const char ire_hdr_v4_normal[] = 4380 " Destination Gateway Flags Ref Use Interface" 4381 " %s\n-------------------- -------------------- ----- ----- ---------- " 4382 "--------- %s\n"; 4383 4384 static boolean_t 4385 ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first, 4386 const sec_attr_list_t *attrs) 4387 { 4388 char dstbuf[MAXHOSTNAMELEN + 1]; 4389 char maskbuf[MAXHOSTNAMELEN + 1]; 4390 char gwbuf[MAXHOSTNAMELEN + 1]; 4391 char ifname[LIFNAMSIZ + 1]; 4392 char flags[10]; /* RTF_ flags */ 4393 uint_t flag_b; 4394 4395 if (!(Aflag || (rp->ipRouteInfo.re_ire_type != IRE_IF_CLONE && 4396 rp->ipRouteInfo.re_ire_type != IRE_BROADCAST && 4397 rp->ipRouteInfo.re_ire_type != IRE_MULTICAST && 4398 rp->ipRouteInfo.re_ire_type != IRE_NOROUTE && 4399 rp->ipRouteInfo.re_ire_type != IRE_LOCAL))) { 4400 return (first); 4401 } 4402 4403 flag_b = form_v4_route_flags(rp, flags); 4404 4405 if (!ire_filter_match_v4(rp, flag_b)) 4406 return (first); 4407 4408 if (first) { 4409 (void) printf(v4compat ? ire_hdr_v4_compat : ire_hdr_v4, 4410 Vflag ? "IRE" : "Routing"); 4411 (void) printf(Vflag ? ire_hdr_v4_verbose : ire_hdr_v4_normal, 4412 RSECflag ? " Gateway security attributes " : "", 4413 RSECflag ? "-------------------------------" : ""); 4414 first = B_FALSE; 4415 } 4416 4417 if (flag_b & FLF_H) { 4418 (void) pr_addr(rp->ipRouteDest, dstbuf, sizeof (dstbuf)); 4419 } else { 4420 (void) pr_net(rp->ipRouteDest, rp->ipRouteMask, 4421 dstbuf, sizeof (dstbuf)); 4422 } 4423 if (Vflag) { 4424 (void) printf("%-20s %-15s %-20s %-6s %5u %3u " 4425 "%-4s%6u %6u %s\n", 4426 dstbuf, 4427 pr_mask(rp->ipRouteMask, maskbuf, sizeof (maskbuf)), 4428 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)), 4429 octetstr(&rp->ipRouteIfIndex, 'a', ifname, sizeof (ifname)), 4430 rp->ipRouteInfo.re_max_frag, 4431 rp->ipRouteInfo.re_ref, 4432 flags, 4433 rp->ipRouteInfo.re_obpkt, 4434 rp->ipRouteInfo.re_ibpkt, 4435 pr_secattr(attrs)); 4436 } else { 4437 (void) printf("%-20s %-20s %-5s %4u %10u %-9s %s\n", 4438 dstbuf, 4439 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)), 4440 flags, 4441 rp->ipRouteInfo.re_ref, 4442 rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt, 4443 octetstr(&rp->ipRouteIfIndex, 'a', 4444 ifname, sizeof (ifname)), 4445 pr_secattr(attrs)); 4446 } 4447 return (first); 4448 } 4449 4450 /* 4451 * Match a user-supplied IP address list against an IPv6 route entry. 4452 * If the user specified "any," then any non-zero address matches. If 4453 * the user specified "none," then only the zero address matches. If 4454 * the user specified a subnet mask length, then use that in matching 4455 * routes (select routes that are at least as specific). If the user 4456 * specified only an address, then use the route's mask (select routes 4457 * that would match that address). IPv4 addresses are ignored. 4458 */ 4459 static boolean_t 4460 v6_addr_match(const Ip6Address *addr, int masklen, const filter_t *fp) 4461 { 4462 const uint8_t *ucp; 4463 int fmasklen; 4464 int i; 4465 char **app; 4466 const uint8_t *aptr; 4467 4468 if (fp->u.a.f_address == NULL) { 4469 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask)) /* any */ 4470 return (!IN6_IS_ADDR_UNSPECIFIED(addr)); 4471 return (IN6_IS_ADDR_UNSPECIFIED(addr)); /* "none" */ 4472 } 4473 fmasklen = 0; 4474 /* 'for' loop 1a: */ 4475 for (ucp = fp->u.a.f_mask.s6_addr; 4476 ucp < fp->u.a.f_mask.s6_addr + sizeof (fp->u.a.f_mask.s6_addr); 4477 ucp++) { 4478 if (*ucp != 0xff) { 4479 if (*ucp != 0) 4480 fmasklen += 9 - ffs(*ucp); 4481 break; /* 'for' loop 1a */ 4482 } 4483 fmasklen += 8; 4484 } /* 'for' loop 1a ends */ 4485 if (fmasklen != IPV6_ABITS) { 4486 if (fmasklen > masklen) 4487 return (B_FALSE); 4488 masklen = fmasklen; 4489 } 4490 /* 'for' loop 1b: */ 4491 for (app = fp->u.a.f_address->h_addr_list; 4492 (aptr = (uint8_t *)*app) != NULL; app++) { 4493 /* LINTED: (note 1) */ 4494 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) 4495 continue; /* 'for' loop 1b */ 4496 ucp = addr->s6_addr; 4497 for (i = masklen; i >= 8; i -= 8) 4498 if (*ucp++ != *aptr++) 4499 break; /* 'for' loop 1b */ 4500 if (i == 0 || 4501 (i < 8 && ((*ucp ^ *aptr) & ~(0xff >> i)) == 0)) 4502 return (B_TRUE); 4503 } /* 'for' loop 1b ends */ 4504 return (B_FALSE); 4505 } 4506 4507 /* 4508 * Run through the filter list for an IPv6 MIB2 IRE. For a given 4509 * type, if there's at least one filter and all filters of that type 4510 * fail to match, then the route doesn't match and isn't displayed. 4511 * If at least one matches, or none are specified, for each of the 4512 * types, then the route is selected and displayed. 4513 */ 4514 static boolean_t 4515 ire_filter_match_v6(const mib2_ipv6RouteEntry_t *rp6, uint_t flag_b) 4516 { 4517 filter_t *fp; 4518 int idx; 4519 4520 /* 'for' loop 1: */ 4521 for (idx = 0; idx < NFILTERKEYS; idx++) 4522 if ((fp = filters[idx]) != NULL) { 4523 /* 'for' loop 2: */ 4524 for (; fp != NULL; fp = fp->f_next) { 4525 switch (idx) { 4526 case FK_AF: 4527 if (fp->u.f_family != AF_INET6) 4528 /* 'for' loop 2 */ 4529 continue; 4530 break; 4531 case FK_OUTIF: 4532 if (!dev_name_match(&rp6-> 4533 ipv6RouteIfIndex, fp->u.f_ifname)) 4534 /* 'for' loop 2 */ 4535 continue; 4536 break; 4537 case FK_DST: 4538 if (!v6_addr_match(&rp6->ipv6RouteDest, 4539 rp6->ipv6RoutePfxLength, fp)) 4540 /* 'for' loop 2 */ 4541 continue; 4542 break; 4543 case FK_FLAGS: 4544 if ((flag_b & fp->u.f.f_flagset) != 4545 fp->u.f.f_flagset || 4546 (flag_b & fp->u.f.f_flagclear)) 4547 /* 'for' loop 2 */ 4548 continue; 4549 break; 4550 } 4551 break; 4552 } /* 'for' loop 2 ends */ 4553 if (fp == NULL) 4554 return (B_FALSE); 4555 } 4556 /* 'for' loop 1 ends */ 4557 return (B_TRUE); 4558 } 4559 4560 /* 4561 * Given an IPv6 MIB2 route entry, form the list of flags for the 4562 * route. 4563 */ 4564 static uint_t 4565 form_v6_route_flags(const mib2_ipv6RouteEntry_t *rp6, char *flags) 4566 { 4567 uint_t flag_b; 4568 4569 flag_b = FLF_U; 4570 (void) strcpy(flags, "U"); 4571 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */ 4572 if (rp6->ipv6RouteInfo.re_flags & RTF_INDIRECT) { 4573 (void) strcat(flags, "I"); 4574 flag_b |= FLF_I; 4575 } else if (rp6->ipv6RouteInfo.re_ire_type & IRE_OFFLINK) { 4576 (void) strcat(flags, "G"); 4577 flag_b |= FLF_G; 4578 } 4579 4580 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */ 4581 if (rp6->ipv6RouteInfo.re_ire_type & IRE_IF_CLONE) { 4582 (void) strcat(flags, "C"); 4583 flag_b |= FLF_C; 4584 } else if (rp6->ipv6RoutePfxLength == IPV6_ABITS) { 4585 (void) strcat(flags, "H"); 4586 flag_b |= FLF_H; 4587 } 4588 4589 if (rp6->ipv6RouteInfo.re_flags & RTF_DYNAMIC) { 4590 (void) strcat(flags, "D"); 4591 flag_b |= FLF_D; 4592 } 4593 if (rp6->ipv6RouteInfo.re_ire_type == IRE_LOCAL) { /* Local */ 4594 (void) strcat(flags, "L"); 4595 flag_b |= FLF_L; 4596 } 4597 if (rp6->ipv6RouteInfo.re_flags & RTF_MULTIRT) { 4598 (void) strcat(flags, "M"); /* Multiroute */ 4599 flag_b |= FLF_M; 4600 } 4601 if (rp6->ipv6RouteInfo.re_flags & RTF_SETSRC) { 4602 (void) strcat(flags, "S"); /* Setsrc */ 4603 flag_b |= FLF_S; 4604 } 4605 if (rp6->ipv6RouteInfo.re_flags & RTF_REJECT) { 4606 (void) strcat(flags, "R"); 4607 flag_b |= FLF_R; 4608 } 4609 if (rp6->ipv6RouteInfo.re_flags & RTF_BLACKHOLE) { 4610 (void) strcat(flags, "B"); 4611 flag_b |= FLF_B; 4612 } 4613 if (rp6->ipv6RouteInfo.re_flags & RTF_ZONE) { 4614 (void) strcat(flags, "Z"); 4615 flag_b |= FLF_Z; 4616 } 4617 return (flag_b); 4618 } 4619 4620 static const char ire_hdr_v6[] = 4621 "\n%s Table: IPv6\n"; 4622 static const char ire_hdr_v6_verbose[] = 4623 " Destination/Mask Gateway If MTU " 4624 "Ref Flags Out In/Fwd %s\n" 4625 "--------------------------- --------------------------- ----- ----- " 4626 "--- ----- ------ ------ %s\n"; 4627 static const char ire_hdr_v6_normal[] = 4628 " Destination/Mask Gateway Flags Ref Use " 4629 " If %s\n" 4630 "--------------------------- --------------------------- ----- --- ------- " 4631 "----- %s\n"; 4632 4633 static boolean_t 4634 ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first, 4635 const sec_attr_list_t *attrs) 4636 { 4637 char dstbuf[MAXHOSTNAMELEN + 1]; 4638 char gwbuf[MAXHOSTNAMELEN + 1]; 4639 char ifname[LIFNAMSIZ + 1]; 4640 char flags[10]; /* RTF_ flags */ 4641 uint_t flag_b; 4642 4643 if (!(Aflag || (rp6->ipv6RouteInfo.re_ire_type != IRE_IF_CLONE && 4644 rp6->ipv6RouteInfo.re_ire_type != IRE_MULTICAST && 4645 rp6->ipv6RouteInfo.re_ire_type != IRE_NOROUTE && 4646 rp6->ipv6RouteInfo.re_ire_type != IRE_LOCAL))) { 4647 return (first); 4648 } 4649 4650 flag_b = form_v6_route_flags(rp6, flags); 4651 4652 if (!ire_filter_match_v6(rp6, flag_b)) 4653 return (first); 4654 4655 if (first) { 4656 (void) printf(ire_hdr_v6, Vflag ? "IRE" : "Routing"); 4657 (void) printf(Vflag ? ire_hdr_v6_verbose : ire_hdr_v6_normal, 4658 RSECflag ? " Gateway security attributes " : "", 4659 RSECflag ? "-------------------------------" : ""); 4660 first = B_FALSE; 4661 } 4662 4663 if (Vflag) { 4664 (void) printf("%-27s %-27s %-5s %5u %3u " 4665 "%-5s %6u %6u %s\n", 4666 pr_prefix6(&rp6->ipv6RouteDest, 4667 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)), 4668 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ? 4669 " --" : 4670 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)), 4671 octetstr(&rp6->ipv6RouteIfIndex, 'a', 4672 ifname, sizeof (ifname)), 4673 rp6->ipv6RouteInfo.re_max_frag, 4674 rp6->ipv6RouteInfo.re_ref, 4675 flags, 4676 rp6->ipv6RouteInfo.re_obpkt, 4677 rp6->ipv6RouteInfo.re_ibpkt, 4678 pr_secattr(attrs)); 4679 } else { 4680 (void) printf("%-27s %-27s %-5s %3u %7u %-5s %s\n", 4681 pr_prefix6(&rp6->ipv6RouteDest, 4682 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)), 4683 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ? 4684 " --" : 4685 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)), 4686 flags, 4687 rp6->ipv6RouteInfo.re_ref, 4688 rp6->ipv6RouteInfo.re_obpkt + rp6->ipv6RouteInfo.re_ibpkt, 4689 octetstr(&rp6->ipv6RouteIfIndex, 'a', 4690 ifname, sizeof (ifname)), 4691 pr_secattr(attrs)); 4692 } 4693 return (first); 4694 } 4695 4696 /* 4697 * Common attribute-gathering routine for all transports. 4698 */ 4699 static mib2_transportMLPEntry_t ** 4700 gather_attrs(const mib_item_t *item, int group, int mib_id, int esize) 4701 { 4702 int transport_count = 0; 4703 const mib_item_t *iptr; 4704 mib2_transportMLPEntry_t **attrs, *tme; 4705 4706 for (iptr = item; iptr != NULL; iptr = iptr->next_item) { 4707 if (iptr->group == group && iptr->mib_id == mib_id) 4708 transport_count += iptr->length / esize; 4709 } 4710 if (transport_count <= 0) 4711 return (NULL); 4712 attrs = calloc(transport_count, sizeof (*attrs)); 4713 if (attrs == NULL) { 4714 perror("gather_attrs calloc failed"); 4715 return (NULL); 4716 } 4717 for (iptr = item; iptr != NULL; iptr = iptr->next_item) { 4718 if (iptr->group == group && iptr->mib_id == EXPER_XPORT_MLP) { 4719 for (tme = iptr->valp; 4720 (char *)tme < (char *)iptr->valp + iptr->length; 4721 /* LINTED: (note 1) */ 4722 tme = (mib2_transportMLPEntry_t *)((char *)tme + 4723 transportMLPSize)) { 4724 attrs[tme->tme_connidx] = tme; 4725 } 4726 } 4727 } 4728 return (attrs); 4729 } 4730 4731 static void 4732 print_transport_label(const mib2_transportMLPEntry_t *attr) 4733 { 4734 if (!RSECflag || attr == NULL || 4735 !(attr->tme_flags & MIB2_TMEF_IS_LABELED)) 4736 return; 4737 4738 if (bisinvalid(&attr->tme_label)) { 4739 (void) printf(" INVALID\n"); 4740 } else if (!blequal(&attr->tme_label, zone_security_label)) { 4741 char *sl_str; 4742 4743 sl_str = sl_to_str(&attr->tme_label); 4744 (void) printf(" %s\n", sl_str); 4745 free(sl_str); 4746 } 4747 } 4748 4749 /* ------------------------------ TCP_REPORT------------------------------- */ 4750 4751 static const char tcp_hdr_v4[] = 4752 "\nTCP: IPv4\n"; 4753 static const char tcp_hdr_v4_compat[] = 4754 "\nTCP\n"; 4755 static const char tcp_hdr_v4_verbose[] = 4756 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack " 4757 " Rto Mss State\n" 4758 "-------------------- ----- -------- -------- ----- -------- -------- " 4759 "----- ----- -----------\n"; 4760 static const char tcp_hdr_v4_normal[] = 4761 " Local Address Remote Address Swind Send-Q Rwind Recv-Q " 4762 " State\n" 4763 "-------------------- -------------------- ----- ------ ----- ------ " 4764 "-----------\n"; 4765 static const char tcp_hdr_v4_pid[] = 4766 " Local Address Remote Address User Pid Command Swind" 4767 " Send-Q Rwind Recv-Q State\n" 4768 "-------------------- -------------------- -------- ------ ------------- ------" 4769 "- ------ ------- ------ -----------\n"; 4770 static const char tcp_hdr_v4_pid_verbose[] = 4771 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack Rto " 4772 " Mss State User Pid Command\n" 4773 "-------------------- ------- -------- -------- ------- -------- -------- -----" 4774 " ----- ----------- -------- ------ --------------\n"; 4775 4776 static const char tcp_hdr_v6[] = 4777 "\nTCP: IPv6\n"; 4778 static const char tcp_hdr_v6_verbose[] = 4779 "Local/Remote Address Swind Snext Suna Rwind Rnext " 4780 " Rack Rto Mss State If\n" 4781 "--------------------------------- ----- -------- -------- ----- -------- " 4782 "-------- ----- ----- ----------- -----\n"; 4783 static const char tcp_hdr_v6_normal[] = 4784 " Local Address Remote Address " 4785 "Swind Send-Q Rwind Recv-Q State If\n" 4786 "--------------------------------- --------------------------------- " 4787 "----- ------ ----- ------ ----------- -----\n"; 4788 static const char tcp_hdr_v6_pid[] = 4789 " Local Address Remote Address User" 4790 " Pid Command Swind Send-Q Rwind Recv-Q State If\n" 4791 "--------------------------------- --------------------------------- --------" 4792 " ------ -------------- ------- ------ ------- ------ ----------- -----\n"; 4793 static const char tcp_hdr_v6_pid_verbose[] = 4794 "Local/Remote Address Swind Snext Suna Rwind Rnext" 4795 " Rack Rto Mss State If User Pid Command\n" 4796 "--------------------------------- ------- -------- -------- ------- --------" 4797 " -------- ----- ----- ----------- ----- -------- ------ --------------\n"; 4798 4799 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *, 4800 conn_pid_info_t *, boolean_t first, 4801 const mib2_transportMLPEntry_t *); 4802 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *, 4803 conn_pid_info_t *, boolean_t first, 4804 const mib2_transportMLPEntry_t *); 4805 4806 4807 static void 4808 tcp_report(const mib_item_t *item) 4809 { 4810 int jtemp = 0; 4811 boolean_t print_hdr_once_v4 = B_TRUE; 4812 boolean_t print_hdr_once_v6 = B_TRUE; 4813 mib2_tcpConnEntry_t *tp; 4814 mib2_tcp6ConnEntry_t *tp6; 4815 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs; 4816 mib2_transportMLPEntry_t **v4a, **v6a; 4817 mib2_transportMLPEntry_t *aptr; 4818 conn_pid_info_t *cpi; 4819 4820 if (!protocol_selected(IPPROTO_TCP)) 4821 return; 4822 4823 /* 4824 * Preparation pass: the kernel returns separate entries for TCP 4825 * connection table entries and Multilevel Port attributes. We loop 4826 * through the attributes first and set up an array for each address 4827 * family. 4828 */ 4829 v4_attrs = family_selected(AF_INET) && RSECflag ? 4830 gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) : 4831 NULL; 4832 v6_attrs = family_selected(AF_INET6) && RSECflag ? 4833 gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) : 4834 NULL; 4835 4836 /* 'for' loop 1: */ 4837 v4a = v4_attrs; 4838 v6a = v6_attrs; 4839 for (; item != NULL; item = item->next_item) { 4840 if (Xflag) { 4841 (void) printf("\n--- Entry %d ---\n", ++jtemp); 4842 (void) printf("Group = %d, mib_id = %d, " 4843 "length = %d, valp = 0x%p\n", 4844 item->group, item->mib_id, 4845 item->length, item->valp); 4846 } 4847 4848 if (!((item->group == MIB2_TCP && 4849 item->mib_id == MIB2_TCP_CONN) || 4850 (item->group == MIB2_TCP6 && 4851 item->mib_id == MIB2_TCP6_CONN) || 4852 (item->group == MIB2_TCP && 4853 item->mib_id == EXPER_XPORT_PROC_INFO) || 4854 (item->group == MIB2_TCP6 && 4855 item->mib_id == EXPER_XPORT_PROC_INFO))) 4856 continue; /* 'for' loop 1 */ 4857 4858 if (item->group == MIB2_TCP && !family_selected(AF_INET)) 4859 continue; /* 'for' loop 1 */ 4860 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6)) 4861 continue; /* 'for' loop 1 */ 4862 4863 if ((!Uflag) && item->group == MIB2_TCP && 4864 item->mib_id == MIB2_TCP_CONN) { 4865 for (tp = (mib2_tcpConnEntry_t *)item->valp; 4866 (char *)tp < (char *)item->valp + item->length; 4867 /* LINTED: (note 1) */ 4868 tp = (mib2_tcpConnEntry_t *)((char *)tp + 4869 tcpConnEntrySize)) { 4870 aptr = v4a == NULL ? NULL : *v4a++; 4871 print_hdr_once_v4 = tcp_report_item_v4(tp, 4872 NULL, print_hdr_once_v4, aptr); 4873 } 4874 } else if ((!Uflag) && item->group == MIB2_TCP6 && 4875 item->mib_id == MIB2_TCP6_CONN) { 4876 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp; 4877 (char *)tp6 < (char *)item->valp + item->length; 4878 /* LINTED: (note 1) */ 4879 tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 + 4880 tcp6ConnEntrySize)) { 4881 aptr = v6a == NULL ? NULL : *v6a++; 4882 print_hdr_once_v6 = tcp_report_item_v6(tp6, 4883 NULL, print_hdr_once_v6, aptr); 4884 } 4885 } else if ((Uflag) && item->group == MIB2_TCP && 4886 item->mib_id == EXPER_XPORT_PROC_INFO) { 4887 for (tp = (mib2_tcpConnEntry_t *)item->valp; 4888 (char *)tp < (char *)item->valp + item->length; 4889 /* LINTED: (note 1) */ 4890 tp = (mib2_tcpConnEntry_t *)((char *)cpi + 4891 cpi->cpi_tot_size)) { 4892 aptr = v4a == NULL ? NULL : *v4a++; 4893 /* LINTED: (note 1) */ 4894 cpi = (conn_pid_info_t *)((char *)tp + 4895 tcpConnEntrySize); 4896 print_hdr_once_v4 = tcp_report_item_v4(tp, 4897 cpi, print_hdr_once_v4, aptr); 4898 } 4899 } else if ((Uflag) && item->group == MIB2_TCP6 && 4900 item->mib_id == EXPER_XPORT_PROC_INFO) { 4901 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp; 4902 (char *)tp6 < (char *)item->valp + item->length; 4903 /* LINTED: (note 1) */ 4904 tp6 = (mib2_tcp6ConnEntry_t *)((char *)cpi + 4905 cpi->cpi_tot_size)) { 4906 aptr = v6a == NULL ? NULL : *v6a++; 4907 /* LINTED: (note 1) */ 4908 cpi = (conn_pid_info_t *)((char *)tp6 + 4909 tcp6ConnEntrySize); 4910 print_hdr_once_v6 = tcp_report_item_v6(tp6, 4911 cpi, print_hdr_once_v6, aptr); 4912 } 4913 } 4914 4915 } /* 'for' loop 1 ends */ 4916 (void) fflush(stdout); 4917 4918 if (v4_attrs != NULL) 4919 free(v4_attrs); 4920 if (v6_attrs != NULL) 4921 free(v6_attrs); 4922 } 4923 4924 static boolean_t 4925 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, conn_pid_info_t *cpi, 4926 boolean_t first, const mib2_transportMLPEntry_t *attr) 4927 { 4928 /* 4929 * lname and fname below are for the hostname as well as the portname 4930 * There is no limit on portname length so we assume MAXHOSTNAMELEN 4931 * as the limit 4932 */ 4933 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 4934 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 4935 4936 4937 if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED)) 4938 return (first); /* Nothing to print */ 4939 4940 if (first) { 4941 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4); 4942 if (Uflag) 4943 (void) printf(Vflag ? tcp_hdr_v4_pid_verbose : 4944 tcp_hdr_v4_pid); 4945 else 4946 (void) printf(Vflag ? tcp_hdr_v4_verbose : 4947 tcp_hdr_v4_normal); 4948 } 4949 4950 if ((!Uflag) && Vflag) { 4951 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x " 4952 "%5u %5u %s\n", 4953 pr_ap(tp->tcpConnLocalAddress, 4954 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), 4955 pr_ap(tp->tcpConnRemAddress, 4956 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), 4957 tp->tcpConnEntryInfo.ce_swnd, 4958 tp->tcpConnEntryInfo.ce_snxt, 4959 tp->tcpConnEntryInfo.ce_suna, 4960 tp->tcpConnEntryInfo.ce_rwnd, 4961 tp->tcpConnEntryInfo.ce_rnxt, 4962 tp->tcpConnEntryInfo.ce_rack, 4963 tp->tcpConnEntryInfo.ce_rto, 4964 tp->tcpConnEntryInfo.ce_mss, 4965 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); 4966 } else if ((!Uflag) && (!Vflag)) { 4967 int sq = (int)tp->tcpConnEntryInfo.ce_snxt - 4968 (int)tp->tcpConnEntryInfo.ce_suna - 1; 4969 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt - 4970 (int)tp->tcpConnEntryInfo.ce_rack; 4971 4972 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n", 4973 pr_ap(tp->tcpConnLocalAddress, 4974 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), 4975 pr_ap(tp->tcpConnRemAddress, 4976 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), 4977 tp->tcpConnEntryInfo.ce_swnd, 4978 (sq >= 0) ? sq : 0, 4979 tp->tcpConnEntryInfo.ce_rwnd, 4980 (rq >= 0) ? rq : 0, 4981 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); 4982 } else if (Uflag && Vflag) { 4983 int i = 0; 4984 pid_t *pids = cpi->cpi_pids; 4985 proc_info_t *pinfo; 4986 do { 4987 pinfo = get_proc_info(*pids); 4988 (void) printf("%-20s\n%-20s %7u %08x %08x %7u %08x " 4989 "%08x %5u %5u %-11s %-8.8s %6u %s\n", 4990 pr_ap(tp->tcpConnLocalAddress, 4991 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), 4992 pr_ap(tp->tcpConnRemAddress, 4993 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), 4994 tp->tcpConnEntryInfo.ce_swnd, 4995 tp->tcpConnEntryInfo.ce_snxt, 4996 tp->tcpConnEntryInfo.ce_suna, 4997 tp->tcpConnEntryInfo.ce_rwnd, 4998 tp->tcpConnEntryInfo.ce_rnxt, 4999 tp->tcpConnEntryInfo.ce_rack, 5000 tp->tcpConnEntryInfo.ce_rto, 5001 tp->tcpConnEntryInfo.ce_mss, 5002 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr), 5003 pinfo->pr_user, (int)*pids, pinfo->pr_psargs); 5004 i++; pids++; 5005 } while (i < cpi->cpi_pids_cnt); 5006 } else if (Uflag && (!Vflag)) { 5007 int sq = (int)tp->tcpConnEntryInfo.ce_snxt - 5008 (int)tp->tcpConnEntryInfo.ce_suna - 1; 5009 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt - 5010 (int)tp->tcpConnEntryInfo.ce_rack; 5011 int i = 0; 5012 pid_t *pids = cpi->cpi_pids; 5013 proc_info_t *pinfo; 5014 do { 5015 pinfo = get_proc_info(*pids); 5016 (void) printf("%-20s %-20s %-8.8s %6u %-13.13s %7u " 5017 "%6d %7u %6d %s\n", 5018 pr_ap(tp->tcpConnLocalAddress, 5019 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)), 5020 pr_ap(tp->tcpConnRemAddress, 5021 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)), 5022 pinfo->pr_user, (int)*pids, pinfo->pr_fname, 5023 tp->tcpConnEntryInfo.ce_swnd, 5024 (sq >= 0) ? sq : 0, 5025 tp->tcpConnEntryInfo.ce_rwnd, 5026 (rq >= 0) ? rq : 0, 5027 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr)); 5028 i++; pids++; 5029 } while (i < cpi->cpi_pids_cnt); 5030 } 5031 5032 print_transport_label(attr); 5033 5034 return (B_FALSE); 5035 } 5036 5037 static boolean_t 5038 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, conn_pid_info_t *cpi, 5039 boolean_t first, const mib2_transportMLPEntry_t *attr) 5040 { 5041 /* 5042 * lname and fname below are for the hostname as well as the portname 5043 * There is no limit on portname length so we assume MAXHOSTNAMELEN 5044 * as the limit 5045 */ 5046 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5047 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5048 char ifname[LIFNAMSIZ + 1]; 5049 char *ifnamep; 5050 5051 if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED)) 5052 return (first); /* Nothing to print */ 5053 5054 if (first) { 5055 (void) printf(tcp_hdr_v6); 5056 if (Uflag) 5057 (void) printf(Vflag ? tcp_hdr_v6_pid_verbose : 5058 tcp_hdr_v6_pid); 5059 else 5060 (void) printf(Vflag ? tcp_hdr_v6_verbose : 5061 tcp_hdr_v6_normal); 5062 } 5063 5064 ifnamep = (tp6->tcp6ConnIfIndex != 0) ? 5065 if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL; 5066 if (ifnamep == NULL) 5067 ifnamep = ""; 5068 5069 if ((!Uflag) && Vflag) { 5070 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x " 5071 "%5u %5u %-11s %s\n", 5072 pr_ap6(&tp6->tcp6ConnLocalAddress, 5073 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)), 5074 pr_ap6(&tp6->tcp6ConnRemAddress, 5075 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)), 5076 tp6->tcp6ConnEntryInfo.ce_swnd, 5077 tp6->tcp6ConnEntryInfo.ce_snxt, 5078 tp6->tcp6ConnEntryInfo.ce_suna, 5079 tp6->tcp6ConnEntryInfo.ce_rwnd, 5080 tp6->tcp6ConnEntryInfo.ce_rnxt, 5081 tp6->tcp6ConnEntryInfo.ce_rack, 5082 tp6->tcp6ConnEntryInfo.ce_rto, 5083 tp6->tcp6ConnEntryInfo.ce_mss, 5084 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), 5085 ifnamep); 5086 } else if ((!Uflag) && (!Vflag)) { 5087 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt - 5088 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1; 5089 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt - 5090 (int)tp6->tcp6ConnEntryInfo.ce_rack; 5091 5092 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n", 5093 pr_ap6(&tp6->tcp6ConnLocalAddress, 5094 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)), 5095 pr_ap6(&tp6->tcp6ConnRemAddress, 5096 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)), 5097 tp6->tcp6ConnEntryInfo.ce_swnd, 5098 (sq >= 0) ? sq : 0, 5099 tp6->tcp6ConnEntryInfo.ce_rwnd, 5100 (rq >= 0) ? rq : 0, 5101 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), 5102 ifnamep); 5103 } else if (Uflag && Vflag) { 5104 int i = 0; 5105 pid_t *pids = cpi->cpi_pids; 5106 proc_info_t *pinfo; 5107 do { 5108 pinfo = get_proc_info(*pids); 5109 (void) printf("%-33s\n%-33s %7u %08x %08x %7u %08x " 5110 "%08x %5u %5u %-11s %-5.5s %-8.8s %6u %s\n", 5111 pr_ap6(&tp6->tcp6ConnLocalAddress, 5112 tp6->tcp6ConnLocalPort, "tcp", lname, 5113 sizeof (lname)), 5114 pr_ap6(&tp6->tcp6ConnRemAddress, 5115 tp6->tcp6ConnRemPort, "tcp", fname, 5116 sizeof (fname)), 5117 tp6->tcp6ConnEntryInfo.ce_swnd, 5118 tp6->tcp6ConnEntryInfo.ce_snxt, 5119 tp6->tcp6ConnEntryInfo.ce_suna, 5120 tp6->tcp6ConnEntryInfo.ce_rwnd, 5121 tp6->tcp6ConnEntryInfo.ce_rnxt, 5122 tp6->tcp6ConnEntryInfo.ce_rack, 5123 tp6->tcp6ConnEntryInfo.ce_rto, 5124 tp6->tcp6ConnEntryInfo.ce_mss, 5125 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), 5126 ifnamep, pinfo->pr_user, (int)*pids, 5127 pinfo->pr_psargs); 5128 i++; pids++; 5129 } while (i < cpi->cpi_pids_cnt); 5130 } else if (Uflag && (!Vflag)) { 5131 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt - 5132 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1; 5133 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt - 5134 (int)tp6->tcp6ConnEntryInfo.ce_rack; 5135 int i = 0; 5136 pid_t *pids = cpi->cpi_pids; 5137 proc_info_t *pinfo; 5138 do { 5139 pinfo = get_proc_info(*pids); 5140 (void) printf("%-33s %-33s %-8.8s %6u %-14.14s %7d " 5141 "%6u %7d %6d %-11s %s\n", 5142 pr_ap6(&tp6->tcp6ConnLocalAddress, 5143 tp6->tcp6ConnLocalPort, "tcp", lname, 5144 sizeof (lname)), 5145 pr_ap6(&tp6->tcp6ConnRemAddress, 5146 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)), 5147 pinfo->pr_user, (int)*pids, pinfo->pr_fname, 5148 tp6->tcp6ConnEntryInfo.ce_swnd, 5149 (sq >= 0) ? sq : 0, 5150 tp6->tcp6ConnEntryInfo.ce_rwnd, 5151 (rq >= 0) ? rq : 0, 5152 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr), 5153 ifnamep); 5154 i++; pids++; 5155 } while (i < cpi->cpi_pids_cnt); 5156 } 5157 5158 print_transport_label(attr); 5159 5160 return (B_FALSE); 5161 } 5162 5163 /* ------------------------------- UDP_REPORT------------------------------- */ 5164 5165 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude, 5166 conn_pid_info_t *cpi, boolean_t first, 5167 const mib2_transportMLPEntry_t *attr); 5168 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6, 5169 conn_pid_info_t *cpi, boolean_t first, 5170 const mib2_transportMLPEntry_t *attr); 5171 5172 static const char udp_hdr_v4[] = 5173 " Local Address Remote Address State\n" 5174 "-------------------- -------------------- ----------\n"; 5175 static const char udp_hdr_v4_pid[] = 5176 " Local Address Remote Address User Pid " 5177 " Command State\n" 5178 "-------------------- -------------------- -------- ------ " 5179 "-------------- ----------\n"; 5180 static const char udp_hdr_v4_pid_verbose[] = 5181 " Local Address Remote Address User Pid State " 5182 " Command\n" 5183 "-------------------- -------------------- -------- ------ ---------- " 5184 "----------------\n"; 5185 5186 static const char udp_hdr_v6[] = 5187 " Local Address Remote Address " 5188 " State If\n" 5189 "--------------------------------- --------------------------------- " 5190 "---------- -----\n"; 5191 static const char udp_hdr_v6_pid[] = 5192 " Local Address Remote Address " 5193 " User Pid Command State If\n" 5194 "--------------------------------- --------------------------------- " 5195 "-------- ------ -------------- ---------- -----\n"; 5196 static const char udp_hdr_v6_pid_verbose[] = 5197 " Local Address Remote Address " 5198 " User Pid State If Command\n" 5199 "--------------------------------- --------------------------------- " 5200 "-------- ------ ---------- ----- ----------------\n"; 5201 5202 5203 static void 5204 udp_report(const mib_item_t *item) 5205 { 5206 int jtemp = 0; 5207 boolean_t print_hdr_once_v4 = B_TRUE; 5208 boolean_t print_hdr_once_v6 = B_TRUE; 5209 mib2_udpEntry_t *ude; 5210 mib2_udp6Entry_t *ude6; 5211 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs; 5212 mib2_transportMLPEntry_t **v4a, **v6a; 5213 mib2_transportMLPEntry_t *aptr; 5214 conn_pid_info_t *cpi; 5215 5216 if (!protocol_selected(IPPROTO_UDP)) 5217 return; 5218 5219 /* 5220 * Preparation pass: the kernel returns separate entries for UDP 5221 * connection table entries and Multilevel Port attributes. We loop 5222 * through the attributes first and set up an array for each address 5223 * family. 5224 */ 5225 v4_attrs = family_selected(AF_INET) && RSECflag ? 5226 gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL; 5227 v6_attrs = family_selected(AF_INET6) && RSECflag ? 5228 gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) : 5229 NULL; 5230 5231 v4a = v4_attrs; 5232 v6a = v6_attrs; 5233 /* 'for' loop 1: */ 5234 for (; item; item = item->next_item) { 5235 if (Xflag) { 5236 (void) printf("\n--- Entry %d ---\n", ++jtemp); 5237 (void) printf("Group = %d, mib_id = %d, " 5238 "length = %d, valp = 0x%p\n", 5239 item->group, item->mib_id, 5240 item->length, item->valp); 5241 } 5242 if (!((item->group == MIB2_UDP && 5243 item->mib_id == MIB2_UDP_ENTRY) || 5244 (item->group == MIB2_UDP6 && 5245 item->mib_id == MIB2_UDP6_ENTRY) || 5246 (item->group == MIB2_UDP && 5247 item->mib_id == EXPER_XPORT_PROC_INFO) || 5248 (item->group == MIB2_UDP6 && 5249 item->mib_id == EXPER_XPORT_PROC_INFO))) 5250 continue; /* 'for' loop 1 */ 5251 5252 if (item->group == MIB2_UDP && !family_selected(AF_INET)) 5253 continue; /* 'for' loop 1 */ 5254 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6)) 5255 continue; /* 'for' loop 1 */ 5256 5257 /* xxx.xxx.xxx.xxx,pppp sss... */ 5258 if ((!Uflag) && item->group == MIB2_UDP && 5259 item->mib_id == MIB2_UDP_ENTRY) { 5260 for (ude = (mib2_udpEntry_t *)item->valp; 5261 (char *)ude < (char *)item->valp + item->length; 5262 /* LINTED: (note 1) */ 5263 ude = (mib2_udpEntry_t *)((char *)ude + 5264 udpEntrySize)) { 5265 aptr = v4a == NULL ? NULL : *v4a++; 5266 print_hdr_once_v4 = udp_report_item_v4(ude, 5267 NULL, print_hdr_once_v4, aptr); 5268 } 5269 } else if ((!Uflag) && item->group == MIB2_UDP6 && 5270 item->mib_id == MIB2_UDP6_ENTRY) { 5271 for (ude6 = (mib2_udp6Entry_t *)item->valp; 5272 (char *)ude6 < (char *)item->valp + item->length; 5273 /* LINTED: (note 1) */ 5274 ude6 = (mib2_udp6Entry_t *)((char *)ude6 + 5275 udp6EntrySize)) { 5276 aptr = v6a == NULL ? NULL : *v6a++; 5277 print_hdr_once_v6 = udp_report_item_v6(ude6, 5278 NULL, print_hdr_once_v6, aptr); 5279 } 5280 } else if ((Uflag) && item->group == MIB2_UDP && 5281 item->mib_id == EXPER_XPORT_PROC_INFO) { 5282 for (ude = (mib2_udpEntry_t *)item->valp; 5283 (char *)ude < (char *)item->valp + item->length; 5284 /* LINTED: (note 1) */ 5285 ude = (mib2_udpEntry_t *)((char *)cpi + 5286 cpi->cpi_tot_size)) { 5287 aptr = v4a == NULL ? NULL : *v4a++; 5288 /* LINTED: (note 1) */ 5289 cpi = (conn_pid_info_t *)((char *)ude + 5290 udpEntrySize); 5291 print_hdr_once_v4 = udp_report_item_v4(ude, 5292 cpi, print_hdr_once_v4, aptr); 5293 } 5294 } else if ((Uflag) && item->group == MIB2_UDP6 && 5295 item->mib_id == EXPER_XPORT_PROC_INFO) { 5296 for (ude6 = (mib2_udp6Entry_t *)item->valp; 5297 (char *)ude6 < (char *)item->valp + item->length; 5298 /* LINTED: (note 1) */ 5299 ude6 = (mib2_udp6Entry_t *)((char *)cpi + 5300 cpi->cpi_tot_size)) { 5301 aptr = v6a == NULL ? NULL : *v6a++; 5302 /* LINTED: (note 1) */ 5303 cpi = (conn_pid_info_t *)((char *)ude6 + 5304 udp6EntrySize); 5305 print_hdr_once_v6 = udp_report_item_v6(ude6, 5306 cpi, print_hdr_once_v6, aptr); 5307 } 5308 } 5309 } /* 'for' loop 1 ends */ 5310 (void) fflush(stdout); 5311 5312 if (v4_attrs != NULL) 5313 free(v4_attrs); 5314 if (v6_attrs != NULL) 5315 free(v6_attrs); 5316 } 5317 5318 static boolean_t 5319 udp_report_item_v4(const mib2_udpEntry_t *ude, conn_pid_info_t *cpi, 5320 boolean_t first, const mib2_transportMLPEntry_t *attr) 5321 { 5322 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5323 /* hostname + portname */ 5324 5325 if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected)) 5326 return (first); /* Nothing to print */ 5327 5328 if (first) { 5329 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n"); 5330 5331 if (Uflag) 5332 (void) printf(Vflag ? udp_hdr_v4_pid_verbose : 5333 udp_hdr_v4_pid); 5334 else 5335 (void) printf(udp_hdr_v4); 5336 5337 first = B_FALSE; 5338 } 5339 5340 (void) printf("%-20s %-20s ", 5341 pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp", 5342 lname, sizeof (lname)), 5343 ude->udpEntryInfo.ue_state == MIB2_UDP_connected ? 5344 pr_ap(ude->udpEntryInfo.ue_RemoteAddress, 5345 ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) : 5346 ""); 5347 if (!Uflag) { 5348 (void) printf("%s\n", 5349 miudp_state(ude->udpEntryInfo.ue_state, attr)); 5350 } else { 5351 int i = 0; 5352 pid_t *pids = cpi->cpi_pids; 5353 proc_info_t *pinfo; 5354 do { 5355 pinfo = get_proc_info(*pids); 5356 (void) printf("%-8.8s %6u ", pinfo->pr_user, 5357 (int)*pids); 5358 if (Vflag) { 5359 (void) printf("%-10.10s %s\n", 5360 miudp_state(ude->udpEntryInfo.ue_state, 5361 attr), 5362 pinfo->pr_psargs); 5363 } else { 5364 (void) printf("%-14.14s %s\n", pinfo->pr_fname, 5365 miudp_state(ude->udpEntryInfo.ue_state, 5366 attr)); 5367 } 5368 i++; pids++; 5369 } while (i < cpi->cpi_pids_cnt); 5370 } 5371 5372 print_transport_label(attr); 5373 5374 return (first); 5375 } 5376 5377 static boolean_t 5378 udp_report_item_v6(const mib2_udp6Entry_t *ude6, conn_pid_info_t *cpi, 5379 boolean_t first, const mib2_transportMLPEntry_t *attr) 5380 { 5381 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5382 /* hostname + portname */ 5383 char ifname[LIFNAMSIZ + 1]; 5384 const char *ifnamep; 5385 5386 if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected)) 5387 return (first); /* Nothing to print */ 5388 5389 if (first) { 5390 (void) printf("\nUDP: IPv6\n"); 5391 5392 if (Uflag) 5393 (void) printf(Vflag ? udp_hdr_v6_pid_verbose : 5394 udp_hdr_v6_pid); 5395 else 5396 (void) printf(udp_hdr_v6); 5397 5398 first = B_FALSE; 5399 } 5400 5401 ifnamep = (ude6->udp6IfIndex != 0) ? 5402 if_indextoname(ude6->udp6IfIndex, ifname) : NULL; 5403 5404 (void) printf("%-33s %-33s ", 5405 pr_ap6(&ude6->udp6LocalAddress, 5406 ude6->udp6LocalPort, "udp", lname, sizeof (lname)), 5407 ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ? 5408 pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress, 5409 ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) : 5410 ""); 5411 if (!Uflag) { 5412 (void) printf("%-10s %s\n", 5413 miudp_state(ude6->udp6EntryInfo.ue_state, attr), 5414 ifnamep == NULL ? "" : ifnamep); 5415 } else { 5416 int i = 0; 5417 pid_t *pids = cpi->cpi_pids; 5418 proc_info_t *pinfo; 5419 do { 5420 pinfo = get_proc_info(*pids); 5421 (void) printf("%-8.8s %6u ", pinfo->pr_user, 5422 (int)*pids); 5423 if (Vflag) { 5424 (void) printf("%-10.10s %-5.5s %s\n", 5425 miudp_state(ude6->udp6EntryInfo.ue_state, 5426 attr), 5427 ifnamep == NULL ? "" : ifnamep, 5428 pinfo->pr_psargs); 5429 } else { 5430 (void) printf("%-14.14s %-10.10s %s\n", 5431 pinfo->pr_fname, 5432 miudp_state(ude6->udp6EntryInfo.ue_state, 5433 attr), 5434 ifnamep == NULL ? "" : ifnamep); 5435 } 5436 i++; pids++; 5437 } while (i < cpi->cpi_pids_cnt); 5438 } 5439 5440 print_transport_label(attr); 5441 5442 return (first); 5443 } 5444 5445 /* ------------------------------ SCTP_REPORT------------------------------- */ 5446 5447 static const char sctp_hdr[] = 5448 "\nSCTP:"; 5449 static const char sctp_hdr_normal[] = 5450 " Local Address Remote Address " 5451 "Swind Send-Q Rwind Recv-Q StrsI/O State\n" 5452 "------------------------------- ------------------------------- " 5453 "------ ------ ------ ------ ------- -----------"; 5454 static const char sctp_hdr_pid[] = 5455 " Local Address Remote Address " 5456 "Swind Send-Q Rwind Recv-Q StrsI/O User Pid Command State\n" 5457 "------------------------------- ------------------------------- ------ " 5458 "------ ------ ------ ------- -------- ------ -------------- -----------"; 5459 static const char sctp_hdr_pid_verbose[] = 5460 " Local Address Remote Address " 5461 "Swind Send-Q Rwind Recv-Q StrsI/O User Pid State Command\n" 5462 "------------------------------- ------------------------------- ------ " 5463 "------ ------ ------ ------- -------- ------ ----------- --------------"; 5464 5465 static const char * 5466 nssctp_state(int state, const mib2_transportMLPEntry_t *attr) 5467 { 5468 static char sctpsbuf[50]; 5469 const char *cp; 5470 5471 switch (state) { 5472 case MIB2_SCTP_closed: 5473 cp = "CLOSED"; 5474 break; 5475 case MIB2_SCTP_cookieWait: 5476 cp = "COOKIE_WAIT"; 5477 break; 5478 case MIB2_SCTP_cookieEchoed: 5479 cp = "COOKIE_ECHOED"; 5480 break; 5481 case MIB2_SCTP_established: 5482 cp = "ESTABLISHED"; 5483 break; 5484 case MIB2_SCTP_shutdownPending: 5485 cp = "SHUTDOWN_PENDING"; 5486 break; 5487 case MIB2_SCTP_shutdownSent: 5488 cp = "SHUTDOWN_SENT"; 5489 break; 5490 case MIB2_SCTP_shutdownReceived: 5491 cp = "SHUTDOWN_RECEIVED"; 5492 break; 5493 case MIB2_SCTP_shutdownAckSent: 5494 cp = "SHUTDOWN_ACK_SENT"; 5495 break; 5496 case MIB2_SCTP_listen: 5497 cp = "LISTEN"; 5498 break; 5499 default: 5500 (void) snprintf(sctpsbuf, sizeof (sctpsbuf), 5501 "UNKNOWN STATE(%d)", state); 5502 cp = sctpsbuf; 5503 break; 5504 } 5505 5506 if (RSECflag && attr != NULL && attr->tme_flags != 0) { 5507 if (cp != sctpsbuf) { 5508 (void) strlcpy(sctpsbuf, cp, sizeof (sctpsbuf)); 5509 cp = sctpsbuf; 5510 } 5511 if (attr->tme_flags & MIB2_TMEF_PRIVATE) 5512 (void) strlcat(sctpsbuf, " P", sizeof (sctpsbuf)); 5513 if (attr->tme_flags & MIB2_TMEF_SHARED) 5514 (void) strlcat(sctpsbuf, " S", sizeof (sctpsbuf)); 5515 } 5516 5517 return (cp); 5518 } 5519 5520 static const mib2_sctpConnRemoteEntry_t * 5521 sctp_getnext_rem(const mib_item_t **itemp, 5522 const mib2_sctpConnRemoteEntry_t *current, uint32_t associd) 5523 { 5524 const mib_item_t *item = *itemp; 5525 const mib2_sctpConnRemoteEntry_t *sre; 5526 5527 for (; item != NULL; item = item->next_item, current = NULL) { 5528 if (!(item->group == MIB2_SCTP && 5529 item->mib_id == MIB2_SCTP_CONN_REMOTE)) { 5530 continue; 5531 } 5532 5533 if (current != NULL) { 5534 /* LINTED: (note 1) */ 5535 sre = (const mib2_sctpConnRemoteEntry_t *) 5536 ((const char *)current + sctpRemoteEntrySize); 5537 } else { 5538 sre = item->valp; 5539 } 5540 for (; (char *)sre < (char *)item->valp + item->length; 5541 /* LINTED: (note 1) */ 5542 sre = (const mib2_sctpConnRemoteEntry_t *) 5543 ((const char *)sre + sctpRemoteEntrySize)) { 5544 if (sre->sctpAssocId != associd) { 5545 continue; 5546 } 5547 *itemp = item; 5548 return (sre); 5549 } 5550 } 5551 *itemp = NULL; 5552 return (NULL); 5553 } 5554 5555 static const mib2_sctpConnLocalEntry_t * 5556 sctp_getnext_local(const mib_item_t **itemp, 5557 const mib2_sctpConnLocalEntry_t *current, uint32_t associd) 5558 { 5559 const mib_item_t *item = *itemp; 5560 const mib2_sctpConnLocalEntry_t *sle; 5561 5562 for (; item != NULL; item = item->next_item, current = NULL) { 5563 if (!(item->group == MIB2_SCTP && 5564 item->mib_id == MIB2_SCTP_CONN_LOCAL)) { 5565 continue; 5566 } 5567 5568 if (current != NULL) { 5569 /* LINTED: (note 1) */ 5570 sle = (const mib2_sctpConnLocalEntry_t *) 5571 ((const char *)current + sctpLocalEntrySize); 5572 } else { 5573 sle = item->valp; 5574 } 5575 for (; (char *)sle < (char *)item->valp + item->length; 5576 /* LINTED: (note 1) */ 5577 sle = (const mib2_sctpConnLocalEntry_t *) 5578 ((const char *)sle + sctpLocalEntrySize)) { 5579 if (sle->sctpAssocId != associd) { 5580 continue; 5581 } 5582 *itemp = item; 5583 return (sle); 5584 } 5585 } 5586 *itemp = NULL; 5587 return (NULL); 5588 } 5589 5590 static void 5591 sctp_pr_addr(int type, char *name, int namelen, const in6_addr_t *addr, 5592 int port) 5593 { 5594 ipaddr_t v4addr; 5595 in6_addr_t v6addr; 5596 5597 /* 5598 * Address is either a v4 mapped or v6 addr. If 5599 * it's a v4 mapped, convert to v4 before 5600 * displaying. 5601 */ 5602 switch (type) { 5603 case MIB2_SCTP_ADDR_V4: 5604 /* v4 */ 5605 v6addr = *addr; 5606 5607 IN6_V4MAPPED_TO_IPADDR(&v6addr, v4addr); 5608 if (port > 0) { 5609 (void) pr_ap(v4addr, port, "sctp", name, namelen); 5610 } else { 5611 (void) pr_addr(v4addr, name, namelen); 5612 } 5613 break; 5614 5615 case MIB2_SCTP_ADDR_V6: 5616 /* v6 */ 5617 if (port > 0) { 5618 (void) pr_ap6(addr, port, "sctp", name, namelen); 5619 } else { 5620 (void) pr_addr6(addr, name, namelen); 5621 } 5622 break; 5623 5624 default: 5625 (void) snprintf(name, namelen, "<unknown addr type>"); 5626 break; 5627 } 5628 } 5629 5630 static boolean_t 5631 sctp_conn_report_item(const mib_item_t *head, conn_pid_info_t *cpi, 5632 boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp, 5633 const mib2_transportMLPEntry_t *attr) 5634 { 5635 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5636 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1]; 5637 const mib2_sctpConnRemoteEntry_t *sre = NULL; 5638 const mib2_sctpConnLocalEntry_t *sle = NULL; 5639 const mib_item_t *local = head; 5640 const mib_item_t *remote = head; 5641 uint32_t id = sp->sctpAssocId; 5642 boolean_t printfirst = B_TRUE; 5643 5644 if (print_sctp_hdr == B_TRUE) { 5645 (void) puts(sctp_hdr); 5646 if (Uflag) 5647 (void) puts(Vflag? sctp_hdr_pid_verbose: sctp_hdr_pid); 5648 else 5649 (void) puts(sctp_hdr_normal); 5650 5651 print_sctp_hdr = B_FALSE; 5652 } 5653 5654 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname), 5655 &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort); 5656 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname), 5657 &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort); 5658 5659 if (Uflag) { 5660 int i = 0; 5661 pid_t *pids = cpi->cpi_pids; 5662 proc_info_t *pinfo; 5663 do { 5664 pinfo = get_proc_info(*pids); 5665 (void) printf("%-31s %-31s %6u %6d %6u %6d " 5666 "%3d/%-3d %-8.8s %6u ", 5667 lname, fname, 5668 sp->sctpConnEntryInfo.ce_swnd, 5669 sp->sctpConnEntryInfo.ce_sendq, 5670 sp->sctpConnEntryInfo.ce_rwnd, 5671 sp->sctpConnEntryInfo.ce_recvq, 5672 sp->sctpAssocInStreams, 5673 sp->sctpAssocOutStreams, 5674 pinfo->pr_user, (int)*pids); 5675 if (Vflag) { 5676 (void) printf("%-11.11s %s\n", 5677 nssctp_state(sp->sctpAssocState, attr), 5678 pinfo->pr_psargs); 5679 } else { 5680 (void) printf("%-14.14s %s\n", 5681 pinfo->pr_fname, 5682 nssctp_state(sp->sctpAssocState, attr)); 5683 } 5684 i++; pids++; 5685 } while (i < cpi->cpi_pids_cnt); 5686 5687 } else { 5688 5689 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n", 5690 lname, fname, 5691 sp->sctpConnEntryInfo.ce_swnd, 5692 sp->sctpConnEntryInfo.ce_sendq, 5693 sp->sctpConnEntryInfo.ce_rwnd, 5694 sp->sctpConnEntryInfo.ce_recvq, 5695 sp->sctpAssocInStreams, sp->sctpAssocOutStreams, 5696 nssctp_state(sp->sctpAssocState, attr)); 5697 } 5698 5699 print_transport_label(attr); 5700 5701 if (!Vflag) { 5702 return (print_sctp_hdr); 5703 } 5704 5705 /* Print remote addresses/local addresses on following lines */ 5706 while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) { 5707 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr, 5708 &sp->sctpAssocRemPrimAddr)) { 5709 if (printfirst == B_TRUE) { 5710 (void) fputs("\t<Remote: ", stdout); 5711 printfirst = B_FALSE; 5712 } else { 5713 (void) fputs(", ", stdout); 5714 } 5715 sctp_pr_addr(sre->sctpAssocRemAddrType, fname, 5716 sizeof (fname), &sre->sctpAssocRemAddr, -1); 5717 if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) { 5718 (void) fputs(fname, stdout); 5719 } else { 5720 (void) printf("(%s)", fname); 5721 } 5722 } 5723 } 5724 if (printfirst == B_FALSE) { 5725 (void) puts(">"); 5726 printfirst = B_TRUE; 5727 } 5728 while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) { 5729 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr, 5730 &sp->sctpAssocLocPrimAddr)) { 5731 if (printfirst == B_TRUE) { 5732 (void) fputs("\t<Local: ", stdout); 5733 printfirst = B_FALSE; 5734 } else { 5735 (void) fputs(", ", stdout); 5736 } 5737 sctp_pr_addr(sle->sctpAssocLocalAddrType, lname, 5738 sizeof (lname), &sle->sctpAssocLocalAddr, -1); 5739 (void) fputs(lname, stdout); 5740 } 5741 } 5742 if (printfirst == B_FALSE) { 5743 (void) puts(">"); 5744 } 5745 5746 return (print_sctp_hdr); 5747 } 5748 5749 static void 5750 sctp_report(const mib_item_t *item) 5751 { 5752 const mib_item_t *head; 5753 const mib2_sctpConnEntry_t *sp; 5754 boolean_t print_sctp_hdr_once = B_TRUE; 5755 mib2_transportMLPEntry_t **attrs, **aptr; 5756 mib2_transportMLPEntry_t *attr; 5757 conn_pid_info_t *cpi; 5758 5759 /* 5760 * Preparation pass: the kernel returns separate entries for SCTP 5761 * connection table entries and Multilevel Port attributes. We loop 5762 * through the attributes first and set up an array for each address 5763 * family. 5764 */ 5765 attrs = RSECflag ? 5766 gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) : 5767 NULL; 5768 5769 aptr = attrs; 5770 head = item; 5771 for (; item != NULL; item = item->next_item) { 5772 5773 if (!((item->group == MIB2_SCTP && 5774 item->mib_id == MIB2_SCTP_CONN) || 5775 (item->group == MIB2_SCTP && 5776 item->mib_id == EXPER_XPORT_PROC_INFO))) 5777 continue; 5778 5779 if ((!Uflag) && item->group == MIB2_SCTP && 5780 item->mib_id == MIB2_SCTP_CONN) { 5781 for (sp = item->valp; 5782 (char *)sp < (char *)item->valp + item->length; 5783 /* LINTED: (note 1) */ 5784 sp = (mib2_sctpConnEntry_t *)((char *)sp + 5785 sctpEntrySize)) { 5786 if (!(Aflag || 5787 sp->sctpAssocState >= 5788 MIB2_SCTP_established)) 5789 continue; 5790 attr = aptr == NULL ? NULL : *aptr++; 5791 print_sctp_hdr_once = sctp_conn_report_item( 5792 head, NULL, print_sctp_hdr_once, sp, attr); 5793 } 5794 } else if ((Uflag) && item->group == MIB2_SCTP && 5795 item->mib_id == EXPER_XPORT_PROC_INFO) { 5796 for (sp = (mib2_sctpConnEntry_t *)item->valp; 5797 (char *)sp < (char *)item->valp + item->length; 5798 /* LINTED: (note 1) */ 5799 sp = (mib2_sctpConnEntry_t *)((char *)cpi + 5800 cpi->cpi_tot_size)) { 5801 /* LINTED: (note 1) */ 5802 cpi = (conn_pid_info_t *)((char *)sp + 5803 sctpEntrySize); 5804 if (!(Aflag || 5805 sp->sctpAssocState >= 5806 MIB2_SCTP_established)) 5807 continue; 5808 attr = aptr == NULL ? NULL : *aptr++; 5809 print_sctp_hdr_once = sctp_conn_report_item( 5810 head, cpi, print_sctp_hdr_once, sp, attr); 5811 } 5812 } 5813 } 5814 if (attrs != NULL) 5815 free(attrs); 5816 } 5817 5818 static char * 5819 plural(int n) 5820 { 5821 return (n != 1 ? "s" : ""); 5822 } 5823 5824 static char * 5825 pluraly(int n) 5826 { 5827 return (n != 1 ? "ies" : "y"); 5828 } 5829 5830 static char * 5831 plurales(int n) 5832 { 5833 return (n != 1 ? "es" : ""); 5834 } 5835 5836 static char * 5837 pktscale(int n) 5838 { 5839 static char buf[6]; 5840 char t; 5841 5842 if (n < 1024) { 5843 t = ' '; 5844 } else if (n < 1024 * 1024) { 5845 t = 'k'; 5846 n /= 1024; 5847 } else if (n < 1024 * 1024 * 1024) { 5848 t = 'm'; 5849 n /= 1024 * 1024; 5850 } else { 5851 t = 'g'; 5852 n /= 1024 * 1024 * 1024; 5853 } 5854 5855 (void) snprintf(buf, sizeof (buf), "%4u%c", n, t); 5856 return (buf); 5857 } 5858 5859 /* --------------------- mrt_report (netstat -m) -------------------------- */ 5860 5861 static void 5862 mrt_report(mib_item_t *item) 5863 { 5864 int jtemp = 0; 5865 struct vifctl *vip; 5866 vifi_t vifi; 5867 struct mfcctl *mfccp; 5868 int numvifs = 0; 5869 int nmfc = 0; 5870 char abuf[MAXHOSTNAMELEN + 1]; 5871 5872 if (!(family_selected(AF_INET))) 5873 return; 5874 5875 /* 'for' loop 1: */ 5876 for (; item; item = item->next_item) { 5877 if (Xflag) { 5878 (void) printf("\n--- Entry %d ---\n", ++jtemp); 5879 (void) printf("Group = %d, mib_id = %d, " 5880 "length = %d, valp = 0x%p\n", 5881 item->group, item->mib_id, item->length, 5882 item->valp); 5883 } 5884 if (item->group != EXPER_DVMRP) 5885 continue; /* 'for' loop 1 */ 5886 5887 switch (item->mib_id) { 5888 5889 case EXPER_DVMRP_VIF: 5890 if (Xflag) 5891 (void) printf("%u records for ipVifTable:\n", 5892 item->length/sizeof (struct vifctl)); 5893 if (item->length/sizeof (struct vifctl) == 0) { 5894 (void) puts("\nVirtual Interface Table is " 5895 "empty"); 5896 break; 5897 } 5898 5899 (void) puts("\nVirtual Interface Table\n" 5900 " Vif Threshold Rate_Limit Local-Address" 5901 " Remote-Address Pkt_in Pkt_out"); 5902 5903 /* 'for' loop 2: */ 5904 for (vip = (struct vifctl *)item->valp; 5905 (char *)vip < (char *)item->valp + item->length; 5906 /* LINTED: (note 1) */ 5907 vip = (struct vifctl *)((char *)vip + 5908 vifctlSize)) { 5909 if (vip->vifc_lcl_addr.s_addr == 0) 5910 continue; /* 'for' loop 2 */ 5911 /* numvifs = vip->vifc_vifi; */ 5912 5913 numvifs++; 5914 (void) printf(" %2u %3u " 5915 "%4u %-15.15s", 5916 vip->vifc_vifi, 5917 vip->vifc_threshold, 5918 vip->vifc_rate_limit, 5919 pr_addr(vip->vifc_lcl_addr.s_addr, 5920 abuf, sizeof (abuf))); 5921 (void) printf(" %-15.15s %8u %8u\n", 5922 (vip->vifc_flags & VIFF_TUNNEL) ? 5923 pr_addr(vip->vifc_rmt_addr.s_addr, 5924 abuf, sizeof (abuf)) : "", 5925 vip->vifc_pkt_in, 5926 vip->vifc_pkt_out); 5927 } /* 'for' loop 2 ends */ 5928 5929 (void) printf("Numvifs: %d\n", numvifs); 5930 break; 5931 5932 case EXPER_DVMRP_MRT: 5933 if (Xflag) 5934 (void) printf("%u records for ipMfcTable:\n", 5935 item->length/sizeof (struct vifctl)); 5936 if (item->length/sizeof (struct vifctl) == 0) { 5937 (void) puts("\nMulticast Forwarding Cache is " 5938 "empty"); 5939 break; 5940 } 5941 5942 (void) puts("\nMulticast Forwarding Cache\n" 5943 " Origin-Subnet Mcastgroup " 5944 "# Pkts In-Vif Out-vifs/Forw-ttl"); 5945 5946 for (mfccp = (struct mfcctl *)item->valp; 5947 (char *)mfccp < (char *)item->valp + item->length; 5948 /* LINTED: (note 1) */ 5949 mfccp = (struct mfcctl *)((char *)mfccp + 5950 mfcctlSize)) { 5951 5952 nmfc++; 5953 (void) printf(" %-30.15s", 5954 pr_addr(mfccp->mfcc_origin.s_addr, 5955 abuf, sizeof (abuf))); 5956 (void) printf("%-15.15s %6s %3u ", 5957 pr_net(mfccp->mfcc_mcastgrp.s_addr, 5958 mfccp->mfcc_mcastgrp.s_addr, 5959 abuf, sizeof (abuf)), 5960 pktscale((int)mfccp->mfcc_pkt_cnt), 5961 mfccp->mfcc_parent); 5962 5963 for (vifi = 0; vifi < MAXVIFS; ++vifi) { 5964 if (mfccp->mfcc_ttls[vifi]) { 5965 (void) printf(" %u (%u)", 5966 vifi, 5967 mfccp->mfcc_ttls[vifi]); 5968 } 5969 5970 } 5971 (void) putchar('\n'); 5972 } 5973 (void) printf("\nTotal no. of entries in cache: %d\n", 5974 nmfc); 5975 break; 5976 } 5977 } /* 'for' loop 1 ends */ 5978 (void) putchar('\n'); 5979 (void) fflush(stdout); 5980 } 5981 5982 /* 5983 * Get the stats for the cache named 'name'. If prefix != 0, then 5984 * interpret the name as a prefix, and sum up stats for all caches 5985 * named 'name*'. 5986 */ 5987 static void 5988 kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes) 5989 { 5990 int len; 5991 int alloc; 5992 int64_t total_alloc = 0; 5993 int alloc_fail, total_alloc_fail = 0; 5994 int buf_size = 0; 5995 int buf_avail; 5996 int buf_total; 5997 int buf_max, total_buf_max = 0; 5998 int buf_inuse, total_buf_inuse = 0; 5999 kstat_t *ksp; 6000 char buf[256]; 6001 6002 len = prefix ? strlen(name) : 256; 6003 6004 /* 'for' loop 1: */ 6005 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { 6006 6007 if (strcmp(ksp->ks_class, "kmem_cache") != 0) 6008 continue; /* 'for' loop 1 */ 6009 6010 /* 6011 * Hack alert: because of the way streams messages are 6012 * allocated, every constructed free dblk has an associated 6013 * mblk. From the allocator's viewpoint those mblks are 6014 * allocated (because they haven't been freed), but from 6015 * our viewpoint they're actually free (because they're 6016 * not currently in use). To account for this caching 6017 * effect we subtract the total constructed free dblks 6018 * from the total allocated mblks to derive mblks in use. 6019 */ 6020 if (strcmp(name, "streams_mblk") == 0 && 6021 strncmp(ksp->ks_name, "streams_dblk", 12) == 0) { 6022 (void) safe_kstat_read(kc, ksp, NULL); 6023 total_buf_inuse -= 6024 kstat_named_value(ksp, "buf_constructed"); 6025 continue; /* 'for' loop 1 */ 6026 } 6027 6028 if (strncmp(ksp->ks_name, name, len) != 0) 6029 continue; /* 'for' loop 1 */ 6030 6031 (void) safe_kstat_read(kc, ksp, NULL); 6032 6033 alloc = kstat_named_value(ksp, "alloc"); 6034 alloc_fail = kstat_named_value(ksp, "alloc_fail"); 6035 buf_size = kstat_named_value(ksp, "buf_size"); 6036 buf_avail = kstat_named_value(ksp, "buf_avail"); 6037 buf_total = kstat_named_value(ksp, "buf_total"); 6038 buf_max = kstat_named_value(ksp, "buf_max"); 6039 buf_inuse = buf_total - buf_avail; 6040 6041 if (Vflag && prefix) { 6042 (void) snprintf(buf, sizeof (buf), "%s%s", title, 6043 ksp->ks_name + len); 6044 (void) printf(" %-18s %6u %9u %11u %11u\n", 6045 buf, buf_inuse, buf_max, alloc, alloc_fail); 6046 } 6047 6048 total_alloc += alloc; 6049 total_alloc_fail += alloc_fail; 6050 total_buf_max += buf_max; 6051 total_buf_inuse += buf_inuse; 6052 *total_bytes += (int64_t)buf_inuse * buf_size; 6053 } /* 'for' loop 1 ends */ 6054 6055 if (buf_size == 0) { 6056 (void) printf("%-22s [couldn't find statistics for %s]\n", 6057 title, name); 6058 return; 6059 } 6060 6061 if (Vflag && prefix) 6062 (void) snprintf(buf, sizeof (buf), "%s_total", title); 6063 else 6064 (void) snprintf(buf, sizeof (buf), "%s", title); 6065 6066 (void) printf("%-22s %6d %9d %11lld %11d\n", buf, 6067 total_buf_inuse, total_buf_max, total_alloc, total_alloc_fail); 6068 } 6069 6070 static void 6071 m_report(void) 6072 { 6073 int64_t total_bytes = 0; 6074 6075 (void) puts("streams allocation:"); 6076 (void) printf("%63s\n", "cumulative allocation"); 6077 (void) printf("%63s\n", 6078 "current maximum total failures"); 6079 6080 kmem_cache_stats("streams", 6081 "stream_head_cache", 0, &total_bytes); 6082 kmem_cache_stats("queues", "queue_cache", 0, &total_bytes); 6083 kmem_cache_stats("mblk", "streams_mblk", 0, &total_bytes); 6084 kmem_cache_stats("dblk", "streams_dblk", 1, &total_bytes); 6085 kmem_cache_stats("linkblk", "linkinfo_cache", 0, &total_bytes); 6086 kmem_cache_stats("syncq", "syncq_cache", 0, &total_bytes); 6087 kmem_cache_stats("qband", "qband_cache", 0, &total_bytes); 6088 6089 (void) printf("\n%lld Kbytes allocated for streams data\n", 6090 total_bytes / 1024); 6091 6092 (void) putchar('\n'); 6093 (void) fflush(stdout); 6094 } 6095 6096 /* --------------------------------- */ 6097 6098 /* 6099 * Print an IPv4 address. Remove the matching part of the domain name 6100 * from the returned name. 6101 */ 6102 static char * 6103 pr_addr(uint_t addr, char *dst, uint_t dstlen) 6104 { 6105 char *cp; 6106 struct hostent *hp = NULL; 6107 static char domain[MAXHOSTNAMELEN + 1]; 6108 static boolean_t first = B_TRUE; 6109 int error_num; 6110 6111 if (first) { 6112 first = B_FALSE; 6113 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 && 6114 (cp = strchr(domain, '.'))) { 6115 (void) strncpy(domain, cp + 1, sizeof (domain)); 6116 } else 6117 domain[0] = 0; 6118 } 6119 cp = NULL; 6120 if (!Nflag) { 6121 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t), AF_INET, 6122 &error_num); 6123 if (hp) { 6124 if ((cp = strchr(hp->h_name, '.')) != NULL && 6125 strcasecmp(cp + 1, domain) == 0) 6126 *cp = 0; 6127 cp = hp->h_name; 6128 } 6129 } 6130 if (cp != NULL) { 6131 (void) strncpy(dst, cp, dstlen); 6132 dst[dstlen - 1] = 0; 6133 } else { 6134 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen); 6135 } 6136 if (hp != NULL) 6137 freehostent(hp); 6138 return (dst); 6139 } 6140 6141 /* 6142 * Print a non-zero IPv4 address. Print " --" if the address is zero. 6143 */ 6144 static char * 6145 pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen) 6146 { 6147 if (addr == INADDR_ANY) { 6148 (void) strlcpy(dst, " --", dstlen); 6149 return (dst); 6150 } 6151 return (pr_addr(addr, dst, dstlen)); 6152 } 6153 6154 /* 6155 * Print an IPv6 address. Remove the matching part of the domain name 6156 * from the returned name. 6157 */ 6158 static char * 6159 pr_addr6(const struct in6_addr *addr, char *dst, uint_t dstlen) 6160 { 6161 char *cp; 6162 struct hostent *hp = NULL; 6163 static char domain[MAXHOSTNAMELEN + 1]; 6164 static boolean_t first = B_TRUE; 6165 int error_num; 6166 6167 if (first) { 6168 first = B_FALSE; 6169 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 && 6170 (cp = strchr(domain, '.'))) { 6171 (void) strncpy(domain, cp + 1, sizeof (domain)); 6172 } else 6173 domain[0] = 0; 6174 } 6175 cp = NULL; 6176 if (!Nflag) { 6177 hp = getipnodebyaddr((char *)addr, 6178 sizeof (struct in6_addr), AF_INET6, &error_num); 6179 if (hp) { 6180 if ((cp = strchr(hp->h_name, '.')) != NULL && 6181 strcasecmp(cp + 1, domain) == 0) 6182 *cp = 0; 6183 cp = hp->h_name; 6184 } 6185 } 6186 if (cp != NULL) { 6187 (void) strncpy(dst, cp, dstlen); 6188 dst[dstlen - 1] = 0; 6189 } else { 6190 (void) inet_ntop(AF_INET6, (void *)addr, dst, dstlen); 6191 } 6192 if (hp != NULL) 6193 freehostent(hp); 6194 return (dst); 6195 } 6196 6197 /* For IPv4 masks */ 6198 static char * 6199 pr_mask(uint_t addr, char *dst, uint_t dstlen) 6200 { 6201 uint8_t *ip_addr = (uint8_t *)&addr; 6202 6203 (void) snprintf(dst, dstlen, "%d.%d.%d.%d", 6204 ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); 6205 return (dst); 6206 } 6207 6208 /* 6209 * For ipv6 masks format is : dest/mask 6210 * Does not print /128 to save space in printout. H flag carries this notion. 6211 */ 6212 static char * 6213 pr_prefix6(const struct in6_addr *addr, uint_t prefixlen, char *dst, 6214 uint_t dstlen) 6215 { 6216 char *cp; 6217 6218 if (IN6_IS_ADDR_UNSPECIFIED(addr) && prefixlen == 0) { 6219 (void) strncpy(dst, "default", dstlen); 6220 dst[dstlen - 1] = 0; 6221 return (dst); 6222 } 6223 6224 (void) pr_addr6(addr, dst, dstlen); 6225 if (prefixlen != IPV6_ABITS) { 6226 /* How much room is left? */ 6227 cp = strchr(dst, '\0'); 6228 if (dst + dstlen > cp) { 6229 dstlen -= (cp - dst); 6230 (void) snprintf(cp, dstlen, "/%d", prefixlen); 6231 } 6232 } 6233 return (dst); 6234 } 6235 6236 /* Print IPv4 address and port */ 6237 static char * 6238 pr_ap(uint_t addr, uint_t port, char *proto, 6239 char *dst, uint_t dstlen) 6240 { 6241 char *cp; 6242 6243 if (addr == INADDR_ANY) { 6244 (void) strncpy(dst, " *", dstlen); 6245 dst[dstlen - 1] = 0; 6246 } else { 6247 (void) pr_addr(addr, dst, dstlen); 6248 } 6249 /* How much room is left? */ 6250 cp = strchr(dst, '\0'); 6251 if (dst + dstlen > cp + 1) { 6252 *cp++ = '.'; 6253 dstlen -= (cp - dst); 6254 dstlen--; 6255 (void) portname(port, proto, cp, dstlen); 6256 } 6257 return (dst); 6258 } 6259 6260 /* Print IPv6 address and port */ 6261 static char * 6262 pr_ap6(const in6_addr_t *addr, uint_t port, char *proto, 6263 char *dst, uint_t dstlen) 6264 { 6265 char *cp; 6266 6267 if (IN6_IS_ADDR_UNSPECIFIED(addr)) { 6268 (void) strncpy(dst, " *", dstlen); 6269 dst[dstlen - 1] = 0; 6270 } else { 6271 (void) pr_addr6(addr, dst, dstlen); 6272 } 6273 /* How much room is left? */ 6274 cp = strchr(dst, '\0'); 6275 if (dst + dstlen + 1 > cp) { 6276 *cp++ = '.'; 6277 dstlen -= (cp - dst); 6278 dstlen--; 6279 (void) portname(port, proto, cp, dstlen); 6280 } 6281 return (dst); 6282 } 6283 6284 /* 6285 * Return the name of the network whose address is given. The address is 6286 * assumed to be that of a net or subnet, not a host. 6287 */ 6288 static char * 6289 pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen) 6290 { 6291 char *cp = NULL; 6292 struct netent *np = NULL; 6293 struct hostent *hp = NULL; 6294 uint_t net; 6295 int subnetshift; 6296 int error_num; 6297 6298 if (addr == INADDR_ANY && mask == INADDR_ANY) { 6299 (void) strncpy(dst, "default", dstlen); 6300 dst[dstlen - 1] = 0; 6301 return (dst); 6302 } 6303 6304 if (!Nflag && addr) { 6305 if (mask == 0) { 6306 if (IN_CLASSA(addr)) { 6307 mask = (uint_t)IN_CLASSA_NET; 6308 subnetshift = 8; 6309 } else if (IN_CLASSB(addr)) { 6310 mask = (uint_t)IN_CLASSB_NET; 6311 subnetshift = 8; 6312 } else { 6313 mask = (uint_t)IN_CLASSC_NET; 6314 subnetshift = 4; 6315 } 6316 /* 6317 * If there are more bits than the standard mask 6318 * would suggest, subnets must be in use. Guess at 6319 * the subnet mask, assuming reasonable width subnet 6320 * fields. 6321 */ 6322 while (addr & ~mask) 6323 /* compiler doesn't sign extend! */ 6324 mask = (mask | ((int)mask >> subnetshift)); 6325 } 6326 net = addr & mask; 6327 while ((mask & 1) == 0) 6328 mask >>= 1, net >>= 1; 6329 np = getnetbyaddr(net, AF_INET); 6330 if (np && np->n_net == net) 6331 cp = np->n_name; 6332 else { 6333 /* 6334 * Look for subnets in hosts map. 6335 */ 6336 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t), 6337 AF_INET, &error_num); 6338 if (hp) 6339 cp = hp->h_name; 6340 } 6341 } 6342 if (cp != NULL) { 6343 (void) strncpy(dst, cp, dstlen); 6344 dst[dstlen - 1] = 0; 6345 } else { 6346 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen); 6347 } 6348 if (hp != NULL) 6349 freehostent(hp); 6350 return (dst); 6351 } 6352 6353 /* 6354 * Return the name of the network whose address is given. 6355 * The address is assumed to be a host address. 6356 */ 6357 static char * 6358 pr_netaddr(uint_t addr, uint_t mask, char *dst, uint_t dstlen) 6359 { 6360 char *cp = NULL; 6361 struct netent *np = NULL; 6362 struct hostent *hp = NULL; 6363 uint_t net; 6364 uint_t netshifted; 6365 int subnetshift; 6366 struct in_addr in; 6367 int error_num; 6368 uint_t nbo_addr = addr; /* network byte order */ 6369 6370 addr = ntohl(addr); 6371 mask = ntohl(mask); 6372 if (addr == INADDR_ANY && mask == INADDR_ANY) { 6373 (void) strncpy(dst, "default", dstlen); 6374 dst[dstlen - 1] = 0; 6375 return (dst); 6376 } 6377 6378 /* Figure out network portion of address (with host portion = 0) */ 6379 if (addr) { 6380 /* Try figuring out mask if unknown (all 0s). */ 6381 if (mask == 0) { 6382 if (IN_CLASSA(addr)) { 6383 mask = (uint_t)IN_CLASSA_NET; 6384 subnetshift = 8; 6385 } else if (IN_CLASSB(addr)) { 6386 mask = (uint_t)IN_CLASSB_NET; 6387 subnetshift = 8; 6388 } else { 6389 mask = (uint_t)IN_CLASSC_NET; 6390 subnetshift = 4; 6391 } 6392 /* 6393 * If there are more bits than the standard mask 6394 * would suggest, subnets must be in use. Guess at 6395 * the subnet mask, assuming reasonable width subnet 6396 * fields. 6397 */ 6398 while (addr & ~mask) 6399 /* compiler doesn't sign extend! */ 6400 mask = (mask | ((int)mask >> subnetshift)); 6401 } 6402 net = netshifted = addr & mask; 6403 while ((mask & 1) == 0) 6404 mask >>= 1, netshifted >>= 1; 6405 } 6406 else 6407 net = netshifted = 0; 6408 6409 /* Try looking up name unless -n was specified. */ 6410 if (!Nflag) { 6411 np = getnetbyaddr(netshifted, AF_INET); 6412 if (np && np->n_net == netshifted) 6413 cp = np->n_name; 6414 else { 6415 /* 6416 * Look for subnets in hosts map. 6417 */ 6418 hp = getipnodebyaddr((char *)&nbo_addr, sizeof (uint_t), 6419 AF_INET, &error_num); 6420 if (hp) 6421 cp = hp->h_name; 6422 } 6423 6424 if (cp != NULL) { 6425 (void) strncpy(dst, cp, dstlen); 6426 dst[dstlen - 1] = 0; 6427 if (hp != NULL) 6428 freehostent(hp); 6429 return (dst); 6430 } 6431 /* 6432 * No name found for net: fallthru and return in decimal 6433 * dot notation. 6434 */ 6435 } 6436 6437 in.s_addr = htonl(net); 6438 (void) inet_ntop(AF_INET, (char *)&in, dst, dstlen); 6439 if (hp != NULL) 6440 freehostent(hp); 6441 return (dst); 6442 } 6443 6444 /* 6445 * Return the filter mode as a string: 6446 * 1 => "INCLUDE" 6447 * 2 => "EXCLUDE" 6448 * otherwise "<unknown>" 6449 */ 6450 static char * 6451 fmodestr(uint_t fmode) 6452 { 6453 switch (fmode) { 6454 case 1: 6455 return ("INCLUDE"); 6456 case 2: 6457 return ("EXCLUDE"); 6458 default: 6459 return ("<unknown>"); 6460 } 6461 } 6462 6463 #define MAX_STRING_SIZE 256 6464 6465 static const char * 6466 pr_secattr(const sec_attr_list_t *attrs) 6467 { 6468 int i; 6469 char buf[MAX_STRING_SIZE + 1], *cp; 6470 static char *sbuf; 6471 static size_t sbuf_len; 6472 struct rtsa_s rtsa; 6473 const sec_attr_list_t *aptr; 6474 6475 if (!RSECflag || attrs == NULL) 6476 return (""); 6477 6478 for (aptr = attrs, i = 1; aptr != NULL; aptr = aptr->sal_next) 6479 i += MAX_STRING_SIZE; 6480 if (i > sbuf_len) { 6481 cp = realloc(sbuf, i); 6482 if (cp == NULL) { 6483 perror("realloc security attribute buffer"); 6484 return (""); 6485 } 6486 sbuf_len = i; 6487 sbuf = cp; 6488 } 6489 6490 cp = sbuf; 6491 while (attrs != NULL) { 6492 const mib2_ipAttributeEntry_t *iae = attrs->sal_attr; 6493 6494 /* note: effectively hard-coded in rtsa_keyword */ 6495 rtsa.rtsa_mask = RTSA_CIPSO | RTSA_SLRANGE | RTSA_DOI; 6496 rtsa.rtsa_slrange = iae->iae_slrange; 6497 rtsa.rtsa_doi = iae->iae_doi; 6498 6499 (void) snprintf(cp, MAX_STRING_SIZE, 6500 "<%s>%s ", rtsa_to_str(&rtsa, buf, sizeof (buf)), 6501 attrs->sal_next == NULL ? "" : ","); 6502 cp += strlen(cp); 6503 attrs = attrs->sal_next; 6504 } 6505 *cp = '\0'; 6506 6507 return (sbuf); 6508 } 6509 6510 /* 6511 * Pretty print a port number. If the Nflag was 6512 * specified, use numbers instead of names. 6513 */ 6514 static char * 6515 portname(uint_t port, char *proto, char *dst, uint_t dstlen) 6516 { 6517 struct servent *sp = NULL; 6518 6519 if (!Nflag && port) 6520 sp = getservbyport(htons(port), proto); 6521 if (sp || port == 0) 6522 (void) snprintf(dst, dstlen, "%.*s", MAXHOSTNAMELEN, 6523 sp ? sp->s_name : "*"); 6524 else 6525 (void) snprintf(dst, dstlen, "%d", port); 6526 dst[dstlen - 1] = 0; 6527 return (dst); 6528 } 6529 6530 /*PRINTFLIKE2*/ 6531 void 6532 fail(int do_perror, char *message, ...) 6533 { 6534 va_list args; 6535 6536 va_start(args, message); 6537 (void) fputs("netstat: ", stderr); 6538 (void) vfprintf(stderr, message, args); 6539 va_end(args); 6540 if (do_perror) 6541 (void) fprintf(stderr, ": %s", strerror(errno)); 6542 (void) fputc('\n', stderr); 6543 exit(2); 6544 } 6545 6546 /* 6547 * Return value of named statistic for given kstat_named kstat; 6548 * return 0LL if named statistic is not in list (use "ll" as a 6549 * type qualifier when printing 64-bit int's with printf() ) 6550 */ 6551 static uint64_t 6552 kstat_named_value(kstat_t *ksp, char *name) 6553 { 6554 kstat_named_t *knp; 6555 uint64_t value; 6556 6557 if (ksp == NULL) 6558 return (0LL); 6559 6560 knp = kstat_data_lookup(ksp, name); 6561 if (knp == NULL) 6562 return (0LL); 6563 6564 switch (knp->data_type) { 6565 case KSTAT_DATA_INT32: 6566 case KSTAT_DATA_UINT32: 6567 value = (uint64_t)(knp->value.ui32); 6568 break; 6569 case KSTAT_DATA_INT64: 6570 case KSTAT_DATA_UINT64: 6571 value = knp->value.ui64; 6572 break; 6573 default: 6574 value = 0LL; 6575 break; 6576 } 6577 6578 return (value); 6579 } 6580 6581 kid_t 6582 safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data) 6583 { 6584 kid_t kstat_chain_id = kstat_read(kc, ksp, data); 6585 6586 if (kstat_chain_id == -1) 6587 fail(1, "kstat_read(%p, '%s') failed", (void *)kc, 6588 ksp->ks_name); 6589 return (kstat_chain_id); 6590 } 6591 6592 /* 6593 * Parse a list of IRE flag characters into a bit field. 6594 */ 6595 static uint_t 6596 flag_bits(const char *arg) 6597 { 6598 const char *cp; 6599 uint_t val; 6600 6601 if (*arg == '\0') 6602 fatal(1, "missing flag list\n"); 6603 6604 val = 0; 6605 while (*arg != '\0') { 6606 if ((cp = strchr(flag_list, *arg)) == NULL) 6607 fatal(1, "%c: illegal flag\n", *arg); 6608 val |= 1 << (cp - flag_list); 6609 arg++; 6610 } 6611 return (val); 6612 } 6613 6614 /* 6615 * Handle -f argument. Validate input format, sort by keyword, and 6616 * save off digested results. 6617 */ 6618 static void 6619 process_filter(char *arg) 6620 { 6621 int idx; 6622 int klen = 0; 6623 char *cp, *cp2; 6624 int val; 6625 filter_t *newf; 6626 struct hostent *hp; 6627 int error_num; 6628 uint8_t *ucp; 6629 int maxv; 6630 6631 /* Look up the keyword first */ 6632 if (strchr(arg, ':') == NULL) { 6633 idx = FK_AF; 6634 } else { 6635 for (idx = 0; idx < NFILTERKEYS; idx++) { 6636 klen = strlen(filter_keys[idx]); 6637 if (strncmp(filter_keys[idx], arg, klen) == 0 && 6638 arg[klen] == ':') 6639 break; 6640 } 6641 if (idx >= NFILTERKEYS) 6642 fatal(1, "%s: unknown filter keyword\n", arg); 6643 6644 /* Advance past keyword and separator. */ 6645 arg += klen + 1; 6646 } 6647 6648 if ((newf = malloc(sizeof (*newf))) == NULL) { 6649 perror("filter"); 6650 exit(1); 6651 } 6652 switch (idx) { 6653 case FK_AF: 6654 if (strcmp(arg, "inet") == 0) { 6655 newf->u.f_family = AF_INET; 6656 } else if (strcmp(arg, "inet6") == 0) { 6657 newf->u.f_family = AF_INET6; 6658 } else if (strcmp(arg, "unix") == 0) { 6659 newf->u.f_family = AF_UNIX; 6660 } else { 6661 newf->u.f_family = strtol(arg, &cp, 0); 6662 if (arg == cp || *cp != '\0') 6663 fatal(1, "%s: unknown address family.\n", arg); 6664 } 6665 break; 6666 6667 case FK_OUTIF: 6668 if (strcmp(arg, "none") == 0) { 6669 newf->u.f_ifname = NULL; 6670 break; 6671 } 6672 if (strcmp(arg, "any") == 0) { 6673 newf->u.f_ifname = ""; 6674 break; 6675 } 6676 val = strtol(arg, &cp, 0); 6677 if (val <= 0 || arg == cp || cp[0] != '\0') { 6678 if ((val = if_nametoindex(arg)) == 0) { 6679 perror(arg); 6680 exit(1); 6681 } 6682 } 6683 newf->u.f_ifname = arg; 6684 break; 6685 6686 case FK_DST: 6687 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask); 6688 if (strcmp(arg, "any") == 0) { 6689 /* Special semantics; any address *but* zero */ 6690 newf->u.a.f_address = NULL; 6691 (void) memset(&newf->u.a.f_mask, 0, 6692 sizeof (newf->u.a.f_mask)); 6693 break; 6694 } 6695 if (strcmp(arg, "none") == 0) { 6696 newf->u.a.f_address = NULL; 6697 break; 6698 } 6699 if ((cp = strrchr(arg, '/')) != NULL) 6700 *cp++ = '\0'; 6701 hp = getipnodebyname(arg, AF_INET6, AI_V4MAPPED|AI_ALL, 6702 &error_num); 6703 if (hp == NULL) 6704 fatal(1, "%s: invalid or unknown host address\n", arg); 6705 newf->u.a.f_address = hp; 6706 if (cp == NULL) { 6707 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask); 6708 } else { 6709 val = strtol(cp, &cp2, 0); 6710 if (cp != cp2 && cp2[0] == '\0') { 6711 /* 6712 * If decode as "/n" works, then translate 6713 * into a mask. 6714 */ 6715 if (hp->h_addr_list[0] != NULL && 6716 /* LINTED: (note 1) */ 6717 IN6_IS_ADDR_V4MAPPED((in6_addr_t *) 6718 hp->h_addr_list[0])) { 6719 maxv = IP_ABITS; 6720 } else { 6721 maxv = IPV6_ABITS; 6722 } 6723 if (val < 0 || val >= maxv) 6724 fatal(1, "%d: not in range 0 to %d\n", 6725 val, maxv - 1); 6726 if (maxv == IP_ABITS) 6727 val += IPV6_ABITS - IP_ABITS; 6728 ucp = newf->u.a.f_mask.s6_addr; 6729 while (val >= 8) 6730 *ucp++ = 0xff, val -= 8; 6731 *ucp++ = (0xff << (8 - val)) & 0xff; 6732 while (ucp < newf->u.a.f_mask.s6_addr + 6733 sizeof (newf->u.a.f_mask.s6_addr)) 6734 *ucp++ = 0; 6735 /* Otherwise, try as numeric address */ 6736 } else if (inet_pton(AF_INET6, 6737 cp, &newf->u.a.f_mask) <= 0) { 6738 fatal(1, "%s: illegal mask format\n", cp); 6739 } 6740 } 6741 break; 6742 6743 case FK_FLAGS: 6744 if (*arg == '+') { 6745 newf->u.f.f_flagset = flag_bits(arg + 1); 6746 newf->u.f.f_flagclear = 0; 6747 } else if (*arg == '-') { 6748 newf->u.f.f_flagset = 0; 6749 newf->u.f.f_flagclear = flag_bits(arg + 1); 6750 } else { 6751 newf->u.f.f_flagset = flag_bits(arg); 6752 newf->u.f.f_flagclear = ~newf->u.f.f_flagset; 6753 } 6754 break; 6755 6756 default: 6757 assert(0); 6758 } 6759 newf->f_next = filters[idx]; 6760 filters[idx] = newf; 6761 } 6762 6763 /* Determine if user wants this address family printed. */ 6764 static boolean_t 6765 family_selected(int family) 6766 { 6767 const filter_t *fp; 6768 6769 if (v4compat && family == AF_INET6) 6770 return (B_FALSE); 6771 if ((fp = filters[FK_AF]) == NULL) 6772 return (B_TRUE); 6773 while (fp != NULL) { 6774 if (fp->u.f_family == family) 6775 return (B_TRUE); 6776 fp = fp->f_next; 6777 } 6778 return (B_FALSE); 6779 } 6780 6781 /* 6782 * Convert the interface index to a string using the buffer `ifname', which 6783 * must be at least LIFNAMSIZ bytes. We first try to map it to name. If that 6784 * fails (e.g., because we're inside a zone and it does not have access to 6785 * interface for the index in question), just return "if#<num>". 6786 */ 6787 static char * 6788 ifindex2str(uint_t ifindex, char *ifname) 6789 { 6790 if (if_indextoname(ifindex, ifname) == NULL) 6791 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex); 6792 6793 return (ifname); 6794 } 6795 6796 /* 6797 * Gets proc info in (proc_info_t) given pid. It doesn't return NULL. 6798 */ 6799 proc_info_t * 6800 get_proc_info(pid_t pid) 6801 { 6802 static pid_t saved_pid = 0; 6803 static proc_info_t saved_proc_info; 6804 static proc_info_t unknown_proc_info = {"<unknown>", "", ""}; 6805 static psinfo_t pinfo; 6806 char path[128]; 6807 int fd; 6808 6809 /* hardcode pid = 0 */ 6810 if (pid == 0) { 6811 saved_proc_info.pr_user = "root"; 6812 saved_proc_info.pr_fname = "sched"; 6813 saved_proc_info.pr_psargs = "sched"; 6814 saved_pid = 0; 6815 return (&saved_proc_info); 6816 } 6817 6818 if (pid == saved_pid) 6819 return (&saved_proc_info); 6820 if ((snprintf(path, 128, "/proc/%u/psinfo", (int)pid) > 0) && 6821 ((fd = open(path, O_RDONLY)) != -1)) { 6822 if (read(fd, &pinfo, sizeof (pinfo)) == sizeof (pinfo)) { 6823 saved_proc_info.pr_user = get_username(pinfo.pr_uid); 6824 saved_proc_info.pr_fname = pinfo.pr_fname; 6825 saved_proc_info.pr_psargs = pinfo.pr_psargs; 6826 saved_pid = pid; 6827 (void) close(fd); 6828 return (&saved_proc_info); 6829 } else { 6830 (void) close(fd); 6831 } 6832 } 6833 6834 return (&unknown_proc_info); 6835 } 6836 6837 /* 6838 * Gets username given uid. It doesn't return NULL. 6839 */ 6840 static char * 6841 get_username(uid_t u) 6842 { 6843 static uid_t saved_uid = UINT_MAX; 6844 static char saved_username[128]; 6845 struct passwd *pw = NULL; 6846 if (u == UINT_MAX) 6847 return ("<unknown>"); 6848 if (u == saved_uid && saved_username[0] != '\0') 6849 return (saved_username); 6850 setpwent(); 6851 if ((pw = getpwuid(u)) != NULL) 6852 (void) strlcpy(saved_username, pw->pw_name, 128); 6853 else 6854 (void) snprintf(saved_username, 128, "%u", u); 6855 saved_uid = u; 6856 return (saved_username); 6857 } 6858 6859 /* 6860 * print the usage line 6861 */ 6862 static void 6863 usage(char *cmdname) 6864 { 6865 (void) fprintf(stderr, "usage: %s [-anuv] [-f address_family] " 6866 "[-T d|u]\n", cmdname); 6867 (void) fprintf(stderr, " %s [-n] [-f address_family] " 6868 "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n", 6869 cmdname); 6870 (void) fprintf(stderr, " %s -m [-v] [-T d|u] " 6871 "[interval [count]]\n", cmdname); 6872 (void) fprintf(stderr, " %s -i [-I interface] [-an] " 6873 "[-f address_family] [-T d|u] [interval [count]]\n", cmdname); 6874 (void) fprintf(stderr, " %s -r [-anv] " 6875 "[-f address_family|filter] [-T d|u]\n", cmdname); 6876 (void) fprintf(stderr, " %s -M [-ns] [-f address_family] " 6877 "[-T d|u]\n", cmdname); 6878 (void) fprintf(stderr, " %s -D [-I interface] " 6879 "[-f address_family] [-T d|u]\n", cmdname); 6880 exit(EXIT_FAILURE); 6881 } 6882 6883 /* 6884 * fatal: print error message to stderr and 6885 * call exit(errcode) 6886 */ 6887 /*PRINTFLIKE2*/ 6888 static void 6889 fatal(int errcode, char *format, ...) 6890 { 6891 va_list argp; 6892 6893 if (format == NULL) 6894 return; 6895 6896 va_start(argp, format); 6897 (void) vfprintf(stderr, format, argp); 6898 va_end(argp); 6899 6900 exit(errcode); 6901 } 6902 6903 6904 /* -------------------UNIX Domain Sockets Report---------------------------- */ 6905 6906 6907 #define NO_ADDR " " 6908 #define SO_PAIR " (socketpair) " 6909 6910 static char *typetoname(t_scalar_t); 6911 static boolean_t uds_report_item(struct sockinfo *, boolean_t); 6912 6913 6914 static char uds_hdr[] = "\nActive UNIX domain sockets\n"; 6915 6916 static char uds_hdr_normal[] = 6917 " Type Local Adress " 6918 " Remote Address\n" 6919 "---------- --------------------------------------- " 6920 "---------------------------------------\n"; 6921 6922 static char uds_hdr_pid[] = 6923 " Type User Pid Command " 6924 " Local Address " 6925 " Remote Address\n" 6926 "---------- -------- ------ -------------- " 6927 "--------------------------------------- " 6928 "---------------------------------------\n"; 6929 static char uds_hdr_pid_verbose[] = 6930 " Type User Pid Local Address " 6931 " Remote Address Command\n" 6932 "---------- -------- ------ --------------------------------------- " 6933 "--------------------------------------- --------------\n"; 6934 6935 /* 6936 * Print a summary of connections related to unix protocols. 6937 */ 6938 static void 6939 uds_report(kstat_ctl_t *kc) 6940 { 6941 int i; 6942 kstat_t *ksp; 6943 struct sockinfo *psi; 6944 boolean_t print_uds_hdr_once = B_TRUE; 6945 6946 if (kc == NULL) { 6947 fail(0, "uds_report: No kstat"); 6948 exit(3); 6949 } 6950 6951 if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) == 6952 (kstat_t *)NULL) { 6953 fail(0, "kstat_data_lookup failed\n"); 6954 } 6955 6956 if (kstat_read(kc, ksp, NULL) == -1) { 6957 fail(0, "kstat_read failed for sock_unix_list\n"); 6958 } 6959 6960 if (ksp->ks_ndata == 0) { 6961 return; /* no AF_UNIX sockets found */ 6962 } 6963 6964 /* 6965 * Having ks_data set with ks_data == NULL shouldn't happen; 6966 * If it does, the sockfs kstat is seriously broken. 6967 */ 6968 if ((psi = ksp->ks_data) == NULL) { 6969 fail(0, "uds_report: no kstat data\n"); 6970 } 6971 6972 for (i = 0; i < ksp->ks_ndata; i++) { 6973 6974 print_uds_hdr_once = uds_report_item(psi, print_uds_hdr_once); 6975 6976 /* if si_size didn't get filled in, then we're done */ 6977 if (psi->si_size == 0 || 6978 !IS_P2ALIGNED(psi->si_size, sizeof (psi))) { 6979 break; 6980 } 6981 6982 /* point to the next sockinfo in the array */ 6983 /* LINTED: (note 1) */ 6984 psi = (struct sockinfo *)(((char *)psi) + psi->si_size); 6985 } 6986 } 6987 6988 static boolean_t 6989 uds_report_item(struct sockinfo *psi, boolean_t first) 6990 { 6991 int i = 0; 6992 pid_t *pids; 6993 proc_info_t *pinfo; 6994 char *laddr, *raddr; 6995 6996 if (first) { 6997 (void) printf("%s", uds_hdr); 6998 if (Uflag) 6999 (void) printf("%s", Vflag?uds_hdr_pid_verbose: 7000 uds_hdr_pid); 7001 else 7002 (void) printf("%s", uds_hdr_normal); 7003 7004 first = B_FALSE; 7005 } 7006 7007 pids = psi->si_pids; 7008 7009 do { 7010 pinfo = get_proc_info(*pids); 7011 raddr = laddr = NO_ADDR; 7012 7013 /* Try to fill laddr */ 7014 if ((psi->si_state & SS_ISBOUND) && 7015 strlen(psi->si_laddr_sun_path) != 0 && 7016 psi->si_laddr_soa_len != 0) { 7017 if (psi->si_faddr_noxlate) { 7018 laddr = SO_PAIR; 7019 } else { 7020 if (psi->si_laddr_soa_len > 7021 sizeof (psi->si_laddr_family)) 7022 laddr = psi->si_laddr_sun_path; 7023 } 7024 } 7025 7026 /* Try to fill raddr */ 7027 if ((psi->si_state & SS_ISCONNECTED) && 7028 strlen(psi->si_faddr_sun_path) != 0 && 7029 psi->si_faddr_soa_len != 0) { 7030 7031 if (psi->si_faddr_noxlate) { 7032 raddr = SO_PAIR; 7033 } else { 7034 if (psi->si_faddr_soa_len > 7035 sizeof (psi->si_faddr_family)) 7036 raddr = psi->si_faddr_sun_path; 7037 } 7038 } 7039 7040 if (Uflag && Vflag) { 7041 (void) printf("%-10.10s %-8.8s %6u " 7042 "%-39.39s %-39.39s %s\n", 7043 typetoname(psi->si_serv_type), pinfo->pr_user, 7044 (int)*pids, laddr, raddr, pinfo->pr_psargs); 7045 } else if (Uflag && (!Vflag)) { 7046 (void) printf("%-10.10s %-8.8s %6u %-14.14s" 7047 "%-39.39s %-39.39s\n", 7048 typetoname(psi->si_serv_type), pinfo->pr_user, 7049 (int)*pids, pinfo->pr_fname, laddr, raddr); 7050 } else { 7051 (void) printf("%-10.10s %s %s\n", 7052 typetoname(psi->si_serv_type), laddr, raddr); 7053 } 7054 7055 i++; pids++; 7056 } while (i < psi->si_pn_cnt); 7057 7058 return (first); 7059 } 7060 7061 static char * 7062 typetoname(t_scalar_t type) 7063 { 7064 switch (type) { 7065 case T_CLTS: 7066 return ("dgram"); 7067 7068 case T_COTS: 7069 return ("stream"); 7070 7071 case T_COTS_ORD: 7072 return ("stream-ord"); 7073 7074 default: 7075 return (""); 7076 } 7077 }