Author: tuexen
Date: Fri Feb 10 22:31:47 2012
New Revision: 231455
URL: http://svn.freebsd.org/changeset/base/231455

Log:
  MFC r224271:
  Fix the following bugs related to the SCTP support of netstat:
  * Correctly handle -a.
  * -A isn't supported.
  * Show all closed 1-to-1 and 1-to-many style sockets.
  * Show all listening 1-to-many style sockets.
  * Use consistent formatting for -W.

Modified:
  stable/8/usr.bin/netstat/sctp.c   (contents, props changed)
Directory Properties:
  stable/8/usr.bin/   (props changed)
  stable/8/usr.bin/apply/   (props changed)
  stable/8/usr.bin/ar/   (props changed)
  stable/8/usr.bin/awk/   (props changed)
  stable/8/usr.bin/biff/   (props changed)
  stable/8/usr.bin/c89/   (props changed)
  stable/8/usr.bin/c99/   (props changed)
  stable/8/usr.bin/calendar/   (props changed)
  stable/8/usr.bin/catman/   (props changed)
  stable/8/usr.bin/checknr/   (props changed)
  stable/8/usr.bin/chpass/Makefile   (props changed)
  stable/8/usr.bin/column/   (props changed)
  stable/8/usr.bin/comm/   (props changed)
  stable/8/usr.bin/compress/   (props changed)
  stable/8/usr.bin/cpio/   (props changed)
  stable/8/usr.bin/cpuset/   (props changed)
  stable/8/usr.bin/csup/   (props changed)
  stable/8/usr.bin/du/   (props changed)
  stable/8/usr.bin/ee/   (props changed)
  stable/8/usr.bin/enigma/   (props changed)
  stable/8/usr.bin/fetch/   (props changed)
  stable/8/usr.bin/find/   (props changed)
  stable/8/usr.bin/finger/   (props changed)
  stable/8/usr.bin/fold/   (props changed)
  stable/8/usr.bin/fstat/   (props changed)
  stable/8/usr.bin/gcore/   (props changed)
  stable/8/usr.bin/getopt/   (props changed)
  stable/8/usr.bin/gzip/   (props changed)
  stable/8/usr.bin/hexdump/   (props changed)
  stable/8/usr.bin/indent/   (props changed)
  stable/8/usr.bin/ipcs/   (props changed)
  stable/8/usr.bin/jot/   (props changed)
  stable/8/usr.bin/kdump/   (props changed)
  stable/8/usr.bin/killall/   (props changed)
  stable/8/usr.bin/ktrace/   (props changed)
  stable/8/usr.bin/lastcomm/   (props changed)
  stable/8/usr.bin/ldd/   (props changed)
  stable/8/usr.bin/less/   (props changed)
  stable/8/usr.bin/lex/   (props changed)
  stable/8/usr.bin/limits/   (props changed)
  stable/8/usr.bin/locale/   (props changed)
  stable/8/usr.bin/locate/   (props changed)
  stable/8/usr.bin/lock/   (props changed)
  stable/8/usr.bin/lockf/   (props changed)
  stable/8/usr.bin/logger/   (props changed)
  stable/8/usr.bin/look/   (props changed)
  stable/8/usr.bin/m4/   (props changed)
  stable/8/usr.bin/mail/   (props changed)
  stable/8/usr.bin/make/   (props changed)
  stable/8/usr.bin/makewhatis/   (props changed)
  stable/8/usr.bin/minigzip/   (props changed)
  stable/8/usr.bin/ncal/   (props changed)
  stable/8/usr.bin/netstat/   (props changed)
  stable/8/usr.bin/netstat/Makefile   (props changed)
  stable/8/usr.bin/netstat/atalk.c   (props changed)
  stable/8/usr.bin/netstat/bpf.c   (props changed)
  stable/8/usr.bin/netstat/if.c   (props changed)
  stable/8/usr.bin/netstat/inet.c   (props changed)
  stable/8/usr.bin/netstat/inet6.c   (props changed)
  stable/8/usr.bin/netstat/ipsec.c   (props changed)
  stable/8/usr.bin/netstat/ipx.c   (props changed)
  stable/8/usr.bin/netstat/main.c   (props changed)
  stable/8/usr.bin/netstat/mbuf.c   (props changed)
  stable/8/usr.bin/netstat/mroute.c   (props changed)
  stable/8/usr.bin/netstat/mroute6.c   (props changed)
  stable/8/usr.bin/netstat/netgraph.c   (props changed)
  stable/8/usr.bin/netstat/netisr.c   (props changed)
  stable/8/usr.bin/netstat/netstat.1   (props changed)
  stable/8/usr.bin/netstat/netstat.h   (props changed)
  stable/8/usr.bin/netstat/pfkey.c   (props changed)
  stable/8/usr.bin/netstat/route.c   (props changed)
  stable/8/usr.bin/netstat/unix.c   (props changed)
  stable/8/usr.bin/newgrp/   (props changed)
  stable/8/usr.bin/nfsstat/   (props changed)
  stable/8/usr.bin/pathchk/   (props changed)
  stable/8/usr.bin/perror/   (props changed)
  stable/8/usr.bin/printf/   (props changed)
  stable/8/usr.bin/procstat/   (props changed)
  stable/8/usr.bin/rlogin/   (props changed)
  stable/8/usr.bin/rpcgen/   (props changed)
  stable/8/usr.bin/rpcinfo/   (props changed)
  stable/8/usr.bin/rs/   (props changed)
  stable/8/usr.bin/ruptime/   (props changed)
  stable/8/usr.bin/script/   (props changed)
  stable/8/usr.bin/sed/   (props changed)
  stable/8/usr.bin/showmount/   (props changed)
  stable/8/usr.bin/sockstat/   (props changed)
  stable/8/usr.bin/split/   (props changed)
  stable/8/usr.bin/stat/   (props changed)
  stable/8/usr.bin/su/   (props changed)
  stable/8/usr.bin/su/Makefile   (props changed)
  stable/8/usr.bin/su/su.1   (props changed)
  stable/8/usr.bin/su/su.c   (props changed)
  stable/8/usr.bin/systat/   (props changed)
  stable/8/usr.bin/tail/   (props changed)
  stable/8/usr.bin/tar/   (props changed)
  stable/8/usr.bin/tftp/   (props changed)
  stable/8/usr.bin/tip/   (props changed)
  stable/8/usr.bin/top/   (props changed)
  stable/8/usr.bin/touch/   (props changed)
  stable/8/usr.bin/tr/   (props changed)
  stable/8/usr.bin/truss/   (props changed)
  stable/8/usr.bin/uname/   (props changed)
  stable/8/usr.bin/unifdef/   (props changed)
  stable/8/usr.bin/uniq/   (props changed)
  stable/8/usr.bin/unzip/   (props changed)
  stable/8/usr.bin/usbhidaction/   (props changed)
  stable/8/usr.bin/usbhidctl/   (props changed)
  stable/8/usr.bin/uudecode/   (props changed)
  stable/8/usr.bin/vmstat/   (props changed)
  stable/8/usr.bin/w/   (props changed)
  stable/8/usr.bin/wall/   (props changed)
  stable/8/usr.bin/whois/   (props changed)
  stable/8/usr.bin/xargs/   (props changed)
  stable/8/usr.bin/xinstall/   (props changed)
  stable/8/usr.bin/xlint/   (props changed)
  stable/8/usr.bin/xz/   (props changed)
  stable/8/usr.bin/yacc/   (props changed)

