1ca007d91SDag-Erling Smørgrav /*- 2fb2ad9d3SUlrich Spörlein * Copyright (c) 2002 Dag-Erling Coïdan Smørgrav 3ca007d91SDag-Erling Smørgrav * All rights reserved. 4ca007d91SDag-Erling Smørgrav * 5ca007d91SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 6ca007d91SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 7ca007d91SDag-Erling Smørgrav * are met: 8ca007d91SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 9ca007d91SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 10ca007d91SDag-Erling Smørgrav * in this position and unchanged. 11ca007d91SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 12ca007d91SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 13ca007d91SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 14ca007d91SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 15ca007d91SDag-Erling Smørgrav * derived from this software without specific prior written permission. 16ca007d91SDag-Erling Smørgrav * 17ca007d91SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18ca007d91SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19ca007d91SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20ca007d91SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21ca007d91SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22ca007d91SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23ca007d91SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24ca007d91SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25ca007d91SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26ca007d91SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27ca007d91SDag-Erling Smørgrav */ 28ca007d91SDag-Erling Smørgrav 29ca007d91SDag-Erling Smørgrav #include <sys/cdefs.h> 30ca007d91SDag-Erling Smørgrav __FBSDID("$FreeBSD$"); 31ca007d91SDag-Erling Smørgrav 32ca007d91SDag-Erling Smørgrav #include <sys/param.h> 33ca007d91SDag-Erling Smørgrav #include <sys/socket.h> 34ca007d91SDag-Erling Smørgrav #include <sys/socketvar.h> 35ca007d91SDag-Erling Smørgrav #include <sys/sysctl.h> 36ca007d91SDag-Erling Smørgrav #include <sys/file.h> 37ca007d91SDag-Erling Smørgrav #include <sys/user.h> 38ca007d91SDag-Erling Smørgrav 39ca007d91SDag-Erling Smørgrav #include <sys/un.h> 40ca007d91SDag-Erling Smørgrav #include <sys/unpcb.h> 41ca007d91SDag-Erling Smørgrav 4202bd9db0SDag-Erling Smørgrav #include <net/route.h> 4302bd9db0SDag-Erling Smørgrav 44ca007d91SDag-Erling Smørgrav #include <netinet/in.h> 45ca007d91SDag-Erling Smørgrav #include <netinet/in_pcb.h> 46d5b4aa90SMichael Tuexen #include <netinet/sctp.h> 47ca007d91SDag-Erling Smørgrav #include <netinet/tcp.h> 487a5642b3SDag-Erling Smørgrav #define TCPSTATES /* load state names */ 497a5642b3SDag-Erling Smørgrav #include <netinet/tcp_fsm.h> 50ca007d91SDag-Erling Smørgrav #include <netinet/tcp_seq.h> 51ca007d91SDag-Erling Smørgrav #include <netinet/tcp_var.h> 52ca007d91SDag-Erling Smørgrav #include <arpa/inet.h> 53ca007d91SDag-Erling Smørgrav 54ca007d91SDag-Erling Smørgrav #include <ctype.h> 55ca007d91SDag-Erling Smørgrav #include <err.h> 56ca007d91SDag-Erling Smørgrav #include <errno.h> 57ca007d91SDag-Erling Smørgrav #include <netdb.h> 58ca007d91SDag-Erling Smørgrav #include <pwd.h> 59ca007d91SDag-Erling Smørgrav #include <stdarg.h> 60ca007d91SDag-Erling Smørgrav #include <stdio.h> 61ca007d91SDag-Erling Smørgrav #include <stdlib.h> 62ca007d91SDag-Erling Smørgrav #include <string.h> 63ca007d91SDag-Erling Smørgrav #include <unistd.h> 64ca007d91SDag-Erling Smørgrav 65b8e20e2dSHiroki Sato #define sstosin(ss) ((struct sockaddr_in *)(ss)) 66b8e20e2dSHiroki Sato #define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) 67b8e20e2dSHiroki Sato #define sstosun(ss) ((struct sockaddr_un *)(ss)) 68b8e20e2dSHiroki Sato #define sstosa(ss) ((struct sockaddr *)(ss)) 69b8e20e2dSHiroki Sato 70ca007d91SDag-Erling Smørgrav static int opt_4; /* Show IPv4 sockets */ 71ca007d91SDag-Erling Smørgrav static int opt_6; /* Show IPv6 sockets */ 72ca007d91SDag-Erling Smørgrav static int opt_c; /* Show connected sockets */ 7300feaafdSAndrew Thompson static int opt_j; /* Show specified jail */ 749b6ca892SBruce M Simpson static int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 75ca007d91SDag-Erling Smørgrav static int opt_l; /* Show listening sockets */ 76*e5cccc35SMichael Tuexen static int opt_S; /* Show protocol stack if applicable */ 777a5642b3SDag-Erling Smørgrav static int opt_s; /* Show protocol state if applicable */ 78ca007d91SDag-Erling Smørgrav static int opt_u; /* Show Unix domain sockets */ 79ca007d91SDag-Erling Smørgrav static int opt_v; /* Verbose mode */ 80ca007d91SDag-Erling Smørgrav 811f3d67aaSGiorgos Keramidas /* 821f3d67aaSGiorgos Keramidas * Default protocols to use if no -P was defined. 831f3d67aaSGiorgos Keramidas */ 84d5b4aa90SMichael Tuexen static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 85b8e20e2dSHiroki Sato static size_t default_numprotos = nitems(default_protos); 861f3d67aaSGiorgos Keramidas 871f3d67aaSGiorgos Keramidas static int *protos; /* protocols to use */ 881f3d67aaSGiorgos Keramidas static size_t numprotos; /* allocated size of protos[] */ 891f3d67aaSGiorgos Keramidas 90ca007d91SDag-Erling Smørgrav static int *ports; 91ca007d91SDag-Erling Smørgrav 92ca007d91SDag-Erling Smørgrav #define INT_BIT (sizeof(int)*CHAR_BIT) 93ca007d91SDag-Erling Smørgrav #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 94ca007d91SDag-Erling Smørgrav #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 95ca007d91SDag-Erling Smørgrav 96e6f718c7SMichael Tuexen struct addr { 97e6f718c7SMichael Tuexen struct sockaddr_storage address; 98e6f718c7SMichael Tuexen struct addr *next; 99e6f718c7SMichael Tuexen }; 100e6f718c7SMichael Tuexen 101ca007d91SDag-Erling Smørgrav struct sock { 102ca007d91SDag-Erling Smørgrav void *socket; 103ca007d91SDag-Erling Smørgrav void *pcb; 10461149f8dSJilles Tjoelker int shown; 105ca007d91SDag-Erling Smørgrav int vflag; 106ca007d91SDag-Erling Smørgrav int family; 107ca007d91SDag-Erling Smørgrav int proto; 1087a5642b3SDag-Erling Smørgrav int state; 109ca007d91SDag-Erling Smørgrav const char *protoname; 110*e5cccc35SMichael Tuexen char stack[TCP_FUNCTION_NAME_LEN_MAX]; 111e6f718c7SMichael Tuexen struct addr *laddr; 112e6f718c7SMichael Tuexen struct addr *faddr; 113ca007d91SDag-Erling Smørgrav struct sock *next; 114ca007d91SDag-Erling Smørgrav }; 115ca007d91SDag-Erling Smørgrav 116ca007d91SDag-Erling Smørgrav #define HASHSIZE 1009 117ca007d91SDag-Erling Smørgrav static struct sock *sockhash[HASHSIZE]; 118ca007d91SDag-Erling Smørgrav 119ca007d91SDag-Erling Smørgrav static struct xfile *xfiles; 120ca007d91SDag-Erling Smørgrav static int nxfiles; 121ca007d91SDag-Erling Smørgrav 122ca007d91SDag-Erling Smørgrav static int 123ca007d91SDag-Erling Smørgrav xprintf(const char *fmt, ...) 124ca007d91SDag-Erling Smørgrav { 125ca007d91SDag-Erling Smørgrav va_list ap; 126ca007d91SDag-Erling Smørgrav int len; 127ca007d91SDag-Erling Smørgrav 128ca007d91SDag-Erling Smørgrav va_start(ap, fmt); 129ca007d91SDag-Erling Smørgrav len = vprintf(fmt, ap); 130ca007d91SDag-Erling Smørgrav va_end(ap); 131ca007d91SDag-Erling Smørgrav if (len < 0) 132ca007d91SDag-Erling Smørgrav err(1, "printf()"); 133ca007d91SDag-Erling Smørgrav return (len); 134ca007d91SDag-Erling Smørgrav } 135ca007d91SDag-Erling Smørgrav 1361f3d67aaSGiorgos Keramidas static int 1371f3d67aaSGiorgos Keramidas get_proto_type(const char *proto) 1381f3d67aaSGiorgos Keramidas { 1391f3d67aaSGiorgos Keramidas struct protoent *pent; 1401f3d67aaSGiorgos Keramidas 1411f3d67aaSGiorgos Keramidas if (strlen(proto) == 0) 1421f3d67aaSGiorgos Keramidas return (0); 1431f3d67aaSGiorgos Keramidas pent = getprotobyname(proto); 1441f3d67aaSGiorgos Keramidas if (pent == NULL) { 1451f3d67aaSGiorgos Keramidas warn("getprotobyname"); 1461f3d67aaSGiorgos Keramidas return (-1); 1471f3d67aaSGiorgos Keramidas } 1481f3d67aaSGiorgos Keramidas return (pent->p_proto); 1491f3d67aaSGiorgos Keramidas } 1501f3d67aaSGiorgos Keramidas 151b8e20e2dSHiroki Sato static void 152b8e20e2dSHiroki Sato init_protos(int num) 1531f3d67aaSGiorgos Keramidas { 1541f3d67aaSGiorgos Keramidas int proto_count = 0; 1551f3d67aaSGiorgos Keramidas 1561f3d67aaSGiorgos Keramidas if (num > 0) { 1571f3d67aaSGiorgos Keramidas proto_count = num; 1581f3d67aaSGiorgos Keramidas } else { 1591f3d67aaSGiorgos Keramidas /* Find the maximum number of possible protocols. */ 1601f3d67aaSGiorgos Keramidas while (getprotoent() != NULL) 1611f3d67aaSGiorgos Keramidas proto_count++; 1621f3d67aaSGiorgos Keramidas endprotoent(); 1631f3d67aaSGiorgos Keramidas } 1641f3d67aaSGiorgos Keramidas 1651f3d67aaSGiorgos Keramidas if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 1661f3d67aaSGiorgos Keramidas err(1, "malloc"); 1671f3d67aaSGiorgos Keramidas numprotos = proto_count; 1681f3d67aaSGiorgos Keramidas } 1691f3d67aaSGiorgos Keramidas 1701f3d67aaSGiorgos Keramidas static int 1711f3d67aaSGiorgos Keramidas parse_protos(char *protospec) 1721f3d67aaSGiorgos Keramidas { 1731f3d67aaSGiorgos Keramidas char *prot; 1741f3d67aaSGiorgos Keramidas int proto_type, proto_index; 1751f3d67aaSGiorgos Keramidas 1761f3d67aaSGiorgos Keramidas if (protospec == NULL) 1771f3d67aaSGiorgos Keramidas return (-1); 1781f3d67aaSGiorgos Keramidas 1791f3d67aaSGiorgos Keramidas init_protos(0); 1801f3d67aaSGiorgos Keramidas proto_index = 0; 181b8e20e2dSHiroki Sato while ((prot = strsep(&protospec, ",")) != NULL) { 1821f3d67aaSGiorgos Keramidas if (strlen(prot) == 0) 1831f3d67aaSGiorgos Keramidas continue; 1841f3d67aaSGiorgos Keramidas proto_type = get_proto_type(prot); 1851f3d67aaSGiorgos Keramidas if (proto_type != -1) 1861f3d67aaSGiorgos Keramidas protos[proto_index++] = proto_type; 1871f3d67aaSGiorgos Keramidas } 1881f3d67aaSGiorgos Keramidas numprotos = proto_index; 1891f3d67aaSGiorgos Keramidas return (proto_index); 1901f3d67aaSGiorgos Keramidas } 1911f3d67aaSGiorgos Keramidas 192ca007d91SDag-Erling Smørgrav static void 193ca007d91SDag-Erling Smørgrav parse_ports(const char *portspec) 194ca007d91SDag-Erling Smørgrav { 195ca007d91SDag-Erling Smørgrav const char *p, *q; 196ca007d91SDag-Erling Smørgrav int port, end; 197ca007d91SDag-Erling Smørgrav 198ca007d91SDag-Erling Smørgrav if (ports == NULL) 1999efed1e6SRobert Drehmel if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 200ca007d91SDag-Erling Smørgrav err(1, "calloc()"); 201ca007d91SDag-Erling Smørgrav p = portspec; 202ca007d91SDag-Erling Smørgrav while (*p != '\0') { 203ca007d91SDag-Erling Smørgrav if (!isdigit(*p)) 204ca007d91SDag-Erling Smørgrav errx(1, "syntax error in port range"); 205ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 206ca007d91SDag-Erling Smørgrav /* nothing */ ; 207ca007d91SDag-Erling Smørgrav for (port = 0; p < q; ++p) 208ca007d91SDag-Erling Smørgrav port = port * 10 + digittoint(*p); 209ca007d91SDag-Erling Smørgrav if (port < 0 || port > 65535) 210ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 211ca007d91SDag-Erling Smørgrav SET_PORT(port); 212ca007d91SDag-Erling Smørgrav switch (*p) { 213ca007d91SDag-Erling Smørgrav case '-': 214ca007d91SDag-Erling Smørgrav ++p; 215ca007d91SDag-Erling Smørgrav break; 216ca007d91SDag-Erling Smørgrav case ',': 217ca007d91SDag-Erling Smørgrav ++p; 218ca007d91SDag-Erling Smørgrav /* fall through */ 219ca007d91SDag-Erling Smørgrav case '\0': 220ca007d91SDag-Erling Smørgrav default: 221ca007d91SDag-Erling Smørgrav continue; 222ca007d91SDag-Erling Smørgrav } 223ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 224ca007d91SDag-Erling Smørgrav /* nothing */ ; 225ca007d91SDag-Erling Smørgrav for (end = 0; p < q; ++p) 226ca007d91SDag-Erling Smørgrav end = end * 10 + digittoint(*p); 227ca007d91SDag-Erling Smørgrav if (end < port || end > 65535) 228ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 229ca007d91SDag-Erling Smørgrav while (port++ < end) 230ca007d91SDag-Erling Smørgrav SET_PORT(port); 231ca007d91SDag-Erling Smørgrav if (*p == ',') 232ca007d91SDag-Erling Smørgrav ++p; 233ca007d91SDag-Erling Smørgrav } 234ca007d91SDag-Erling Smørgrav } 235ca007d91SDag-Erling Smørgrav 236ca007d91SDag-Erling Smørgrav static void 237b8e20e2dSHiroki Sato sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 238ca007d91SDag-Erling Smørgrav { 239ca007d91SDag-Erling Smørgrav struct sockaddr_in *sin4; 240ca007d91SDag-Erling Smørgrav struct sockaddr_in6 *sin6; 241ca007d91SDag-Erling Smørgrav 242b8e20e2dSHiroki Sato bzero(ss, sizeof(*ss)); 243ca007d91SDag-Erling Smørgrav switch (af) { 244ca007d91SDag-Erling Smørgrav case AF_INET: 245b8e20e2dSHiroki Sato sin4 = sstosin(ss); 246b8e20e2dSHiroki Sato sin4->sin_len = sizeof(*sin4); 247ca007d91SDag-Erling Smørgrav sin4->sin_family = af; 248ca007d91SDag-Erling Smørgrav sin4->sin_port = port; 249ca007d91SDag-Erling Smørgrav sin4->sin_addr = *(struct in_addr *)addr; 250ca007d91SDag-Erling Smørgrav break; 251ca007d91SDag-Erling Smørgrav case AF_INET6: 252b8e20e2dSHiroki Sato sin6 = sstosin6(ss); 253b8e20e2dSHiroki Sato sin6->sin6_len = sizeof(*sin6); 254ca007d91SDag-Erling Smørgrav sin6->sin6_family = af; 255ca007d91SDag-Erling Smørgrav sin6->sin6_port = port; 256ca007d91SDag-Erling Smørgrav sin6->sin6_addr = *(struct in6_addr *)addr; 257b8e20e2dSHiroki Sato #define s6_addr16 __u6_addr.__u6_addr16 258b8e20e2dSHiroki Sato if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 259b8e20e2dSHiroki Sato sin6->sin6_scope_id = 260b8e20e2dSHiroki Sato ntohs(sin6->sin6_addr.s6_addr16[1]); 261b8e20e2dSHiroki Sato sin6->sin6_addr.s6_addr16[1] = 0; 262b8e20e2dSHiroki Sato } 263ca007d91SDag-Erling Smørgrav break; 264ca007d91SDag-Erling Smørgrav default: 265ca007d91SDag-Erling Smørgrav abort(); 266ca007d91SDag-Erling Smørgrav } 267ca007d91SDag-Erling Smørgrav } 268ca007d91SDag-Erling Smørgrav 269ca007d91SDag-Erling Smørgrav static void 270bedcf91dSMichael Tuexen free_socket(struct sock *sock) 271bedcf91dSMichael Tuexen { 272bedcf91dSMichael Tuexen struct addr *cur, *next; 273bedcf91dSMichael Tuexen 274bedcf91dSMichael Tuexen cur = sock->laddr; 275bedcf91dSMichael Tuexen while (cur != NULL) { 276bedcf91dSMichael Tuexen next = cur->next; 277bedcf91dSMichael Tuexen free(cur); 278bedcf91dSMichael Tuexen cur = next; 279bedcf91dSMichael Tuexen } 280bedcf91dSMichael Tuexen cur = sock->faddr; 281bedcf91dSMichael Tuexen while (cur != NULL) { 282bedcf91dSMichael Tuexen next = cur->next; 283bedcf91dSMichael Tuexen free(cur); 284bedcf91dSMichael Tuexen cur = next; 285bedcf91dSMichael Tuexen } 286bedcf91dSMichael Tuexen free(sock); 287bedcf91dSMichael Tuexen } 288bedcf91dSMichael Tuexen 289bedcf91dSMichael Tuexen static void 290d5b4aa90SMichael Tuexen gather_sctp(void) 291d5b4aa90SMichael Tuexen { 292d5b4aa90SMichael Tuexen struct sock *sock; 293d5b4aa90SMichael Tuexen struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 294d5b4aa90SMichael Tuexen struct xsctp_inpcb *xinpcb; 295d5b4aa90SMichael Tuexen struct xsctp_tcb *xstcb; 296d5b4aa90SMichael Tuexen struct xsctp_raddr *xraddr; 297d5b4aa90SMichael Tuexen struct xsctp_laddr *xladdr; 298d5b4aa90SMichael Tuexen const char *varname; 299d5b4aa90SMichael Tuexen size_t len, offset; 300d5b4aa90SMichael Tuexen char *buf; 301d5b4aa90SMichael Tuexen int hash, vflag; 302d5b4aa90SMichael Tuexen int no_stcb, local_all_loopback, foreign_all_loopback; 303d5b4aa90SMichael Tuexen 304d5b4aa90SMichael Tuexen vflag = 0; 305d5b4aa90SMichael Tuexen if (opt_4) 306d5b4aa90SMichael Tuexen vflag |= INP_IPV4; 307d5b4aa90SMichael Tuexen if (opt_6) 308d5b4aa90SMichael Tuexen vflag |= INP_IPV6; 309d5b4aa90SMichael Tuexen 310d5b4aa90SMichael Tuexen varname = "net.inet.sctp.assoclist"; 311d5b4aa90SMichael Tuexen if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { 312d5b4aa90SMichael Tuexen if (errno != ENOENT) 313d5b4aa90SMichael Tuexen err(1, "sysctlbyname()"); 314d5b4aa90SMichael Tuexen return; 315d5b4aa90SMichael Tuexen } 316d5b4aa90SMichael Tuexen if ((buf = (char *)malloc(len)) == NULL) { 317d5b4aa90SMichael Tuexen err(1, "malloc()"); 318d5b4aa90SMichael Tuexen return; 319d5b4aa90SMichael Tuexen } 320d5b4aa90SMichael Tuexen if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { 321d5b4aa90SMichael Tuexen err(1, "sysctlbyname()"); 322d5b4aa90SMichael Tuexen free(buf); 323d5b4aa90SMichael Tuexen return; 324d5b4aa90SMichael Tuexen } 325d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)buf; 326d5b4aa90SMichael Tuexen offset = sizeof(struct xsctp_inpcb); 327d5b4aa90SMichael Tuexen while ((offset < len) && (xinpcb->last == 0)) { 328d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 329d5b4aa90SMichael Tuexen err(1, "malloc()"); 330d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 331d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 332d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 333c1eb13c7SMichael Tuexen if (xinpcb->maxqlen == 0) 3346414db1bSMichael Tuexen sock->state = SCTP_CLOSED; 3356414db1bSMichael Tuexen else 3366414db1bSMichael Tuexen sock->state = SCTP_LISTEN; 337d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 338d5b4aa90SMichael Tuexen sock->family = AF_INET6; 339edc9c7fcSMichael Tuexen /* 340edc9c7fcSMichael Tuexen * Currently there is no way to distinguish between 341edc9c7fcSMichael Tuexen * IPv6 only sockets or dual family sockets. 342edc9c7fcSMichael Tuexen * So mark it as dual socket. 343edc9c7fcSMichael Tuexen */ 344edc9c7fcSMichael Tuexen sock->vflag = INP_IPV6 | INP_IPV4; 345d5b4aa90SMichael Tuexen } else { 346d5b4aa90SMichael Tuexen sock->family = AF_INET; 347d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 348d5b4aa90SMichael Tuexen } 349d5b4aa90SMichael Tuexen prev_laddr = NULL; 350d5b4aa90SMichael Tuexen local_all_loopback = 1; 351d5b4aa90SMichael Tuexen while (offset < len) { 352d5b4aa90SMichael Tuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 353d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 354d5b4aa90SMichael Tuexen if (xladdr->last == 1) 355d5b4aa90SMichael Tuexen break; 356d5b4aa90SMichael Tuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 357d5b4aa90SMichael Tuexen err(1, "malloc()"); 358d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 359d5b4aa90SMichael Tuexen case AF_INET: 360d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 361d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 36227569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 36327569d01SRenato Botelho &xladdr->address.sin.sin_addr)) 364d5b4aa90SMichael Tuexen local_all_loopback = 0; 365d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 36627569d01SRenato Botelho sockaddr(&laddr->address, AF_INET, 367d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 368d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 369d5b4aa90SMichael Tuexen break; 370d5b4aa90SMichael Tuexen case AF_INET6: 37127569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 37227569d01SRenato Botelho &xladdr->address.sin6.sin6_addr)) 373d5b4aa90SMichael Tuexen local_all_loopback = 0; 37427569d01SRenato Botelho sockaddr(&laddr->address, AF_INET6, 375d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 376d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 377d5b4aa90SMichael Tuexen break; 378d5b4aa90SMichael Tuexen default: 379463a577bSEitan Adler errx(1, "address family %d not supported", 380d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 381d5b4aa90SMichael Tuexen } 382d5b4aa90SMichael Tuexen laddr->next = NULL; 383d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 384d5b4aa90SMichael Tuexen sock->laddr = laddr; 385d5b4aa90SMichael Tuexen else 386d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 387d5b4aa90SMichael Tuexen prev_laddr = laddr; 388d5b4aa90SMichael Tuexen } 389d5b4aa90SMichael Tuexen if (sock->laddr == NULL) { 39027569d01SRenato Botelho if ((sock->laddr = 39127569d01SRenato Botelho calloc(1, sizeof(struct addr))) == NULL) 392d5b4aa90SMichael Tuexen err(1, "malloc()"); 393d5b4aa90SMichael Tuexen sock->laddr->address.ss_family = sock->family; 394d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 39527569d01SRenato Botelho sock->laddr->address.ss_len = 39627569d01SRenato Botelho sizeof(struct sockaddr_in); 397d5b4aa90SMichael Tuexen else 39827569d01SRenato Botelho sock->laddr->address.ss_len = 39927569d01SRenato Botelho sizeof(struct sockaddr_in6); 400d5b4aa90SMichael Tuexen local_all_loopback = 0; 401d5b4aa90SMichael Tuexen } 402d5b4aa90SMichael Tuexen if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 403d5b4aa90SMichael Tuexen err(1, "malloc()"); 404d5b4aa90SMichael Tuexen sock->faddr->address.ss_family = sock->family; 405d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 40627569d01SRenato Botelho sock->faddr->address.ss_len = 40727569d01SRenato Botelho sizeof(struct sockaddr_in); 408d5b4aa90SMichael Tuexen else 40927569d01SRenato Botelho sock->faddr->address.ss_len = 41027569d01SRenato Botelho sizeof(struct sockaddr_in6); 411d5b4aa90SMichael Tuexen no_stcb = 1; 412d5b4aa90SMichael Tuexen while (offset < len) { 413d5b4aa90SMichael Tuexen xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 414d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_tcb); 415bedcf91dSMichael Tuexen if (no_stcb) { 41627569d01SRenato Botelho if (opt_l && (sock->vflag & vflag) && 417d5b4aa90SMichael Tuexen (!opt_L || !local_all_loopback) && 418d5b4aa90SMichael Tuexen ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 419d5b4aa90SMichael Tuexen (xstcb->last == 1))) { 42027569d01SRenato Botelho hash = (int)((uintptr_t)sock->socket % 42127569d01SRenato Botelho HASHSIZE); 422d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 423d5b4aa90SMichael Tuexen sockhash[hash] = sock; 424bedcf91dSMichael Tuexen } else { 425bedcf91dSMichael Tuexen free_socket(sock); 426bedcf91dSMichael Tuexen } 427d5b4aa90SMichael Tuexen } 428d5b4aa90SMichael Tuexen if (xstcb->last == 1) 429d5b4aa90SMichael Tuexen break; 430d5b4aa90SMichael Tuexen no_stcb = 0; 431d5b4aa90SMichael Tuexen if (opt_c) { 432d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 433d5b4aa90SMichael Tuexen err(1, "malloc()"); 434d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 435d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 436d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 4376414db1bSMichael Tuexen sock->state = (int)xstcb->state; 438d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 439d5b4aa90SMichael Tuexen sock->family = AF_INET6; 440edc9c7fcSMichael Tuexen /* 441edc9c7fcSMichael Tuexen * Currently there is no way to distinguish 442edc9c7fcSMichael Tuexen * between IPv6 only sockets or dual family 443edc9c7fcSMichael Tuexen * sockets. So mark it as dual socket. 444edc9c7fcSMichael Tuexen */ 445edc9c7fcSMichael Tuexen sock->vflag = INP_IPV6 | INP_IPV4; 446d5b4aa90SMichael Tuexen } else { 447d5b4aa90SMichael Tuexen sock->family = AF_INET; 448d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 449d5b4aa90SMichael Tuexen } 450d5b4aa90SMichael Tuexen } 451d5b4aa90SMichael Tuexen prev_laddr = NULL; 452d5b4aa90SMichael Tuexen local_all_loopback = 1; 453d5b4aa90SMichael Tuexen while (offset < len) { 45427569d01SRenato Botelho xladdr = (struct xsctp_laddr *)(void *)(buf + 45527569d01SRenato Botelho offset); 456d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 457d5b4aa90SMichael Tuexen if (xladdr->last == 1) 458d5b4aa90SMichael Tuexen break; 459d5b4aa90SMichael Tuexen if (!opt_c) 460d5b4aa90SMichael Tuexen continue; 46127569d01SRenato Botelho laddr = calloc(1, sizeof(struct addr)); 46227569d01SRenato Botelho if (laddr == NULL) 463d5b4aa90SMichael Tuexen err(1, "malloc()"); 464d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 465d5b4aa90SMichael Tuexen case AF_INET: 466d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 467d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 46827569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 46927569d01SRenato Botelho &xladdr->address.sin.sin_addr)) 470d5b4aa90SMichael Tuexen local_all_loopback = 0; 471d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 47227569d01SRenato Botelho sockaddr(&laddr->address, AF_INET, 473d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 474d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 475d5b4aa90SMichael Tuexen break; 476d5b4aa90SMichael Tuexen case AF_INET6: 47727569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 47827569d01SRenato Botelho &xladdr->address.sin6.sin6_addr)) 479d5b4aa90SMichael Tuexen local_all_loopback = 0; 48027569d01SRenato Botelho sockaddr(&laddr->address, AF_INET6, 481d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 482d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 483d5b4aa90SMichael Tuexen break; 484d5b4aa90SMichael Tuexen default: 48527569d01SRenato Botelho errx(1, 48627569d01SRenato Botelho "address family %d not supported", 487d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 488d5b4aa90SMichael Tuexen } 489d5b4aa90SMichael Tuexen laddr->next = NULL; 490d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 491d5b4aa90SMichael Tuexen sock->laddr = laddr; 492d5b4aa90SMichael Tuexen else 493d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 494d5b4aa90SMichael Tuexen prev_laddr = laddr; 495d5b4aa90SMichael Tuexen } 496d5b4aa90SMichael Tuexen prev_faddr = NULL; 497d5b4aa90SMichael Tuexen foreign_all_loopback = 1; 498d5b4aa90SMichael Tuexen while (offset < len) { 49927569d01SRenato Botelho xraddr = (struct xsctp_raddr *)(void *)(buf + 50027569d01SRenato Botelho offset); 501d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_raddr); 502d5b4aa90SMichael Tuexen if (xraddr->last == 1) 503d5b4aa90SMichael Tuexen break; 504d5b4aa90SMichael Tuexen if (!opt_c) 505d5b4aa90SMichael Tuexen continue; 50627569d01SRenato Botelho faddr = calloc(1, sizeof(struct addr)); 50727569d01SRenato Botelho if (faddr == NULL) 508d5b4aa90SMichael Tuexen err(1, "malloc()"); 509d5b4aa90SMichael Tuexen switch (xraddr->address.sa.sa_family) { 510d5b4aa90SMichael Tuexen case AF_INET: 511d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 512d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 51327569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 51427569d01SRenato Botelho &xraddr->address.sin.sin_addr)) 515d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 516d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 51727569d01SRenato Botelho sockaddr(&faddr->address, AF_INET, 518d5b4aa90SMichael Tuexen &xraddr->address.sin.sin_addr, 519d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 520d5b4aa90SMichael Tuexen break; 521d5b4aa90SMichael Tuexen case AF_INET6: 52227569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 52327569d01SRenato Botelho &xraddr->address.sin6.sin6_addr)) 524d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 52527569d01SRenato Botelho sockaddr(&faddr->address, AF_INET6, 526d5b4aa90SMichael Tuexen &xraddr->address.sin6.sin6_addr, 527d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 528d5b4aa90SMichael Tuexen break; 529d5b4aa90SMichael Tuexen default: 53027569d01SRenato Botelho errx(1, 53127569d01SRenato Botelho "address family %d not supported", 532d5b4aa90SMichael Tuexen xraddr->address.sa.sa_family); 533d5b4aa90SMichael Tuexen } 534d5b4aa90SMichael Tuexen faddr->next = NULL; 535d5b4aa90SMichael Tuexen if (prev_faddr == NULL) 536d5b4aa90SMichael Tuexen sock->faddr = faddr; 537d5b4aa90SMichael Tuexen else 538d5b4aa90SMichael Tuexen prev_faddr->next = faddr; 539d5b4aa90SMichael Tuexen prev_faddr = faddr; 540d5b4aa90SMichael Tuexen } 541bedcf91dSMichael Tuexen if (opt_c) { 542edc9c7fcSMichael Tuexen if ((sock->vflag & vflag) && 543edc9c7fcSMichael Tuexen (!opt_L || 54427569d01SRenato Botelho !(local_all_loopback || 54527569d01SRenato Botelho foreign_all_loopback))) { 54627569d01SRenato Botelho hash = (int)((uintptr_t)sock->socket % 54727569d01SRenato Botelho HASHSIZE); 548d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 549d5b4aa90SMichael Tuexen sockhash[hash] = sock; 550bedcf91dSMichael Tuexen } else { 551bedcf91dSMichael Tuexen free_socket(sock); 552bedcf91dSMichael Tuexen } 553d5b4aa90SMichael Tuexen } 554d5b4aa90SMichael Tuexen } 555d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 556d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_inpcb); 557d5b4aa90SMichael Tuexen } 558d5b4aa90SMichael Tuexen free(buf); 559d5b4aa90SMichael Tuexen } 560d5b4aa90SMichael Tuexen 561d5b4aa90SMichael Tuexen static void 562ca007d91SDag-Erling Smørgrav gather_inet(int proto) 563ca007d91SDag-Erling Smørgrav { 564ca007d91SDag-Erling Smørgrav struct xinpgen *xig, *exig; 565ca007d91SDag-Erling Smørgrav struct xinpcb *xip; 566bf40d2caSGleb Smirnoff struct xtcpcb *xtp = NULL; 567ca007d91SDag-Erling Smørgrav struct xsocket *so; 568ca007d91SDag-Erling Smørgrav struct sock *sock; 569e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 570ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 571ca007d91SDag-Erling Smørgrav size_t len, bufsize; 572ca007d91SDag-Erling Smørgrav void *buf; 5736eb1d5baSMichael Tuexen int hash, retry, vflag; 574ca007d91SDag-Erling Smørgrav 5756eb1d5baSMichael Tuexen vflag = 0; 576ca007d91SDag-Erling Smørgrav if (opt_4) 577ca007d91SDag-Erling Smørgrav vflag |= INP_IPV4; 578ca007d91SDag-Erling Smørgrav if (opt_6) 579ca007d91SDag-Erling Smørgrav vflag |= INP_IPV6; 580ca007d91SDag-Erling Smørgrav 581ca007d91SDag-Erling Smørgrav switch (proto) { 582ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 583ca007d91SDag-Erling Smørgrav varname = "net.inet.tcp.pcblist"; 584ca007d91SDag-Erling Smørgrav protoname = "tcp"; 585ca007d91SDag-Erling Smørgrav break; 586ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 587ca007d91SDag-Erling Smørgrav varname = "net.inet.udp.pcblist"; 588ca007d91SDag-Erling Smørgrav protoname = "udp"; 589ca007d91SDag-Erling Smørgrav break; 5902cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 5912cfbdf89SRuslan Ermilov varname = "net.inet.divert.pcblist"; 5922cfbdf89SRuslan Ermilov protoname = "div"; 5932cfbdf89SRuslan Ermilov break; 594ca007d91SDag-Erling Smørgrav default: 5951f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 596ca007d91SDag-Erling Smørgrav } 597ca007d91SDag-Erling Smørgrav 598ca007d91SDag-Erling Smørgrav buf = NULL; 599ca007d91SDag-Erling Smørgrav bufsize = 8192; 600ca007d91SDag-Erling Smørgrav retry = 5; 601ca007d91SDag-Erling Smørgrav do { 602ca007d91SDag-Erling Smørgrav for (;;) { 603ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 604ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 605ca007d91SDag-Erling Smørgrav len = bufsize; 606ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 607ca007d91SDag-Erling Smørgrav break; 6084b2a3d41SRuslan Ermilov if (errno == ENOENT) 6094b2a3d41SRuslan Ermilov goto out; 610003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 611ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 612ca007d91SDag-Erling Smørgrav bufsize *= 2; 613ca007d91SDag-Erling Smørgrav } 614ca007d91SDag-Erling Smørgrav xig = (struct xinpgen *)buf; 6156dbe8d53SRobert Drehmel exig = (struct xinpgen *)(void *) 6166dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exig); 617ca007d91SDag-Erling Smørgrav if (xig->xig_len != sizeof *xig || 618ca007d91SDag-Erling Smørgrav exig->xig_len != sizeof *exig) 619ca007d91SDag-Erling Smørgrav errx(1, "struct xinpgen size mismatch"); 620ca007d91SDag-Erling Smørgrav } while (xig->xig_gen != exig->xig_gen && retry--); 621ca007d91SDag-Erling Smørgrav 622ca007d91SDag-Erling Smørgrav if (xig->xig_gen != exig->xig_gen && opt_v) 623ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 624ca007d91SDag-Erling Smørgrav 625ca007d91SDag-Erling Smørgrav for (;;) { 6266dbe8d53SRobert Drehmel xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 627ca007d91SDag-Erling Smørgrav if (xig >= exig) 628ca007d91SDag-Erling Smørgrav break; 629ca007d91SDag-Erling Smørgrav switch (proto) { 630ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 631cc65eb4eSGleb Smirnoff xtp = (struct xtcpcb *)xig; 632cc65eb4eSGleb Smirnoff xip = &xtp->xt_inp; 633b8e20e2dSHiroki Sato if (xtp->xt_len != sizeof(*xtp)) { 634ca007d91SDag-Erling Smørgrav warnx("struct xtcpcb size mismatch"); 635ca007d91SDag-Erling Smørgrav goto out; 636ca007d91SDag-Erling Smørgrav } 637cc65eb4eSGleb Smirnoff protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp"; 638ca007d91SDag-Erling Smørgrav break; 639ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 6402cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 641cc65eb4eSGleb Smirnoff xip = (struct xinpcb *)xig; 642b8e20e2dSHiroki Sato if (xip->xi_len != sizeof(*xip)) { 643ca007d91SDag-Erling Smørgrav warnx("struct xinpcb size mismatch"); 644ca007d91SDag-Erling Smørgrav goto out; 645ca007d91SDag-Erling Smørgrav } 646ca007d91SDag-Erling Smørgrav break; 647ca007d91SDag-Erling Smørgrav default: 6481f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 649ca007d91SDag-Erling Smørgrav } 650cc65eb4eSGleb Smirnoff so = &xip->xi_socket; 651cc65eb4eSGleb Smirnoff if ((xip->inp_vflag & vflag) == 0) 652ca007d91SDag-Erling Smørgrav continue; 653cc65eb4eSGleb Smirnoff if (xip->inp_vflag & INP_IPV4) { 654cc65eb4eSGleb Smirnoff if ((xip->inp_fport == 0 && !opt_l) || 655cc65eb4eSGleb Smirnoff (xip->inp_fport != 0 && !opt_c)) 6561e6690e5SDag-Erling Smørgrav continue; 6579b6ca892SBruce M Simpson #define __IN_IS_ADDR_LOOPBACK(pina) \ 6589b6ca892SBruce M Simpson ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 6599b6ca892SBruce M Simpson if (opt_L && 660cc65eb4eSGleb Smirnoff (__IN_IS_ADDR_LOOPBACK(&xip->inp_faddr) || 661cc65eb4eSGleb Smirnoff __IN_IS_ADDR_LOOPBACK(&xip->inp_laddr))) 6629b6ca892SBruce M Simpson continue; 6639b6ca892SBruce M Simpson #undef __IN_IS_ADDR_LOOPBACK 664cc65eb4eSGleb Smirnoff } else if (xip->inp_vflag & INP_IPV6) { 665cc65eb4eSGleb Smirnoff if ((xip->inp_fport == 0 && !opt_l) || 666cc65eb4eSGleb Smirnoff (xip->inp_fport != 0 && !opt_c)) 6671e6690e5SDag-Erling Smørgrav continue; 6689b6ca892SBruce M Simpson if (opt_L && 669cc65eb4eSGleb Smirnoff (IN6_IS_ADDR_LOOPBACK(&xip->in6p_faddr) || 670cc65eb4eSGleb Smirnoff IN6_IS_ADDR_LOOPBACK(&xip->in6p_laddr))) 6719b6ca892SBruce M Simpson continue; 6721e6690e5SDag-Erling Smørgrav } else { 6731e6690e5SDag-Erling Smørgrav if (opt_v) 674cc65eb4eSGleb Smirnoff warnx("invalid vflag 0x%x", xip->inp_vflag); 6751e6690e5SDag-Erling Smørgrav continue; 6761e6690e5SDag-Erling Smørgrav } 677b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 678ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 679e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 680e6f718c7SMichael Tuexen err(1, "malloc()"); 681e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 682e6f718c7SMichael Tuexen err(1, "malloc()"); 683ca007d91SDag-Erling Smørgrav sock->socket = so->xso_so; 684ca007d91SDag-Erling Smørgrav sock->proto = proto; 685cc65eb4eSGleb Smirnoff if (xip->inp_vflag & INP_IPV4) { 686ca007d91SDag-Erling Smørgrav sock->family = AF_INET; 687e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 688cc65eb4eSGleb Smirnoff &xip->inp_laddr, xip->inp_lport); 689e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 690cc65eb4eSGleb Smirnoff &xip->inp_faddr, xip->inp_fport); 691cc65eb4eSGleb Smirnoff } else if (xip->inp_vflag & INP_IPV6) { 692ca007d91SDag-Erling Smørgrav sock->family = AF_INET6; 693e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 694cc65eb4eSGleb Smirnoff &xip->in6p_laddr, xip->inp_lport); 695e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 696cc65eb4eSGleb Smirnoff &xip->in6p_faddr, xip->inp_fport); 697ca007d91SDag-Erling Smørgrav } 698e6f718c7SMichael Tuexen laddr->next = NULL; 699e6f718c7SMichael Tuexen faddr->next = NULL; 700e6f718c7SMichael Tuexen sock->laddr = laddr; 701e6f718c7SMichael Tuexen sock->faddr = faddr; 702cc65eb4eSGleb Smirnoff sock->vflag = xip->inp_vflag; 703*e5cccc35SMichael Tuexen if (proto == IPPROTO_TCP) { 704cc65eb4eSGleb Smirnoff sock->state = xtp->t_state; 705*e5cccc35SMichael Tuexen memcpy(sock->stack, xtp->xt_stack, 706*e5cccc35SMichael Tuexen TCP_FUNCTION_NAME_LEN_MAX); 707*e5cccc35SMichael Tuexen } 708ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 709ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 710ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 711ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 712ca007d91SDag-Erling Smørgrav } 713ca007d91SDag-Erling Smørgrav out: 714ca007d91SDag-Erling Smørgrav free(buf); 715ca007d91SDag-Erling Smørgrav } 716ca007d91SDag-Erling Smørgrav 717ca007d91SDag-Erling Smørgrav static void 718ca007d91SDag-Erling Smørgrav gather_unix(int proto) 719ca007d91SDag-Erling Smørgrav { 720ca007d91SDag-Erling Smørgrav struct xunpgen *xug, *exug; 721ca007d91SDag-Erling Smørgrav struct xunpcb *xup; 722ca007d91SDag-Erling Smørgrav struct sock *sock; 723e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 724ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 725ca007d91SDag-Erling Smørgrav size_t len, bufsize; 726ca007d91SDag-Erling Smørgrav void *buf; 727ca007d91SDag-Erling Smørgrav int hash, retry; 728ca007d91SDag-Erling Smørgrav 729ca007d91SDag-Erling Smørgrav switch (proto) { 730ca007d91SDag-Erling Smørgrav case SOCK_STREAM: 731ca007d91SDag-Erling Smørgrav varname = "net.local.stream.pcblist"; 732ca007d91SDag-Erling Smørgrav protoname = "stream"; 733ca007d91SDag-Erling Smørgrav break; 734ca007d91SDag-Erling Smørgrav case SOCK_DGRAM: 735ca007d91SDag-Erling Smørgrav varname = "net.local.dgram.pcblist"; 736ca007d91SDag-Erling Smørgrav protoname = "dgram"; 737ca007d91SDag-Erling Smørgrav break; 738b8e20e2dSHiroki Sato case SOCK_SEQPACKET: 739b8e20e2dSHiroki Sato varname = "net.local.seqpacket.pcblist"; 740b8e20e2dSHiroki Sato protoname = "seqpac"; 741b8e20e2dSHiroki Sato break; 742ca007d91SDag-Erling Smørgrav default: 743ca007d91SDag-Erling Smørgrav abort(); 744ca007d91SDag-Erling Smørgrav } 745ca007d91SDag-Erling Smørgrav buf = NULL; 746ca007d91SDag-Erling Smørgrav bufsize = 8192; 747ca007d91SDag-Erling Smørgrav retry = 5; 748ca007d91SDag-Erling Smørgrav do { 749ca007d91SDag-Erling Smørgrav for (;;) { 750ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 751ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 752ca007d91SDag-Erling Smørgrav len = bufsize; 753ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 754ca007d91SDag-Erling Smørgrav break; 755003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 756ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 757ca007d91SDag-Erling Smørgrav bufsize *= 2; 758ca007d91SDag-Erling Smørgrav } 759ca007d91SDag-Erling Smørgrav xug = (struct xunpgen *)buf; 7606dbe8d53SRobert Drehmel exug = (struct xunpgen *)(void *) 761b8e20e2dSHiroki Sato ((char *)buf + len - sizeof(*exug)); 762b8e20e2dSHiroki Sato if (xug->xug_len != sizeof(*xug) || 763b8e20e2dSHiroki Sato exug->xug_len != sizeof(*exug)) { 764ca007d91SDag-Erling Smørgrav warnx("struct xinpgen size mismatch"); 765ca007d91SDag-Erling Smørgrav goto out; 766ca007d91SDag-Erling Smørgrav } 767ca007d91SDag-Erling Smørgrav } while (xug->xug_gen != exug->xug_gen && retry--); 768ca007d91SDag-Erling Smørgrav 769ca007d91SDag-Erling Smørgrav if (xug->xug_gen != exug->xug_gen && opt_v) 770ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 771ca007d91SDag-Erling Smørgrav 772ca007d91SDag-Erling Smørgrav for (;;) { 7736dbe8d53SRobert Drehmel xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 774ca007d91SDag-Erling Smørgrav if (xug >= exug) 775ca007d91SDag-Erling Smørgrav break; 776ca007d91SDag-Erling Smørgrav xup = (struct xunpcb *)xug; 777b8e20e2dSHiroki Sato if (xup->xu_len != sizeof(*xup)) { 778ca007d91SDag-Erling Smørgrav warnx("struct xunpcb size mismatch"); 779ca007d91SDag-Erling Smørgrav goto out; 780ca007d91SDag-Erling Smørgrav } 7811e6690e5SDag-Erling Smørgrav if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 7821e6690e5SDag-Erling Smørgrav (xup->xu_unp.unp_conn != NULL && !opt_c)) 7831e6690e5SDag-Erling Smørgrav continue; 784b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 785ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 786e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 787e6f718c7SMichael Tuexen err(1, "malloc()"); 788e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 789e6f718c7SMichael Tuexen err(1, "malloc()"); 790ca007d91SDag-Erling Smørgrav sock->socket = xup->xu_socket.xso_so; 791ca007d91SDag-Erling Smørgrav sock->pcb = xup->xu_unpp; 792ca007d91SDag-Erling Smørgrav sock->proto = proto; 793ca007d91SDag-Erling Smørgrav sock->family = AF_UNIX; 794ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 795ca007d91SDag-Erling Smørgrav if (xup->xu_unp.unp_addr != NULL) 796e6f718c7SMichael Tuexen laddr->address = 7976dbe8d53SRobert Drehmel *(struct sockaddr_storage *)(void *)&xup->xu_addr; 798ca007d91SDag-Erling Smørgrav else if (xup->xu_unp.unp_conn != NULL) 799e6f718c7SMichael Tuexen *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 800e6f718c7SMichael Tuexen laddr->next = NULL; 801e6f718c7SMichael Tuexen faddr->next = NULL; 802e6f718c7SMichael Tuexen sock->laddr = laddr; 803e6f718c7SMichael Tuexen sock->faddr = faddr; 804ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 805ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 806ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 807ca007d91SDag-Erling Smørgrav } 808ca007d91SDag-Erling Smørgrav out: 809ca007d91SDag-Erling Smørgrav free(buf); 810ca007d91SDag-Erling Smørgrav } 811ca007d91SDag-Erling Smørgrav 812ca007d91SDag-Erling Smørgrav static void 813ca007d91SDag-Erling Smørgrav getfiles(void) 814ca007d91SDag-Erling Smørgrav { 815003e7e49SMikolaj Golub size_t len, olen; 816ca007d91SDag-Erling Smørgrav 817b8e20e2dSHiroki Sato olen = len = sizeof(*xfiles); 818003e7e49SMikolaj Golub if ((xfiles = malloc(len)) == NULL) 819ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 820ca007d91SDag-Erling Smørgrav while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 821003e7e49SMikolaj Golub if (errno != ENOMEM || len != olen) 822ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 823003e7e49SMikolaj Golub olen = len *= 2; 824ca007d91SDag-Erling Smørgrav if ((xfiles = realloc(xfiles, len)) == NULL) 825ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 826ca007d91SDag-Erling Smørgrav } 827b8e20e2dSHiroki Sato if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 828ca007d91SDag-Erling Smørgrav errx(1, "struct xfile size mismatch"); 829b8e20e2dSHiroki Sato nxfiles = len / sizeof(*xfiles); 830ca007d91SDag-Erling Smørgrav } 831ca007d91SDag-Erling Smørgrav 832ca007d91SDag-Erling Smørgrav static int 833baa7f281SMichael Tuexen printaddr(struct sockaddr_storage *ss) 834ca007d91SDag-Erling Smørgrav { 835ca007d91SDag-Erling Smørgrav struct sockaddr_un *sun; 836b8e20e2dSHiroki Sato char addrstr[NI_MAXHOST] = { '\0', '\0' }; 837b8e20e2dSHiroki Sato int error, off, port = 0; 838ca007d91SDag-Erling Smørgrav 839baa7f281SMichael Tuexen switch (ss->ss_family) { 840ca007d91SDag-Erling Smørgrav case AF_INET: 841b8e20e2dSHiroki Sato if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) 842ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 843b8e20e2dSHiroki Sato port = ntohs(sstosin(ss)->sin_port); 844ca007d91SDag-Erling Smørgrav break; 845ca007d91SDag-Erling Smørgrav case AF_INET6: 846b8e20e2dSHiroki Sato if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 847ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 848b8e20e2dSHiroki Sato port = ntohs(sstosin6(ss)->sin6_port); 849ca007d91SDag-Erling Smørgrav break; 850ca007d91SDag-Erling Smørgrav case AF_UNIX: 851b8e20e2dSHiroki Sato sun = sstosun(ss); 852ca007d91SDag-Erling Smørgrav off = (int)((char *)&sun->sun_path - (char *)sun); 853ca007d91SDag-Erling Smørgrav return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 854ca007d91SDag-Erling Smørgrav } 855b8e20e2dSHiroki Sato if (addrstr[0] == '\0') { 856b8e20e2dSHiroki Sato error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, 857b8e20e2dSHiroki Sato sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 858b8e20e2dSHiroki Sato if (error) 859b8e20e2dSHiroki Sato errx(1, "getnameinfo()"); 860b8e20e2dSHiroki Sato } 861ca007d91SDag-Erling Smørgrav if (port == 0) 862ca007d91SDag-Erling Smørgrav return xprintf("%s:*", addrstr); 863ca007d91SDag-Erling Smørgrav else 864ca007d91SDag-Erling Smørgrav return xprintf("%s:%d", addrstr, port); 865ca007d91SDag-Erling Smørgrav } 866ca007d91SDag-Erling Smørgrav 867ca007d91SDag-Erling Smørgrav static const char * 868ca007d91SDag-Erling Smørgrav getprocname(pid_t pid) 869ca007d91SDag-Erling Smørgrav { 870ca007d91SDag-Erling Smørgrav static struct kinfo_proc proc; 871ca007d91SDag-Erling Smørgrav size_t len; 872ca007d91SDag-Erling Smørgrav int mib[4]; 873ca007d91SDag-Erling Smørgrav 874ca007d91SDag-Erling Smørgrav mib[0] = CTL_KERN; 875ca007d91SDag-Erling Smørgrav mib[1] = KERN_PROC; 876ca007d91SDag-Erling Smørgrav mib[2] = KERN_PROC_PID; 877ca007d91SDag-Erling Smørgrav mib[3] = (int)pid; 878b8e20e2dSHiroki Sato len = sizeof(proc); 879b8e20e2dSHiroki Sato if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 88048c513e0SMaxim Konovalov /* Do not warn if the process exits before we get its name. */ 88148c513e0SMaxim Konovalov if (errno != ESRCH) 882ca007d91SDag-Erling Smørgrav warn("sysctl()"); 883ca007d91SDag-Erling Smørgrav return ("??"); 884ca007d91SDag-Erling Smørgrav } 885f487a6a8SEd Maste return (proc.ki_comm); 886ca007d91SDag-Erling Smørgrav } 887ca007d91SDag-Erling Smørgrav 888ae94787dSMaxime Henrion static int 88900feaafdSAndrew Thompson getprocjid(pid_t pid) 89000feaafdSAndrew Thompson { 89100feaafdSAndrew Thompson static struct kinfo_proc proc; 89200feaafdSAndrew Thompson size_t len; 89300feaafdSAndrew Thompson int mib[4]; 89400feaafdSAndrew Thompson 89500feaafdSAndrew Thompson mib[0] = CTL_KERN; 89600feaafdSAndrew Thompson mib[1] = KERN_PROC; 89700feaafdSAndrew Thompson mib[2] = KERN_PROC_PID; 89800feaafdSAndrew Thompson mib[3] = (int)pid; 899b8e20e2dSHiroki Sato len = sizeof(proc); 900b8e20e2dSHiroki Sato if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 90100feaafdSAndrew Thompson /* Do not warn if the process exits before we get its jid. */ 90200feaafdSAndrew Thompson if (errno != ESRCH) 90300feaafdSAndrew Thompson warn("sysctl()"); 90400feaafdSAndrew Thompson return (-1); 90500feaafdSAndrew Thompson } 90600feaafdSAndrew Thompson return (proc.ki_jid); 90700feaafdSAndrew Thompson } 90800feaafdSAndrew Thompson 90900feaafdSAndrew Thompson static int 910ae94787dSMaxime Henrion check_ports(struct sock *s) 911ae94787dSMaxime Henrion { 912ae94787dSMaxime Henrion int port; 913e6f718c7SMichael Tuexen struct addr *addr; 914ae94787dSMaxime Henrion 915ae94787dSMaxime Henrion if (ports == NULL) 916ae94787dSMaxime Henrion return (1); 917ae94787dSMaxime Henrion if ((s->family != AF_INET) && (s->family != AF_INET6)) 918ae94787dSMaxime Henrion return (1); 919e6f718c7SMichael Tuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 920b8e20e2dSHiroki Sato if (s->family == AF_INET) 921b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 922ae94787dSMaxime Henrion else 923b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 924ae94787dSMaxime Henrion if (CHK_PORT(port)) 925ae94787dSMaxime Henrion return (1); 926e6f718c7SMichael Tuexen } 927e6f718c7SMichael Tuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 928b8e20e2dSHiroki Sato if (s->family == AF_INET) 929b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 930ae94787dSMaxime Henrion else 931b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 932ae94787dSMaxime Henrion if (CHK_PORT(port)) 933ae94787dSMaxime Henrion return (1); 934e6f718c7SMichael Tuexen } 935ae94787dSMaxime Henrion return (0); 936ae94787dSMaxime Henrion } 937ae94787dSMaxime Henrion 9386414db1bSMichael Tuexen static const char * 9396414db1bSMichael Tuexen sctp_state(int state) 9406414db1bSMichael Tuexen { 9416414db1bSMichael Tuexen switch (state) { 9426414db1bSMichael Tuexen case SCTP_CLOSED: 9436414db1bSMichael Tuexen return "CLOSED"; 9446414db1bSMichael Tuexen break; 9456414db1bSMichael Tuexen case SCTP_BOUND: 9466414db1bSMichael Tuexen return "BOUND"; 9476414db1bSMichael Tuexen break; 9486414db1bSMichael Tuexen case SCTP_LISTEN: 9496414db1bSMichael Tuexen return "LISTEN"; 9506414db1bSMichael Tuexen break; 9516414db1bSMichael Tuexen case SCTP_COOKIE_WAIT: 9526414db1bSMichael Tuexen return "COOKIE_WAIT"; 9536414db1bSMichael Tuexen break; 9546414db1bSMichael Tuexen case SCTP_COOKIE_ECHOED: 9556414db1bSMichael Tuexen return "COOKIE_ECHOED"; 9566414db1bSMichael Tuexen break; 9576414db1bSMichael Tuexen case SCTP_ESTABLISHED: 9586414db1bSMichael Tuexen return "ESTABLISHED"; 9596414db1bSMichael Tuexen break; 9606414db1bSMichael Tuexen case SCTP_SHUTDOWN_SENT: 9616414db1bSMichael Tuexen return "SHUTDOWN_SENT"; 9626414db1bSMichael Tuexen break; 9636414db1bSMichael Tuexen case SCTP_SHUTDOWN_RECEIVED: 9646414db1bSMichael Tuexen return "SHUTDOWN_RECEIVED"; 9656414db1bSMichael Tuexen break; 9666414db1bSMichael Tuexen case SCTP_SHUTDOWN_ACK_SENT: 9676414db1bSMichael Tuexen return "SHUTDOWN_ACK_SENT"; 9686414db1bSMichael Tuexen break; 9696414db1bSMichael Tuexen case SCTP_SHUTDOWN_PENDING: 9706414db1bSMichael Tuexen return "SHUTDOWN_PENDING"; 9716414db1bSMichael Tuexen break; 9726414db1bSMichael Tuexen default: 9736414db1bSMichael Tuexen return "UNKNOWN"; 9746414db1bSMichael Tuexen break; 9756414db1bSMichael Tuexen } 9766414db1bSMichael Tuexen } 9776414db1bSMichael Tuexen 978ca007d91SDag-Erling Smørgrav static void 97961149f8dSJilles Tjoelker displaysock(struct sock *s, int pos) 980ca007d91SDag-Erling Smørgrav { 981ca007d91SDag-Erling Smørgrav void *p; 9824e13a5b0SMichael Tuexen int hash, first; 983e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 98481091202SMichael Tuexen struct sock *s_tmp; 985ca007d91SDag-Erling Smørgrav 986ca007d91SDag-Erling Smørgrav while (pos < 29) 987ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 988ca007d91SDag-Erling Smørgrav pos += xprintf("%s", s->protoname); 989ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV4) 990ca007d91SDag-Erling Smørgrav pos += xprintf("4"); 991ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV6) 992ca007d91SDag-Erling Smørgrav pos += xprintf("6"); 993edc9c7fcSMichael Tuexen if (s->vflag & (INP_IPV4 | INP_IPV6)) 994edc9c7fcSMichael Tuexen pos += xprintf(" "); 995e6f718c7SMichael Tuexen laddr = s->laddr; 996e6f718c7SMichael Tuexen faddr = s->faddr; 9974e13a5b0SMichael Tuexen first = 1; 998e6f718c7SMichael Tuexen while (laddr != NULL || faddr != NULL) { 999ca007d91SDag-Erling Smørgrav while (pos < 36) 1000ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 1001ca007d91SDag-Erling Smørgrav switch (s->family) { 1002ca007d91SDag-Erling Smørgrav case AF_INET: 1003ca007d91SDag-Erling Smørgrav case AF_INET6: 1004e6f718c7SMichael Tuexen if (laddr != NULL) { 1005e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 100609bbda21SMaxim Konovalov if (s->family == AF_INET6 && pos >= 58) 100709bbda21SMaxim Konovalov pos += xprintf(" "); 1008e6f718c7SMichael Tuexen } 1009ca007d91SDag-Erling Smørgrav while (pos < 58) 1010ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 1011e6f718c7SMichael Tuexen if (faddr != NULL) 1012e6f718c7SMichael Tuexen pos += printaddr(&faddr->address); 1013ca007d91SDag-Erling Smørgrav break; 1014ca007d91SDag-Erling Smørgrav case AF_UNIX: 1015e6f718c7SMichael Tuexen if ((laddr == NULL) || (faddr == NULL)) 1016e6f718c7SMichael Tuexen errx(1, "laddr = %p or faddr = %p is NULL", 1017e6f718c7SMichael Tuexen (void *)laddr, (void *)faddr); 1018ca007d91SDag-Erling Smørgrav /* server */ 1019e6f718c7SMichael Tuexen if (laddr->address.ss_len > 0) { 1020e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 1021ca007d91SDag-Erling Smørgrav break; 1022ca007d91SDag-Erling Smørgrav } 1023ca007d91SDag-Erling Smørgrav /* client */ 1024e6f718c7SMichael Tuexen p = *(void **)&(faddr->address); 1025b4eb37c6SJohn-Mark Gurney if (p == NULL) { 1026b4eb37c6SJohn-Mark Gurney pos += xprintf("(not connected)"); 1027b4eb37c6SJohn-Mark Gurney break; 1028b4eb37c6SJohn-Mark Gurney } 1029b4eb37c6SJohn-Mark Gurney pos += xprintf("-> "); 1030ca007d91SDag-Erling Smørgrav for (hash = 0; hash < HASHSIZE; ++hash) { 103181091202SMichael Tuexen for (s_tmp = sockhash[hash]; 103281091202SMichael Tuexen s_tmp != NULL; 103381091202SMichael Tuexen s_tmp = s_tmp->next) 103481091202SMichael Tuexen if (s_tmp->pcb == p) 1035ca007d91SDag-Erling Smørgrav break; 103681091202SMichael Tuexen if (s_tmp != NULL) 1037ca007d91SDag-Erling Smørgrav break; 1038ca007d91SDag-Erling Smørgrav } 103927569d01SRenato Botelho if (s_tmp == NULL || s_tmp->laddr == NULL || 104081091202SMichael Tuexen s_tmp->laddr->address.ss_len == 0) 1041ca007d91SDag-Erling Smørgrav pos += xprintf("??"); 1042ca007d91SDag-Erling Smørgrav else 104381091202SMichael Tuexen pos += printaddr(&s_tmp->laddr->address); 1044ca007d91SDag-Erling Smørgrav break; 1045ca007d91SDag-Erling Smørgrav default: 1046ca007d91SDag-Erling Smørgrav abort(); 1047ca007d91SDag-Erling Smørgrav } 1048*e5cccc35SMichael Tuexen if (first) { 1049*e5cccc35SMichael Tuexen if (opt_s && 1050*e5cccc35SMichael Tuexen (s->proto == IPPROTO_SCTP || 1051*e5cccc35SMichael Tuexen s->proto == IPPROTO_TCP)) { 10524e13a5b0SMichael Tuexen while (pos < 80) 10534e13a5b0SMichael Tuexen pos += xprintf(" "); 10546414db1bSMichael Tuexen switch (s->proto) { 10556414db1bSMichael Tuexen case IPPROTO_SCTP: 1056*e5cccc35SMichael Tuexen pos += xprintf("%s", 1057*e5cccc35SMichael Tuexen sctp_state(s->state)); 10586414db1bSMichael Tuexen break; 10596414db1bSMichael Tuexen case IPPROTO_TCP: 1060*e5cccc35SMichael Tuexen if (s->state >= 0 && 1061*e5cccc35SMichael Tuexen s->state < TCP_NSTATES) 10626414db1bSMichael Tuexen pos += 1063*e5cccc35SMichael Tuexen xprintf("%s", 1064*e5cccc35SMichael Tuexen tcpstates[s->state]); 10654e13a5b0SMichael Tuexen else 10664e13a5b0SMichael Tuexen pos += xprintf("?"); 10676414db1bSMichael Tuexen break; 10686414db1bSMichael Tuexen } 10694e13a5b0SMichael Tuexen } 1070*e5cccc35SMichael Tuexen if (opt_S && s->proto == IPPROTO_TCP) { 1071*e5cccc35SMichael Tuexen while (pos < 80) 1072*e5cccc35SMichael Tuexen pos += xprintf(" "); 1073*e5cccc35SMichael Tuexen if (opt_s) 1074*e5cccc35SMichael Tuexen while (pos < 93) 1075*e5cccc35SMichael Tuexen pos += xprintf(" "); 1076*e5cccc35SMichael Tuexen xprintf("%.*s", TCP_FUNCTION_NAME_LEN_MAX, 1077*e5cccc35SMichael Tuexen s->stack); 1078*e5cccc35SMichael Tuexen } 1079*e5cccc35SMichael Tuexen } 1080e6f718c7SMichael Tuexen if (laddr != NULL) 1081e6f718c7SMichael Tuexen laddr = laddr->next; 1082e6f718c7SMichael Tuexen if (faddr != NULL) 1083e6f718c7SMichael Tuexen faddr = faddr->next; 1084e6f718c7SMichael Tuexen if ((laddr != NULL) || (faddr != NULL)) { 1085e6f718c7SMichael Tuexen xprintf("\n"); 1086e6f718c7SMichael Tuexen pos = 0; 1087e6f718c7SMichael Tuexen } 10884e13a5b0SMichael Tuexen first = 0; 1089e6f718c7SMichael Tuexen } 10904e13a5b0SMichael Tuexen xprintf("\n"); 1091ca007d91SDag-Erling Smørgrav } 109261149f8dSJilles Tjoelker 109361149f8dSJilles Tjoelker static void 109461149f8dSJilles Tjoelker display(void) 109561149f8dSJilles Tjoelker { 109661149f8dSJilles Tjoelker struct passwd *pwd; 109761149f8dSJilles Tjoelker struct xfile *xf; 109861149f8dSJilles Tjoelker struct sock *s; 109961149f8dSJilles Tjoelker int hash, n, pos; 110061149f8dSJilles Tjoelker 11017a5642b3SDag-Erling Smørgrav printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", 110261149f8dSJilles Tjoelker "USER", "COMMAND", "PID", "FD", "PROTO", 110361149f8dSJilles Tjoelker "LOCAL ADDRESS", "FOREIGN ADDRESS"); 11047a5642b3SDag-Erling Smørgrav if (opt_s) 11057a5642b3SDag-Erling Smørgrav printf(" %-12s", "STATE"); 1106*e5cccc35SMichael Tuexen if (opt_S) 1107*e5cccc35SMichael Tuexen printf(" %.*s", TCP_FUNCTION_NAME_LEN_MAX, "STACK"); 11087a5642b3SDag-Erling Smørgrav printf("\n"); 110961149f8dSJilles Tjoelker setpassent(1); 111061149f8dSJilles Tjoelker for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 111161149f8dSJilles Tjoelker if (xf->xf_data == NULL) 111261149f8dSJilles Tjoelker continue; 111300feaafdSAndrew Thompson if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 111400feaafdSAndrew Thompson continue; 111561149f8dSJilles Tjoelker hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 11167e80c6b0SMichael Tuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 11177e80c6b0SMichael Tuexen if ((void *)s->socket != xf->xf_data) 111861149f8dSJilles Tjoelker continue; 111961149f8dSJilles Tjoelker if (!check_ports(s)) 112061149f8dSJilles Tjoelker continue; 112161149f8dSJilles Tjoelker s->shown = 1; 112261149f8dSJilles Tjoelker pos = 0; 112361149f8dSJilles Tjoelker if ((pwd = getpwuid(xf->xf_uid)) == NULL) 112461149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_uid); 112561149f8dSJilles Tjoelker else 112661149f8dSJilles Tjoelker pos += xprintf("%s ", pwd->pw_name); 112761149f8dSJilles Tjoelker while (pos < 9) 112861149f8dSJilles Tjoelker pos += xprintf(" "); 112961149f8dSJilles Tjoelker pos += xprintf("%.10s", getprocname(xf->xf_pid)); 113061149f8dSJilles Tjoelker while (pos < 20) 113161149f8dSJilles Tjoelker pos += xprintf(" "); 113261149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_pid); 113361149f8dSJilles Tjoelker while (pos < 26) 113461149f8dSJilles Tjoelker pos += xprintf(" "); 113561149f8dSJilles Tjoelker pos += xprintf("%d ", xf->xf_fd); 113661149f8dSJilles Tjoelker displaysock(s, pos); 113761149f8dSJilles Tjoelker } 11387e80c6b0SMichael Tuexen } 113900feaafdSAndrew Thompson if (opt_j >= 0) 114000feaafdSAndrew Thompson return; 114161149f8dSJilles Tjoelker for (hash = 0; hash < HASHSIZE; hash++) { 114261149f8dSJilles Tjoelker for (s = sockhash[hash]; s != NULL; s = s->next) { 114361149f8dSJilles Tjoelker if (s->shown) 114461149f8dSJilles Tjoelker continue; 114561149f8dSJilles Tjoelker if (!check_ports(s)) 114661149f8dSJilles Tjoelker continue; 114761149f8dSJilles Tjoelker pos = 0; 114861149f8dSJilles Tjoelker pos += xprintf("%-8s %-10s %-5s %-2s ", 114961149f8dSJilles Tjoelker "?", "?", "?", "?"); 115061149f8dSJilles Tjoelker displaysock(s, pos); 115161149f8dSJilles Tjoelker } 115261149f8dSJilles Tjoelker } 1153ca007d91SDag-Erling Smørgrav } 1154ca007d91SDag-Erling Smørgrav 11551f3d67aaSGiorgos Keramidas static int set_default_protos(void) 11561f3d67aaSGiorgos Keramidas { 11571f3d67aaSGiorgos Keramidas struct protoent *prot; 11581f3d67aaSGiorgos Keramidas const char *pname; 11591f3d67aaSGiorgos Keramidas size_t pindex; 11601f3d67aaSGiorgos Keramidas 11611f3d67aaSGiorgos Keramidas init_protos(default_numprotos); 11621f3d67aaSGiorgos Keramidas 11631f3d67aaSGiorgos Keramidas for (pindex = 0; pindex < default_numprotos; pindex++) { 11641f3d67aaSGiorgos Keramidas pname = default_protos[pindex]; 11651f3d67aaSGiorgos Keramidas prot = getprotobyname(pname); 11661f3d67aaSGiorgos Keramidas if (prot == NULL) 11671f3d67aaSGiorgos Keramidas err(1, "getprotobyname: %s", pname); 11681f3d67aaSGiorgos Keramidas protos[pindex] = prot->p_proto; 11691f3d67aaSGiorgos Keramidas } 11701f3d67aaSGiorgos Keramidas numprotos = pindex; 11711f3d67aaSGiorgos Keramidas return (pindex); 11721f3d67aaSGiorgos Keramidas } 11731f3d67aaSGiorgos Keramidas 1174ca007d91SDag-Erling Smørgrav static void 1175ca007d91SDag-Erling Smørgrav usage(void) 1176ca007d91SDag-Erling Smørgrav { 11771f3d67aaSGiorgos Keramidas fprintf(stderr, 1178*e5cccc35SMichael Tuexen "usage: sockstat [-46cLlSsu] [-j jid] [-p ports] [-P protocols]\n"); 1179ca007d91SDag-Erling Smørgrav exit(1); 1180ca007d91SDag-Erling Smørgrav } 1181ca007d91SDag-Erling Smørgrav 1182ca007d91SDag-Erling Smørgrav int 1183ca007d91SDag-Erling Smørgrav main(int argc, char *argv[]) 1184ca007d91SDag-Erling Smørgrav { 11851f3d67aaSGiorgos Keramidas int protos_defined = -1; 11861f3d67aaSGiorgos Keramidas int o, i; 1187ca007d91SDag-Erling Smørgrav 118800feaafdSAndrew Thompson opt_j = -1; 1189*e5cccc35SMichael Tuexen while ((o = getopt(argc, argv, "46cj:Llp:P:Ssuv")) != -1) 1190ca007d91SDag-Erling Smørgrav switch (o) { 1191ca007d91SDag-Erling Smørgrav case '4': 1192ca007d91SDag-Erling Smørgrav opt_4 = 1; 1193ca007d91SDag-Erling Smørgrav break; 1194ca007d91SDag-Erling Smørgrav case '6': 1195ca007d91SDag-Erling Smørgrav opt_6 = 1; 1196ca007d91SDag-Erling Smørgrav break; 1197ca007d91SDag-Erling Smørgrav case 'c': 1198ca007d91SDag-Erling Smørgrav opt_c = 1; 1199ca007d91SDag-Erling Smørgrav break; 120000feaafdSAndrew Thompson case 'j': 120100feaafdSAndrew Thompson opt_j = atoi(optarg); 120200feaafdSAndrew Thompson break; 12039b6ca892SBruce M Simpson case 'L': 12049b6ca892SBruce M Simpson opt_L = 1; 12059b6ca892SBruce M Simpson break; 1206ca007d91SDag-Erling Smørgrav case 'l': 1207ca007d91SDag-Erling Smørgrav opt_l = 1; 1208ca007d91SDag-Erling Smørgrav break; 1209ca007d91SDag-Erling Smørgrav case 'p': 1210ca007d91SDag-Erling Smørgrav parse_ports(optarg); 1211ca007d91SDag-Erling Smørgrav break; 12121f3d67aaSGiorgos Keramidas case 'P': 12131f3d67aaSGiorgos Keramidas protos_defined = parse_protos(optarg); 12141f3d67aaSGiorgos Keramidas break; 1215*e5cccc35SMichael Tuexen case 'S': 1216*e5cccc35SMichael Tuexen opt_S = 1; 1217*e5cccc35SMichael Tuexen break; 12187a5642b3SDag-Erling Smørgrav case 's': 12197a5642b3SDag-Erling Smørgrav opt_s = 1; 12207a5642b3SDag-Erling Smørgrav break; 1221ca007d91SDag-Erling Smørgrav case 'u': 1222ca007d91SDag-Erling Smørgrav opt_u = 1; 1223ca007d91SDag-Erling Smørgrav break; 1224ca007d91SDag-Erling Smørgrav case 'v': 1225ca007d91SDag-Erling Smørgrav ++opt_v; 1226ca007d91SDag-Erling Smørgrav break; 1227ca007d91SDag-Erling Smørgrav default: 1228ca007d91SDag-Erling Smørgrav usage(); 1229ca007d91SDag-Erling Smørgrav } 1230ca007d91SDag-Erling Smørgrav 1231ca007d91SDag-Erling Smørgrav argc -= optind; 1232ca007d91SDag-Erling Smørgrav argv += optind; 1233ca007d91SDag-Erling Smørgrav 1234ca007d91SDag-Erling Smørgrav if (argc > 0) 1235ca007d91SDag-Erling Smørgrav usage(); 1236ca007d91SDag-Erling Smørgrav 1237d2d77d2aSGiorgos Keramidas if ((!opt_4 && !opt_6) && protos_defined != -1) 12381f3d67aaSGiorgos Keramidas opt_4 = opt_6 = 1; 1239d2d77d2aSGiorgos Keramidas if (!opt_4 && !opt_6 && !opt_u) 1240d2d77d2aSGiorgos Keramidas opt_4 = opt_6 = opt_u = 1; 1241d2d77d2aSGiorgos Keramidas if ((opt_4 || opt_6) && protos_defined == -1) 1242d2d77d2aSGiorgos Keramidas protos_defined = set_default_protos(); 1243ca007d91SDag-Erling Smørgrav if (!opt_c && !opt_l) 1244ca007d91SDag-Erling Smørgrav opt_c = opt_l = 1; 1245ca007d91SDag-Erling Smørgrav 1246ca007d91SDag-Erling Smørgrav if (opt_4 || opt_6) { 12471f3d67aaSGiorgos Keramidas for (i = 0; i < protos_defined; i++) 1248d5b4aa90SMichael Tuexen if (protos[i] == IPPROTO_SCTP) 1249d5b4aa90SMichael Tuexen gather_sctp(); 1250d5b4aa90SMichael Tuexen else 12511f3d67aaSGiorgos Keramidas gather_inet(protos[i]); 1252ca007d91SDag-Erling Smørgrav } 12531f3d67aaSGiorgos Keramidas 12541f3d67aaSGiorgos Keramidas if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1255ca007d91SDag-Erling Smørgrav gather_unix(SOCK_STREAM); 1256ca007d91SDag-Erling Smørgrav gather_unix(SOCK_DGRAM); 1257b8e20e2dSHiroki Sato gather_unix(SOCK_SEQPACKET); 1258ca007d91SDag-Erling Smørgrav } 1259ca007d91SDag-Erling Smørgrav getfiles(); 1260ca007d91SDag-Erling Smørgrav display(); 1261ca007d91SDag-Erling Smørgrav exit(0); 1262ca007d91SDag-Erling Smørgrav } 1263