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