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