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