]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/inet.c
network_cmds-356.9.tar.gz
[apple/network_cmds.git] / netstat.tproj / inet.c
1 /*
2 * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 ** @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26 */
27 /*
28 * Copyright (c) 1983, 1988, 1993, 1995
29 * The Regents of the University of California. All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
60 #ifndef lint
61 /*
62 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
63 */
64 static const char rcsid[] =
65 "$Id: inet.c,v 1.9 2006/04/04 04:36:27 lindak Exp $";
66 #endif /* not lint */
67
68 #include <sys/param.h>
69 #include <sys/queue.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <sys/sysctl.h>
73
74 #include <net/route.h>
75 #include <netinet/in.h>
76 #include <netinet/in_systm.h>
77 #include <netinet/ip.h>
78 #ifdef INET6
79 #include <netinet/ip6.h>
80 #endif /* INET6 */
81 #include <netinet/in_pcb.h>
82 #include <netinet/ip_icmp.h>
83 #include <netinet/icmp_var.h>
84 #include <netinet/igmp_var.h>
85 #include <netinet/ip_var.h>
86 #include <netinet/tcp.h>
87 #include <netinet/tcpip.h>
88 #include <netinet/tcp_seq.h>
89 #define TCPSTATES
90 #include <netinet/tcp_fsm.h>
91 #include <netinet/tcp_var.h>
92 #include <netinet/udp.h>
93 #include <netinet/udp_var.h>
94
95 #include <arpa/inet.h>
96 #include <err.h>
97 #include <errno.h>
98 #include <netdb.h>
99 #include <stdio.h>
100 #include <stdlib.h>
101 #include <stdint.h>
102 #include <string.h>
103 #include <unistd.h>
104 #include "netstat.h"
105
106 #define ROUNDUP64(a) \
107 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint64_t) - 1))) : sizeof(uint64_t))
108 #define ADVANCE64(x, n) (((char *)x) += ROUNDUP64(n))
109
110 char *inetname (struct in_addr *);
111 void inetprint (struct in_addr *, int, char *, int);
112 #ifdef INET6
113 extern void inet6print (struct in6_addr *, int, char *, int);
114 static int udp_done, tcp_done;
115 #endif /* INET6 */
116
117 #ifdef SRVCACHE
118 typedef struct __table_private table_t;
119
120 extern table_t *_nc_table_new(uint32_t n);
121 extern void _nc_table_free(table_t *tin);
122
123 extern void _nc_table_insert(table_t *t, const char *key, void *datum);
124 extern void *_nc_table_find(table_t *t, const char *key);
125 extern void _nc_table_delete(table_t *t, const char *key);
126
127 static table_t *_serv_cache = NULL;
128
129 /*
130 * Read and cache all known services
131 */
132 static void
133 _serv_cache_open()
134 {
135 struct servent *s;
136 char *key, *name, *test;
137
138 if (_serv_cache != NULL) return;
139
140 _serv_cache = _nc_table_new(8192);
141 setservent(0);
142
143 while (NULL != (s = getservent()))
144 {
145 if (s->s_name == NULL) continue;
146 key = NULL;
147 asprintf(&key, "%hu/%s", (unsigned short)ntohs(s->s_port), s->s_proto);
148 name = strdup(s->s_name);
149 test = _nc_table_find(_serv_cache, key);
150 if (test == NULL) _nc_table_insert(_serv_cache, key, name);
151 free(key);
152 }
153
154 endservent();
155 }
156
157 void
158 _serv_cache_close()
159 {
160 _nc_table_free(_serv_cache);
161 _serv_cache = NULL;
162 }
163
164 struct servent *
165 _serv_cache_getservbyport(int port, char *proto)
166 {
167 static struct servent s;
168 char *key;
169 unsigned short p;
170
171 _serv_cache_open();
172
173 memset(&s, 0, sizeof(struct servent));
174 asprintf(&key, "%u/%s", port, (proto == NULL) ? "udp" : proto);
175
176 s.s_name = _nc_table_find(_serv_cache, key);
177 free(key);
178 if (s.s_name == NULL) return NULL;
179
180 p = port;
181 s.s_port = htons(p);
182 s.s_proto = proto;
183 return &s;
184 }
185
186 #endif SRVCACHE
187
188 /*
189 * Print a summary of connections related to an Internet
190 * protocol. For TCP, also give state of connection.
191 * Listening processes (aflag) are suppressed unless the
192 * -a (all) flag is specified.
193 */
194 #if !TARGET_OS_EMBEDDED
195
196 struct xgen_n {
197 u_int32_t xgn_len; /* length of this structure */
198 u_int32_t xgn_kind; /* number of PCBs at this time */
199 };
200
201 #define ALL_XGN_KIND_INP (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_INPCB)
202 #define ALL_XGN_KIND_TCP (ALL_XGN_KIND_INP | XSO_TCPCB)
203
204 void
205 protopr(uint32_t proto, /* for sysctl version we pass proto # */
206 char *name, int af)
207 {
208 int istcp;
209 static int first = 1;
210 char *buf, *next;
211 const char *mibvar;
212 struct xinpgen *xig, *oxig;
213 struct xgen_n *xgn;
214 size_t len;
215 struct xtcpcb_n *tp = NULL;
216 struct xinpcb_n *inp = NULL;
217 struct xsocket_n *so = NULL;
218 struct xsockbuf_n *so_rcv = NULL;
219 struct xsockbuf_n *so_snd = NULL;
220 struct xsockstat_n *so_stat = NULL;
221 int which = 0;
222
223 istcp = 0;
224 switch (proto) {
225 case IPPROTO_TCP:
226 #ifdef INET6
227 if (tcp_done != 0)
228 return;
229 else
230 tcp_done = 1;
231 #endif
232 istcp = 1;
233 mibvar = "net.inet.tcp.pcblist_n";
234 break;
235 case IPPROTO_UDP:
236 #ifdef INET6
237 if (udp_done != 0)
238 return;
239 else
240 udp_done = 1;
241 #endif
242 mibvar = "net.inet.udp.pcblist_n";
243 break;
244 case IPPROTO_DIVERT:
245 mibvar = "net.inet.divert.pcblist_n";
246 break;
247 default:
248 mibvar = "net.inet.raw.pcblist_n";
249 break;
250 }
251 len = 0;
252 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
253 if (errno != ENOENT)
254 warn("sysctl: %s", mibvar);
255 return;
256 }
257 if ((buf = malloc(len)) == 0) {
258 warn("malloc %lu bytes", (u_long)len);
259 return;
260 }
261 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
262 warn("sysctl: %s", mibvar);
263 free(buf);
264 return;
265 }
266
267 /*
268 * Bail-out to avoid logic error in the loop below when
269 * there is in fact no more control block to process
270 */
271 if (len <= sizeof(struct xinpgen)) {
272 free(buf);
273 return;
274 }
275
276 oxig = xig = (struct xinpgen *)buf;
277 for (next = buf + ROUNDUP64(xig->xig_len); next < buf + len; next += ROUNDUP64(xgn->xgn_len)) {
278
279 xgn = (struct xgen_n*)next;
280 if (xgn->xgn_len <= sizeof(struct xinpgen))
281 break;
282
283 if ((which & xgn->xgn_kind) == 0) {
284 which |= xgn->xgn_kind;
285 switch (xgn->xgn_kind) {
286 case XSO_SOCKET:
287 so = (struct xsocket_n *)xgn;
288 break;
289 case XSO_RCVBUF:
290 so_rcv = (struct xsockbuf_n *)xgn;
291 break;
292 case XSO_SNDBUF:
293 so_snd = (struct xsockbuf_n *)xgn;
294 break;
295 case XSO_STATS:
296 so_stat = (struct xsockstat_n *)xgn;
297 break;
298 case XSO_INPCB:
299 inp = (struct xinpcb_n *)xgn;
300 break;
301 case XSO_TCPCB:
302 tp = (struct xtcpcb_n *)xgn;
303 break;
304 default:
305 printf("unexpected kind %d\n", xgn->xgn_kind);
306 break;
307 }
308 } else {
309 printf("got %d twice\n", xgn->xgn_kind);
310 }
311
312 if ((istcp && which != ALL_XGN_KIND_TCP) || (!istcp && which != ALL_XGN_KIND_INP))
313 continue;
314 which = 0;
315
316 /* Ignore sockets for protocols other than the desired one. */
317 if (so->xso_protocol != (int)proto)
318 continue;
319
320 /* Ignore PCBs which were freed during copyout. */
321 if (inp->inp_gencnt > oxig->xig_gen)
322 continue;
323
324 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
325 #ifdef INET6
326 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
327 #endif /* INET6 */
328 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
329 #ifdef INET6
330 && (inp->inp_vflag &
331 INP_IPV6) == 0
332 #endif /* INET6 */
333 ))
334 )
335 continue;
336
337 /*
338 * Local address is not an indication of listening socket or
339 * server sockey but just rather the socket has been bound.
340 * That why many UDP sockets were not displayed in the original code.
341 */
342 if (!aflag && istcp && tp->t_state <= TCPS_LISTEN)
343 continue;
344
345 if (Lflag && !so->so_qlimit)
346 continue;
347
348 if (first) {
349 if (!Lflag) {
350 printf("Active Internet connections");
351 if (aflag)
352 printf(" (including servers)");
353 } else
354 printf(
355 "Current listen queue sizes (qlen/incqlen/maxqlen)");
356 putchar('\n');
357 if (Aflag)
358 #if !TARGET_OS_EMBEDDED
359 printf("%-16.16s ", "Socket");
360 #else
361 printf("%-8.8s ", "Socket");
362 #endif
363 if (Lflag)
364 printf("%-14.14s %-22.22s\n",
365 "Listen", "Local Address");
366 else {
367 printf((Aflag && !Wflag) ?
368 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %-11.11s" :
369 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %-11.11s",
370 "Proto", "Recv-Q", "Send-Q",
371 "Local Address", "Foreign Address",
372 "(state)");
373 if (bflag > 0)
374 printf(" %10.10s %10.10s", "rxbytes", "txbytes");
375 if (prioflag >= 0)
376 printf(" %7.7s[%1d] %7.7s[%1d]", "rxbytes", prioflag, "txbytes", prioflag);
377 printf("\n");
378 }
379 first = 0;
380 }
381 if (Aflag) {
382 if (istcp)
383 #if !TARGET_OS_EMBEDDED
384 printf("%16lx ", (u_long)inp->inp_ppcb);
385 #else
386 printf("%8lx ", (u_long)inp->inp_ppcb);
387
388 #endif
389 else
390 #if !TARGET_OS_EMBEDDED
391 printf("%16lx ", (u_long)so->so_pcb);
392 #else
393 printf("%8lx ", (u_long)so->so_pcb);
394 #endif
395 }
396 if (Lflag) {
397 char buf[15];
398
399 snprintf(buf, 15, "%d/%d/%d", so->so_qlen,
400 so->so_incqlen, so->so_qlimit);
401 printf("%-14.14s ", buf);
402 }
403 else {
404 const char *vchar;
405
406 #ifdef INET6
407 if ((inp->inp_vflag & INP_IPV6) != 0)
408 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
409 ? "46" : "6 ";
410 else
411 #endif
412 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
413 ? "4 " : " ";
414
415 printf("%-3.3s%-2.2s %6u %6u ", name, vchar,
416 so_rcv->sb_cc,
417 so_snd->sb_cc);
418 }
419 if (nflag) {
420 if (inp->inp_vflag & INP_IPV4) {
421 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
422 name, 1);
423 if (!Lflag)
424 inetprint(&inp->inp_faddr,
425 (int)inp->inp_fport, name, 1);
426 }
427 #ifdef INET6
428 else if (inp->inp_vflag & INP_IPV6) {
429 inet6print(&inp->in6p_laddr,
430 (int)inp->inp_lport, name, 1);
431 if (!Lflag)
432 inet6print(&inp->in6p_faddr,
433 (int)inp->inp_fport, name, 1);
434 } /* else nothing printed now */
435 #endif /* INET6 */
436 } else if (inp->inp_flags & INP_ANONPORT) {
437 if (inp->inp_vflag & INP_IPV4) {
438 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
439 name, 1);
440 if (!Lflag)
441 inetprint(&inp->inp_faddr,
442 (int)inp->inp_fport, name, 0);
443 }
444 #ifdef INET6
445 else if (inp->inp_vflag & INP_IPV6) {
446 inet6print(&inp->in6p_laddr,
447 (int)inp->inp_lport, name, 1);
448 if (!Lflag)
449 inet6print(&inp->in6p_faddr,
450 (int)inp->inp_fport, name, 0);
451 } /* else nothing printed now */
452 #endif /* INET6 */
453 } else {
454 if (inp->inp_vflag & INP_IPV4) {
455 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
456 name, 0);
457 if (!Lflag)
458 inetprint(&inp->inp_faddr,
459 (int)inp->inp_fport, name,
460 inp->inp_lport !=
461 inp->inp_fport);
462 }
463 #ifdef INET6
464 else if (inp->inp_vflag & INP_IPV6) {
465 inet6print(&inp->in6p_laddr,
466 (int)inp->inp_lport, name, 0);
467 if (!Lflag)
468 inet6print(&inp->in6p_faddr,
469 (int)inp->inp_fport, name,
470 inp->inp_lport !=
471 inp->inp_fport);
472 } /* else nothing printed now */
473 #endif /* INET6 */
474 }
475 if (istcp && !Lflag) {
476 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
477 printf("%-11d", tp->t_state);
478 else {
479 printf("%-11s", tcpstates[tp->t_state]);
480 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
481 /* Show T/TCP `hidden state' */
482 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
483 putchar('*');
484 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
485 }
486 }
487 if (!istcp)
488 printf("%-11s", " ");
489 if (bflag > 0) {
490 int i;
491 u_int64_t rxbytes = 0;
492 u_int64_t txbytes = 0;
493
494 for (i = 0; i < SO_TC_MAX; i++) {
495 rxbytes += so_stat->xst_tc_stats[i].rxbytes;
496 txbytes += so_stat->xst_tc_stats[i].txbytes;
497 }
498
499 printf(" %10llu %10llu", rxbytes, txbytes);
500 }
501 if (prioflag >= 0) {
502 printf(" %10llu %10llu",
503 prioflag < SO_TC_MAX ? so_stat->xst_tc_stats[prioflag].rxbytes : 0,
504 prioflag < SO_TC_MAX ? so_stat->xst_tc_stats[prioflag].txbytes : 0);
505 }
506 putchar('\n');
507 }
508 if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
509 if (oxig->xig_count > xig->xig_count) {
510 printf("Some %s sockets may have been deleted.\n",
511 name);
512 } else if (oxig->xig_count < xig->xig_count) {
513 printf("Some %s sockets may have been created.\n",
514 name);
515 } else {
516 printf("Some %s sockets may have been created or deleted",
517 name);
518 }
519 }
520 free(buf);
521 }
522
523 #else /* TARGET_OS_EMBEDDED */
524
525 void
526 protopr(uint32_t proto, /* for sysctl version we pass proto # */
527 char *name, int af)
528 {
529 int istcp;
530 static int first = 1;
531 char *buf;
532 const char *mibvar;
533 struct xinpgen *xig, *oxig;
534 struct tcpcb *tp = NULL;
535 struct inpcb *inp;
536 struct xsocket *so;
537 size_t len;
538
539 istcp = 0;
540 switch (proto) {
541 case IPPROTO_TCP:
542 #ifdef INET6
543 if (tcp_done != 0)
544 return;
545 else
546 tcp_done = 1;
547 #endif
548 istcp = 1;
549 mibvar = "net.inet.tcp.pcblist";
550 break;
551 case IPPROTO_UDP:
552 #ifdef INET6
553 if (udp_done != 0)
554 return;
555 else
556 udp_done = 1;
557 #endif
558 mibvar = "net.inet.udp.pcblist";
559 break;
560 case IPPROTO_DIVERT:
561 mibvar = "net.inet.divert.pcblist";
562 break;
563 default:
564 mibvar = "net.inet.raw.pcblist";
565 break;
566 }
567 len = 0;
568 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
569 if (errno != ENOENT)
570 warn("sysctl: %s", mibvar);
571 return;
572 }
573 if ((buf = malloc(len)) == 0) {
574 warn("malloc %lu bytes", (u_long)len);
575 return;
576 }
577 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
578 warn("sysctl: %s", mibvar);
579 free(buf);
580 return;
581 }
582
583 /*
584 * Bail-out to avoid logic error in the loop below when
585 * there is in fact no more control block to process
586 */
587 if (len <= sizeof(struct xinpgen)) {
588 free(buf);
589 return;
590 }
591
592 oxig = xig = (struct xinpgen *)buf;
593 for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
594 xig->xig_len > sizeof(struct xinpgen);
595 xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
596 if (istcp) {
597 tp = &((struct xtcpcb *)xig)->xt_tp;
598 inp = &((struct xtcpcb *)xig)->xt_inp;
599 so = &((struct xtcpcb *)xig)->xt_socket;
600 } else {
601 inp = &((struct xinpcb *)xig)->xi_inp;
602 so = &((struct xinpcb *)xig)->xi_socket;
603 }
604
605 /* Ignore sockets for protocols other than the desired one. */
606 if (so->xso_protocol != (int)proto)
607 continue;
608
609 /* Ignore PCBs which were freed during copyout. */
610 if (inp->inp_gencnt > oxig->xig_gen)
611 continue;
612
613 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
614 #ifdef INET6
615 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
616 #endif /* INET6 */
617 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
618 #ifdef INET6
619 && (inp->inp_vflag &
620 INP_IPV6) == 0
621 #endif /* INET6 */
622 ))
623 )
624 continue;
625
626 /*
627 * Local address is not an indication of listening socket or
628 * server sockey but just rather the socket has been bound.
629 * That why many UDP sockets were not displayed in the original code.
630 */
631 if (!aflag && istcp && tp->t_state <= TCPS_LISTEN)
632 continue;
633
634 if (Lflag && !so->so_qlimit)
635 continue;
636
637 if (first) {
638 if (!Lflag) {
639 printf("Active Internet connections");
640 if (aflag)
641 printf(" (including servers)");
642 } else
643 printf(
644 "Current listen queue sizes (qlen/incqlen/maxqlen)");
645 putchar('\n');
646 if (Aflag)
647 printf("%-8.8s ", "Socket");
648 if (Lflag)
649 printf("%-14.14s %-22.22s\n",
650 "Listen", "Local Address");
651 else
652 printf((Aflag && !Wflag) ?
653 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
654 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
655 "Proto", "Recv-Q", "Send-Q",
656 "Local Address", "Foreign Address",
657 "(state)");
658 first = 0;
659 }
660 if (Aflag) {
661 if (istcp)
662 printf("%8lx ", (u_long)inp->inp_ppcb);
663 else
664 printf("%8lx ", (u_long)so->so_pcb);
665 }
666 if (Lflag) {
667 char buf[15];
668
669 snprintf(buf, 15, "%d/%d/%d", so->so_qlen,
670 so->so_incqlen, so->so_qlimit);
671 printf("%-14.14s ", buf);
672 }
673 else {
674 const char *vchar;
675
676 #ifdef INET6
677 if ((inp->inp_vflag & INP_IPV6) != 0)
678 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
679 ? "46" : "6 ";
680 else
681 #endif
682 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
683 ? "4 " : " ";
684
685 printf("%-3.3s%-2.2s %6u %6u ", name, vchar,
686 so->so_rcv.sb_cc,
687 so->so_snd.sb_cc);
688 }
689 if (nflag) {
690 if (inp->inp_vflag & INP_IPV4) {
691 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
692 name, 1);
693 if (!Lflag)
694 inetprint(&inp->inp_faddr,
695 (int)inp->inp_fport, name, 1);
696 }
697 #ifdef INET6
698 else if (inp->inp_vflag & INP_IPV6) {
699 inet6print(&inp->in6p_laddr,
700 (int)inp->inp_lport, name, 1);
701 if (!Lflag)
702 inet6print(&inp->in6p_faddr,
703 (int)inp->inp_fport, name, 1);
704 } /* else nothing printed now */
705 #endif /* INET6 */
706 } else if (inp->inp_flags & INP_ANONPORT) {
707 if (inp->inp_vflag & INP_IPV4) {
708 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
709 name, 1);
710 if (!Lflag)
711 inetprint(&inp->inp_faddr,
712 (int)inp->inp_fport, name, 0);
713 }
714 #ifdef INET6
715 else if (inp->inp_vflag & INP_IPV6) {
716 inet6print(&inp->in6p_laddr,
717 (int)inp->inp_lport, name, 1);
718 if (!Lflag)
719 inet6print(&inp->in6p_faddr,
720 (int)inp->inp_fport, name, 0);
721 } /* else nothing printed now */
722 #endif /* INET6 */
723 } else {
724 if (inp->inp_vflag & INP_IPV4) {
725 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
726 name, 0);
727 if (!Lflag)
728 inetprint(&inp->inp_faddr,
729 (int)inp->inp_fport, name,
730 inp->inp_lport !=
731 inp->inp_fport);
732 }
733 #ifdef INET6
734 else if (inp->inp_vflag & INP_IPV6) {
735 inet6print(&inp->in6p_laddr,
736 (int)inp->inp_lport, name, 0);
737 if (!Lflag)
738 inet6print(&inp->in6p_faddr,
739 (int)inp->inp_fport, name,
740 inp->inp_lport !=
741 inp->inp_fport);
742 } /* else nothing printed now */
743 #endif /* INET6 */
744 }
745 if (istcp && !Lflag) {
746 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
747 printf("%d", tp->t_state);
748 else {
749 printf("%s", tcpstates[tp->t_state]);
750 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
751 /* Show T/TCP `hidden state' */
752 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
753 putchar('*');
754 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
755 }
756 }
757 putchar('\n');
758 }
759 if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
760 if (oxig->xig_count > xig->xig_count) {
761 printf("Some %s sockets may have been deleted.\n",
762 name);
763 } else if (oxig->xig_count < xig->xig_count) {
764 printf("Some %s sockets may have been created.\n",
765 name);
766 } else {
767 printf("Some %s sockets may have been created or deleted",
768 name);
769 }
770 }
771 free(buf);
772 }
773 #endif /* TARGET_OS_EMBEDDED */
774
775 /*
776 * Dump TCP statistics structure.
777 */
778 void
779 tcp_stats(uint32_t off , char *name, int af )
780 {
781 static struct tcpstat ptcpstat;
782 struct tcpstat tcpstat;
783 size_t len = sizeof tcpstat;
784
785 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
786 warn("sysctl: net.inet.tcp.stats");
787 return;
788 }
789
790 #ifdef INET6
791 if (tcp_done != 0 && interval == 0)
792 return;
793 else
794 tcp_done = 1;
795 #endif
796
797 printf ("%s:\n", name);
798
799 #define TCPDIFF(f) (tcpstat.f - ptcpstat.f)
800 #define p(f, m) if (TCPDIFF(f) || sflag <= 1) \
801 printf(m, TCPDIFF(f), plural(TCPDIFF(f)))
802 #define p1a(f, m) if (TCPDIFF(f) || sflag <= 1) \
803 printf(m, TCPDIFF(f))
804 #define p2(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \
805 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2), plural(TCPDIFF(f2)))
806 #define p2a(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \
807 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2))
808 #define p3(f, m) if (TCPDIFF(f) || sflag <= 1) \
809 printf(m, TCPDIFF(f), plurales(TCPDIFF(f)))
810
811 p(tcps_sndtotal, "\t%u packet%s sent\n");
812 p2(tcps_sndpack,tcps_sndbyte,
813 "\t\t%u data packet%s (%u byte%s)\n");
814 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
815 "\t\t%u data packet%s (%u byte%s) retransmitted\n");
816 p(tcps_mturesent, "\t\t%u resend%s initiated by MTU discovery\n");
817 p2a(tcps_sndacks, tcps_delack,
818 "\t\t%u ack-only packet%s (%u delayed)\n");
819 p(tcps_sndurg, "\t\t%u URG only packet%s\n");
820 p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
821 p(tcps_sndwinup, "\t\t%u window update packet%s\n");
822 p(tcps_sndctrl, "\t\t%u control packet%s\n");
823 p(tcps_rcvtotal, "\t%u packet%s received\n");
824 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %u byte%s)\n");
825 p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
826 p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n");
827 p2(tcps_rcvpack, tcps_rcvbyte,
828 "\t\t%u packet%s (%u byte%s) received in-sequence\n");
829 p2(tcps_rcvduppack, tcps_rcvdupbyte,
830 "\t\t%u completely duplicate packet%s (%u byte%s)\n");
831 p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
832 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
833 "\t\t%u packet%s with some dup. data (%u byte%s duped)\n");
834 p2(tcps_rcvoopack, tcps_rcvoobyte,
835 "\t\t%u out-of-order packet%s (%u byte%s)\n");
836 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
837 "\t\t%u packet%s (%u byte%s) of data after window\n");
838 p(tcps_rcvwinprobe, "\t\t%u window probe%s\n");
839 p(tcps_rcvwinupd, "\t\t%u window update packet%s\n");
840 p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n");
841 p(tcps_badrst, "\t\t%u bad reset%s\n");
842 p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n");
843 p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n");
844 p1a(tcps_rcvshort, "\t\t%u discarded because packet too short\n");
845 p(tcps_connattempt, "\t%u connection request%s\n");
846 p(tcps_accepts, "\t%u connection accept%s\n");
847 p(tcps_badsyn, "\t%u bad connection attempt%s\n");
848 p(tcps_listendrop, "\t%u listen queue overflow%s\n");
849 p(tcps_connects, "\t%u connection%s established (including accepts)\n");
850 p2(tcps_closed, tcps_drops,
851 "\t%u connection%s closed (including %u drop%s)\n");
852 p(tcps_cachedrtt, "\t\t%u connection%s updated cached RTT on close\n");
853 p(tcps_cachedrttvar,
854 "\t\t%u connection%s updated cached RTT variance on close\n");
855 p(tcps_cachedssthresh,
856 "\t\t%u connection%s updated cached ssthresh on close\n");
857 p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
858 p2(tcps_rttupdated, tcps_segstimed,
859 "\t%u segment%s updated rtt (of %u attempt%s)\n");
860 p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
861 p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
862 p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n");
863 p(tcps_persisttimeo, "\t%u persist timeout%s\n");
864 p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n");
865 p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
866 p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
867 p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
868 p(tcps_predack, "\t%u correct ACK header prediction%s\n");
869 p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
870 #ifdef TCP_MAX_SACK
871 /* TCP_MAX_SACK indicates the header has the SACK structures */
872 p(tcps_sack_recovery_episode, "\t%u SACK recovery episode%s\n");
873 p(tcps_sack_rexmits,
874 "\t%u segment rexmit%s in SACK recovery episodes\n");
875 p(tcps_sack_rexmit_bytes,
876 "\t%u byte rexmit%s in SACK recovery episodes\n");
877 p(tcps_sack_rcv_blocks,
878 "\t%u SACK option%s (SACK blocks) received\n");
879 p(tcps_sack_send_blocks, "\t%u SACK option%s (SACK blocks) sent\n");
880 p1a(tcps_sack_sboverflow, "\t%u SACK scoreboard overflow\n");
881 #endif /* TCP_MAX_SACK */
882
883 if (interval > 0)
884 bcopy(&tcpstat, &ptcpstat, len);
885
886 #undef TCPDIFF
887 #undef p
888 #undef p1a
889 #undef p2
890 #undef p2a
891 #undef p3
892 }
893
894 /*
895 * Dump UDP statistics structure.
896 */
897 void
898 udp_stats(uint32_t off , char *name, int af )
899 {
900 static struct udpstat pudpstat;
901 struct udpstat udpstat;
902 size_t len = sizeof udpstat;
903 uint32_t delivered;
904
905 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
906 warn("sysctl: net.inet.udp.stats");
907 return;
908 }
909
910 #ifdef INET6
911 if (udp_done != 0 && interval == 0)
912 return;
913 else
914 udp_done = 1;
915 #endif
916
917 printf("%s:\n", name);
918
919 #define UDPDIFF(f) (udpstat.f - pudpstat.f)
920 #define p(f, m) if (UDPDIFF(f) || sflag <= 1) \
921 printf(m, UDPDIFF(f), plural(UDPDIFF(f)))
922 #define p1a(f, m) if (UDPDIFF(f) || sflag <= 1) \
923 printf(m, UDPDIFF(f))
924 p(udps_ipackets, "\t%u datagram%s received\n");
925 p1a(udps_hdrops, "\t%u with incomplete header\n");
926 p1a(udps_badlen, "\t%u with bad data length field\n");
927 p1a(udps_badsum, "\t%u with bad checksum\n");
928 p1a(udps_noport, "\t%u dropped due to no socket\n");
929 p(udps_noportbcast,
930 "\t%u broadcast/multicast datagram%s dropped due to no socket\n");
931 p1a(udps_fullsock, "\t%u dropped due to full socket buffers\n");
932 p1a(udpps_pcbhashmiss, "\t%u not for hashed pcb\n");
933 delivered = UDPDIFF(udps_ipackets) -
934 UDPDIFF(udps_hdrops) -
935 UDPDIFF(udps_badlen) -
936 UDPDIFF(udps_badsum) -
937 UDPDIFF(udps_noport) -
938 UDPDIFF(udps_noportbcast) -
939 UDPDIFF(udps_fullsock);
940 if (delivered || sflag <= 1)
941 printf("\t%u delivered\n", delivered);
942 p(udps_opackets, "\t%u datagram%s output\n");
943
944 if (interval > 0)
945 bcopy(&udpstat, &pudpstat, len);
946
947 #undef UDPDIFF
948 #undef p
949 #undef p1a
950 }
951
952 /*
953 * Dump IP statistics structure.
954 */
955 void
956 ip_stats(uint32_t off , char *name, int af )
957 {
958 static struct ipstat pipstat;
959 struct ipstat ipstat;
960 size_t len = sizeof ipstat;
961
962 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) {
963 warn("sysctl: net.inet.ip.stats");
964 return;
965 }
966
967 printf("%s:\n", name);
968
969 #define IPDIFF(f) (ipstat.f - pipstat.f)
970 #define p(f, m) if (IPDIFF(f) || sflag <= 1) \
971 printf(m, IPDIFF(f), plural(IPDIFF(f)))
972 #define p1a(f, m) if (IPDIFF(f) || sflag <= 1) \
973 printf(m, IPDIFF(f))
974
975 p(ips_total, "\t%u total packet%s received\n");
976 p(ips_badsum, "\t%u bad header checksum%s\n");
977 p1a(ips_toosmall, "\t%u with size smaller than minimum\n");
978 p1a(ips_tooshort, "\t%u with data size < data length\n");
979 p1a(ips_toolong, "\t%u with ip length > max ip packet size\n");
980 p1a(ips_badhlen, "\t%u with header length < data size\n");
981 p1a(ips_badlen, "\t%u with data length < header length\n");
982 p1a(ips_badoptions, "\t%u with bad options\n");
983 p1a(ips_badvers, "\t%u with incorrect version number\n");
984 p(ips_fragments, "\t%u fragment%s received\n");
985 p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n");
986 p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n");
987 p(ips_reassembled, "\t%u packet%s reassembled ok\n");
988 p(ips_delivered, "\t%u packet%s for this host\n");
989 p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n");
990 p(ips_forward, "\t%u packet%s forwarded");
991 p(ips_fastforward, " (%u packet%s fast forwarded)");
992 if (IPDIFF(ips_forward) || sflag <= 1)
993 putchar('\n');
994 p(ips_cantforward, "\t%u packet%s not forwardable\n");
995 p(ips_notmember,
996 "\t%u packet%s received for unknown multicast group\n");
997 p(ips_redirectsent, "\t%u redirect%s sent\n");
998 p(ips_localout, "\t%u packet%s sent from this host\n");
999 p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n");
1000 p(ips_odropped,
1001 "\t%u output packet%s dropped due to no bufs, etc.\n");
1002 p(ips_noroute, "\t%u output packet%s discarded due to no route\n");
1003 p(ips_fragmented, "\t%u output datagram%s fragmented\n");
1004 p(ips_ofragments, "\t%u fragment%s created\n");
1005 p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n");
1006 p(ips_nogif, "\t%u tunneling packet%s that can't find gif\n");
1007 p(ips_badaddr, "\t%u datagram%s with bad address in header\n");
1008 p(ips_pktdropcntrl, "\t%u packet%s dropped due to no bufs for control data\n");
1009
1010 if (interval > 0)
1011 bcopy(&ipstat, &pipstat, len);
1012
1013 #undef IPDIFF
1014 #undef p
1015 #undef p1a
1016 }
1017
1018 static char *icmpnames[] = {
1019 "echo reply",
1020 "#1",
1021 "#2",
1022 "destination unreachable",
1023 "source quench",
1024 "routing redirect",
1025 "#6",
1026 "#7",
1027 "echo",
1028 "router advertisement",
1029 "router solicitation",
1030 "time exceeded",
1031 "parameter problem",
1032 "time stamp",
1033 "time stamp reply",
1034 "information request",
1035 "information request reply",
1036 "address mask request",
1037 "address mask reply",
1038 };
1039
1040 /*
1041 * Dump ICMP statistics.
1042 */
1043 void
1044 icmp_stats(uint32_t off , char *name, int af )
1045 {
1046 static struct icmpstat picmpstat;
1047 struct icmpstat icmpstat;
1048 int i, first;
1049 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
1050 size_t len;
1051
1052 mib[0] = CTL_NET;
1053 mib[1] = PF_INET;
1054 mib[2] = IPPROTO_ICMP;
1055 mib[3] = ICMPCTL_STATS;
1056
1057 len = sizeof icmpstat;
1058 memset(&icmpstat, 0, len);
1059 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
1060 return; /* XXX should complain, but not traditional */
1061
1062 printf("%s:\n", name);
1063
1064 #define ICMPDIFF(f) (icmpstat.f - picmpstat.f)
1065 #define p(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1066 printf(m, ICMPDIFF(f), plural(ICMPDIFF(f)))
1067 #define p1a(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1068 printf(m, ICMPDIFF(f))
1069
1070 p(icps_error, "\t%u call%s to icmp_error\n");
1071 p(icps_oldicmp,
1072 "\t%u error%s not generated 'cuz old message was icmp\n");
1073 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
1074 if (ICMPDIFF(icps_outhist[i]) != 0) {
1075 if (first) {
1076 printf("\tOutput histogram:\n");
1077 first = 0;
1078 }
1079 printf("\t\t%s: %u\n", icmpnames[i],
1080 ICMPDIFF(icps_outhist[i]));
1081 }
1082 p(icps_badcode, "\t%u message%s with bad code fields\n");
1083 p(icps_tooshort, "\t%u message%s < minimum length\n");
1084 p(icps_checksum, "\t%u bad checksum%s\n");
1085 p(icps_badlen, "\t%u message%s with bad length\n");
1086 p1a(icps_bmcastecho, "\t%u multicast echo requests ignored\n");
1087 p1a(icps_bmcasttstamp, "\t%u multicast timestamp requests ignored\n");
1088 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
1089 if (ICMPDIFF(icps_inhist[i]) != 0) {
1090 if (first) {
1091 printf("\tInput histogram:\n");
1092 first = 0;
1093 }
1094 printf("\t\t%s: %u\n", icmpnames[i],
1095 ICMPDIFF(icps_inhist[i]));
1096 }
1097 p(icps_reflect, "\t%u message response%s generated\n");
1098
1099 #undef ICMPDIFF
1100 #undef p
1101 #undef p1a
1102 mib[3] = ICMPCTL_MASKREPL;
1103 len = sizeof i;
1104 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
1105 return;
1106 printf("\tICMP address mask responses are %sabled\n",
1107 i ? "en" : "dis");
1108
1109 if (interval > 0)
1110 bcopy(&icmpstat, &picmpstat, sizeof (icmpstat));
1111 }
1112
1113 /*
1114 * Dump IGMP statistics structure.
1115 */
1116 void
1117 igmp_stats(uint32_t off , char *name, int af )
1118 {
1119 static struct igmpstat_v3 pigmpstat;
1120 struct igmpstat_v3 igmpstat;
1121 size_t len = sizeof igmpstat;
1122
1123 if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) {
1124 warn("sysctl: net.inet.igmp.v3stats");
1125 return;
1126 }
1127
1128 if (igmpstat.igps_version != IGPS_VERSION_3) {
1129 warnx("%s: version mismatch (%d != %d)", __func__,
1130 igmpstat.igps_version, IGPS_VERSION_3);
1131 }
1132 if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
1133 warnx("%s: size mismatch (%d != %d)", __func__,
1134 igmpstat.igps_len, IGPS_VERSION3_LEN);
1135 }
1136
1137 printf("%s:\n", name);
1138
1139 #define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f))
1140 #define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
1141 printf(m, IGMPDIFF(f), plural(IGMPDIFF(f)))
1142 #define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
1143 printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y")
1144
1145 p64(igps_rcv_total, "\t%ju message%s received\n");
1146 p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1147 p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
1148 p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1149 py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
1150 py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
1151 py64(igps_rcv_badqueries,
1152 "\t%ju membership quer%s received with invalid field(s)\n");
1153 py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
1154 py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
1155 py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
1156 py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
1157 p64(igps_rcv_reports, "\t%ju membership report%s received\n");
1158 p64(igps_rcv_badreports,
1159 "\t%ju membership report%s received with invalid field(s)\n");
1160 p64(igps_rcv_ourreports,
1161 "\t%ju membership report%s received for groups to which we belong\n");
1162 p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
1163 p64(igps_snd_reports, "\t%ju membership report%s sent\n");
1164
1165 if (interval > 0)
1166 bcopy(&igmpstat, &pigmpstat, len);
1167
1168 #undef IGMPDIFF
1169 #undef p64
1170 #undef py64
1171 }
1172
1173 /*
1174 * Pretty print an Internet address (net address + port).
1175 */
1176 void
1177 inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
1178 {
1179 struct servent *sp = 0;
1180 char line[80], *cp;
1181 int width;
1182
1183 if (Wflag)
1184 snprintf(line, sizeof(line), "%s.", inetname(in));
1185 else
1186 snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
1187 cp = index(line, '\0');
1188 if (!numeric_port && port)
1189 #ifdef _SERVICE_CACHE_
1190 sp = _serv_cache_getservbyport(port, proto);
1191 #else
1192 sp = getservbyport((int)port, proto);
1193 #endif
1194 if (sp || port == 0)
1195 snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*");
1196 else
1197 snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port));
1198 width = (Aflag && !Wflag) ? 18 : 22;
1199 if (Wflag)
1200 printf("%-*s ", width, line);
1201 else
1202 printf("%-*.*s ", width, width, line);
1203 }
1204
1205 /*
1206 * Construct an Internet address representation.
1207 * If the nflag has been supplied, give
1208 * numeric value, otherwise try for symbolic name.
1209 */
1210 char *
1211 inetname(struct in_addr *inp)
1212 {
1213 register char *cp;
1214 static char line[MAXHOSTNAMELEN];
1215 struct hostent *hp;
1216 struct netent *np;
1217
1218 cp = 0;
1219 if (!nflag && inp->s_addr != INADDR_ANY) {
1220 int net = inet_netof(*inp);
1221 int lna = inet_lnaof(*inp);
1222
1223 if (lna == INADDR_ANY) {
1224 np = getnetbyaddr(net, AF_INET);
1225 if (np)
1226 cp = np->n_name;
1227 }
1228 if (cp == 0) {
1229 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
1230 if (hp) {
1231 cp = hp->h_name;
1232 //### trimdomain(cp, strlen(cp));
1233 }
1234 }
1235 }
1236 if (inp->s_addr == INADDR_ANY)
1237 strlcpy(line, "*", sizeof(line));
1238 else if (cp) {
1239 strncpy(line, cp, sizeof(line) - 1);
1240 line[sizeof(line) - 1] = '\0';
1241 } else {
1242 inp->s_addr = ntohl(inp->s_addr);
1243 #define C(x) ((u_int)((x) & 0xff))
1244 snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24),
1245 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
1246 }
1247 return (line);
1248 }