Modified: stable/8/usr.bin/netstat/sctp.c
==============================================================================
--- stable/8/usr.bin/netstat/sctp.c     Fri Feb 10 22:29:41 2012        
(r231454)
+++ stable/8/usr.bin/netstat/sctp.c     Fri Feb 10 22:31:47 2012        
(r231455)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
+ * Copyright (c) 2011, by Michael Tuexen. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -63,7 +64,6 @@ __FBSDID("$FreeBSD$");
 
 #ifdef SCTP
 
-void   inetprint(struct in_addr *, int, const char *, int);
 static void sctp_statesprint(uint32_t state);
 
 #define        NETSTAT_SCTP_STATES_CLOSED              0x0
@@ -102,6 +102,124 @@ struct xraddr_entry {
         LIST_ENTRY(xraddr_entry) xraddr_entries;
 };
 
+/*
+ * Construct an Internet address representation.
+ * If numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+static char *
+inetname(struct in_addr *inp)
+{
+       char *cp;
+       static char line[MAXHOSTNAMELEN];
+       struct hostent *hp;
+       struct netent *np;
+
+       cp = 0;
+       if (!numeric_addr && inp->s_addr != INADDR_ANY) {
+               int net = inet_netof(*inp);
+               int lna = inet_lnaof(*inp);
+
+               if (lna == INADDR_ANY) {
+                       np = getnetbyaddr(net, AF_INET);
+                       if (np)
+                               cp = np->n_name;
+               }
+               if (cp == 0) {
+                       hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+                       if (hp) {
+                               cp = hp->h_name;
+                               trimdomain(cp, strlen(cp));
+                       }
+               }
+       }
+       if (inp->s_addr == INADDR_ANY)
+               strcpy(line, "*");
+       else if (cp) {
+               strlcpy(line, cp, sizeof(line));
+       } else {
+               inp->s_addr = ntohl(inp->s_addr);
+#define        C(x)    ((u_int)((x) & 0xff))
+               sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+                   C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
+               inp->s_addr = htonl(inp->s_addr);
+       }
+       return (line);
+}
+
+#ifdef INET6
+static char ntop_buf[INET6_ADDRSTRLEN];
+
+static char *
+inet6name(struct in6_addr *in6p)
+{
+       char *cp;
+       static char line[50];
+       struct hostent *hp;
+       static char domain[MAXHOSTNAMELEN];
+       static int first = 1;
+
+       if (first && !numeric_addr) {
+               first = 0;
+               if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+                   (cp = index(domain, '.')))
+                       (void) strcpy(domain, cp + 1);
+               else
+                       domain[0] = 0;
+       }
+       cp = 0;
+       if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+               hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
+               if (hp) {
+                       if ((cp = index(hp->h_name, '.')) &&
+                           !strcmp(cp + 1, domain))
+                               *cp = 0;
+                       cp = hp->h_name;
+               }
+       }
+       if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+               strcpy(line, "*");
+       else if (cp)
+               strcpy(line, cp);
+       else
+               sprintf(line, "%s",
+                       inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
+                               sizeof(ntop_buf)));
+       return (line);
+}
+#endif
+
+static void
+sctp_print_address(union sctp_sockstore *address, int port, int num_port)
+{
+       struct servent *sp = 0;
+       char line[80], *cp;
+       int width;
+
+       switch (address->sa.sa_family) {
+       case AF_INET:
+               sprintf(line, "%.*s.", Wflag ? 39 : 16, 
inetname(&address->sin.sin_addr));
+               break;
+#ifdef INET6
+       case AF_INET6:
+               sprintf(line, "%.*s.", Wflag ? 39 : 16, 
inet6name(&address->sin6.sin6_addr));
+               break;
+#endif
+       default:
+               sprintf(line, "%.*s.", Wflag ? 39 : 16, "");
+               break;
+       }
+       cp = index(line, '\0');
+       if (!num_port && port)
+               sp = getservbyport((int)port, "sctp");
+       if (sp || port == 0)
+               sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
+       else
+               sprintf(cp, "%d ", ntohs((u_short)port));
+       width = Wflag ? 45 : 22;
+       printf("%-*.*s ", width, width, line);
+}
+
 static int
 sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
 {
@@ -150,18 +268,14 @@ sctp_skip_xinpcb_ifneed(char *buf, const
 }
 
 static void
-sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
+sctp_process_tcb(struct xsctp_tcb *xstcb,
     char *buf, const size_t buflen, size_t *offset, int *indent)
 {
        int i, xl_total = 0, xr_total = 0, x_max;
-       struct sockaddr *sa;
        struct xsctp_raddr *xraddr;
        struct xsctp_laddr *xladdr;
        struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
        struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
-#ifdef INET6
-       struct sockaddr_in6 *in6;
-#endif
 
        LIST_INIT(&xladdr_head);
        LIST_INIT(&xraddr_head);
@@ -220,38 +334,22 @@ sctp_process_tcb(struct xsctp_tcb *xstcb
        x_max = (xl_total > xr_total) ? xl_total : xr_total;
        for (i = 0; i < x_max; i++) {
                if (((*indent == 0) && i > 0) || *indent > 0)
-                       printf("%-11s ", " ");
+                       printf("%-12s ", " ");
 
                if (xl != NULL) {
-                       sa = &(xl->xladdr->address.sa);
-                       if ((sa->sa_family) == AF_INET)
-                               inetprint(&((struct sockaddr_in *)sa)->sin_addr,
-                                   htons(xstcb->local_port),
-                                   name, numeric_port);
-#ifdef INET6
-                       else {
-                               in6 = (struct sockaddr_in6 *)sa;
-                               inet6print(&in6->sin6_addr,
-                                   htons(xstcb->local_port),
-                                   name, numeric_port);
+                       sctp_print_address(&(xl->xladdr->address),
+                           htons(xstcb->local_port), numeric_port);
+               } else {
+                       if (Wflag) {
+                               printf("%-45s ", " ");
+                       } else {
+                               printf("%-22s ", " ");
                        }
-#endif
                }
 
                if (xr != NULL && !Lflag) {
-                       sa = &(xr->xraddr->address.sa);
-                       if ((sa->sa_family) == AF_INET)
-                               inetprint(&((struct sockaddr_in *)sa)->sin_addr,
-                                   htons(xstcb->remote_port),
-                                   name, numeric_port);
-#ifdef INET6
-                       else {
-                               in6 = (struct sockaddr_in6 *)sa;
-                               inet6print(&in6->sin6_addr,
-                                   htons(xstcb->remote_port),
-                                   name, numeric_port);
-                       }
-#endif
+                       sctp_print_address(&(xr->xraddr->address),
+                           htons(xstcb->remote_port), numeric_port);
                }
 
                if (xl != NULL)
@@ -285,53 +383,21 @@ out:
        }
 }
 
-#ifdef SCTP_DEBUG
-uint32_t sctp_pdup[64];
-int sctp_pcnt = 0;
-#endif
-
 static void
-sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
+sctp_process_inpcb(struct xsctp_inpcb *xinpcb,
     char *buf, const size_t buflen, size_t *offset)
 {
-       int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
+       int indent = 0, xladdr_total = 0, is_listening = 0;
        static int first = 1;
-       char *tname;
+       char *tname, *pname;
        struct xsctp_tcb *xstcb;
        struct xsctp_laddr *xladdr;
-       struct sockaddr *sa;
-#ifdef INET6
-       struct sockaddr_in6 *in6;
-#endif
+       size_t offset_laddr;
+       int process_closed;
 
-       if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
-           SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
+       if (xinpcb->maxqlen > 0)
                is_listening = 1;
 
-       if (!Lflag && !is_listening &&
-           !(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
-#ifdef SCTP_DEBUG
-               int i, found = 0;
-
-               for (i = 0; i < sctp_pcnt; i++) {
-                       if (sctp_pdup[i] == xinpcb->flags) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found) {
-                       sctp_pdup[sctp_pcnt++] = xinpcb->flags;
-                       if (sctp_pcnt >= 64)
-                               sctp_pcnt = 0;
-                       printf("[0x%08x]", xinpcb->flags);
-               }
-#endif
-               offset_backup = *offset;
-               if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
-                       return;
-               *offset = offset_backup;
-       }
-
        if (first) {
                if (!Lflag) {
                        printf("Active SCTP associations");
@@ -340,90 +406,115 @@ sctp_process_inpcb(struct xsctp_inpcb *x
                } else
                        printf("Current listen queue sizes (qlen/maxqlen)");
                putchar('\n');
-               if (Aflag)
-                       printf("%-8.8s ", "Socket");
                if (Lflag)
-                       printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
+                       printf("%-6.6s %-5.5s %-8.8s %-22.22s\n",
                            "Proto", "Type", "Listen", "Local Address");
                else
-                       printf((Aflag && !Wflag) ?
-                           "%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
-                           "%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
-                           "Proto", "Type",
-                           "Local Address", "Foreign Address",
-                           "(state)");
+                       if (Wflag)
+                               printf("%-6.6s %-5.5s %-45.45s %-45.45s %s\n",
+                                   "Proto", "Type",
+                                   "Local Address", "Foreign Address",
+                                   "(state)");
+                       else
+                               printf("%-6.6s %-5.5s %-22.22s %-22.22s %s\n",
+                                   "Proto", "Type",
+                                   "Local Address", "Foreign Address",
+                                   "(state)");
                first = 0;
        }
-       if (Lflag && xinpcb->maxqlen == 0) {
+       xladdr = (struct xsctp_laddr *)(buf + *offset);
+       if (Lflag && !is_listening) {
                (int)sctp_skip_xinpcb_ifneed(buf, buflen, offset);
                return;
        }
-       if (Aflag)
-               printf("%8lx ", (u_long)xinpcb);
 
-       printf("%-5.5s ", name);
+       if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+               /* Can't distinguish between sctp46 and sctp6 */
+               pname = "sctp46";
+       } else {
+               pname = "sctp4";
+       }
 
        if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
                tname = "1to1";
        else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
                tname = "1toN";
        else
