Index: freebsd-head/usr.bin/systat/netcmds.c =================================================================== --- freebsd-head/usr.bin/systat/netcmds.c (revision 239266) +++ freebsd-head/usr.bin/systat/netcmds.c (working copy) @@ -61,8 +61,16 @@ static const char sccsid[] = "@(#)netcmd #define streq(a,b) (strcmp(a,b)==0) +union storage_addr { + struct in_addr in; +#ifdef INET6 + struct in6_addr in6; +#endif +}; + static struct hitem { - struct in_addr addr; + union storage_addr addr; + int family; int onoff; } *hosts; @@ -73,7 +81,7 @@ static int selectproto(const char *); static void showprotos(void); static int selectport(long, int); static void showports(void); -static int selecthost(struct in_addr *, int); +static int selecthost(union storage_addr *, int, int); static void showhosts(void); int @@ -96,7 +104,7 @@ netcmd(const char *cmd, const char *args } if (prefix(cmd, "reset")) { selectproto(0); - selecthost(0, 0); + selecthost(0, 0, 0); selectport(-1, 0); return (1); } @@ -126,8 +134,13 @@ changeitems(const char *args, int onoff) { char *cp, *tmpstr, *tmpstr1; struct servent *sp; - struct hostent *hp; - struct in_addr in; + struct addrinfo hint, *res, *res0; + union storage_addr addr; +#ifdef INET6 + int family = AF_UNSPEC; +#else + int family = AF_INET; +#endif tmpstr = tmpstr1 = strdup(args); cp = strchr(tmpstr1, '\n'); @@ -143,22 +156,50 @@ changeitems(const char *args, int onoff) *cp++ = '\0'; if (cp - tmpstr1 == 0) break; + if (streq(tmpstr1, "-4")) { + family = AF_INET; + continue; + } +#ifdef INET6 + else if (streq(tmpstr1, "-6")) { + family = AF_INET6; + continue; + } +#endif sp = getservbyname(tmpstr1, protos == TCP ? "tcp" : protos == UDP ? "udp" : 0); if (sp) { selectport(sp->s_port, onoff); continue; } - hp = gethostbyname(tmpstr1); - if (hp == 0) { - in.s_addr = inet_addr(tmpstr1); - if ((int)in.s_addr == -1) { - error("%s: unknown host or port", tmpstr1); + memset(&hint, 0, sizeof(hint)); + hint.ai_family = family; + hint.ai_protocol = (protos == TCP ? IPPROTO_TCP : protos == UDP ? IPPROTO_UDP : 0); + hint.ai_flags = AI_ADDRCONFIG; + if ( (getaddrinfo(tmpstr1, 0, &hint, &res0))) { + error("%s: unknown host or port", tmpstr1); + continue; + } + for (res = res0; res; res = res->ai_next) { + switch (res->ai_family) { + case AF_INET : + memcpy(&addr.in, + &((struct sockaddr_in *)res->ai_addr)->sin_addr, + sizeof(addr.in)); + break; +#ifdef INET6 + case AF_INET6 : + memcpy(&addr.in6, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(addr.in6)); + break; +#endif + default : continue; } - } else - in = *(struct in_addr *)hp->h_addr; - selecthost(&in, onoff); + selecthost(&addr, res->ai_family, onoff); + } + freeaddrinfo(res0); } free(tmpstr); } @@ -253,12 +294,17 @@ showports(void) } } +#define af4cmp(x, y) (memcmp(&x.s_addr, &y.s_addr, sizeof(x.s_addr))==0) +#ifdef INET6 +#define af6cmp(x, y) (memcmp(&x.s6_addr, &y.s6_addr, sizeof(x.s6_addr))==0) +#endif + static int -selecthost(struct in_addr *in, int onoff) +selecthost(union storage_addr *addr, int family, int onoff) { struct hitem *p; - if (in == 0) { + if (addr == 0) { if (hosts == 0) return (0); free((char *)hosts), hosts = 0; @@ -266,7 +312,13 @@ selecthost(struct in_addr *in, int onoff return (1); } for (p = hosts; p < hosts+nhosts; p++) - if (p->addr.s_addr == in->s_addr) { +#ifdef INET6 + if (p->family == family && family == AF_INET ? + af4cmp(p->addr.in, addr->in) : af6cmp(p->addr.in6, addr->in6)) +#else + if (p->family == family && af4cmp(p->addr.in, addr->in)) +#endif + { p->onoff = onoff; return (0); } @@ -275,7 +327,8 @@ selecthost(struct in_addr *in, int onoff else hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p)); p = &hosts[nhosts++]; - p->addr = *in; + p->addr = *addr; + p->family = family; p->onoff = onoff; return (1); } @@ -287,9 +340,13 @@ checkhost(struct inpcb *inp) if (hosts) for (p = hosts; p < hosts+nhosts; p++) - if (p->addr.s_addr == inp->inp_laddr.s_addr || - p->addr.s_addr == inp->inp_faddr.s_addr) - return (p->onoff); + if (((inp->inp_vflag & INP_IPV4) && p->family == AF_INET && + (af4cmp(p->addr.in, inp->inp_laddr) || af4cmp(p->addr.in, inp->inp_faddr))) +#ifdef INET6 + || ((inp->inp_vflag & INP_IPV6) && p->family == AF_INET6 && + (af6cmp(p->addr.in6, inp->in6p_laddr) || af6cmp(p->addr.in6, inp->in6p_faddr))) +#endif + ) return (p->onoff); return (1); } @@ -298,11 +355,37 @@ showhosts(void) { struct hitem *p; struct hostent *hp; + const void *host; + socklen_t len; +#ifdef INET6 + char str[INET6_ADDRSTRLEN]; +#else + char str[INET_ADDRSTRLEN]; +#endif for (p = hosts; p < hosts+nhosts; p++) { - hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET); + switch (p->family) { + case AF_INET : + host = (const void *)&p->addr.in; + len = sizeof(p->addr.in); + break; +#ifdef INET6 + case AF_INET6 : + host = (const void *)&p->addr.in6; + len = sizeof(p->addr.in6); + break; +#endif + default : + continue; + } + hp = gethostbyaddr(host, len, p->family); if (!p->onoff) addch('!'); - printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr)); +#ifdef INET6 + printw("%s%s ", hp ? hp->h_name : (char *)inet_ntop(p->family, host, str, INET6_ADDRSTRLEN), + p->family == AF_INET ? "(v4)" : "(v6)"); +#else + printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr.in)); +#endif } }