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> 48*7a5642b3SDag-Erling Smørgrav #define TCPSTATES /* load state names */ 49*7a5642b3SDag-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*7a5642b3SDag-Erling Smørgrav static int opt_s; /* Show protocol state if applicable */ 77ca007d91SDag-Erling Smørgrav static int opt_u; /* Show Unix domain sockets */ 78ca007d91SDag-Erling Smørgrav static int opt_v; /* Verbose mode */ 79ca007d91SDag-Erling Smørgrav 801f3d67aaSGiorgos Keramidas /* 811f3d67aaSGiorgos Keramidas * Default protocols to use if no -P was defined. 821f3d67aaSGiorgos Keramidas */ 83d5b4aa90SMichael Tuexen static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 84b8e20e2dSHiroki Sato static size_t default_numprotos = nitems(default_protos); 851f3d67aaSGiorgos Keramidas 861f3d67aaSGiorgos Keramidas static int *protos; /* protocols to use */ 871f3d67aaSGiorgos Keramidas static size_t numprotos; /* allocated size of protos[] */ 881f3d67aaSGiorgos Keramidas 89ca007d91SDag-Erling Smørgrav static int *ports; 90ca007d91SDag-Erling Smørgrav 91ca007d91SDag-Erling Smørgrav #define INT_BIT (sizeof(int)*CHAR_BIT) 92ca007d91SDag-Erling Smørgrav #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 93ca007d91SDag-Erling Smørgrav #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 94ca007d91SDag-Erling Smørgrav 95e6f718c7SMichael Tuexen struct addr { 96e6f718c7SMichael Tuexen struct sockaddr_storage address; 97e6f718c7SMichael Tuexen struct addr *next; 98e6f718c7SMichael Tuexen }; 99e6f718c7SMichael Tuexen 100ca007d91SDag-Erling Smørgrav struct sock { 101ca007d91SDag-Erling Smørgrav void *socket; 102ca007d91SDag-Erling Smørgrav void *pcb; 10361149f8dSJilles Tjoelker int shown; 104ca007d91SDag-Erling Smørgrav int vflag; 105ca007d91SDag-Erling Smørgrav int family; 106ca007d91SDag-Erling Smørgrav int proto; 107*7a5642b3SDag-Erling Smørgrav int state; 108ca007d91SDag-Erling Smørgrav const char *protoname; 109e6f718c7SMichael Tuexen struct addr *laddr; 110e6f718c7SMichael Tuexen struct addr *faddr; 111ca007d91SDag-Erling Smørgrav struct sock *next; 112ca007d91SDag-Erling Smørgrav }; 113ca007d91SDag-Erling Smørgrav 114ca007d91SDag-Erling Smørgrav #define HASHSIZE 1009 115ca007d91SDag-Erling Smørgrav static struct sock *sockhash[HASHSIZE]; 116ca007d91SDag-Erling Smørgrav 117ca007d91SDag-Erling Smørgrav static struct xfile *xfiles; 118ca007d91SDag-Erling Smørgrav static int nxfiles; 119ca007d91SDag-Erling Smørgrav 120ca007d91SDag-Erling Smørgrav static int 121ca007d91SDag-Erling Smørgrav xprintf(const char *fmt, ...) 122ca007d91SDag-Erling Smørgrav { 123ca007d91SDag-Erling Smørgrav va_list ap; 124ca007d91SDag-Erling Smørgrav int len; 125ca007d91SDag-Erling Smørgrav 126ca007d91SDag-Erling Smørgrav va_start(ap, fmt); 127ca007d91SDag-Erling Smørgrav len = vprintf(fmt, ap); 128ca007d91SDag-Erling Smørgrav va_end(ap); 129ca007d91SDag-Erling Smørgrav if (len < 0) 130ca007d91SDag-Erling Smørgrav err(1, "printf()"); 131ca007d91SDag-Erling Smørgrav return (len); 132ca007d91SDag-Erling Smørgrav } 133ca007d91SDag-Erling Smørgrav 1341f3d67aaSGiorgos Keramidas 1351f3d67aaSGiorgos Keramidas static int 1361f3d67aaSGiorgos Keramidas get_proto_type(const char *proto) 1371f3d67aaSGiorgos Keramidas { 1381f3d67aaSGiorgos Keramidas struct protoent *pent; 1391f3d67aaSGiorgos Keramidas 1401f3d67aaSGiorgos Keramidas if (strlen(proto) == 0) 1411f3d67aaSGiorgos Keramidas return (0); 1421f3d67aaSGiorgos Keramidas pent = getprotobyname(proto); 1431f3d67aaSGiorgos Keramidas if (pent == NULL) { 1441f3d67aaSGiorgos Keramidas warn("getprotobyname"); 1451f3d67aaSGiorgos Keramidas return (-1); 1461f3d67aaSGiorgos Keramidas } 1471f3d67aaSGiorgos Keramidas return (pent->p_proto); 1481f3d67aaSGiorgos Keramidas } 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 1711f3d67aaSGiorgos Keramidas static int 1721f3d67aaSGiorgos Keramidas parse_protos(char *protospec) 1731f3d67aaSGiorgos Keramidas { 1741f3d67aaSGiorgos Keramidas char *prot; 1751f3d67aaSGiorgos Keramidas int proto_type, proto_index; 1761f3d67aaSGiorgos Keramidas 1771f3d67aaSGiorgos Keramidas if (protospec == NULL) 1781f3d67aaSGiorgos Keramidas return (-1); 1791f3d67aaSGiorgos Keramidas 1801f3d67aaSGiorgos Keramidas init_protos(0); 1811f3d67aaSGiorgos Keramidas proto_index = 0; 182b8e20e2dSHiroki Sato while ((prot = strsep(&protospec, ",")) != NULL) { 1831f3d67aaSGiorgos Keramidas if (strlen(prot) == 0) 1841f3d67aaSGiorgos Keramidas continue; 1851f3d67aaSGiorgos Keramidas proto_type = get_proto_type(prot); 1861f3d67aaSGiorgos Keramidas if (proto_type != -1) 1871f3d67aaSGiorgos Keramidas protos[proto_index++] = proto_type; 1881f3d67aaSGiorgos Keramidas } 1891f3d67aaSGiorgos Keramidas numprotos = proto_index; 1901f3d67aaSGiorgos Keramidas return (proto_index); 1911f3d67aaSGiorgos Keramidas } 1921f3d67aaSGiorgos Keramidas 1931f3d67aaSGiorgos Keramidas 194ca007d91SDag-Erling Smørgrav static void 195ca007d91SDag-Erling Smørgrav parse_ports(const char *portspec) 196ca007d91SDag-Erling Smørgrav { 197ca007d91SDag-Erling Smørgrav const char *p, *q; 198ca007d91SDag-Erling Smørgrav int port, end; 199ca007d91SDag-Erling Smørgrav 200ca007d91SDag-Erling Smørgrav if (ports == NULL) 2019efed1e6SRobert Drehmel if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 202ca007d91SDag-Erling Smørgrav err(1, "calloc()"); 203ca007d91SDag-Erling Smørgrav p = portspec; 204ca007d91SDag-Erling Smørgrav while (*p != '\0') { 205ca007d91SDag-Erling Smørgrav if (!isdigit(*p)) 206ca007d91SDag-Erling Smørgrav errx(1, "syntax error in port range"); 207ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 208ca007d91SDag-Erling Smørgrav /* nothing */ ; 209ca007d91SDag-Erling Smørgrav for (port = 0; p < q; ++p) 210ca007d91SDag-Erling Smørgrav port = port * 10 + digittoint(*p); 211ca007d91SDag-Erling Smørgrav if (port < 0 || port > 65535) 212ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 213ca007d91SDag-Erling Smørgrav SET_PORT(port); 214ca007d91SDag-Erling Smørgrav switch (*p) { 215ca007d91SDag-Erling Smørgrav case '-': 216ca007d91SDag-Erling Smørgrav ++p; 217ca007d91SDag-Erling Smørgrav break; 218ca007d91SDag-Erling Smørgrav case ',': 219ca007d91SDag-Erling Smørgrav ++p; 220ca007d91SDag-Erling Smørgrav /* fall through */ 221ca007d91SDag-Erling Smørgrav case '\0': 222ca007d91SDag-Erling Smørgrav default: 223ca007d91SDag-Erling Smørgrav continue; 224ca007d91SDag-Erling Smørgrav } 225ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 226ca007d91SDag-Erling Smørgrav /* nothing */ ; 227ca007d91SDag-Erling Smørgrav for (end = 0; p < q; ++p) 228ca007d91SDag-Erling Smørgrav end = end * 10 + digittoint(*p); 229ca007d91SDag-Erling Smørgrav if (end < port || end > 65535) 230ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 231ca007d91SDag-Erling Smørgrav while (port++ < end) 232ca007d91SDag-Erling Smørgrav SET_PORT(port); 233ca007d91SDag-Erling Smørgrav if (*p == ',') 234ca007d91SDag-Erling Smørgrav ++p; 235ca007d91SDag-Erling Smørgrav } 236ca007d91SDag-Erling Smørgrav } 237ca007d91SDag-Erling Smørgrav 238ca007d91SDag-Erling Smørgrav static void 239b8e20e2dSHiroki Sato sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 240ca007d91SDag-Erling Smørgrav { 241ca007d91SDag-Erling Smørgrav struct sockaddr_in *sin4; 242ca007d91SDag-Erling Smørgrav struct sockaddr_in6 *sin6; 243ca007d91SDag-Erling Smørgrav 244b8e20e2dSHiroki Sato bzero(ss, sizeof(*ss)); 245ca007d91SDag-Erling Smørgrav switch (af) { 246ca007d91SDag-Erling Smørgrav case AF_INET: 247b8e20e2dSHiroki Sato sin4 = sstosin(ss); 248b8e20e2dSHiroki Sato sin4->sin_len = sizeof(*sin4); 249ca007d91SDag-Erling Smørgrav sin4->sin_family = af; 250ca007d91SDag-Erling Smørgrav sin4->sin_port = port; 251ca007d91SDag-Erling Smørgrav sin4->sin_addr = *(struct in_addr *)addr; 252ca007d91SDag-Erling Smørgrav break; 253ca007d91SDag-Erling Smørgrav case AF_INET6: 254b8e20e2dSHiroki Sato sin6 = sstosin6(ss); 255b8e20e2dSHiroki Sato sin6->sin6_len = sizeof(*sin6); 256ca007d91SDag-Erling Smørgrav sin6->sin6_family = af; 257ca007d91SDag-Erling Smørgrav sin6->sin6_port = port; 258ca007d91SDag-Erling Smørgrav sin6->sin6_addr = *(struct in6_addr *)addr; 259b8e20e2dSHiroki Sato #define s6_addr16 __u6_addr.__u6_addr16 260b8e20e2dSHiroki Sato if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 261b8e20e2dSHiroki Sato sin6->sin6_scope_id = 262b8e20e2dSHiroki Sato ntohs(sin6->sin6_addr.s6_addr16[1]); 263b8e20e2dSHiroki Sato sin6->sin6_addr.s6_addr16[1] = 0; 264b8e20e2dSHiroki Sato } 265ca007d91SDag-Erling Smørgrav break; 266ca007d91SDag-Erling Smørgrav default: 267ca007d91SDag-Erling Smørgrav abort(); 268ca007d91SDag-Erling Smørgrav } 269ca007d91SDag-Erling Smørgrav } 270ca007d91SDag-Erling Smørgrav 271ca007d91SDag-Erling Smørgrav static void 272bedcf91dSMichael Tuexen free_socket(struct sock *sock) 273bedcf91dSMichael Tuexen { 274bedcf91dSMichael Tuexen struct addr *cur, *next; 275bedcf91dSMichael Tuexen 276bedcf91dSMichael Tuexen cur = sock->laddr; 277bedcf91dSMichael Tuexen while (cur != NULL) { 278bedcf91dSMichael Tuexen next = cur->next; 279bedcf91dSMichael Tuexen free(cur); 280bedcf91dSMichael Tuexen cur = next; 281bedcf91dSMichael Tuexen } 282bedcf91dSMichael Tuexen cur = sock->faddr; 283bedcf91dSMichael Tuexen while (cur != NULL) { 284bedcf91dSMichael Tuexen next = cur->next; 285bedcf91dSMichael Tuexen free(cur); 286bedcf91dSMichael Tuexen cur = next; 287bedcf91dSMichael Tuexen } 288bedcf91dSMichael Tuexen free(sock); 289bedcf91dSMichael Tuexen } 290bedcf91dSMichael Tuexen 291bedcf91dSMichael Tuexen static void 292d5b4aa90SMichael Tuexen gather_sctp(void) 293d5b4aa90SMichael Tuexen { 294d5b4aa90SMichael Tuexen struct sock *sock; 295d5b4aa90SMichael Tuexen struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 296d5b4aa90SMichael Tuexen struct xsctp_inpcb *xinpcb; 297d5b4aa90SMichael Tuexen struct xsctp_tcb *xstcb; 298d5b4aa90SMichael Tuexen struct xsctp_raddr *xraddr; 299d5b4aa90SMichael Tuexen struct xsctp_laddr *xladdr; 300d5b4aa90SMichael Tuexen const char *varname; 301d5b4aa90SMichael Tuexen size_t len, offset; 302d5b4aa90SMichael Tuexen char *buf; 303d5b4aa90SMichael Tuexen int hash, vflag; 304d5b4aa90SMichael Tuexen int no_stcb, local_all_loopback, foreign_all_loopback; 305d5b4aa90SMichael Tuexen 306d5b4aa90SMichael Tuexen vflag = 0; 307d5b4aa90SMichael Tuexen if (opt_4) 308d5b4aa90SMichael Tuexen vflag |= INP_IPV4; 309d5b4aa90SMichael Tuexen if (opt_6) 310d5b4aa90SMichael Tuexen vflag |= INP_IPV6; 311d5b4aa90SMichael Tuexen 312d5b4aa90SMichael Tuexen varname = "net.inet.sctp.assoclist"; 313d5b4aa90SMichael Tuexen if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { 314d5b4aa90SMichael Tuexen if (errno != ENOENT) 315d5b4aa90SMichael Tuexen err(1, "sysctlbyname()"); 316d5b4aa90SMichael Tuexen return; 317d5b4aa90SMichael Tuexen } 318d5b4aa90SMichael Tuexen if ((buf = (char *)malloc(len)) == NULL) { 319d5b4aa90SMichael Tuexen err(1, "malloc()"); 320d5b4aa90SMichael Tuexen return; 321d5b4aa90SMichael Tuexen } 322d5b4aa90SMichael Tuexen if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { 323d5b4aa90SMichael Tuexen err(1, "sysctlbyname()"); 324d5b4aa90SMichael Tuexen free(buf); 325d5b4aa90SMichael Tuexen return; 326d5b4aa90SMichael Tuexen } 327d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)buf; 328d5b4aa90SMichael Tuexen offset = sizeof(struct xsctp_inpcb); 329d5b4aa90SMichael Tuexen while ((offset < len) && (xinpcb->last == 0)) { 330d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 331d5b4aa90SMichael Tuexen err(1, "malloc()"); 332d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 333d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 334d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 335d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 336d5b4aa90SMichael Tuexen sock->family = AF_INET6; 337d5b4aa90SMichael Tuexen sock->vflag = INP_IPV6; 338d5b4aa90SMichael Tuexen } else { 339d5b4aa90SMichael Tuexen sock->family = AF_INET; 340d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 341d5b4aa90SMichael Tuexen } 342d5b4aa90SMichael Tuexen prev_laddr = NULL; 343d5b4aa90SMichael Tuexen local_all_loopback = 1; 344d5b4aa90SMichael Tuexen while (offset < len) { 345d5b4aa90SMichael Tuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 346d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 347d5b4aa90SMichael Tuexen if (xladdr->last == 1) 348d5b4aa90SMichael Tuexen break; 349d5b4aa90SMichael Tuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 350d5b4aa90SMichael Tuexen err(1, "malloc()"); 351d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 352d5b4aa90SMichael Tuexen case AF_INET: 353d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 354d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 355d5b4aa90SMichael Tuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 356d5b4aa90SMichael Tuexen local_all_loopback = 0; 357d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 358d5b4aa90SMichael Tuexen sockaddr(&laddr->address, 359d5b4aa90SMichael Tuexen AF_INET, 360d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 361d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 362d5b4aa90SMichael Tuexen break; 363d5b4aa90SMichael Tuexen case AF_INET6: 364d5b4aa90SMichael Tuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 365d5b4aa90SMichael Tuexen local_all_loopback = 0; 366d5b4aa90SMichael Tuexen sockaddr(&laddr->address, 367d5b4aa90SMichael Tuexen AF_INET6, 368d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 369d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 370d5b4aa90SMichael Tuexen break; 371d5b4aa90SMichael Tuexen default: 372d5b4aa90SMichael Tuexen errx(1, "adress family %d not supported", 373d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 374d5b4aa90SMichael Tuexen } 375d5b4aa90SMichael Tuexen laddr->next = NULL; 376d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 377d5b4aa90SMichael Tuexen sock->laddr = laddr; 378d5b4aa90SMichael Tuexen else 379d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 380d5b4aa90SMichael Tuexen prev_laddr = laddr; 381d5b4aa90SMichael Tuexen } 382d5b4aa90SMichael Tuexen if (sock->laddr == NULL) { 383d5b4aa90SMichael Tuexen if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) 384d5b4aa90SMichael Tuexen err(1, "malloc()"); 385d5b4aa90SMichael Tuexen sock->laddr->address.ss_family = sock->family; 386d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 387d5b4aa90SMichael Tuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 388d5b4aa90SMichael Tuexen else 389d5b4aa90SMichael Tuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 390d5b4aa90SMichael Tuexen local_all_loopback = 0; 391d5b4aa90SMichael Tuexen } 392d5b4aa90SMichael Tuexen if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 393d5b4aa90SMichael Tuexen err(1, "malloc()"); 394d5b4aa90SMichael Tuexen sock->faddr->address.ss_family = sock->family; 395d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 396d5b4aa90SMichael Tuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 397d5b4aa90SMichael Tuexen else 398d5b4aa90SMichael Tuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 399d5b4aa90SMichael Tuexen no_stcb = 1; 400d5b4aa90SMichael Tuexen while (offset < len) { 401d5b4aa90SMichael Tuexen xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 402d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_tcb); 403bedcf91dSMichael Tuexen if (no_stcb) { 404bedcf91dSMichael Tuexen if (opt_l && 405d5b4aa90SMichael Tuexen (!opt_L || !local_all_loopback) && 406d5b4aa90SMichael Tuexen ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 407d5b4aa90SMichael Tuexen (xstcb->last == 1))) { 408d5b4aa90SMichael Tuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 409d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 410d5b4aa90SMichael Tuexen sockhash[hash] = sock; 411bedcf91dSMichael Tuexen } else { 412bedcf91dSMichael Tuexen free_socket(sock); 413bedcf91dSMichael Tuexen } 414d5b4aa90SMichael Tuexen } 415d5b4aa90SMichael Tuexen if (xstcb->last == 1) 416d5b4aa90SMichael Tuexen break; 417d5b4aa90SMichael Tuexen no_stcb = 0; 418d5b4aa90SMichael Tuexen if (opt_c) { 419d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 420d5b4aa90SMichael Tuexen err(1, "malloc()"); 421d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 422d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 423d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 424d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 425d5b4aa90SMichael Tuexen sock->family = AF_INET6; 426d5b4aa90SMichael Tuexen sock->vflag = INP_IPV6; 427d5b4aa90SMichael Tuexen } else { 428d5b4aa90SMichael Tuexen sock->family = AF_INET; 429d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 430d5b4aa90SMichael Tuexen } 431d5b4aa90SMichael Tuexen } 432d5b4aa90SMichael Tuexen prev_laddr = NULL; 433d5b4aa90SMichael Tuexen local_all_loopback = 1; 434d5b4aa90SMichael Tuexen while (offset < len) { 435d5b4aa90SMichael Tuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 436d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 437d5b4aa90SMichael Tuexen if (xladdr->last == 1) 438d5b4aa90SMichael Tuexen break; 439d5b4aa90SMichael Tuexen if (!opt_c) 440d5b4aa90SMichael Tuexen continue; 441d5b4aa90SMichael Tuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 442d5b4aa90SMichael Tuexen err(1, "malloc()"); 443d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 444d5b4aa90SMichael Tuexen case AF_INET: 445d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 446d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 447d5b4aa90SMichael Tuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 448d5b4aa90SMichael Tuexen local_all_loopback = 0; 449d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 450d5b4aa90SMichael Tuexen sockaddr(&laddr->address, 451d5b4aa90SMichael Tuexen AF_INET, 452d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 453d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 454d5b4aa90SMichael Tuexen break; 455d5b4aa90SMichael Tuexen case AF_INET6: 456d5b4aa90SMichael Tuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 457d5b4aa90SMichael Tuexen local_all_loopback = 0; 458d5b4aa90SMichael Tuexen sockaddr(&laddr->address, 459d5b4aa90SMichael Tuexen AF_INET6, 460d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 461d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 462d5b4aa90SMichael Tuexen break; 463d5b4aa90SMichael Tuexen default: 464d5b4aa90SMichael Tuexen errx(1, "adress family %d not supported", 465d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 466d5b4aa90SMichael Tuexen } 467d5b4aa90SMichael Tuexen laddr->next = NULL; 468d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 469d5b4aa90SMichael Tuexen sock->laddr = laddr; 470d5b4aa90SMichael Tuexen else 471d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 472d5b4aa90SMichael Tuexen prev_laddr = laddr; 473d5b4aa90SMichael Tuexen } 474d5b4aa90SMichael Tuexen prev_faddr = NULL; 475d5b4aa90SMichael Tuexen foreign_all_loopback = 1; 476d5b4aa90SMichael Tuexen while (offset < len) { 477d5b4aa90SMichael Tuexen xraddr = (struct xsctp_raddr *)(void *)(buf + offset); 478d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_raddr); 479d5b4aa90SMichael Tuexen if (xraddr->last == 1) 480d5b4aa90SMichael Tuexen break; 481d5b4aa90SMichael Tuexen if (!opt_c) 482d5b4aa90SMichael Tuexen continue; 483d5b4aa90SMichael Tuexen if ((faddr = calloc(1, sizeof(struct addr))) == NULL) 484d5b4aa90SMichael Tuexen err(1, "malloc()"); 485d5b4aa90SMichael Tuexen switch (xraddr->address.sa.sa_family) { 486d5b4aa90SMichael Tuexen case AF_INET: 487d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 488d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 489d5b4aa90SMichael Tuexen if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) 490d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 491d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 492d5b4aa90SMichael Tuexen sockaddr(&faddr->address, 493d5b4aa90SMichael Tuexen AF_INET, 494d5b4aa90SMichael Tuexen &xraddr->address.sin.sin_addr, 495d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 496d5b4aa90SMichael Tuexen break; 497d5b4aa90SMichael Tuexen case AF_INET6: 498d5b4aa90SMichael Tuexen if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) 499d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 500d5b4aa90SMichael Tuexen sockaddr(&faddr->address, 501d5b4aa90SMichael Tuexen AF_INET6, 502d5b4aa90SMichael Tuexen &xraddr->address.sin6.sin6_addr, 503d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 504d5b4aa90SMichael Tuexen break; 505d5b4aa90SMichael Tuexen default: 506d5b4aa90SMichael Tuexen errx(1, "adress family %d not supported", 507d5b4aa90SMichael Tuexen xraddr->address.sa.sa_family); 508d5b4aa90SMichael Tuexen } 509d5b4aa90SMichael Tuexen faddr->next = NULL; 510d5b4aa90SMichael Tuexen if (prev_faddr == NULL) 511d5b4aa90SMichael Tuexen sock->faddr = faddr; 512d5b4aa90SMichael Tuexen else 513d5b4aa90SMichael Tuexen prev_faddr->next = faddr; 514d5b4aa90SMichael Tuexen prev_faddr = faddr; 515d5b4aa90SMichael Tuexen } 516bedcf91dSMichael Tuexen if (opt_c) { 517bedcf91dSMichael Tuexen if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { 518d5b4aa90SMichael Tuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 519d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 520d5b4aa90SMichael Tuexen sockhash[hash] = sock; 521bedcf91dSMichael Tuexen } else { 522bedcf91dSMichael Tuexen free_socket(sock); 523bedcf91dSMichael Tuexen } 524d5b4aa90SMichael Tuexen } 525d5b4aa90SMichael Tuexen } 526d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 527d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_inpcb); 528d5b4aa90SMichael Tuexen } 529d5b4aa90SMichael Tuexen free(buf); 530d5b4aa90SMichael Tuexen } 531d5b4aa90SMichael Tuexen 532d5b4aa90SMichael Tuexen static void 533ca007d91SDag-Erling Smørgrav gather_inet(int proto) 534ca007d91SDag-Erling Smørgrav { 535ca007d91SDag-Erling Smørgrav struct xinpgen *xig, *exig; 536ca007d91SDag-Erling Smørgrav struct xinpcb *xip; 537ca007d91SDag-Erling Smørgrav struct xtcpcb *xtp; 538ca007d91SDag-Erling Smørgrav struct inpcb *inp; 539ca007d91SDag-Erling Smørgrav struct xsocket *so; 540ca007d91SDag-Erling Smørgrav struct sock *sock; 541e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 542ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 543ca007d91SDag-Erling Smørgrav size_t len, bufsize; 544ca007d91SDag-Erling Smørgrav void *buf; 545*7a5642b3SDag-Erling Smørgrav int hash, retry, state, vflag; 546ca007d91SDag-Erling Smørgrav 547*7a5642b3SDag-Erling Smørgrav state = vflag = 0; 548ca007d91SDag-Erling Smørgrav if (opt_4) 549ca007d91SDag-Erling Smørgrav vflag |= INP_IPV4; 550ca007d91SDag-Erling Smørgrav if (opt_6) 551ca007d91SDag-Erling Smørgrav vflag |= INP_IPV6; 552ca007d91SDag-Erling Smørgrav 553ca007d91SDag-Erling Smørgrav switch (proto) { 554ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 555ca007d91SDag-Erling Smørgrav varname = "net.inet.tcp.pcblist"; 556ca007d91SDag-Erling Smørgrav protoname = "tcp"; 557ca007d91SDag-Erling Smørgrav break; 558ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 559ca007d91SDag-Erling Smørgrav varname = "net.inet.udp.pcblist"; 560ca007d91SDag-Erling Smørgrav protoname = "udp"; 561ca007d91SDag-Erling Smørgrav break; 5622cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 5632cfbdf89SRuslan Ermilov varname = "net.inet.divert.pcblist"; 5642cfbdf89SRuslan Ermilov protoname = "div"; 5652cfbdf89SRuslan Ermilov break; 566ca007d91SDag-Erling Smørgrav default: 5671f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 568ca007d91SDag-Erling Smørgrav } 569ca007d91SDag-Erling Smørgrav 570ca007d91SDag-Erling Smørgrav buf = NULL; 571ca007d91SDag-Erling Smørgrav bufsize = 8192; 572ca007d91SDag-Erling Smørgrav retry = 5; 573ca007d91SDag-Erling Smørgrav do { 574ca007d91SDag-Erling Smørgrav for (;;) { 575ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 576ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 577ca007d91SDag-Erling Smørgrav len = bufsize; 578ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 579ca007d91SDag-Erling Smørgrav break; 5804b2a3d41SRuslan Ermilov if (errno == ENOENT) 5814b2a3d41SRuslan Ermilov goto out; 582003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 583ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 584ca007d91SDag-Erling Smørgrav bufsize *= 2; 585ca007d91SDag-Erling Smørgrav } 586ca007d91SDag-Erling Smørgrav xig = (struct xinpgen *)buf; 5876dbe8d53SRobert Drehmel exig = (struct xinpgen *)(void *) 5886dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exig); 589ca007d91SDag-Erling Smørgrav if (xig->xig_len != sizeof *xig || 590ca007d91SDag-Erling Smørgrav exig->xig_len != sizeof *exig) 591ca007d91SDag-Erling Smørgrav errx(1, "struct xinpgen size mismatch"); 592ca007d91SDag-Erling Smørgrav } while (xig->xig_gen != exig->xig_gen && retry--); 593ca007d91SDag-Erling Smørgrav 594ca007d91SDag-Erling Smørgrav if (xig->xig_gen != exig->xig_gen && opt_v) 595ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 596ca007d91SDag-Erling Smørgrav 597ca007d91SDag-Erling Smørgrav for (;;) { 5986dbe8d53SRobert Drehmel xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 599ca007d91SDag-Erling Smørgrav if (xig >= exig) 600ca007d91SDag-Erling Smørgrav break; 601ca007d91SDag-Erling Smørgrav switch (proto) { 602ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 603ca007d91SDag-Erling Smørgrav xtp = (struct xtcpcb *)xig; 604b8e20e2dSHiroki Sato if (xtp->xt_len != sizeof(*xtp)) { 605ca007d91SDag-Erling Smørgrav warnx("struct xtcpcb size mismatch"); 606ca007d91SDag-Erling Smørgrav goto out; 607ca007d91SDag-Erling Smørgrav } 608ca007d91SDag-Erling Smørgrav inp = &xtp->xt_inp; 609ca007d91SDag-Erling Smørgrav so = &xtp->xt_socket; 61009fe6320SNavdeep Parhar protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; 611*7a5642b3SDag-Erling Smørgrav state = xtp->xt_tp.t_state; 612ca007d91SDag-Erling Smørgrav break; 613ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 6142cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 615ca007d91SDag-Erling Smørgrav xip = (struct xinpcb *)xig; 616b8e20e2dSHiroki Sato if (xip->xi_len != sizeof(*xip)) { 617ca007d91SDag-Erling Smørgrav warnx("struct xinpcb size mismatch"); 618ca007d91SDag-Erling Smørgrav goto out; 619ca007d91SDag-Erling Smørgrav } 620ca007d91SDag-Erling Smørgrav inp = &xip->xi_inp; 621ca007d91SDag-Erling Smørgrav so = &xip->xi_socket; 622ca007d91SDag-Erling Smørgrav break; 623ca007d91SDag-Erling Smørgrav default: 6241f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 625ca007d91SDag-Erling Smørgrav } 626ca007d91SDag-Erling Smørgrav if ((inp->inp_vflag & vflag) == 0) 627ca007d91SDag-Erling Smørgrav continue; 6281e6690e5SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 6291e6690e5SDag-Erling Smørgrav if ((inp->inp_fport == 0 && !opt_l) || 6301e6690e5SDag-Erling Smørgrav (inp->inp_fport != 0 && !opt_c)) 6311e6690e5SDag-Erling Smørgrav continue; 6329b6ca892SBruce M Simpson #define __IN_IS_ADDR_LOOPBACK(pina) \ 6339b6ca892SBruce M Simpson ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 6349b6ca892SBruce M Simpson if (opt_L && 6359b6ca892SBruce M Simpson (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || 6369b6ca892SBruce M Simpson __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) 6379b6ca892SBruce M Simpson continue; 6389b6ca892SBruce M Simpson #undef __IN_IS_ADDR_LOOPBACK 6391e6690e5SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 6404cf172fdSRobert Watson if ((inp->inp_fport == 0 && !opt_l) || 6414cf172fdSRobert Watson (inp->inp_fport != 0 && !opt_c)) 6421e6690e5SDag-Erling Smørgrav continue; 6439b6ca892SBruce M Simpson if (opt_L && 6449b6ca892SBruce M Simpson (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || 6459b6ca892SBruce M Simpson IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) 6469b6ca892SBruce M Simpson continue; 6471e6690e5SDag-Erling Smørgrav } else { 6481e6690e5SDag-Erling Smørgrav if (opt_v) 6491e6690e5SDag-Erling Smørgrav warnx("invalid vflag 0x%x", inp->inp_vflag); 6501e6690e5SDag-Erling Smørgrav continue; 6511e6690e5SDag-Erling Smørgrav } 652b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 653ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 654e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 655e6f718c7SMichael Tuexen err(1, "malloc()"); 656e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 657e6f718c7SMichael Tuexen err(1, "malloc()"); 658ca007d91SDag-Erling Smørgrav sock->socket = so->xso_so; 659ca007d91SDag-Erling Smørgrav sock->proto = proto; 660ca007d91SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 661ca007d91SDag-Erling Smørgrav sock->family = AF_INET; 662e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 663ca007d91SDag-Erling Smørgrav &inp->inp_laddr, inp->inp_lport); 664e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 665ca007d91SDag-Erling Smørgrav &inp->inp_faddr, inp->inp_fport); 666ca007d91SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 667ca007d91SDag-Erling Smørgrav sock->family = AF_INET6; 668e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 6694cf172fdSRobert Watson &inp->in6p_laddr, inp->inp_lport); 670e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 6714cf172fdSRobert Watson &inp->in6p_faddr, inp->inp_fport); 672ca007d91SDag-Erling Smørgrav } 673e6f718c7SMichael Tuexen laddr->next = NULL; 674e6f718c7SMichael Tuexen faddr->next = NULL; 675e6f718c7SMichael Tuexen sock->laddr = laddr; 676e6f718c7SMichael Tuexen sock->faddr = faddr; 677ca007d91SDag-Erling Smørgrav sock->vflag = inp->inp_vflag; 678*7a5642b3SDag-Erling Smørgrav if (proto == IPPROTO_TCP) 679*7a5642b3SDag-Erling Smørgrav sock->state = xtp->xt_tp.t_state; 680ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 681ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 682ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 683ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 684ca007d91SDag-Erling Smørgrav } 685ca007d91SDag-Erling Smørgrav out: 686ca007d91SDag-Erling Smørgrav free(buf); 687ca007d91SDag-Erling Smørgrav } 688ca007d91SDag-Erling Smørgrav 689ca007d91SDag-Erling Smørgrav static void 690ca007d91SDag-Erling Smørgrav gather_unix(int proto) 691ca007d91SDag-Erling Smørgrav { 692ca007d91SDag-Erling Smørgrav struct xunpgen *xug, *exug; 693ca007d91SDag-Erling Smørgrav struct xunpcb *xup; 694ca007d91SDag-Erling Smørgrav struct sock *sock; 695e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 696ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 697ca007d91SDag-Erling Smørgrav size_t len, bufsize; 698ca007d91SDag-Erling Smørgrav void *buf; 699ca007d91SDag-Erling Smørgrav int hash, retry; 700ca007d91SDag-Erling Smørgrav 701ca007d91SDag-Erling Smørgrav switch (proto) { 702ca007d91SDag-Erling Smørgrav case SOCK_STREAM: 703ca007d91SDag-Erling Smørgrav varname = "net.local.stream.pcblist"; 704ca007d91SDag-Erling Smørgrav protoname = "stream"; 705ca007d91SDag-Erling Smørgrav break; 706ca007d91SDag-Erling Smørgrav case SOCK_DGRAM: 707ca007d91SDag-Erling Smørgrav varname = "net.local.dgram.pcblist"; 708ca007d91SDag-Erling Smørgrav protoname = "dgram"; 709ca007d91SDag-Erling Smørgrav break; 710b8e20e2dSHiroki Sato case SOCK_SEQPACKET: 711b8e20e2dSHiroki Sato varname = "net.local.seqpacket.pcblist"; 712b8e20e2dSHiroki Sato protoname = "seqpac"; 713b8e20e2dSHiroki Sato break; 714ca007d91SDag-Erling Smørgrav default: 715ca007d91SDag-Erling Smørgrav abort(); 716ca007d91SDag-Erling Smørgrav } 717ca007d91SDag-Erling Smørgrav buf = NULL; 718ca007d91SDag-Erling Smørgrav bufsize = 8192; 719ca007d91SDag-Erling Smørgrav retry = 5; 720ca007d91SDag-Erling Smørgrav do { 721ca007d91SDag-Erling Smørgrav for (;;) { 722ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 723ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 724ca007d91SDag-Erling Smørgrav len = bufsize; 725ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 726ca007d91SDag-Erling Smørgrav break; 727003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 728ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 729ca007d91SDag-Erling Smørgrav bufsize *= 2; 730ca007d91SDag-Erling Smørgrav } 731ca007d91SDag-Erling Smørgrav xug = (struct xunpgen *)buf; 7326dbe8d53SRobert Drehmel exug = (struct xunpgen *)(void *) 733b8e20e2dSHiroki Sato ((char *)buf + len - sizeof(*exug)); 734b8e20e2dSHiroki Sato if (xug->xug_len != sizeof(*xug) || 735b8e20e2dSHiroki Sato exug->xug_len != sizeof(*exug)) { 736ca007d91SDag-Erling Smørgrav warnx("struct xinpgen size mismatch"); 737ca007d91SDag-Erling Smørgrav goto out; 738ca007d91SDag-Erling Smørgrav } 739ca007d91SDag-Erling Smørgrav } while (xug->xug_gen != exug->xug_gen && retry--); 740ca007d91SDag-Erling Smørgrav 741ca007d91SDag-Erling Smørgrav if (xug->xug_gen != exug->xug_gen && opt_v) 742ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 743ca007d91SDag-Erling Smørgrav 744ca007d91SDag-Erling Smørgrav for (;;) { 7456dbe8d53SRobert Drehmel xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 746ca007d91SDag-Erling Smørgrav if (xug >= exug) 747ca007d91SDag-Erling Smørgrav break; 748ca007d91SDag-Erling Smørgrav xup = (struct xunpcb *)xug; 749b8e20e2dSHiroki Sato if (xup->xu_len != sizeof(*xup)) { 750ca007d91SDag-Erling Smørgrav warnx("struct xunpcb size mismatch"); 751ca007d91SDag-Erling Smørgrav goto out; 752ca007d91SDag-Erling Smørgrav } 7531e6690e5SDag-Erling Smørgrav if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 7541e6690e5SDag-Erling Smørgrav (xup->xu_unp.unp_conn != NULL && !opt_c)) 7551e6690e5SDag-Erling Smørgrav continue; 756b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 757ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 758e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 759e6f718c7SMichael Tuexen err(1, "malloc()"); 760e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 761e6f718c7SMichael Tuexen err(1, "malloc()"); 762ca007d91SDag-Erling Smørgrav sock->socket = xup->xu_socket.xso_so; 763ca007d91SDag-Erling Smørgrav sock->pcb = xup->xu_unpp; 764ca007d91SDag-Erling Smørgrav sock->proto = proto; 765ca007d91SDag-Erling Smørgrav sock->family = AF_UNIX; 766ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 767ca007d91SDag-Erling Smørgrav if (xup->xu_unp.unp_addr != NULL) 768e6f718c7SMichael Tuexen laddr->address = 7696dbe8d53SRobert Drehmel *(struct sockaddr_storage *)(void *)&xup->xu_addr; 770ca007d91SDag-Erling Smørgrav else if (xup->xu_unp.unp_conn != NULL) 771e6f718c7SMichael Tuexen *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 772e6f718c7SMichael Tuexen laddr->next = NULL; 773e6f718c7SMichael Tuexen faddr->next = NULL; 774e6f718c7SMichael Tuexen sock->laddr = laddr; 775e6f718c7SMichael Tuexen sock->faddr = faddr; 776ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 777ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 778ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 779ca007d91SDag-Erling Smørgrav } 780ca007d91SDag-Erling Smørgrav out: 781ca007d91SDag-Erling Smørgrav free(buf); 782ca007d91SDag-Erling Smørgrav } 783ca007d91SDag-Erling Smørgrav 784ca007d91SDag-Erling Smørgrav static void 785ca007d91SDag-Erling Smørgrav getfiles(void) 786ca007d91SDag-Erling Smørgrav { 787003e7e49SMikolaj Golub size_t len, olen; 788ca007d91SDag-Erling Smørgrav 789b8e20e2dSHiroki Sato olen = len = sizeof(*xfiles); 790003e7e49SMikolaj Golub if ((xfiles = malloc(len)) == NULL) 791ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 792ca007d91SDag-Erling Smørgrav while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 793003e7e49SMikolaj Golub if (errno != ENOMEM || len != olen) 794ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 795003e7e49SMikolaj Golub olen = len *= 2; 796ca007d91SDag-Erling Smørgrav if ((xfiles = realloc(xfiles, len)) == NULL) 797ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 798ca007d91SDag-Erling Smørgrav } 799b8e20e2dSHiroki Sato if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 800ca007d91SDag-Erling Smørgrav errx(1, "struct xfile size mismatch"); 801b8e20e2dSHiroki Sato nxfiles = len / sizeof(*xfiles); 802ca007d91SDag-Erling Smørgrav } 803ca007d91SDag-Erling Smørgrav 804ca007d91SDag-Erling Smørgrav static int 805baa7f281SMichael Tuexen printaddr(struct sockaddr_storage *ss) 806ca007d91SDag-Erling Smørgrav { 807ca007d91SDag-Erling Smørgrav struct sockaddr_un *sun; 808b8e20e2dSHiroki Sato char addrstr[NI_MAXHOST] = { '\0', '\0' }; 809b8e20e2dSHiroki Sato int error, off, port = 0; 810ca007d91SDag-Erling Smørgrav 811baa7f281SMichael Tuexen switch (ss->ss_family) { 812ca007d91SDag-Erling Smørgrav case AF_INET: 813b8e20e2dSHiroki Sato if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) 814ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 815b8e20e2dSHiroki Sato port = ntohs(sstosin(ss)->sin_port); 816ca007d91SDag-Erling Smørgrav break; 817ca007d91SDag-Erling Smørgrav case AF_INET6: 818b8e20e2dSHiroki Sato if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 819ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 820b8e20e2dSHiroki Sato port = ntohs(sstosin6(ss)->sin6_port); 821ca007d91SDag-Erling Smørgrav break; 822ca007d91SDag-Erling Smørgrav case AF_UNIX: 823b8e20e2dSHiroki Sato sun = sstosun(ss); 824ca007d91SDag-Erling Smørgrav off = (int)((char *)&sun->sun_path - (char *)sun); 825ca007d91SDag-Erling Smørgrav return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 826ca007d91SDag-Erling Smørgrav } 827b8e20e2dSHiroki Sato if (addrstr[0] == '\0') { 828b8e20e2dSHiroki Sato error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, 829b8e20e2dSHiroki Sato sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 830b8e20e2dSHiroki Sato if (error) 831b8e20e2dSHiroki Sato errx(1, "getnameinfo()"); 832b8e20e2dSHiroki Sato } 833ca007d91SDag-Erling Smørgrav if (port == 0) 834ca007d91SDag-Erling Smørgrav return xprintf("%s:*", addrstr); 835ca007d91SDag-Erling Smørgrav else 836ca007d91SDag-Erling Smørgrav return xprintf("%s:%d", addrstr, port); 837ca007d91SDag-Erling Smørgrav } 838ca007d91SDag-Erling Smørgrav 839ca007d91SDag-Erling Smørgrav static const char * 840ca007d91SDag-Erling Smørgrav getprocname(pid_t pid) 841ca007d91SDag-Erling Smørgrav { 842ca007d91SDag-Erling Smørgrav static struct kinfo_proc proc; 843ca007d91SDag-Erling Smørgrav size_t len; 844ca007d91SDag-Erling Smørgrav int mib[4]; 845ca007d91SDag-Erling Smørgrav 846ca007d91SDag-Erling Smørgrav mib[0] = CTL_KERN; 847ca007d91SDag-Erling Smørgrav mib[1] = KERN_PROC; 848ca007d91SDag-Erling Smørgrav mib[2] = KERN_PROC_PID; 849ca007d91SDag-Erling Smørgrav mib[3] = (int)pid; 850b8e20e2dSHiroki Sato len = sizeof(proc); 851b8e20e2dSHiroki Sato if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 85248c513e0SMaxim Konovalov /* Do not warn if the process exits before we get its name. */ 85348c513e0SMaxim Konovalov if (errno != ESRCH) 854ca007d91SDag-Erling Smørgrav warn("sysctl()"); 855ca007d91SDag-Erling Smørgrav return ("??"); 856ca007d91SDag-Erling Smørgrav } 857f487a6a8SEd Maste return (proc.ki_comm); 858ca007d91SDag-Erling Smørgrav } 859ca007d91SDag-Erling Smørgrav 860ae94787dSMaxime Henrion static int 86100feaafdSAndrew Thompson getprocjid(pid_t pid) 86200feaafdSAndrew Thompson { 86300feaafdSAndrew Thompson static struct kinfo_proc proc; 86400feaafdSAndrew Thompson size_t len; 86500feaafdSAndrew Thompson int mib[4]; 86600feaafdSAndrew Thompson 86700feaafdSAndrew Thompson mib[0] = CTL_KERN; 86800feaafdSAndrew Thompson mib[1] = KERN_PROC; 86900feaafdSAndrew Thompson mib[2] = KERN_PROC_PID; 87000feaafdSAndrew Thompson mib[3] = (int)pid; 871b8e20e2dSHiroki Sato len = sizeof(proc); 872b8e20e2dSHiroki Sato if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 87300feaafdSAndrew Thompson /* Do not warn if the process exits before we get its jid. */ 87400feaafdSAndrew Thompson if (errno != ESRCH) 87500feaafdSAndrew Thompson warn("sysctl()"); 87600feaafdSAndrew Thompson return (-1); 87700feaafdSAndrew Thompson } 87800feaafdSAndrew Thompson return (proc.ki_jid); 87900feaafdSAndrew Thompson } 88000feaafdSAndrew Thompson 88100feaafdSAndrew Thompson static int 882ae94787dSMaxime Henrion check_ports(struct sock *s) 883ae94787dSMaxime Henrion { 884ae94787dSMaxime Henrion int port; 885e6f718c7SMichael Tuexen struct addr *addr; 886ae94787dSMaxime Henrion 887ae94787dSMaxime Henrion if (ports == NULL) 888ae94787dSMaxime Henrion return (1); 889ae94787dSMaxime Henrion if ((s->family != AF_INET) && (s->family != AF_INET6)) 890ae94787dSMaxime Henrion return (1); 891e6f718c7SMichael Tuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 892b8e20e2dSHiroki Sato if (s->family == AF_INET) 893b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 894ae94787dSMaxime Henrion else 895b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 896ae94787dSMaxime Henrion if (CHK_PORT(port)) 897ae94787dSMaxime Henrion return (1); 898e6f718c7SMichael Tuexen } 899e6f718c7SMichael Tuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 900b8e20e2dSHiroki Sato if (s->family == AF_INET) 901b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 902ae94787dSMaxime Henrion else 903b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 904ae94787dSMaxime Henrion if (CHK_PORT(port)) 905ae94787dSMaxime Henrion return (1); 906e6f718c7SMichael Tuexen } 907ae94787dSMaxime Henrion return (0); 908ae94787dSMaxime Henrion } 909ae94787dSMaxime Henrion 910ca007d91SDag-Erling Smørgrav static void 91161149f8dSJilles Tjoelker displaysock(struct sock *s, int pos) 912ca007d91SDag-Erling Smørgrav { 913ca007d91SDag-Erling Smørgrav void *p; 91461149f8dSJilles Tjoelker int hash; 915e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 91681091202SMichael Tuexen struct sock *s_tmp; 917ca007d91SDag-Erling Smørgrav 918ca007d91SDag-Erling Smørgrav while (pos < 29) 919ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 920ca007d91SDag-Erling Smørgrav pos += xprintf("%s", s->protoname); 921ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV4) 922ca007d91SDag-Erling Smørgrav pos += xprintf("4 "); 923ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV6) 924ca007d91SDag-Erling Smørgrav pos += xprintf("6 "); 925e6f718c7SMichael Tuexen laddr = s->laddr; 926e6f718c7SMichael Tuexen faddr = s->faddr; 927e6f718c7SMichael Tuexen while (laddr != NULL || faddr != NULL) { 928ca007d91SDag-Erling Smørgrav while (pos < 36) 929ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 930ca007d91SDag-Erling Smørgrav switch (s->family) { 931ca007d91SDag-Erling Smørgrav case AF_INET: 932ca007d91SDag-Erling Smørgrav case AF_INET6: 933e6f718c7SMichael Tuexen if (laddr != NULL) { 934e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 93509bbda21SMaxim Konovalov if (s->family == AF_INET6 && pos >= 58) 93609bbda21SMaxim Konovalov pos += xprintf(" "); 937e6f718c7SMichael Tuexen } 938ca007d91SDag-Erling Smørgrav while (pos < 58) 939ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 940e6f718c7SMichael Tuexen if (faddr != NULL) 941e6f718c7SMichael Tuexen pos += printaddr(&faddr->address); 942ca007d91SDag-Erling Smørgrav break; 943ca007d91SDag-Erling Smørgrav case AF_UNIX: 944e6f718c7SMichael Tuexen if ((laddr == NULL) || (faddr == NULL)) 945e6f718c7SMichael Tuexen errx(1, "laddr = %p or faddr = %p is NULL", 946e6f718c7SMichael Tuexen (void *)laddr, (void *)faddr); 947ca007d91SDag-Erling Smørgrav /* server */ 948e6f718c7SMichael Tuexen if (laddr->address.ss_len > 0) { 949e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 950ca007d91SDag-Erling Smørgrav break; 951ca007d91SDag-Erling Smørgrav } 952ca007d91SDag-Erling Smørgrav /* client */ 953e6f718c7SMichael Tuexen p = *(void **)&(faddr->address); 954b4eb37c6SJohn-Mark Gurney if (p == NULL) { 955b4eb37c6SJohn-Mark Gurney pos += xprintf("(not connected)"); 956b4eb37c6SJohn-Mark Gurney break; 957b4eb37c6SJohn-Mark Gurney } 958b4eb37c6SJohn-Mark Gurney pos += xprintf("-> "); 959ca007d91SDag-Erling Smørgrav for (hash = 0; hash < HASHSIZE; ++hash) { 96081091202SMichael Tuexen for (s_tmp = sockhash[hash]; 96181091202SMichael Tuexen s_tmp != NULL; 96281091202SMichael Tuexen s_tmp = s_tmp->next) 96381091202SMichael Tuexen if (s_tmp->pcb == p) 964ca007d91SDag-Erling Smørgrav break; 96581091202SMichael Tuexen if (s_tmp != NULL) 966ca007d91SDag-Erling Smørgrav break; 967ca007d91SDag-Erling Smørgrav } 96881091202SMichael Tuexen if (s_tmp == NULL || 96981091202SMichael Tuexen s_tmp->laddr == NULL || 97081091202SMichael Tuexen s_tmp->laddr->address.ss_len == 0) 971ca007d91SDag-Erling Smørgrav pos += xprintf("??"); 972ca007d91SDag-Erling Smørgrav else 97381091202SMichael Tuexen pos += printaddr(&s_tmp->laddr->address); 974ca007d91SDag-Erling Smørgrav break; 975ca007d91SDag-Erling Smørgrav default: 976ca007d91SDag-Erling Smørgrav abort(); 977ca007d91SDag-Erling Smørgrav } 978e6f718c7SMichael Tuexen if (laddr != NULL) 979e6f718c7SMichael Tuexen laddr = laddr->next; 980e6f718c7SMichael Tuexen if (faddr != NULL) 981e6f718c7SMichael Tuexen faddr = faddr->next; 982e6f718c7SMichael Tuexen if ((laddr != NULL) || (faddr != NULL)) { 983e6f718c7SMichael Tuexen xprintf("\n"); 984e6f718c7SMichael Tuexen pos = 0; 985e6f718c7SMichael Tuexen } 986e6f718c7SMichael Tuexen } 987*7a5642b3SDag-Erling Smørgrav if (opt_s && s->proto == IPPROTO_TCP) { 988*7a5642b3SDag-Erling Smørgrav while (pos < 80) 989*7a5642b3SDag-Erling Smørgrav pos += xprintf(" "); 990*7a5642b3SDag-Erling Smørgrav if (s->state >= 0 && s->state < TCP_NSTATES) 991*7a5642b3SDag-Erling Smørgrav pos += xprintf("%s", tcpstates[s->state]); 992*7a5642b3SDag-Erling Smørgrav else 993*7a5642b3SDag-Erling Smørgrav pos += xprintf("?"); 994*7a5642b3SDag-Erling Smørgrav } 995ca007d91SDag-Erling Smørgrav } 99661149f8dSJilles Tjoelker 99761149f8dSJilles Tjoelker static void 99861149f8dSJilles Tjoelker display(void) 99961149f8dSJilles Tjoelker { 100061149f8dSJilles Tjoelker struct passwd *pwd; 100161149f8dSJilles Tjoelker struct xfile *xf; 100261149f8dSJilles Tjoelker struct sock *s; 100361149f8dSJilles Tjoelker int hash, n, pos; 100461149f8dSJilles Tjoelker 1005*7a5642b3SDag-Erling Smørgrav printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", 100661149f8dSJilles Tjoelker "USER", "COMMAND", "PID", "FD", "PROTO", 100761149f8dSJilles Tjoelker "LOCAL ADDRESS", "FOREIGN ADDRESS"); 1008*7a5642b3SDag-Erling Smørgrav if (opt_s) 1009*7a5642b3SDag-Erling Smørgrav printf(" %-12s", "STATE"); 1010*7a5642b3SDag-Erling Smørgrav printf("\n"); 101161149f8dSJilles Tjoelker setpassent(1); 101261149f8dSJilles Tjoelker for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 101361149f8dSJilles Tjoelker if (xf->xf_data == NULL) 101461149f8dSJilles Tjoelker continue; 101500feaafdSAndrew Thompson if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 101600feaafdSAndrew Thompson continue; 101761149f8dSJilles Tjoelker hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 10187e80c6b0SMichael Tuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 10197e80c6b0SMichael Tuexen if ((void *)s->socket != xf->xf_data) 102061149f8dSJilles Tjoelker continue; 102161149f8dSJilles Tjoelker if (!check_ports(s)) 102261149f8dSJilles Tjoelker continue; 102361149f8dSJilles Tjoelker s->shown = 1; 102461149f8dSJilles Tjoelker pos = 0; 102561149f8dSJilles Tjoelker if ((pwd = getpwuid(xf->xf_uid)) == NULL) 102661149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_uid); 102761149f8dSJilles Tjoelker else 102861149f8dSJilles Tjoelker pos += xprintf("%s ", pwd->pw_name); 102961149f8dSJilles Tjoelker while (pos < 9) 103061149f8dSJilles Tjoelker pos += xprintf(" "); 103161149f8dSJilles Tjoelker pos += xprintf("%.10s", getprocname(xf->xf_pid)); 103261149f8dSJilles Tjoelker while (pos < 20) 103361149f8dSJilles Tjoelker pos += xprintf(" "); 103461149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_pid); 103561149f8dSJilles Tjoelker while (pos < 26) 103661149f8dSJilles Tjoelker pos += xprintf(" "); 103761149f8dSJilles Tjoelker pos += xprintf("%d ", xf->xf_fd); 103861149f8dSJilles Tjoelker displaysock(s, pos); 1039*7a5642b3SDag-Erling Smørgrav xprintf("\n"); 104061149f8dSJilles Tjoelker } 10417e80c6b0SMichael Tuexen } 104200feaafdSAndrew Thompson if (opt_j >= 0) 104300feaafdSAndrew Thompson return; 104461149f8dSJilles Tjoelker for (hash = 0; hash < HASHSIZE; hash++) { 104561149f8dSJilles Tjoelker for (s = sockhash[hash]; s != NULL; s = s->next) { 104661149f8dSJilles Tjoelker if (s->shown) 104761149f8dSJilles Tjoelker continue; 104861149f8dSJilles Tjoelker if (!check_ports(s)) 104961149f8dSJilles Tjoelker continue; 105061149f8dSJilles Tjoelker pos = 0; 105161149f8dSJilles Tjoelker pos += xprintf("%-8s %-10s %-5s %-2s ", 105261149f8dSJilles Tjoelker "?", "?", "?", "?"); 105361149f8dSJilles Tjoelker displaysock(s, pos); 1054*7a5642b3SDag-Erling Smørgrav xprintf("\n"); 105561149f8dSJilles Tjoelker } 105661149f8dSJilles Tjoelker } 1057ca007d91SDag-Erling Smørgrav } 1058ca007d91SDag-Erling Smørgrav 10591f3d67aaSGiorgos Keramidas static int set_default_protos(void) 10601f3d67aaSGiorgos Keramidas { 10611f3d67aaSGiorgos Keramidas struct protoent *prot; 10621f3d67aaSGiorgos Keramidas const char *pname; 10631f3d67aaSGiorgos Keramidas size_t pindex; 10641f3d67aaSGiorgos Keramidas 10651f3d67aaSGiorgos Keramidas init_protos(default_numprotos); 10661f3d67aaSGiorgos Keramidas 10671f3d67aaSGiorgos Keramidas for (pindex = 0; pindex < default_numprotos; pindex++) { 10681f3d67aaSGiorgos Keramidas pname = default_protos[pindex]; 10691f3d67aaSGiorgos Keramidas prot = getprotobyname(pname); 10701f3d67aaSGiorgos Keramidas if (prot == NULL) 10711f3d67aaSGiorgos Keramidas err(1, "getprotobyname: %s", pname); 10721f3d67aaSGiorgos Keramidas protos[pindex] = prot->p_proto; 10731f3d67aaSGiorgos Keramidas } 10741f3d67aaSGiorgos Keramidas numprotos = pindex; 10751f3d67aaSGiorgos Keramidas return (pindex); 10761f3d67aaSGiorgos Keramidas } 10771f3d67aaSGiorgos Keramidas 10781f3d67aaSGiorgos Keramidas 1079ca007d91SDag-Erling Smørgrav static void 1080ca007d91SDag-Erling Smørgrav usage(void) 1081ca007d91SDag-Erling Smørgrav { 10821f3d67aaSGiorgos Keramidas fprintf(stderr, 1083*7a5642b3SDag-Erling Smørgrav "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); 1084ca007d91SDag-Erling Smørgrav exit(1); 1085ca007d91SDag-Erling Smørgrav } 1086ca007d91SDag-Erling Smørgrav 1087ca007d91SDag-Erling Smørgrav int 1088ca007d91SDag-Erling Smørgrav main(int argc, char *argv[]) 1089ca007d91SDag-Erling Smørgrav { 10901f3d67aaSGiorgos Keramidas int protos_defined = -1; 10911f3d67aaSGiorgos Keramidas int o, i; 1092ca007d91SDag-Erling Smørgrav 109300feaafdSAndrew Thompson opt_j = -1; 1094*7a5642b3SDag-Erling Smørgrav while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) 1095ca007d91SDag-Erling Smørgrav switch (o) { 1096ca007d91SDag-Erling Smørgrav case '4': 1097ca007d91SDag-Erling Smørgrav opt_4 = 1; 1098ca007d91SDag-Erling Smørgrav break; 1099ca007d91SDag-Erling Smørgrav case '6': 1100ca007d91SDag-Erling Smørgrav opt_6 = 1; 1101ca007d91SDag-Erling Smørgrav break; 1102ca007d91SDag-Erling Smørgrav case 'c': 1103ca007d91SDag-Erling Smørgrav opt_c = 1; 1104ca007d91SDag-Erling Smørgrav break; 110500feaafdSAndrew Thompson case 'j': 110600feaafdSAndrew Thompson opt_j = atoi(optarg); 110700feaafdSAndrew Thompson break; 11089b6ca892SBruce M Simpson case 'L': 11099b6ca892SBruce M Simpson opt_L = 1; 11109b6ca892SBruce M Simpson break; 1111ca007d91SDag-Erling Smørgrav case 'l': 1112ca007d91SDag-Erling Smørgrav opt_l = 1; 1113ca007d91SDag-Erling Smørgrav break; 1114ca007d91SDag-Erling Smørgrav case 'p': 1115ca007d91SDag-Erling Smørgrav parse_ports(optarg); 1116ca007d91SDag-Erling Smørgrav break; 11171f3d67aaSGiorgos Keramidas case 'P': 11181f3d67aaSGiorgos Keramidas protos_defined = parse_protos(optarg); 11191f3d67aaSGiorgos Keramidas break; 1120*7a5642b3SDag-Erling Smørgrav case 's': 1121*7a5642b3SDag-Erling Smørgrav opt_s = 1; 1122*7a5642b3SDag-Erling Smørgrav break; 1123ca007d91SDag-Erling Smørgrav case 'u': 1124ca007d91SDag-Erling Smørgrav opt_u = 1; 1125ca007d91SDag-Erling Smørgrav break; 1126ca007d91SDag-Erling Smørgrav case 'v': 1127ca007d91SDag-Erling Smørgrav ++opt_v; 1128ca007d91SDag-Erling Smørgrav break; 1129ca007d91SDag-Erling Smørgrav default: 1130ca007d91SDag-Erling Smørgrav usage(); 1131ca007d91SDag-Erling Smørgrav } 1132ca007d91SDag-Erling Smørgrav 1133ca007d91SDag-Erling Smørgrav argc -= optind; 1134ca007d91SDag-Erling Smørgrav argv += optind; 1135ca007d91SDag-Erling Smørgrav 1136ca007d91SDag-Erling Smørgrav if (argc > 0) 1137ca007d91SDag-Erling Smørgrav usage(); 1138ca007d91SDag-Erling Smørgrav 1139d2d77d2aSGiorgos Keramidas if ((!opt_4 && !opt_6) && protos_defined != -1) 11401f3d67aaSGiorgos Keramidas opt_4 = opt_6 = 1; 1141d2d77d2aSGiorgos Keramidas if (!opt_4 && !opt_6 && !opt_u) 1142d2d77d2aSGiorgos Keramidas opt_4 = opt_6 = opt_u = 1; 1143d2d77d2aSGiorgos Keramidas if ((opt_4 || opt_6) && protos_defined == -1) 1144d2d77d2aSGiorgos Keramidas protos_defined = set_default_protos(); 1145ca007d91SDag-Erling Smørgrav if (!opt_c && !opt_l) 1146ca007d91SDag-Erling Smørgrav opt_c = opt_l = 1; 1147ca007d91SDag-Erling Smørgrav 1148ca007d91SDag-Erling Smørgrav if (opt_4 || opt_6) { 11491f3d67aaSGiorgos Keramidas for (i = 0; i < protos_defined; i++) 1150d5b4aa90SMichael Tuexen if (protos[i] == IPPROTO_SCTP) 1151d5b4aa90SMichael Tuexen gather_sctp(); 1152d5b4aa90SMichael Tuexen else 11531f3d67aaSGiorgos Keramidas gather_inet(protos[i]); 1154ca007d91SDag-Erling Smørgrav } 11551f3d67aaSGiorgos Keramidas 11561f3d67aaSGiorgos Keramidas if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1157ca007d91SDag-Erling Smørgrav gather_unix(SOCK_STREAM); 1158ca007d91SDag-Erling Smørgrav gather_unix(SOCK_DGRAM); 1159b8e20e2dSHiroki Sato gather_unix(SOCK_SEQPACKET); 1160ca007d91SDag-Erling Smørgrav } 1161ca007d91SDag-Erling Smørgrav getfiles(); 1162ca007d91SDag-Erling Smørgrav display(); 1163ca007d91SDag-Erling Smørgrav exit(0); 1164ca007d91SDag-Erling Smørgrav } 1165