=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/systat/netstat.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- src/usr.bin/systat/netstat.c 1999/12/08 10:50:04 1.11 +++ src/usr.bin/systat/netstat.c 2000/01/05 11:04:22 1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: netstat.c,v 1.11 1999/12/08 10:50:04 angelos Exp $ */ +/* $OpenBSD: netstat.c,v 1.12 2000/01/05 11:04:22 itojun Exp $ */ /* $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; #endif -static char rcsid[] = "$OpenBSD: netstat.c,v 1.11 1999/12/08 10:50:04 angelos Exp $"; +static char rcsid[] = "$OpenBSD: netstat.c,v 1.12 2000/01/05 11:04:22 itojun Exp $"; #endif /* not lint */ /* @@ -79,8 +79,12 @@ #include "extern.h" static void enter __P((struct inpcb *, struct socket *, int, char *)); -static char *inetname __P((struct in_addr)); +static const char *inetname __P((struct in_addr)); static void inetprint __P((struct in_addr *, int, char *)); +#ifdef INET6 +static const char *inet6name __P((struct in6_addr *)); +static void inet6print __P((struct in6_addr *, int, char *)); +#endif #define streq(a,b) (strcmp(a,b)==0) #define YMAX(w) ((w)->_maxy-1) @@ -95,6 +99,7 @@ struct netinfo { struct netinfo *nif_forw, *nif_prev; + int nif_family; short nif_line; /* line on screen */ short nif_seen; /* 0 when not present in list */ short nif_flags; @@ -103,8 +108,14 @@ short nif_state; /* tcp state */ char *nif_proto; /* protocol */ struct in_addr nif_laddr; /* local address */ +#ifdef INET6 + struct in6_addr nif_laddr6; /* local address */ +#endif long nif_lport; /* local port */ struct in_addr nif_faddr; /* foreign address */ +#ifdef INET6 + struct in6_addr nif_faddr6; /* foreign address */ +#endif long nif_fport; /* foreign port */ long nif_rcvcc; /* rcv buffer character count */ long nif_sndcc; /* snd buffer character count */ @@ -117,8 +128,6 @@ static int aflag = 0; static int nflag = 0; static int lastrow = 1; -static void enter(), inetprint(); -static char *inetname(); void closenetstat(w) @@ -211,8 +220,21 @@ prev = next; next = inpcb.inp_queue.cqe_next; - if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) +#ifndef INET6 + if (inpcb.inp_flags & INP_IPV6) continue; +#endif + + if (!aflag) { + if (!(inpcb.inp_flags & INP_IPV6) + && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) + continue; +#ifdef INET6 + if ((inpcb.inp_flags & INP_IPV6) + && IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6)) + continue; +#endif + } if (nhosts && !checkhost(&inpcb)) continue; if (nports && !checkport(&inpcb)) @@ -247,17 +269,36 @@ * will appear as ``not seen'' in the kernel * data structures. */ - for (p = netcb.nif_forw; - p != (struct netinfo *)&netcb; - p = p->nif_forw) { + for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) { +#ifdef INET6 + if (p->nif_family == AF_INET && (inp->inp_flags & INP_IPV6)) + continue; + if (p->nif_family == AF_INET6 && !(inp->inp_flags & INP_IPV6)) + continue; +#endif if (!streq(proto, p->nif_proto)) continue; - if (p->nif_lport != inp->inp_lport || - p->nif_laddr.s_addr != inp->inp_laddr.s_addr) + if (p->nif_family == AF_INET) { + if (p->nif_lport != inp->inp_lport || + p->nif_laddr.s_addr != inp->inp_laddr.s_addr) + continue; + if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr && + p->nif_fport == inp->inp_fport) + break; + + } +#ifdef INET6 + else if (p->nif_family == AF_INET6) { + if (p->nif_lport != inp->inp_lport || + !IN6_ARE_ADDR_EQUAL(&p->nif_laddr6, &inp->inp_laddr6)) + continue; + if (IN6_ARE_ADDR_EQUAL(&p->nif_faddr, &inp->inp_faddr) && + p->nif_fport == inp->inp_fport) + break; + } +#endif + else continue; - if (p->nif_faddr.s_addr == inp->inp_faddr.s_addr && - p->nif_fport == inp->inp_fport) - break; } if (p == (struct netinfo *)&netcb) { if ((p = malloc(sizeof(*p))) == NULL) { @@ -269,12 +310,23 @@ netcb.nif_forw->nif_prev = p; netcb.nif_forw = p; p->nif_line = -1; - p->nif_laddr = inp->inp_laddr; p->nif_lport = inp->inp_lport; - p->nif_faddr = inp->inp_faddr; p->nif_fport = inp->inp_fport; p->nif_proto = proto; p->nif_flags = NIF_LACHG|NIF_FACHG; +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) { + p->nif_laddr6 = inp->inp_laddr6; + p->nif_faddr6 = inp->inp_faddr6; + p->nif_family = AF_INET6; + } + else +#endif + { + p->nif_laddr = inp->inp_laddr; + p->nif_faddr = inp->inp_faddr; + p->nif_family = AF_INET; + } } p->nif_rcvcc = so->so_rcv.sb_cc; p->nif_sndcc = so->so_snd.sb_cc; @@ -339,9 +391,7 @@ /* * Update existing connections and add new ones. */ - for (p = netcb.nif_forw; - p != (struct netinfo *)&netcb; - p = p->nif_forw) { + for (p = netcb.nif_forw; p != (struct netinfo *)&netcb; p = p->nif_forw) { if (p->nif_line == -1) { /* * Add a new entry if possible. @@ -353,15 +403,41 @@ } if (p->nif_flags & NIF_LACHG) { wmove(wnd, p->nif_line, LADDR); - inetprint(&p->nif_laddr, p->nif_lport, p->nif_proto); + switch (p->nif_family) { + case AF_INET: + inetprint(&p->nif_laddr, p->nif_lport, + p->nif_proto); + break; +#ifdef INET6 + case AF_INET6: + inet6print(&p->nif_laddr6, p->nif_lport, + p->nif_proto); + break; +#endif + } p->nif_flags &= ~NIF_LACHG; } if (p->nif_flags & NIF_FACHG) { wmove(wnd, p->nif_line, FADDR); - inetprint(&p->nif_faddr, p->nif_fport, p->nif_proto); + switch (p->nif_family) { + case AF_INET: + inetprint(&p->nif_faddr, p->nif_fport, + p->nif_proto); + break; +#ifdef INET6 + case AF_INET6: + inet6print(&p->nif_faddr6, p->nif_fport, + p->nif_proto); + break; +#endif + } p->nif_flags &= ~NIF_FACHG; } mvwaddstr(wnd, p->nif_line, PROTO, p->nif_proto); +#ifdef INET6 + if (p->nif_family == AF_INET6) + waddstr(wnd, "6"); +#endif mvwprintw(wnd, p->nif_line, RCVCC, "%6d", p->nif_rcvcc); mvwprintw(wnd, p->nif_line, SNDCC, "%6d", p->nif_sndcc); if (streq(p->nif_proto, "tcp")) @@ -410,12 +486,41 @@ waddstr(wnd, line); } +#ifdef INET6 +static void +inet6print(in6, port, proto) + register struct in6_addr *in6; + int port; + char *proto; +{ + struct servent *sp = 0; + char line[80], *cp; + + snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6)); + cp = strchr(line, '\0'); + if (!nflag && port) + sp = getservbyport(port, proto); + if (sp || port == 0) + snprintf(cp, sizeof line - strlen(cp), "%.8s", + sp ? sp->s_name : "*"); + else + snprintf(cp, sizeof line - strlen(cp), "%d", + ntohs((u_short)port)); + /* pad to full column to clear any garbage */ + cp = strchr(line, '\0'); + while (cp - line < 22 && cp - line < sizeof line-1) + *cp++ = ' '; + *cp = '\0'; + waddstr(wnd, line); +} +#endif + /* * Construct an Internet address representation. * If the nflag has been supplied, give * numeric value, otherwise try for symbolic name. */ -static char * +static const char * inetname(in) struct in_addr in; { @@ -453,6 +558,32 @@ } return (line); } + +#ifdef INET6 +static const char * +inet6name(in6) + struct in6_addr *in6; +{ + static char line[NI_MAXHOST]; + struct sockaddr_in6 sin6; + int flags; + + if (nflag) + flags = NI_NUMERICHOST; + else + flags = 0; + if (IN6_IS_ADDR_UNSPECIFIED(in6)) + return "*"; + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_addr = *in6; + if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, + line, sizeof(line), NULL, 0, flags) == 0) + return line; + return "?"; +} +#endif int cmdnetstat(cmd, args)