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