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