X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/8052502f69480852fa9ccecf3788125a3d1c6aaf..b8dff1509d79abed3d82c4d8bfb2e73c7d0f1d1a:/netstat.tproj/inet.c diff --git a/netstat.tproj/inet.c b/netstat.tproj/inet.c index 37d869f..4942fc0 100644 --- a/netstat.tproj/inet.c +++ b/netstat.tproj/inet.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; */ static const char rcsid[] = - "$Id: inet.c,v 1.2 2001/07/31 05:54:11 wsanchez Exp $"; + "$Id: inet.c,v 1.9 2006/04/04 04:36:27 lindak Exp $"; #endif /* not lint */ #include @@ -44,12 +44,14 @@ static const char rcsid[] = #include #include #include -#include #include #include #include #include +#ifdef INET6 +#include +#endif /* INET6 */ #include #include #include @@ -60,9 +62,7 @@ static const char rcsid[] = #include #define TCPSTATES #include -#include #include -#include #include #include @@ -72,13 +72,89 @@ static const char rcsid[] = #include #include #include +#include #include #include #include "netstat.h" -char *inetname __P((struct in_addr *)); -void inetprint __P((struct in_addr *, int, char *, int)); +char *inetname (struct in_addr *); +void inetprint (struct in_addr *, int, char *, int); +#ifdef INET6 +extern void inet6print (struct in6_addr *, int, char *, int); +static int udp_done, tcp_done; +#endif /* INET6 */ + +#ifdef SRVCACHE +typedef struct __table_private table_t; + +extern table_t *_nc_table_new(uint32_t n); +extern void _nc_table_free(table_t *tin); + +extern void _nc_table_insert(table_t *t, const char *key, void *datum); +extern void *_nc_table_find(table_t *t, const char *key); +extern void _nc_table_delete(table_t *t, const char *key); + +static table_t *_serv_cache = NULL; +/* + * Read and cache all known services + */ +static void +_serv_cache_open() +{ + struct servent *s; + char *key, *name, *test; + + if (_serv_cache != NULL) return; + + _serv_cache = _nc_table_new(8192); + setservent(0); + + while (NULL != (s = getservent())) + { + if (s->s_name == NULL) continue; + key = NULL; + asprintf(&key, "%hu/%s", (unsigned short)ntohs(s->s_port), s->s_proto); + name = strdup(s->s_name); + test = _nc_table_find(_serv_cache, key); + if (test == NULL) _nc_table_insert(_serv_cache, key, name); + free(key); + } + + endservent(); +} + +void +_serv_cache_close() +{ + _nc_table_free(_serv_cache); + _serv_cache = NULL; +} + +struct servent * +_serv_cache_getservbyport(int port, char *proto) +{ + static struct servent s; + char *key; + unsigned short p; + + _serv_cache_open(); + + memset(&s, 0, sizeof(struct servent)); + asprintf(&key, "%u/%s", port, (proto == NULL) ? "udp" : proto); + + s.s_name = _nc_table_find(_serv_cache, key); + free(key); + if (s.s_name == NULL) return NULL; + + p = port; + s.s_port = htons(p); + s.s_proto = proto; + return &s; +} + +#endif SRVCACHE + /* * Print a summary of connections related to an Internet * protocol. For TCP, also give state of connection. @@ -86,15 +162,14 @@ void inetprint __P((struct in_addr *, int, char *, int)); * -a (all) flag is specified. */ void -protopr(proto, name) - u_long proto; /* for sysctl version we pass proto # */ - char *name; +protopr(u_long proto, /* for sysctl version we pass proto # */ + char *name, int af) { int istcp; static int first = 1; char *buf; const char *mibvar; - struct tcpcb *tp; + struct tcpcb *tp = NULL; struct inpcb *inp; struct xinpgen *xig, *oxig; struct xsocket *so; @@ -103,10 +178,22 @@ protopr(proto, name) istcp = 0; switch (proto) { case IPPROTO_TCP: +#ifdef INET6 + if (tcp_done != 0) + return; + else + tcp_done = 1; +#endif istcp = 1; mibvar = "net.inet.tcp.pcblist"; break; case IPPROTO_UDP: +#ifdef INET6 + if (udp_done != 0) + return; + else + udp_done = 1; +#endif mibvar = "net.inet.udp.pcblist"; break; case IPPROTO_DIVERT: @@ -121,7 +208,7 @@ protopr(proto, name) if (errno != ENOENT) warn("sysctl: %s", mibvar); return; - } + } if ((buf = malloc(len)) == 0) { warn("malloc %lu bytes", (u_long)len); return; @@ -131,7 +218,16 @@ protopr(proto, name) free(buf); return; } - + + /* + * Bail-out to avoid logic error in the loop below when + * there is in fact no more control block to process + */ + if (len <= sizeof(struct xinpgen)) { + free(buf); + return; + } + oxig = xig = (struct xinpgen *)buf; for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); xig->xig_len > sizeof(struct xinpgen); @@ -146,59 +242,170 @@ protopr(proto, name) } /* Ignore sockets for protocols other than the desired one. */ - if (so->xso_protocol != proto) + if (so->xso_protocol != (int)proto) continue; /* Ignore PCBs which were freed during copyout. */ if (inp->inp_gencnt > oxig->xig_gen) continue; - if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY) + if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) +#ifdef INET6 + || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) +#endif /* INET6 */ + || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 +#ifdef INET6 + && (inp->inp_vflag & + INP_IPV6) == 0 +#endif /* INET6 */ + )) + ) continue; - - if (first) { - printf("Active Internet connections"); - if (aflag) - printf(" (including servers)"); +#ifdef __APPLE__ + /* + * Local address is not an indication of listening socket or + * server sockey but just rather the socket has been bound. + * That why many UDP sockets were not displayed in the original code. + */ + if (!aflag && istcp && tp->t_state <= TCPS_LISTEN) + continue; +#else + if (!aflag && + ( + (af == AF_INET && + inet_lnaof(inp->inp_laddr) == INADDR_ANY) +#ifdef INET6 + || (af == AF_INET6 && + IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) +#endif /* INET6 */ + || (af == AF_UNSPEC && + (((inp->inp_vflag & INP_IPV4) != 0 && + inet_lnaof(inp->inp_laddr) == INADDR_ANY) +#ifdef INET6 + || ((inp->inp_vflag & INP_IPV6) != 0 && + IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) +#endif + )) + )) + continue; +#endif + + if (Lflag && !so->so_qlimit) + continue; + + if (first) { + if (!Lflag) { + printf("Active Internet connections"); + if (aflag) + printf(" (including servers)"); + } else + printf( + "Current listen queue sizes (qlen/incqlen/maxqlen)"); putchar('\n'); if (Aflag) printf("%-8.8s ", "Socket"); - printf(Aflag ? - "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : - "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", - "Proto", "Recv-Q", "Send-Q", - "Local Address", "Foreign Address", "(state)"); + if (Lflag) + printf("%-14.14s %-22.22s\n", + "Listen", "Local Address"); + else + printf((Aflag && !Wflag) ? + "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : + "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Foreign Address", + "(state)"); first = 0; } - if (Aflag) { - if (istcp) - printf("%8lx ", (u_long)inp->inp_ppcb); + if (Aflag) { + if (istcp) + printf("%8lx ", (u_long)inp->inp_ppcb); + else + printf("%8lx ", (u_long)so->so_pcb); + } + if (Lflag) { + char buf[15]; + + snprintf(buf, 15, "%d/%d/%d", so->so_qlen, + so->so_incqlen, so->so_qlimit); + printf("%-14.14s ", buf); + } + else { + const char *vchar; + +#ifdef INET6 + if ((inp->inp_vflag & INP_IPV6) != 0) + vchar = ((inp->inp_vflag & INP_IPV4) != 0) + ? "46" : "6 "; else - printf("%8lx ", (u_long)so->so_pcb); +#endif + vchar = ((inp->inp_vflag & INP_IPV4) != 0) + ? "4 " : " "; + + printf("%-3.3s%-2.2s %6u %6u ", name, vchar, + so->so_rcv.sb_cc, + so->so_snd.sb_cc); } - printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc, - so->so_snd.sb_cc); if (nflag) { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 1); - inetprint(&inp->inp_faddr, (int)inp->inp_fport, - name, 1); + if (inp->inp_vflag & INP_IPV4) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 1); + if (!Lflag) + inetprint(&inp->inp_faddr, + (int)inp->inp_fport, name, 1); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + inet6print(&inp->in6p_laddr, + (int)inp->inp_lport, name, 1); + if (!Lflag) + inet6print(&inp->in6p_faddr, + (int)inp->inp_fport, name, 1); + } /* else nothing printed now */ +#endif /* INET6 */ } else if (inp->inp_flags & INP_ANONPORT) { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 1); - inetprint(&inp->inp_faddr, (int)inp->inp_fport, - name, 0); + if (inp->inp_vflag & INP_IPV4) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 1); + if (!Lflag) + inetprint(&inp->inp_faddr, + (int)inp->inp_fport, name, 0); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + inet6print(&inp->in6p_laddr, + (int)inp->inp_lport, name, 1); + if (!Lflag) + inet6print(&inp->in6p_faddr, + (int)inp->inp_fport, name, 0); + } /* else nothing printed now */ +#endif /* INET6 */ } else { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 0); - inetprint(&inp->inp_faddr, (int)inp->inp_fport, - name, inp->inp_lport != inp->inp_fport); + if (inp->inp_vflag & INP_IPV4) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 0); + if (!Lflag) + inetprint(&inp->inp_faddr, + (int)inp->inp_fport, name, + inp->inp_lport != + inp->inp_fport); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + inet6print(&inp->in6p_laddr, + (int)inp->inp_lport, name, 0); + if (!Lflag) + inet6print(&inp->in6p_faddr, + (int)inp->inp_fport, name, + inp->inp_lport != + inp->inp_fport); + } /* else nothing printed now */ +#endif /* INET6 */ } - if (istcp) { + if (istcp && !Lflag) { if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) - printf(" %d", tp->t_state); + printf("%d", tp->t_state); else { - printf(" %s", tcpstates[tp->t_state]); + printf("%s", tcpstates[tp->t_state]); #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) /* Show T/TCP `hidden state' */ if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) @@ -216,7 +423,7 @@ protopr(proto, name) printf("Some %s sockets may have been created.\n", name); } else { - printf("Some %s sockets may have been created or deleted\n", + printf("Some %s sockets may have been created or deleted", name); } } @@ -227,88 +434,113 @@ protopr(proto, name) * Dump TCP statistics structure. */ void -tcp_stats(off, name) - u_long off; - char *name; +tcp_stats(u_long off , char *name, int af ) { + static struct tcpstat ptcpstat; struct tcpstat tcpstat; size_t len = sizeof tcpstat; - + if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { warn("sysctl: net.inet.tcp.stats"); return; } +#ifdef INET6 + if (tcp_done != 0 && interval == 0) + return; + else + tcp_done = 1; +#endif + printf ("%s:\n", name); -#define p(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f, plural(tcpstat.f)) -#define p1a(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f) -#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ - printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) -#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ - printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) -#define p3(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f, plurales(tcpstat.f)) - - p(tcps_sndtotal, "\t%lu packet%s sent\n"); +#define TCPDIFF(f) (tcpstat.f - ptcpstat.f) +#define p(f, m) if (TCPDIFF(f) || sflag <= 1) \ + printf(m, TCPDIFF(f), plural(TCPDIFF(f))) +#define p1a(f, m) if (TCPDIFF(f) || sflag <= 1) \ + printf(m, TCPDIFF(f)) +#define p2(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \ + printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2), plural(TCPDIFF(f2))) +#define p2a(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \ + printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2)) +#define p3(f, m) if (TCPDIFF(f) || sflag <= 1) \ + printf(m, TCPDIFF(f), plurales(TCPDIFF(f))) + + p(tcps_sndtotal, "\t%u packet%s sent\n"); p2(tcps_sndpack,tcps_sndbyte, - "\t\t%lu data packet%s (%lu byte%s)\n"); + "\t\t%u data packet%s (%u byte%s)\n"); p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, - "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); - p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); + "\t\t%u data packet%s (%u byte%s) retransmitted\n"); + p(tcps_mturesent, "\t\t%u resend%s initiated by MTU discovery\n"); p2a(tcps_sndacks, tcps_delack, - "\t\t%lu ack-only packet%s (%lu delayed)\n"); - p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); - p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); - p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); - p(tcps_sndctrl, "\t\t%lu control packet%s\n"); - p(tcps_rcvtotal, "\t%lu packet%s received\n"); - p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); - p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); - p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); + "\t\t%u ack-only packet%s (%u delayed)\n"); + p(tcps_sndurg, "\t\t%u URG only packet%s\n"); + p(tcps_sndprobe, "\t\t%u window probe packet%s\n"); + p(tcps_sndwinup, "\t\t%u window update packet%s\n"); + p(tcps_sndctrl, "\t\t%u control packet%s\n"); + p(tcps_rcvtotal, "\t%u packet%s received\n"); + p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %u byte%s)\n"); + p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n"); + p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n"); p2(tcps_rcvpack, tcps_rcvbyte, - "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); + "\t\t%u packet%s (%u byte%s) received in-sequence\n"); p2(tcps_rcvduppack, tcps_rcvdupbyte, - "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); - p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); + "\t\t%u completely duplicate packet%s (%u byte%s)\n"); + p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n"); p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, - "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); + "\t\t%u packet%s with some dup. data (%u byte%s duped)\n"); p2(tcps_rcvoopack, tcps_rcvoobyte, - "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); + "\t\t%u out-of-order packet%s (%u byte%s)\n"); p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, - "\t\t%lu packet%s (%lu byte%s) of data after window\n"); - p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); - p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); - p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); - p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); - p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); - p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); - p(tcps_connattempt, "\t%lu connection request%s\n"); - p(tcps_accepts, "\t%lu connection accept%s\n"); - p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); - p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); - p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); + "\t\t%u packet%s (%u byte%s) of data after window\n"); + p(tcps_rcvwinprobe, "\t\t%u window probe%s\n"); + p(tcps_rcvwinupd, "\t\t%u window update packet%s\n"); + p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n"); + p(tcps_badrst, "\t\t%u bad reset%s\n"); + p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n"); + p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n"); + p1a(tcps_rcvshort, "\t\t%u discarded because packet too short\n"); + p(tcps_connattempt, "\t%u connection request%s\n"); + p(tcps_accepts, "\t%u connection accept%s\n"); + p(tcps_badsyn, "\t%u bad connection attempt%s\n"); + p(tcps_listendrop, "\t%u listen queue overflow%s\n"); + p(tcps_connects, "\t%u connection%s established (including accepts)\n"); p2(tcps_closed, tcps_drops, - "\t%lu connection%s closed (including %lu drop%s)\n"); - p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); + "\t%u connection%s closed (including %u drop%s)\n"); + p(tcps_cachedrtt, "\t\t%u connection%s updated cached RTT on close\n"); p(tcps_cachedrttvar, - "\t\t%lu connection%s updated cached RTT variance on close\n"); + "\t\t%u connection%s updated cached RTT variance on close\n"); p(tcps_cachedssthresh, - "\t\t%lu connection%s updated cached ssthresh on close\n"); - p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); + "\t\t%u connection%s updated cached ssthresh on close\n"); + p(tcps_conndrops, "\t%u embryonic connection%s dropped\n"); p2(tcps_rttupdated, tcps_segstimed, - "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); - p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); - p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); - p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); - p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); - p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); - p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); - p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); - p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); - p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); + "\t%u segment%s updated rtt (of %u attempt%s)\n"); + p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n"); + p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n"); + p(tcps_persisttimeo, "\t%u persist timeout%s\n"); + p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n"); + p(tcps_keeptimeo, "\t%u keepalive timeout%s\n"); + p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n"); + p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n"); + p(tcps_predack, "\t%u correct ACK header prediction%s\n"); + p(tcps_preddat, "\t%u correct data packet header prediction%s\n"); +#ifdef TCP_MAX_SACK + /* TCP_MAX_SACK indicates the header has the SACK structures */ + p(tcps_sack_recovery_episode, "\t%u SACK recovery episode%s\n"); + p(tcps_sack_rexmits, + "\t%u segment rexmit%s in SACK recovery episodes\n"); + p(tcps_sack_rexmit_bytes, + "\t%u byte rexmit%s in SACK recovery episodes\n"); + p(tcps_sack_rcv_blocks, + "\t%u SACK option%s (SACK blocks) received\n"); + p(tcps_sack_send_blocks, "\t%u SACK option%s (SACK blocks) sent\n"); + p1a(tcps_sack_sboverflow, "\t%u SACK scoreboard overflow\n"); +#endif /* TCP_MAX_SACK */ + + if (interval > 0) + bcopy(&tcpstat, &ptcpstat, len); + +#undef TCPDIFF #undef p #undef p1a #undef p2 @@ -320,10 +552,9 @@ tcp_stats(off, name) * Dump UDP statistics structure. */ void -udp_stats(off, name) - u_long off; - char *name; +udp_stats(u_long off , char *name, int af ) { + static struct udpstat pudpstat; struct udpstat udpstat; size_t len = sizeof udpstat; u_long delivered; @@ -333,30 +564,47 @@ udp_stats(off, name) return; } +#ifdef INET6 + if (udp_done != 0 && interval == 0) + return; + else + udp_done = 1; +#endif + printf("%s:\n", name); -#define p(f, m) if (udpstat.f || sflag <= 1) \ - printf(m, udpstat.f, plural(udpstat.f)) -#define p1a(f, m) if (udpstat.f || sflag <= 1) \ - printf(m, udpstat.f) - p(udps_ipackets, "\t%lu datagram%s received\n"); - p1a(udps_hdrops, "\t%lu with incomplete header\n"); - p1a(udps_badlen, "\t%lu with bad data length field\n"); - p1a(udps_badsum, "\t%lu with bad checksum\n"); - p1a(udps_noport, "\t%lu dropped due to no socket\n"); + +#define UDPDIFF(f) (udpstat.f - pudpstat.f) +#define p(f, m) if (UDPDIFF(f) || sflag <= 1) \ + printf(m, UDPDIFF(f), plural(UDPDIFF(f))) +#define p1a(f, m) if (UDPDIFF(f) || sflag <= 1) \ + printf(m, UDPDIFF(f)) + p(udps_ipackets, "\t%u datagram%s received\n"); + p1a(udps_hdrops, "\t%u with incomplete header\n"); + p1a(udps_badlen, "\t%u with bad data length field\n"); + p1a(udps_badsum, "\t%u with bad checksum\n"); +#ifndef __APPLE__ + p1a(udps_nosum, "\t%u with no checksum\n"); +#endif + p1a(udps_noport, "\t%u dropped due to no socket\n"); p(udps_noportbcast, - "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); - p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); - p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); - delivered = udpstat.udps_ipackets - - udpstat.udps_hdrops - - udpstat.udps_badlen - - udpstat.udps_badsum - - udpstat.udps_noport - - udpstat.udps_noportbcast - - udpstat.udps_fullsock; + "\t%u broadcast/multicast datagram%s dropped due to no socket\n"); + p1a(udps_fullsock, "\t%u dropped due to full socket buffers\n"); + p1a(udpps_pcbhashmiss, "\t%u not for hashed pcb\n"); + delivered = UDPDIFF(udps_ipackets) - + UDPDIFF(udps_hdrops) - + UDPDIFF(udps_badlen) - + UDPDIFF(udps_badsum) - + UDPDIFF(udps_noport) - + UDPDIFF(udps_noportbcast) - + UDPDIFF(udps_fullsock); if (delivered || sflag <= 1) printf("\t%lu delivered\n", delivered); - p(udps_opackets, "\t%lu datagram%s output\n"); + p(udps_opackets, "\t%u datagram%s output\n"); + + if (interval > 0) + bcopy(&udpstat, &pudpstat, len); + +#undef UDPDIFF #undef p #undef p1a } @@ -365,10 +613,9 @@ udp_stats(off, name) * Dump IP statistics structure. */ void -ip_stats(off, name) - u_long off; - char *name; +ip_stats(u_long off , char *name, int af ) { + static struct ipstat pipstat; struct ipstat ipstat; size_t len = sizeof ipstat; @@ -379,41 +626,50 @@ ip_stats(off, name) printf("%s:\n", name); -#define p(f, m) if (ipstat.f || sflag <= 1) \ - printf(m, ipstat.f, plural(ipstat.f)) -#define p1a(f, m) if (ipstat.f || sflag <= 1) \ - printf(m, ipstat.f) - - p(ips_total, "\t%lu total packet%s received\n"); - p(ips_badsum, "\t%lu bad header checksum%s\n"); - p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); - p1a(ips_tooshort, "\t%lu with data size < data length\n"); - p1a(ips_badhlen, "\t%lu with header length < data size\n"); - p1a(ips_badlen, "\t%lu with data length < header length\n"); - p1a(ips_badoptions, "\t%lu with bad options\n"); - p1a(ips_badvers, "\t%lu with incorrect version number\n"); - p(ips_fragments, "\t%lu fragment%s received\n"); - p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); - p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); - p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); - p(ips_delivered, "\t%lu packet%s for this host\n"); - p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); - p(ips_forward, "\t%lu packet%s forwarded"); - p(ips_fastforward, " (%lu packet%s fast forwarded)"); - if (ipstat.ips_forward || sflag <= 1) +#define IPDIFF(f) (ipstat.f - pipstat.f) +#define p(f, m) if (IPDIFF(f) || sflag <= 1) \ + printf(m, IPDIFF(f), plural(IPDIFF(f))) +#define p1a(f, m) if (IPDIFF(f) || sflag <= 1) \ + printf(m, IPDIFF(f)) + + p(ips_total, "\t%u total packet%s received\n"); + p(ips_badsum, "\t%u bad header checksum%s\n"); + p1a(ips_toosmall, "\t%u with size smaller than minimum\n"); + p1a(ips_tooshort, "\t%u with data size < data length\n"); + p1a(ips_toolong, "\t%u with ip length > max ip packet size\n"); + p1a(ips_badhlen, "\t%u with header length < data size\n"); + p1a(ips_badlen, "\t%u with data length < header length\n"); + p1a(ips_badoptions, "\t%u with bad options\n"); + p1a(ips_badvers, "\t%u with incorrect version number\n"); + p(ips_fragments, "\t%u fragment%s received\n"); + p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n"); + p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n"); + p(ips_reassembled, "\t%u packet%s reassembled ok\n"); + p(ips_delivered, "\t%u packet%s for this host\n"); + p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n"); + p(ips_forward, "\t%u packet%s forwarded"); + p(ips_fastforward, " (%u packet%s fast forwarded)"); + if (IPDIFF(ips_forward) || sflag <= 1) putchar('\n'); - p(ips_cantforward, "\t%lu packet%s not forwardable\n"); + p(ips_cantforward, "\t%u packet%s not forwardable\n"); p(ips_notmember, - "\t%lu packet%s received for unknown multicast group\n"); - p(ips_redirectsent, "\t%lu redirect%s sent\n"); - p(ips_localout, "\t%lu packet%s sent from this host\n"); - p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); + "\t%u packet%s received for unknown multicast group\n"); + p(ips_redirectsent, "\t%u redirect%s sent\n"); + p(ips_localout, "\t%u packet%s sent from this host\n"); + p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n"); p(ips_odropped, - "\t%lu output packet%s dropped due to no bufs, etc.\n"); - p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); - p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); - p(ips_ofragments, "\t%lu fragment%s created\n"); - p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); + "\t%u output packet%s dropped due to no bufs, etc.\n"); + p(ips_noroute, "\t%u output packet%s discarded due to no route\n"); + p(ips_fragmented, "\t%u output datagram%s fragmented\n"); + p(ips_ofragments, "\t%u fragment%s created\n"); + p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n"); + p(ips_nogif, "\t%u tunneling packet%s that can't find gif\n"); + p(ips_badaddr, "\t%u datagram%s with bad address in header\n"); + + if (interval > 0) + bcopy(&ipstat, &pipstat, len); + +#undef IPDIFF #undef p #undef p1a } @@ -444,10 +700,9 @@ static char *icmpnames[] = { * Dump ICMP statistics. */ void -icmp_stats(off, name) - u_long off; - char *name; +icmp_stats(u_long off , char *name, int af ) { + static struct icmpstat picmpstat; struct icmpstat icmpstat; int i, first; int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ @@ -465,39 +720,42 @@ icmp_stats(off, name) printf("%s:\n", name); -#define p(f, m) if (icmpstat.f || sflag <= 1) \ - printf(m, icmpstat.f, plural(icmpstat.f)) -#define p1a(f, m) if (icmpstat.f || sflag <= 1) \ - printf(m, icmpstat.f) +#define ICMPDIFF(f) (icmpstat.f - picmpstat.f) +#define p(f, m) if (ICMPDIFF(f) || sflag <= 1) \ + printf(m, ICMPDIFF(f), plural(ICMPDIFF(f))) +#define p1a(f, m) if (ICMPDIFF(f) || sflag <= 1) \ + printf(m, ICMPDIFF(f)) - p(icps_error, "\t%lu call%s to icmp_error\n"); + p(icps_error, "\t%u call%s to icmp_error\n"); p(icps_oldicmp, - "\t%lu error%s not generated 'cuz old message was icmp\n"); + "\t%u error%s not generated 'cuz old message was icmp\n"); for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) - if (icmpstat.icps_outhist[i] != 0) { + if (ICMPDIFF(icps_outhist[i]) != 0) { if (first) { printf("\tOutput histogram:\n"); first = 0; } - printf("\t\t%s: %lu\n", icmpnames[i], - icmpstat.icps_outhist[i]); + printf("\t\t%s: %u\n", icmpnames[i], + ICMPDIFF(icps_outhist[i])); } - p(icps_badcode, "\t%lu message%s with bad code fields\n"); - p(icps_tooshort, "\t%lu message%s < minimum length\n"); - p(icps_checksum, "\t%lu bad checksum%s\n"); - p(icps_badlen, "\t%lu message%s with bad length\n"); - p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); - p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); + p(icps_badcode, "\t%u message%s with bad code fields\n"); + p(icps_tooshort, "\t%u message%s < minimum length\n"); + p(icps_checksum, "\t%u bad checksum%s\n"); + p(icps_badlen, "\t%u message%s with bad length\n"); + p1a(icps_bmcastecho, "\t%u multicast echo requests ignored\n"); + p1a(icps_bmcasttstamp, "\t%u multicast timestamp requests ignored\n"); for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) - if (icmpstat.icps_inhist[i] != 0) { + if (ICMPDIFF(icps_inhist[i]) != 0) { if (first) { printf("\tInput histogram:\n"); first = 0; } - printf("\t\t%s: %lu\n", icmpnames[i], - icmpstat.icps_inhist[i]); + printf("\t\t%s: %u\n", icmpnames[i], + ICMPDIFF(icps_inhist[i])); } - p(icps_reflect, "\t%lu message response%s generated\n"); + p(icps_reflect, "\t%u message response%s generated\n"); + +#undef ICMPDIFF #undef p #undef p1a mib[3] = ICMPCTL_MASKREPL; @@ -506,16 +764,18 @@ icmp_stats(off, name) return; printf("\tICMP address mask responses are %sabled\n", i ? "en" : "dis"); + + if (interval > 0) + bcopy(&icmpstat, &picmpstat, sizeof (icmpstat)); } /* * Dump IGMP statistics structure. */ void -igmp_stats(off, name) - u_long off; - char *name; +igmp_stats(u_long off , char *name, int af ) { + static struct igmpstat pigmpstat; struct igmpstat igmpstat; size_t len = sizeof igmpstat; @@ -526,10 +786,11 @@ igmp_stats(off, name) printf("%s:\n", name); -#define p(f, m) if (igmpstat.f || sflag <= 1) \ - printf(m, igmpstat.f, plural(igmpstat.f)) -#define py(f, m) if (igmpstat.f || sflag <= 1) \ - printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") +#define IGMPDIFF(f) (igmpstat.f - pigmpstat.f) +#define p(f, m) if (IGMPDIFF(f) || sflag <= 1) \ + printf(m, IGMPDIFF(f), plural(IGMPDIFF(f))) +#define py(f, m) if (IGMPDIFF(f) || sflag <= 1) \ + printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y") p(igps_rcv_total, "\t%u message%s received\n"); p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); @@ -539,6 +800,11 @@ igmp_stats(off, name) p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); p(igps_snd_reports, "\t%u membership report%s sent\n"); + + if (interval > 0) + bcopy(&igmpstat, &pigmpstat, len); + +#undef IGMPDIFF #undef p #undef py } @@ -547,26 +813,32 @@ igmp_stats(off, name) * Pretty print an Internet address (net address + port). */ void -inetprint(in, port, proto,numeric) - register struct in_addr *in; - int port; - char *proto; - int numeric; +inetprint(struct in_addr *in, int port, char *proto, int numeric_port) { struct servent *sp = 0; char line[80], *cp; int width; - sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); + if (Wflag) + sprintf(line, "%s.", inetname(in)); + else + sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in)); cp = index(line, '\0'); - if (!numeric && port) + if (!numeric_port && port) +#ifdef _SERVICE_CACHE_ + sp = _serv_cache_getservbyport(port, proto); +#else sp = getservbyport((int)port, proto); +#endif if (sp || port == 0) - sprintf(cp, "%.15s", sp ? sp->s_name : "*"); + sprintf(cp, "%.15s ", sp ? sp->s_name : "*"); + else + sprintf(cp, "%d ", ntohs((u_short)port)); + width = (Aflag && !Wflag) ? 18 : 22; + if (Wflag) + printf("%-*s ", width, line); else - sprintf(cp, "%d", ntohs((u_short)port)); - width = Aflag ? 18 : 22; - printf(" %-*.*s", width, width, line); + printf("%-*.*s ", width, width, line); } /* @@ -575,11 +847,10 @@ inetprint(in, port, proto,numeric) * numeric value, otherwise try for symbolic name. */ char * -inetname(inp) - struct in_addr *inp; +inetname(struct in_addr *inp) { register char *cp; - static char line[MAXHOSTNAMELEN + 1]; + static char line[MAXHOSTNAMELEN]; struct hostent *hp; struct netent *np; @@ -597,7 +868,7 @@ inetname(inp) hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); if (hp) { cp = hp->h_name; - trimdomain(cp); + //### trimdomain(cp, strlen(cp)); } } }