-               return;
-
-       printf("%-5.5s ", tname);
+               tname = "????";
 
        if (Lflag) {
                char buf1[9];
 
                snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
+               printf("%-6.6s %-5.5s ", pname, tname);
                printf("%-8.8s ", buf1);
        }
-       /*
-        * process the local address.  This routine are used for Lflag.
-        */
+
+       offset_laddr = *offset;
+       process_closed = 0;
+retry:
        while (*offset < buflen) {
                xladdr = (struct xsctp_laddr *)(buf + *offset);
                *offset += sizeof(struct xsctp_laddr);
-               if (xladdr->last == 1)
+               if (xladdr->last) {
+                       if (aflag && !Lflag && (xladdr_total == 0) && 
process_closed) {
+                               printf("%-6.6s %-5.5s ", pname, tname);
+                               if (Wflag) {
+                                       printf("%-91.91s CLOSED", " ");
+                               } else {
+                                       printf("%-45.45s CLOSED", " ");
+                               }
+                       }
+                       if (process_closed || is_listening) {
+                               putchar('\n');
+                       }
                        break;
+               }
 
-               if (!Lflag && !is_listening)
+               if (!Lflag && !is_listening && !process_closed)
                        continue;
 
-               if (xladdr_total != 0)
+               if (xladdr_total == 0) {
+                       printf("%-6.6s %-5.5s ", pname, tname);
+               } else {
                        putchar('\n');
-               if (xladdr_total > 0)
                        printf((Lflag) ?
-                           "%-20.20s " : "%-11.11s ", " ");
-
-               sa = &(xladdr->address.sa);
-               if ((sa->sa_family) == AF_INET)
-                       inetprint(&((struct sockaddr_in *)sa)->sin_addr,
-                           htons(xinpcb->local_port), name, numeric_port);
-#ifdef INET6
-               else {
-                       in6 = (struct sockaddr_in6 *)sa;
-                       inet6print(&in6->sin6_addr,
-                           htons(xinpcb->local_port), name, numeric_port);
+                           "%-21.21s " : "%-12.12s ", " ");
+               }
+               sctp_print_address(&(xladdr->address),
+                   htons(xinpcb->local_port), numeric_port);
+               if (aflag && !Lflag && xladdr_total == 0) {
+                       if (Wflag) {
+                               if (process_closed) {
+                                       printf("%-45.45s CLOSED", " ");
+                               } else {
+                                       printf("%-45.45s LISTEN", " ");
+                               }
+                       } else {
+                               if (process_closed) {
+                                       printf("%-22.22s CLOSED", " ");
+                               } else {
+                                       printf("%-22.22s LISTEN", " ");
+                               }
+                       }
                }
-#endif
-
-               if (!Lflag && xladdr_total == 0 && is_listening == 1)
-                       printf("%-22.22s LISTEN", " ");
-
                xladdr_total++;
        }
 
        xstcb = (struct xsctp_tcb *)(buf + *offset);
        *offset += sizeof(struct xsctp_tcb);
+       if (aflag && (xladdr_total == 0) && xstcb->last && !process_closed) {
+               process_closed = 1;
+               *offset = offset_laddr;
+               goto retry;
+       }
        while (xstcb->last == 0 && *offset < buflen) {
-               sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
+               printf("%-6.6s %-5.5s ", pname, tname);
+               sctp_process_tcb(xstcb, buf, buflen, offset, &indent);
                indent++;
                xstcb = (struct xsctp_tcb *)(buf + *offset);
                *offset += sizeof(struct xsctp_tcb);
        }
-
-       putchar('\n');
 }
 
 /*
@@ -461,7 +552,7 @@ sctp_protopr(u_long off __unused,
        xinpcb = (struct xsctp_inpcb *)(buf + offset);
        offset += sizeof(struct xsctp_inpcb);
        while (xinpcb->last == 0 && offset < len) {
-               sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
+               sctp_process_inpcb(xinpcb, buf, (const size_t)len,
                    &offset);
 
                xinpcb = (struct xsctp_inpcb *)(buf + offset);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to