diff options
Diffstat (limited to 'usr.bin/sockstat/sockstat.c')
-rw-r--r-- | usr.bin/sockstat/sockstat.c | 570 |
1 files changed, 451 insertions, 119 deletions
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index c80c833..d1ec0d3 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/in_pcb.h> +#include <netinet/sctp.h> #include <netinet/tcp.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_var.h> @@ -59,6 +60,11 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> +#define sstosin(ss) ((struct sockaddr_in *)(ss)) +#define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) +#define sstosun(ss) ((struct sockaddr_un *)(ss)) +#define sstosa(ss) ((struct sockaddr *)(ss)) + static int opt_4; /* Show IPv4 sockets */ static int opt_6; /* Show IPv6 sockets */ static int opt_c; /* Show connected sockets */ @@ -71,9 +77,8 @@ static int opt_v; /* Verbose mode */ /* * Default protocols to use if no -P was defined. */ -static const char *default_protos[] = {"tcp", "udp", "divert" }; -static size_t default_numprotos = - sizeof(default_protos) / sizeof(default_protos[0]); +static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; +static size_t default_numprotos = nitems(default_protos); static int *protos; /* protocols to use */ static size_t numprotos; /* allocated size of protos[] */ @@ -84,6 +89,11 @@ static int *ports; #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) +struct addr { + struct sockaddr_storage address; + struct addr *next; +}; + struct sock { void *socket; void *pcb; @@ -92,8 +102,8 @@ struct sock { int family; int proto; const char *protoname; - struct sockaddr_storage laddr; - struct sockaddr_storage faddr; + struct addr *laddr; + struct addr *faddr; struct sock *next; }; @@ -134,7 +144,8 @@ get_proto_type(const char *proto) } -static void init_protos(int num) +static void +init_protos(int num) { int proto_count = 0; @@ -157,7 +168,6 @@ static int parse_protos(char *protospec) { char *prot; - char *tmp = protospec; int proto_type, proto_index; if (protospec == NULL) @@ -165,7 +175,7 @@ parse_protos(char *protospec) init_protos(0); proto_index = 0; - while ((prot = strsep(&tmp, ",")) != NULL) { + while ((prot = strsep(&protospec, ",")) != NULL) { if (strlen(prot) == 0) continue; proto_type = get_proto_type(prot); @@ -222,26 +232,32 @@ parse_ports(const char *portspec) } static void -sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port) +sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) { struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; - bzero(sa, sizeof *sa); + bzero(ss, sizeof(*ss)); switch (af) { case AF_INET: - sin4 = (struct sockaddr_in *)sa; - sin4->sin_len = sizeof *sin4; + sin4 = sstosin(ss); + sin4->sin_len = sizeof(*sin4); sin4->sin_family = af; sin4->sin_port = port; sin4->sin_addr = *(struct in_addr *)addr; break; case AF_INET6: - sin6 = (struct sockaddr_in6 *)sa; - sin6->sin6_len = sizeof *sin6; + sin6 = sstosin6(ss); + sin6->sin6_len = sizeof(*sin6); sin6->sin6_family = af; sin6->sin6_port = port; sin6->sin6_addr = *(struct in6_addr *)addr; +#define s6_addr16 __u6_addr.__u6_addr16 + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + sin6->sin6_scope_id = + ntohs(sin6->sin6_addr.s6_addr16[1]); + sin6->sin6_addr.s6_addr16[1] = 0; + } break; default: abort(); @@ -249,6 +265,267 @@ sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port) } static void +free_socket(struct sock *sock) +{ + struct addr *cur, *next; + + cur = sock->laddr; + while (cur != NULL) { + next = cur->next; + free(cur); + cur = next; + } + cur = sock->faddr; + while (cur != NULL) { + next = cur->next; + free(cur); + cur = next; + } + free(sock); +} + +static void +gather_sctp(void) +{ + struct sock *sock; + struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; + struct xsctp_inpcb *xinpcb; + struct xsctp_tcb *xstcb; + struct xsctp_raddr *xraddr; + struct xsctp_laddr *xladdr; + const char *varname; + size_t len, offset; + char *buf; + int hash, vflag; + int no_stcb, local_all_loopback, foreign_all_loopback; + + vflag = 0; + if (opt_4) + vflag |= INP_IPV4; + if (opt_6) + vflag |= INP_IPV6; + + varname = "net.inet.sctp.assoclist"; + if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + err(1, "sysctlbyname()"); + return; + } + if ((buf = (char *)malloc(len)) == NULL) { + err(1, "malloc()"); + return; + } + if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { + err(1, "sysctlbyname()"); + free(buf); + return; + } + xinpcb = (struct xsctp_inpcb *)(void *)buf; + offset = sizeof(struct xsctp_inpcb); + while ((offset < len) && (xinpcb->last == 0)) { + if ((sock = calloc(1, sizeof *sock)) == NULL) + err(1, "malloc()"); + sock->socket = xinpcb->socket; + sock->proto = IPPROTO_SCTP; + sock->protoname = "sctp"; + if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { + sock->family = AF_INET6; + sock->vflag = INP_IPV6; + } else { + sock->family = AF_INET; + sock->vflag = INP_IPV4; + } + prev_laddr = NULL; + local_all_loopback = 1; + while (offset < len) { + xladdr = (struct xsctp_laddr *)(void *)(buf + offset); + offset += sizeof(struct xsctp_laddr); + if (xladdr->last == 1) + break; + if ((laddr = calloc(1, sizeof(struct addr))) == NULL) + err(1, "malloc()"); + switch (xladdr->address.sa.sa_family) { + case AF_INET: +#define __IN_IS_ADDR_LOOPBACK(pina) \ + ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) + local_all_loopback = 0; +#undef __IN_IS_ADDR_LOOPBACK + sockaddr(&laddr->address, + AF_INET, + &xladdr->address.sin.sin_addr, + htons(xinpcb->local_port)); + break; + case AF_INET6: + if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) + local_all_loopback = 0; + sockaddr(&laddr->address, + AF_INET6, + &xladdr->address.sin6.sin6_addr, + htons(xinpcb->local_port)); + break; + default: + errx(1, "adress family %d not supported", + xladdr->address.sa.sa_family); + } + laddr->next = NULL; + if (prev_laddr == NULL) + sock->laddr = laddr; + else + prev_laddr->next = laddr; + prev_laddr = laddr; + } + if (sock->laddr == NULL) { + if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) + err(1, "malloc()"); + sock->laddr->address.ss_family = sock->family; + if (sock->family == AF_INET) + sock->laddr->address.ss_len = sizeof(struct sockaddr_in); + else + sock->laddr->address.ss_len = sizeof(struct sockaddr_in); + local_all_loopback = 0; + } + if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) + err(1, "malloc()"); + sock->faddr->address.ss_family = sock->family; + if (sock->family == AF_INET) + sock->faddr->address.ss_len = sizeof(struct sockaddr_in); + else + sock->faddr->address.ss_len = sizeof(struct sockaddr_in); + no_stcb = 1; + while (offset < len) { + xstcb = (struct xsctp_tcb *)(void *)(buf + offset); + offset += sizeof(struct xsctp_tcb); + if (no_stcb) { + if (opt_l && + (!opt_L || !local_all_loopback) && + ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || + (xstcb->last == 1))) { + hash = (int)((uintptr_t)sock->socket % HASHSIZE); + sock->next = sockhash[hash]; + sockhash[hash] = sock; + } else { + free_socket(sock); + } + } + if (xstcb->last == 1) + break; + no_stcb = 0; + if (opt_c) { + if ((sock = calloc(1, sizeof *sock)) == NULL) + err(1, "malloc()"); + sock->socket = xinpcb->socket; + sock->proto = IPPROTO_SCTP; + sock->protoname = "sctp"; + if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { + sock->family = AF_INET6; + sock->vflag = INP_IPV6; + } else { + sock->family = AF_INET; + sock->vflag = INP_IPV4; + } + } + prev_laddr = NULL; + local_all_loopback = 1; + while (offset < len) { + xladdr = (struct xsctp_laddr *)(void *)(buf + offset); + offset += sizeof(struct xsctp_laddr); + if (xladdr->last == 1) + break; + if (!opt_c) + continue; + if ((laddr = calloc(1, sizeof(struct addr))) == NULL) + err(1, "malloc()"); + switch (xladdr->address.sa.sa_family) { + case AF_INET: +#define __IN_IS_ADDR_LOOPBACK(pina) \ + ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) + local_all_loopback = 0; +#undef __IN_IS_ADDR_LOOPBACK + sockaddr(&laddr->address, + AF_INET, + &xladdr->address.sin.sin_addr, + htons(xstcb->local_port)); + break; + case AF_INET6: + if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) + local_all_loopback = 0; + sockaddr(&laddr->address, + AF_INET6, + &xladdr->address.sin6.sin6_addr, + htons(xstcb->local_port)); + break; + default: + errx(1, "adress family %d not supported", + xladdr->address.sa.sa_family); + } + laddr->next = NULL; + if (prev_laddr == NULL) + sock->laddr = laddr; + else + prev_laddr->next = laddr; + prev_laddr = laddr; + } + prev_faddr = NULL; + foreign_all_loopback = 1; + while (offset < len) { + xraddr = (struct xsctp_raddr *)(void *)(buf + offset); + offset += sizeof(struct xsctp_raddr); + if (xraddr->last == 1) + break; + if (!opt_c) + continue; + if ((faddr = calloc(1, sizeof(struct addr))) == NULL) + err(1, "malloc()"); + switch (xraddr->address.sa.sa_family) { + case AF_INET: +#define __IN_IS_ADDR_LOOPBACK(pina) \ + ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) + foreign_all_loopback = 0; +#undef __IN_IS_ADDR_LOOPBACK + sockaddr(&faddr->address, + AF_INET, + &xraddr->address.sin.sin_addr, + htons(xstcb->remote_port)); + break; + case AF_INET6: + if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) + foreign_all_loopback = 0; + sockaddr(&faddr->address, + AF_INET6, + &xraddr->address.sin6.sin6_addr, + htons(xstcb->remote_port)); + break; + default: + errx(1, "adress family %d not supported", + xraddr->address.sa.sa_family); + } + faddr->next = NULL; + if (prev_faddr == NULL) + sock->faddr = faddr; + else + prev_faddr->next = faddr; + prev_faddr = faddr; + } + if (opt_c) { + if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { + hash = (int)((uintptr_t)sock->socket % HASHSIZE); + sock->next = sockhash[hash]; + sockhash[hash] = sock; + } else { + free_socket(sock); + } + } + } + xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); + offset += sizeof(struct xsctp_inpcb); + } + free(buf); +} + +static void gather_inet(int proto) { struct xinpgen *xig, *exig; @@ -257,6 +534,7 @@ gather_inet(int proto) struct inpcb *inp; struct xsocket *so; struct sock *sock; + struct addr *laddr, *faddr; const char *varname, *protoname; size_t len, bufsize; void *buf; @@ -319,7 +597,7 @@ gather_inet(int proto) switch (proto) { case IPPROTO_TCP: xtp = (struct xtcpcb *)xig; - if (xtp->xt_len != sizeof *xtp) { + if (xtp->xt_len != sizeof(*xtp)) { warnx("struct xtcpcb size mismatch"); goto out; } @@ -330,7 +608,7 @@ gather_inet(int proto) case IPPROTO_UDP: case IPPROTO_DIVERT: xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { + if (xip->xi_len != sizeof(*xip)) { warnx("struct xinpcb size mismatch"); goto out; } @@ -366,23 +644,31 @@ gather_inet(int proto) warnx("invalid vflag 0x%x", inp->inp_vflag); continue; } - if ((sock = calloc(1, sizeof *sock)) == NULL) + if ((sock = calloc(1, sizeof(*sock))) == NULL) + err(1, "malloc()"); + if ((laddr = calloc(1, sizeof *laddr)) == NULL) + err(1, "malloc()"); + if ((faddr = calloc(1, sizeof *faddr)) == NULL) err(1, "malloc()"); sock->socket = so->xso_so; sock->proto = proto; if (inp->inp_vflag & INP_IPV4) { sock->family = AF_INET; - sockaddr(&sock->laddr, sock->family, + sockaddr(&laddr->address, sock->family, &inp->inp_laddr, inp->inp_lport); - sockaddr(&sock->faddr, sock->family, + sockaddr(&faddr->address, sock->family, &inp->inp_faddr, inp->inp_fport); } else if (inp->inp_vflag & INP_IPV6) { sock->family = AF_INET6; - sockaddr(&sock->laddr, sock->family, + sockaddr(&laddr->address, sock->family, &inp->in6p_laddr, inp->inp_lport); - sockaddr(&sock->faddr, sock->family, + sockaddr(&faddr->address, sock->family, &inp->in6p_faddr, inp->inp_fport); } + laddr->next = NULL; + faddr->next = NULL; + sock->laddr = laddr; + sock->faddr = faddr; sock->vflag = inp->inp_vflag; sock->protoname = protoname; hash = (int)((uintptr_t)sock->socket % HASHSIZE); @@ -399,6 +685,7 @@ gather_unix(int proto) struct xunpgen *xug, *exug; struct xunpcb *xup; struct sock *sock; + struct addr *laddr, *faddr; const char *varname, *protoname; size_t len, bufsize; void *buf; @@ -413,6 +700,10 @@ gather_unix(int proto) varname = "net.local.dgram.pcblist"; protoname = "dgram"; break; + case SOCK_SEQPACKET: + varname = "net.local.seqpacket.pcblist"; + protoname = "seqpac"; + break; default: abort(); } @@ -432,9 +723,9 @@ gather_unix(int proto) } xug = (struct xunpgen *)buf; exug = (struct xunpgen *)(void *) - ((char *)buf + len - sizeof *exug); - if (xug->xug_len != sizeof *xug || - exug->xug_len != sizeof *exug) { + ((char *)buf + len - sizeof(*exug)); + if (xug->xug_len != sizeof(*xug) || + exug->xug_len != sizeof(*exug)) { warnx("struct xinpgen size mismatch"); goto out; } @@ -448,14 +739,18 @@ gather_unix(int proto) if (xug >= exug) break; xup = (struct xunpcb *)xug; - if (xup->xu_len != sizeof *xup) { + if (xup->xu_len != sizeof(*xup)) { warnx("struct xunpcb size mismatch"); goto out; } if ((xup->xu_unp.unp_conn == NULL && !opt_l) || (xup->xu_unp.unp_conn != NULL && !opt_c)) continue; - if ((sock = calloc(1, sizeof *sock)) == NULL) + if ((sock = calloc(1, sizeof(*sock))) == NULL) + err(1, "malloc()"); + if ((laddr = calloc(1, sizeof *laddr)) == NULL) + err(1, "malloc()"); + if ((faddr = calloc(1, sizeof *faddr)) == NULL) err(1, "malloc()"); sock->socket = xup->xu_socket.xso_so; sock->pcb = xup->xu_unpp; @@ -463,10 +758,14 @@ gather_unix(int proto) sock->family = AF_UNIX; sock->protoname = protoname; if (xup->xu_unp.unp_addr != NULL) - sock->laddr = + laddr->address = *(struct sockaddr_storage *)(void *)&xup->xu_addr; else if (xup->xu_unp.unp_conn != NULL) - *(void **)&sock->faddr = xup->xu_unp.unp_conn; + *(void **)&(faddr->address) = xup->xu_unp.unp_conn; + laddr->next = NULL; + faddr->next = NULL; + sock->laddr = laddr; + sock->faddr = faddr; hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; sockhash[hash] = sock; @@ -480,7 +779,7 @@ getfiles(void) { size_t len, olen; - olen = len = sizeof *xfiles; + olen = len = sizeof(*xfiles); if ((xfiles = malloc(len)) == NULL) err(1, "malloc()"); while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { @@ -490,39 +789,40 @@ getfiles(void) if ((xfiles = realloc(xfiles, len)) == NULL) err(1, "realloc()"); } - if (len > 0 && xfiles->xf_size != sizeof *xfiles) + if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) errx(1, "struct xfile size mismatch"); - nxfiles = len / sizeof *xfiles; + nxfiles = len / sizeof(*xfiles); } static int -printaddr(int af, struct sockaddr_storage *ss) +printaddr(struct sockaddr_storage *ss) { - char addrstr[INET6_ADDRSTRLEN] = { '\0', '\0' }; struct sockaddr_un *sun; - void *addr = NULL; /* Keep compiler happy. */ - int off, port = 0; + char addrstr[NI_MAXHOST] = { '\0', '\0' }; + int error, off, port = 0; - switch (af) { + switch (ss->ss_family) { case AF_INET: - addr = &((struct sockaddr_in *)ss)->sin_addr; - if (inet_lnaof(*(struct in_addr *)addr) == INADDR_ANY) + if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) addrstr[0] = '*'; - port = ntohs(((struct sockaddr_in *)ss)->sin_port); + port = ntohs(sstosin(ss)->sin_port); break; case AF_INET6: - addr = &((struct sockaddr_in6 *)ss)->sin6_addr; - if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)addr)) + if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) addrstr[0] = '*'; - port = ntohs(((struct sockaddr_in6 *)ss)->sin6_port); + port = ntohs(sstosin6(ss)->sin6_port); break; case AF_UNIX: - sun = (struct sockaddr_un *)ss; + sun = sstosun(ss); off = (int)((char *)&sun->sun_path - (char *)sun); return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); } - if (addrstr[0] == '\0') - inet_ntop(af, addr, addrstr, sizeof addrstr); + if (addrstr[0] == '\0') { + error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, + sizeof(addrstr), NULL, 0, NI_NUMERICHOST); + if (error) + errx(1, "getnameinfo()"); + } if (port == 0) return xprintf("%s:*", addrstr); else @@ -540,8 +840,8 @@ getprocname(pid_t pid) mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = (int)pid; - len = sizeof proc; - if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { + len = sizeof(proc); + if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { /* Do not warn if the process exits before we get its name. */ if (errno != ESRCH) warn("sysctl()"); @@ -561,8 +861,8 @@ getprocjid(pid_t pid) mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = (int)pid; - len = sizeof proc; - if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { + len = sizeof(proc); + if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { /* Do not warn if the process exits before we get its jid. */ if (errno != ESRCH) warn("sysctl()"); @@ -575,23 +875,28 @@ static int check_ports(struct sock *s) { int port; + struct addr *addr; if (ports == NULL) return (1); if ((s->family != AF_INET) && (s->family != AF_INET6)) return (1); - if (s->family == AF_INET) - port = ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port); - else - port = ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port); - if (CHK_PORT(port)) - return (1); - if (s->family == AF_INET) - port = ntohs(((struct sockaddr_in *)(&s->faddr))->sin_port); - else - port = ntohs(((struct sockaddr_in6 *)(&s->faddr))->sin6_port); - if (CHK_PORT(port)) - return (1); + for (addr = s->laddr; addr != NULL; addr = addr->next) { + if (s->family == AF_INET) + port = ntohs(sstosin(&addr->address)->sin_port); + else + port = ntohs(sstosin6(&addr->address)->sin6_port); + if (CHK_PORT(port)) + return (1); + } + for (addr = s->faddr; addr != NULL; addr = addr->next) { + if (s->family == AF_INET) + port = ntohs(sstosin(&addr->address)->sin_port); + else + port = ntohs(sstosin6(&addr->address)->sin6_port); + if (CHK_PORT(port)) + return (1); + } return (0); } @@ -600,6 +905,8 @@ displaysock(struct sock *s, int pos) { void *p; int hash; + struct addr *laddr, *faddr; + struct sock *s_tmp; while (pos < 29) pos += xprintf(" "); @@ -608,45 +915,67 @@ displaysock(struct sock *s, int pos) pos += xprintf("4 "); if (s->vflag & INP_IPV6) pos += xprintf("6 "); - while (pos < 36) - pos += xprintf(" "); - switch (s->family) { - case AF_INET: - case AF_INET6: - pos += printaddr(s->family, &s->laddr); - if (s->family == AF_INET6 && pos >= 58) + laddr = s->laddr; + faddr = s->faddr; + while (laddr != NULL || faddr != NULL) { + while (pos < 36) pos += xprintf(" "); - while (pos < 58) - pos += xprintf(" "); - pos += printaddr(s->family, &s->faddr); - break; - case AF_UNIX: - /* server */ - if (s->laddr.ss_len > 0) { - pos += printaddr(s->family, &s->laddr); + switch (s->family) { + case AF_INET: + case AF_INET6: + if (laddr != NULL) { + pos += printaddr(&laddr->address); + if (s->family == AF_INET6 && pos >= 58) + pos += xprintf(" "); + } + while (pos < 58) + pos += xprintf(" "); + if (faddr != NULL) + pos += printaddr(&faddr->address); break; - } - /* client */ - p = *(void **)&s->faddr; - if (p == NULL) { - pos += xprintf("(not connected)"); + case AF_UNIX: + if ((laddr == NULL) || (faddr == NULL)) + errx(1, "laddr = %p or faddr = %p is NULL", + (void *)laddr, (void *)faddr); + /* server */ + if (laddr->address.ss_len > 0) { + pos += printaddr(&laddr->address); + break; + } + /* client */ + p = *(void **)&(faddr->address); + if (p == NULL) { + pos += xprintf("(not connected)"); + break; + } + pos += xprintf("-> "); + for (hash = 0; hash < HASHSIZE; ++hash) { + for (s_tmp = sockhash[hash]; + s_tmp != NULL; + s_tmp = s_tmp->next) + if (s_tmp->pcb == p) + break; + if (s_tmp != NULL) + break; + } + if (s_tmp == NULL || + s_tmp->laddr == NULL || + s_tmp->laddr->address.ss_len == 0) + pos += xprintf("??"); + else + pos += printaddr(&s_tmp->laddr->address); break; + default: + abort(); } - pos += xprintf("-> "); - for (hash = 0; hash < HASHSIZE; ++hash) { - for (s = sockhash[hash]; s != NULL; s = s->next) - if (s->pcb == p) - break; - if (s != NULL) - break; + if (laddr != NULL) + laddr = laddr->next; + if (faddr != NULL) + faddr = faddr->next; + if ((laddr != NULL) || (faddr != NULL)) { + xprintf("\n"); + pos = 0; } - if (s == NULL || s->laddr.ss_len == 0) - pos += xprintf("??"); - else - pos += printaddr(s->family, &s->laddr); - break; - default: - abort(); } xprintf("\n"); } @@ -669,29 +998,28 @@ display(void) if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) continue; hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); - for (s = sockhash[hash]; s != NULL; s = s->next) - if ((void *)s->socket == xf->xf_data) - break; - if (s == NULL) - continue; - if (!check_ports(s)) - continue; - s->shown = 1; - pos = 0; - if ((pwd = getpwuid(xf->xf_uid)) == NULL) - pos += xprintf("%lu ", (u_long)xf->xf_uid); - else - pos += xprintf("%s ", pwd->pw_name); - while (pos < 9) - pos += xprintf(" "); - pos += xprintf("%.10s", getprocname(xf->xf_pid)); - while (pos < 20) - pos += xprintf(" "); - pos += xprintf("%lu ", (u_long)xf->xf_pid); - while (pos < 26) - pos += xprintf(" "); - pos += xprintf("%d ", xf->xf_fd); - displaysock(s, pos); + for (s = sockhash[hash]; s != NULL; s = s->next) { + if ((void *)s->socket != xf->xf_data) + continue; + if (!check_ports(s)) + continue; + s->shown = 1; + pos = 0; + if ((pwd = getpwuid(xf->xf_uid)) == NULL) + pos += xprintf("%lu ", (u_long)xf->xf_uid); + else + pos += xprintf("%s ", pwd->pw_name); + while (pos < 9) + pos += xprintf(" "); + pos += xprintf("%.10s", getprocname(xf->xf_pid)); + while (pos < 20) + pos += xprintf(" "); + pos += xprintf("%lu ", (u_long)xf->xf_pid); + while (pos < 26) + pos += xprintf(" "); + pos += xprintf("%d ", xf->xf_fd); + displaysock(s, pos); + } } if (opt_j >= 0) return; @@ -797,12 +1125,16 @@ main(int argc, char *argv[]) if (opt_4 || opt_6) { for (i = 0; i < protos_defined; i++) - gather_inet(protos[i]); + if (protos[i] == IPPROTO_SCTP) + gather_sctp(); + else + gather_inet(protos[i]); } if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { gather_unix(SOCK_STREAM); gather_unix(SOCK_DGRAM); + gather_unix(SOCK_SEQPACKET); } getfiles(); display(); |