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> 46ca007d91SDag-Erling Smørgrav #include <netinet/tcp.h> 47ca007d91SDag-Erling Smørgrav #include <netinet/tcp_seq.h> 48ca007d91SDag-Erling Smørgrav #include <netinet/tcp_var.h> 49ca007d91SDag-Erling Smørgrav #include <arpa/inet.h> 50ca007d91SDag-Erling Smørgrav 51ca007d91SDag-Erling Smørgrav #include <ctype.h> 52ca007d91SDag-Erling Smørgrav #include <err.h> 53ca007d91SDag-Erling Smørgrav #include <errno.h> 54ca007d91SDag-Erling Smørgrav #include <netdb.h> 55ca007d91SDag-Erling Smørgrav #include <pwd.h> 56ca007d91SDag-Erling Smørgrav #include <stdarg.h> 57ca007d91SDag-Erling Smørgrav #include <stdio.h> 58ca007d91SDag-Erling Smørgrav #include <stdlib.h> 59ca007d91SDag-Erling Smørgrav #include <string.h> 60ca007d91SDag-Erling Smørgrav #include <unistd.h> 61ca007d91SDag-Erling Smørgrav 62ca007d91SDag-Erling Smørgrav static int opt_4; /* Show IPv4 sockets */ 63ca007d91SDag-Erling Smørgrav static int opt_6; /* Show IPv6 sockets */ 64ca007d91SDag-Erling Smørgrav static int opt_c; /* Show connected sockets */ 6500feaafdSAndrew Thompson static int opt_j; /* Show specified jail */ 669b6ca892SBruce M Simpson static int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 67ca007d91SDag-Erling Smørgrav static int opt_l; /* Show listening sockets */ 68ca007d91SDag-Erling Smørgrav static int opt_u; /* Show Unix domain sockets */ 69ca007d91SDag-Erling Smørgrav static int opt_v; /* Verbose mode */ 70ca007d91SDag-Erling Smørgrav 711f3d67aaSGiorgos Keramidas /* 721f3d67aaSGiorgos Keramidas * Default protocols to use if no -P was defined. 731f3d67aaSGiorgos Keramidas */ 741f3d67aaSGiorgos Keramidas static const char *default_protos[] = {"tcp", "udp", "divert" }; 751f3d67aaSGiorgos Keramidas static size_t default_numprotos = 761f3d67aaSGiorgos Keramidas sizeof(default_protos) / sizeof(default_protos[0]); 771f3d67aaSGiorgos Keramidas 781f3d67aaSGiorgos Keramidas static int *protos; /* protocols to use */ 791f3d67aaSGiorgos Keramidas static size_t numprotos; /* allocated size of protos[] */ 801f3d67aaSGiorgos Keramidas 81ca007d91SDag-Erling Smørgrav static int *ports; 82ca007d91SDag-Erling Smørgrav 83ca007d91SDag-Erling Smørgrav #define INT_BIT (sizeof(int)*CHAR_BIT) 84ca007d91SDag-Erling Smørgrav #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 85ca007d91SDag-Erling Smørgrav #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 86ca007d91SDag-Erling Smørgrav 87*e6f718c7SMichael Tuexen struct addr { 88*e6f718c7SMichael Tuexen struct sockaddr_storage address; 89*e6f718c7SMichael Tuexen struct addr *next; 90*e6f718c7SMichael Tuexen }; 91*e6f718c7SMichael Tuexen 92ca007d91SDag-Erling Smørgrav struct sock { 93ca007d91SDag-Erling Smørgrav void *socket; 94ca007d91SDag-Erling Smørgrav void *pcb; 9561149f8dSJilles Tjoelker int shown; 96ca007d91SDag-Erling Smørgrav int vflag; 97ca007d91SDag-Erling Smørgrav int family; 98ca007d91SDag-Erling Smørgrav int proto; 99ca007d91SDag-Erling Smørgrav const char *protoname; 100*e6f718c7SMichael Tuexen struct addr *laddr; 101*e6f718c7SMichael Tuexen struct addr *faddr; 102ca007d91SDag-Erling Smørgrav struct sock *next; 103ca007d91SDag-Erling Smørgrav }; 104ca007d91SDag-Erling Smørgrav 105ca007d91SDag-Erling Smørgrav #define HASHSIZE 1009 106ca007d91SDag-Erling Smørgrav static struct sock *sockhash[HASHSIZE]; 107ca007d91SDag-Erling Smørgrav 108ca007d91SDag-Erling Smørgrav static struct xfile *xfiles; 109ca007d91SDag-Erling Smørgrav static int nxfiles; 110ca007d91SDag-Erling Smørgrav 111ca007d91SDag-Erling Smørgrav static int 112ca007d91SDag-Erling Smørgrav xprintf(const char *fmt, ...) 113ca007d91SDag-Erling Smørgrav { 114ca007d91SDag-Erling Smørgrav va_list ap; 115ca007d91SDag-Erling Smørgrav int len; 116ca007d91SDag-Erling Smørgrav 117ca007d91SDag-Erling Smørgrav va_start(ap, fmt); 118ca007d91SDag-Erling Smørgrav len = vprintf(fmt, ap); 119ca007d91SDag-Erling Smørgrav va_end(ap); 120ca007d91SDag-Erling Smørgrav if (len < 0) 121ca007d91SDag-Erling Smørgrav err(1, "printf()"); 122ca007d91SDag-Erling Smørgrav return (len); 123ca007d91SDag-Erling Smørgrav } 124ca007d91SDag-Erling Smørgrav 1251f3d67aaSGiorgos Keramidas 1261f3d67aaSGiorgos Keramidas static int 1271f3d67aaSGiorgos Keramidas get_proto_type(const char *proto) 1281f3d67aaSGiorgos Keramidas { 1291f3d67aaSGiorgos Keramidas struct protoent *pent; 1301f3d67aaSGiorgos Keramidas 1311f3d67aaSGiorgos Keramidas if (strlen(proto) == 0) 1321f3d67aaSGiorgos Keramidas return (0); 1331f3d67aaSGiorgos Keramidas pent = getprotobyname(proto); 1341f3d67aaSGiorgos Keramidas if (pent == NULL) { 1351f3d67aaSGiorgos Keramidas warn("getprotobyname"); 1361f3d67aaSGiorgos Keramidas return (-1); 1371f3d67aaSGiorgos Keramidas } 1381f3d67aaSGiorgos Keramidas return (pent->p_proto); 1391f3d67aaSGiorgos Keramidas } 1401f3d67aaSGiorgos Keramidas 1411f3d67aaSGiorgos Keramidas 1421f3d67aaSGiorgos Keramidas static void init_protos(int num) 1431f3d67aaSGiorgos Keramidas { 1441f3d67aaSGiorgos Keramidas int proto_count = 0; 1451f3d67aaSGiorgos Keramidas 1461f3d67aaSGiorgos Keramidas if (num > 0) { 1471f3d67aaSGiorgos Keramidas proto_count = num; 1481f3d67aaSGiorgos Keramidas } else { 1491f3d67aaSGiorgos Keramidas /* Find the maximum number of possible protocols. */ 1501f3d67aaSGiorgos Keramidas while (getprotoent() != NULL) 1511f3d67aaSGiorgos Keramidas proto_count++; 1521f3d67aaSGiorgos Keramidas endprotoent(); 1531f3d67aaSGiorgos Keramidas } 1541f3d67aaSGiorgos Keramidas 1551f3d67aaSGiorgos Keramidas if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 1561f3d67aaSGiorgos Keramidas err(1, "malloc"); 1571f3d67aaSGiorgos Keramidas numprotos = proto_count; 1581f3d67aaSGiorgos Keramidas } 1591f3d67aaSGiorgos Keramidas 1601f3d67aaSGiorgos Keramidas 1611f3d67aaSGiorgos Keramidas static int 1621f3d67aaSGiorgos Keramidas parse_protos(char *protospec) 1631f3d67aaSGiorgos Keramidas { 1641f3d67aaSGiorgos Keramidas char *prot; 1651f3d67aaSGiorgos Keramidas char *tmp = protospec; 1661f3d67aaSGiorgos Keramidas int proto_type, proto_index; 1671f3d67aaSGiorgos Keramidas 1681f3d67aaSGiorgos Keramidas if (protospec == NULL) 1691f3d67aaSGiorgos Keramidas return (-1); 1701f3d67aaSGiorgos Keramidas 1711f3d67aaSGiorgos Keramidas init_protos(0); 1721f3d67aaSGiorgos Keramidas proto_index = 0; 1731f3d67aaSGiorgos Keramidas while ((prot = strsep(&tmp, ",")) != NULL) { 1741f3d67aaSGiorgos Keramidas if (strlen(prot) == 0) 1751f3d67aaSGiorgos Keramidas continue; 1761f3d67aaSGiorgos Keramidas proto_type = get_proto_type(prot); 1771f3d67aaSGiorgos Keramidas if (proto_type != -1) 1781f3d67aaSGiorgos Keramidas protos[proto_index++] = proto_type; 1791f3d67aaSGiorgos Keramidas } 1801f3d67aaSGiorgos Keramidas numprotos = proto_index; 1811f3d67aaSGiorgos Keramidas return (proto_index); 1821f3d67aaSGiorgos Keramidas } 1831f3d67aaSGiorgos Keramidas 1841f3d67aaSGiorgos Keramidas 185ca007d91SDag-Erling Smørgrav static void 186ca007d91SDag-Erling Smørgrav parse_ports(const char *portspec) 187ca007d91SDag-Erling Smørgrav { 188ca007d91SDag-Erling Smørgrav const char *p, *q; 189ca007d91SDag-Erling Smørgrav int port, end; 190ca007d91SDag-Erling Smørgrav 191ca007d91SDag-Erling Smørgrav if (ports == NULL) 1929efed1e6SRobert Drehmel if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 193ca007d91SDag-Erling Smørgrav err(1, "calloc()"); 194ca007d91SDag-Erling Smørgrav p = portspec; 195ca007d91SDag-Erling Smørgrav while (*p != '\0') { 196ca007d91SDag-Erling Smørgrav if (!isdigit(*p)) 197ca007d91SDag-Erling Smørgrav errx(1, "syntax error in port range"); 198ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 199ca007d91SDag-Erling Smørgrav /* nothing */ ; 200ca007d91SDag-Erling Smørgrav for (port = 0; p < q; ++p) 201ca007d91SDag-Erling Smørgrav port = port * 10 + digittoint(*p); 202ca007d91SDag-Erling Smørgrav if (port < 0 || port > 65535) 203ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 204ca007d91SDag-Erling Smørgrav SET_PORT(port); 205ca007d91SDag-Erling Smørgrav switch (*p) { 206ca007d91SDag-Erling Smørgrav case '-': 207ca007d91SDag-Erling Smørgrav ++p; 208ca007d91SDag-Erling Smørgrav break; 209ca007d91SDag-Erling Smørgrav case ',': 210ca007d91SDag-Erling Smørgrav ++p; 211ca007d91SDag-Erling Smørgrav /* fall through */ 212ca007d91SDag-Erling Smørgrav case '\0': 213ca007d91SDag-Erling Smørgrav default: 214ca007d91SDag-Erling Smørgrav continue; 215ca007d91SDag-Erling Smørgrav } 216ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 217ca007d91SDag-Erling Smørgrav /* nothing */ ; 218ca007d91SDag-Erling Smørgrav for (end = 0; p < q; ++p) 219ca007d91SDag-Erling Smørgrav end = end * 10 + digittoint(*p); 220ca007d91SDag-Erling Smørgrav if (end < port || end > 65535) 221ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 222ca007d91SDag-Erling Smørgrav while (port++ < end) 223ca007d91SDag-Erling Smørgrav SET_PORT(port); 224ca007d91SDag-Erling Smørgrav if (*p == ',') 225ca007d91SDag-Erling Smørgrav ++p; 226ca007d91SDag-Erling Smørgrav } 227ca007d91SDag-Erling Smørgrav } 228ca007d91SDag-Erling Smørgrav 229ca007d91SDag-Erling Smørgrav static void 230ca007d91SDag-Erling Smørgrav sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port) 231ca007d91SDag-Erling Smørgrav { 232ca007d91SDag-Erling Smørgrav struct sockaddr_in *sin4; 233ca007d91SDag-Erling Smørgrav struct sockaddr_in6 *sin6; 234ca007d91SDag-Erling Smørgrav 235ca007d91SDag-Erling Smørgrav bzero(sa, sizeof *sa); 236ca007d91SDag-Erling Smørgrav switch (af) { 237ca007d91SDag-Erling Smørgrav case AF_INET: 238ca007d91SDag-Erling Smørgrav sin4 = (struct sockaddr_in *)sa; 239ca007d91SDag-Erling Smørgrav sin4->sin_len = sizeof *sin4; 240ca007d91SDag-Erling Smørgrav sin4->sin_family = af; 241ca007d91SDag-Erling Smørgrav sin4->sin_port = port; 242ca007d91SDag-Erling Smørgrav sin4->sin_addr = *(struct in_addr *)addr; 243ca007d91SDag-Erling Smørgrav break; 244ca007d91SDag-Erling Smørgrav case AF_INET6: 245ca007d91SDag-Erling Smørgrav sin6 = (struct sockaddr_in6 *)sa; 246ca007d91SDag-Erling Smørgrav sin6->sin6_len = sizeof *sin6; 247ca007d91SDag-Erling Smørgrav sin6->sin6_family = af; 248ca007d91SDag-Erling Smørgrav sin6->sin6_port = port; 249ca007d91SDag-Erling Smørgrav sin6->sin6_addr = *(struct in6_addr *)addr; 250ca007d91SDag-Erling Smørgrav break; 251ca007d91SDag-Erling Smørgrav default: 252ca007d91SDag-Erling Smørgrav abort(); 253ca007d91SDag-Erling Smørgrav } 254ca007d91SDag-Erling Smørgrav } 255ca007d91SDag-Erling Smørgrav 256ca007d91SDag-Erling Smørgrav static void 257ca007d91SDag-Erling Smørgrav gather_inet(int proto) 258ca007d91SDag-Erling Smørgrav { 259ca007d91SDag-Erling Smørgrav struct xinpgen *xig, *exig; 260ca007d91SDag-Erling Smørgrav struct xinpcb *xip; 261ca007d91SDag-Erling Smørgrav struct xtcpcb *xtp; 262ca007d91SDag-Erling Smørgrav struct inpcb *inp; 263ca007d91SDag-Erling Smørgrav struct xsocket *so; 264ca007d91SDag-Erling Smørgrav struct sock *sock; 265*e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 266ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 267ca007d91SDag-Erling Smørgrav size_t len, bufsize; 268ca007d91SDag-Erling Smørgrav void *buf; 269ca007d91SDag-Erling Smørgrav int hash, retry, vflag; 270ca007d91SDag-Erling Smørgrav 271ca007d91SDag-Erling Smørgrav vflag = 0; 272ca007d91SDag-Erling Smørgrav if (opt_4) 273ca007d91SDag-Erling Smørgrav vflag |= INP_IPV4; 274ca007d91SDag-Erling Smørgrav if (opt_6) 275ca007d91SDag-Erling Smørgrav vflag |= INP_IPV6; 276ca007d91SDag-Erling Smørgrav 277ca007d91SDag-Erling Smørgrav switch (proto) { 278ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 279ca007d91SDag-Erling Smørgrav varname = "net.inet.tcp.pcblist"; 280ca007d91SDag-Erling Smørgrav protoname = "tcp"; 281ca007d91SDag-Erling Smørgrav break; 282ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 283ca007d91SDag-Erling Smørgrav varname = "net.inet.udp.pcblist"; 284ca007d91SDag-Erling Smørgrav protoname = "udp"; 285ca007d91SDag-Erling Smørgrav break; 2862cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 2872cfbdf89SRuslan Ermilov varname = "net.inet.divert.pcblist"; 2882cfbdf89SRuslan Ermilov protoname = "div"; 2892cfbdf89SRuslan Ermilov break; 290ca007d91SDag-Erling Smørgrav default: 2911f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 292ca007d91SDag-Erling Smørgrav } 293ca007d91SDag-Erling Smørgrav 294ca007d91SDag-Erling Smørgrav buf = NULL; 295ca007d91SDag-Erling Smørgrav bufsize = 8192; 296ca007d91SDag-Erling Smørgrav retry = 5; 297ca007d91SDag-Erling Smørgrav do { 298ca007d91SDag-Erling Smørgrav for (;;) { 299ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 300ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 301ca007d91SDag-Erling Smørgrav len = bufsize; 302ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 303ca007d91SDag-Erling Smørgrav break; 3044b2a3d41SRuslan Ermilov if (errno == ENOENT) 3054b2a3d41SRuslan Ermilov goto out; 306003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 307ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 308ca007d91SDag-Erling Smørgrav bufsize *= 2; 309ca007d91SDag-Erling Smørgrav } 310ca007d91SDag-Erling Smørgrav xig = (struct xinpgen *)buf; 3116dbe8d53SRobert Drehmel exig = (struct xinpgen *)(void *) 3126dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exig); 313ca007d91SDag-Erling Smørgrav if (xig->xig_len != sizeof *xig || 314ca007d91SDag-Erling Smørgrav exig->xig_len != sizeof *exig) 315ca007d91SDag-Erling Smørgrav errx(1, "struct xinpgen size mismatch"); 316ca007d91SDag-Erling Smørgrav } while (xig->xig_gen != exig->xig_gen && retry--); 317ca007d91SDag-Erling Smørgrav 318ca007d91SDag-Erling Smørgrav if (xig->xig_gen != exig->xig_gen && opt_v) 319ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 320ca007d91SDag-Erling Smørgrav 321ca007d91SDag-Erling Smørgrav for (;;) { 3226dbe8d53SRobert Drehmel xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 323ca007d91SDag-Erling Smørgrav if (xig >= exig) 324ca007d91SDag-Erling Smørgrav break; 325ca007d91SDag-Erling Smørgrav switch (proto) { 326ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 327ca007d91SDag-Erling Smørgrav xtp = (struct xtcpcb *)xig; 328ca007d91SDag-Erling Smørgrav if (xtp->xt_len != sizeof *xtp) { 329ca007d91SDag-Erling Smørgrav warnx("struct xtcpcb size mismatch"); 330ca007d91SDag-Erling Smørgrav goto out; 331ca007d91SDag-Erling Smørgrav } 332ca007d91SDag-Erling Smørgrav inp = &xtp->xt_inp; 333ca007d91SDag-Erling Smørgrav so = &xtp->xt_socket; 33409fe6320SNavdeep Parhar protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; 335ca007d91SDag-Erling Smørgrav break; 336ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 3372cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 338ca007d91SDag-Erling Smørgrav xip = (struct xinpcb *)xig; 339ca007d91SDag-Erling Smørgrav if (xip->xi_len != sizeof *xip) { 340ca007d91SDag-Erling Smørgrav warnx("struct xinpcb size mismatch"); 341ca007d91SDag-Erling Smørgrav goto out; 342ca007d91SDag-Erling Smørgrav } 343ca007d91SDag-Erling Smørgrav inp = &xip->xi_inp; 344ca007d91SDag-Erling Smørgrav so = &xip->xi_socket; 345ca007d91SDag-Erling Smørgrav break; 346ca007d91SDag-Erling Smørgrav default: 3471f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 348ca007d91SDag-Erling Smørgrav } 349ca007d91SDag-Erling Smørgrav if ((inp->inp_vflag & vflag) == 0) 350ca007d91SDag-Erling Smørgrav continue; 3511e6690e5SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 3521e6690e5SDag-Erling Smørgrav if ((inp->inp_fport == 0 && !opt_l) || 3531e6690e5SDag-Erling Smørgrav (inp->inp_fport != 0 && !opt_c)) 3541e6690e5SDag-Erling Smørgrav continue; 3559b6ca892SBruce M Simpson #define __IN_IS_ADDR_LOOPBACK(pina) \ 3569b6ca892SBruce M Simpson ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 3579b6ca892SBruce M Simpson if (opt_L && 3589b6ca892SBruce M Simpson (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || 3599b6ca892SBruce M Simpson __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) 3609b6ca892SBruce M Simpson continue; 3619b6ca892SBruce M Simpson #undef __IN_IS_ADDR_LOOPBACK 3621e6690e5SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 3634cf172fdSRobert Watson if ((inp->inp_fport == 0 && !opt_l) || 3644cf172fdSRobert Watson (inp->inp_fport != 0 && !opt_c)) 3651e6690e5SDag-Erling Smørgrav continue; 3669b6ca892SBruce M Simpson if (opt_L && 3679b6ca892SBruce M Simpson (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || 3689b6ca892SBruce M Simpson IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) 3699b6ca892SBruce M Simpson continue; 3701e6690e5SDag-Erling Smørgrav } else { 3711e6690e5SDag-Erling Smørgrav if (opt_v) 3721e6690e5SDag-Erling Smørgrav warnx("invalid vflag 0x%x", inp->inp_vflag); 3731e6690e5SDag-Erling Smørgrav continue; 3741e6690e5SDag-Erling Smørgrav } 375ca007d91SDag-Erling Smørgrav if ((sock = calloc(1, sizeof *sock)) == NULL) 376ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 377*e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 378*e6f718c7SMichael Tuexen err(1, "malloc()"); 379*e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 380*e6f718c7SMichael Tuexen err(1, "malloc()"); 381ca007d91SDag-Erling Smørgrav sock->socket = so->xso_so; 382ca007d91SDag-Erling Smørgrav sock->proto = proto; 383ca007d91SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 384ca007d91SDag-Erling Smørgrav sock->family = AF_INET; 385*e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 386ca007d91SDag-Erling Smørgrav &inp->inp_laddr, inp->inp_lport); 387*e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 388ca007d91SDag-Erling Smørgrav &inp->inp_faddr, inp->inp_fport); 389ca007d91SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 390ca007d91SDag-Erling Smørgrav sock->family = AF_INET6; 391*e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 3924cf172fdSRobert Watson &inp->in6p_laddr, inp->inp_lport); 393*e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 3944cf172fdSRobert Watson &inp->in6p_faddr, inp->inp_fport); 395ca007d91SDag-Erling Smørgrav } 396*e6f718c7SMichael Tuexen laddr->next = NULL; 397*e6f718c7SMichael Tuexen faddr->next = NULL; 398*e6f718c7SMichael Tuexen sock->laddr = laddr; 399*e6f718c7SMichael Tuexen sock->faddr = faddr; 400ca007d91SDag-Erling Smørgrav sock->vflag = inp->inp_vflag; 401ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 402ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 403ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 404ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 405ca007d91SDag-Erling Smørgrav } 406ca007d91SDag-Erling Smørgrav out: 407ca007d91SDag-Erling Smørgrav free(buf); 408ca007d91SDag-Erling Smørgrav } 409ca007d91SDag-Erling Smørgrav 410ca007d91SDag-Erling Smørgrav static void 411ca007d91SDag-Erling Smørgrav gather_unix(int proto) 412ca007d91SDag-Erling Smørgrav { 413ca007d91SDag-Erling Smørgrav struct xunpgen *xug, *exug; 414ca007d91SDag-Erling Smørgrav struct xunpcb *xup; 415ca007d91SDag-Erling Smørgrav struct sock *sock; 416*e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 417ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 418ca007d91SDag-Erling Smørgrav size_t len, bufsize; 419ca007d91SDag-Erling Smørgrav void *buf; 420ca007d91SDag-Erling Smørgrav int hash, retry; 421ca007d91SDag-Erling Smørgrav 422ca007d91SDag-Erling Smørgrav switch (proto) { 423ca007d91SDag-Erling Smørgrav case SOCK_STREAM: 424ca007d91SDag-Erling Smørgrav varname = "net.local.stream.pcblist"; 425ca007d91SDag-Erling Smørgrav protoname = "stream"; 426ca007d91SDag-Erling Smørgrav break; 427ca007d91SDag-Erling Smørgrav case SOCK_DGRAM: 428ca007d91SDag-Erling Smørgrav varname = "net.local.dgram.pcblist"; 429ca007d91SDag-Erling Smørgrav protoname = "dgram"; 430ca007d91SDag-Erling Smørgrav break; 431ca007d91SDag-Erling Smørgrav default: 432ca007d91SDag-Erling Smørgrav abort(); 433ca007d91SDag-Erling Smørgrav } 434ca007d91SDag-Erling Smørgrav buf = NULL; 435ca007d91SDag-Erling Smørgrav bufsize = 8192; 436ca007d91SDag-Erling Smørgrav retry = 5; 437ca007d91SDag-Erling Smørgrav do { 438ca007d91SDag-Erling Smørgrav for (;;) { 439ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 440ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 441ca007d91SDag-Erling Smørgrav len = bufsize; 442ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 443ca007d91SDag-Erling Smørgrav break; 444003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 445ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 446ca007d91SDag-Erling Smørgrav bufsize *= 2; 447ca007d91SDag-Erling Smørgrav } 448ca007d91SDag-Erling Smørgrav xug = (struct xunpgen *)buf; 4496dbe8d53SRobert Drehmel exug = (struct xunpgen *)(void *) 4506dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exug); 451ca007d91SDag-Erling Smørgrav if (xug->xug_len != sizeof *xug || 452ca007d91SDag-Erling Smørgrav exug->xug_len != sizeof *exug) { 453ca007d91SDag-Erling Smørgrav warnx("struct xinpgen size mismatch"); 454ca007d91SDag-Erling Smørgrav goto out; 455ca007d91SDag-Erling Smørgrav } 456ca007d91SDag-Erling Smørgrav } while (xug->xug_gen != exug->xug_gen && retry--); 457ca007d91SDag-Erling Smørgrav 458ca007d91SDag-Erling Smørgrav if (xug->xug_gen != exug->xug_gen && opt_v) 459ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 460ca007d91SDag-Erling Smørgrav 461ca007d91SDag-Erling Smørgrav for (;;) { 4626dbe8d53SRobert Drehmel xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 463ca007d91SDag-Erling Smørgrav if (xug >= exug) 464ca007d91SDag-Erling Smørgrav break; 465ca007d91SDag-Erling Smørgrav xup = (struct xunpcb *)xug; 466ca007d91SDag-Erling Smørgrav if (xup->xu_len != sizeof *xup) { 467ca007d91SDag-Erling Smørgrav warnx("struct xunpcb size mismatch"); 468ca007d91SDag-Erling Smørgrav goto out; 469ca007d91SDag-Erling Smørgrav } 4701e6690e5SDag-Erling Smørgrav if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 4711e6690e5SDag-Erling Smørgrav (xup->xu_unp.unp_conn != NULL && !opt_c)) 4721e6690e5SDag-Erling Smørgrav continue; 473ca007d91SDag-Erling Smørgrav if ((sock = calloc(1, sizeof *sock)) == NULL) 474ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 475*e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 476*e6f718c7SMichael Tuexen err(1, "malloc()"); 477*e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 478*e6f718c7SMichael Tuexen err(1, "malloc()"); 479ca007d91SDag-Erling Smørgrav sock->socket = xup->xu_socket.xso_so; 480ca007d91SDag-Erling Smørgrav sock->pcb = xup->xu_unpp; 481ca007d91SDag-Erling Smørgrav sock->proto = proto; 482ca007d91SDag-Erling Smørgrav sock->family = AF_UNIX; 483ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 484ca007d91SDag-Erling Smørgrav if (xup->xu_unp.unp_addr != NULL) 485*e6f718c7SMichael Tuexen laddr->address = 4866dbe8d53SRobert Drehmel *(struct sockaddr_storage *)(void *)&xup->xu_addr; 487ca007d91SDag-Erling Smørgrav else if (xup->xu_unp.unp_conn != NULL) 488*e6f718c7SMichael Tuexen *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 489*e6f718c7SMichael Tuexen laddr->next = NULL; 490*e6f718c7SMichael Tuexen faddr->next = NULL; 491*e6f718c7SMichael Tuexen sock->laddr = laddr; 492*e6f718c7SMichael Tuexen sock->faddr = faddr; 493ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 494ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 495ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 496ca007d91SDag-Erling Smørgrav } 497ca007d91SDag-Erling Smørgrav out: 498ca007d91SDag-Erling Smørgrav free(buf); 499ca007d91SDag-Erling Smørgrav } 500ca007d91SDag-Erling Smørgrav 501ca007d91SDag-Erling Smørgrav static void 502ca007d91SDag-Erling Smørgrav getfiles(void) 503ca007d91SDag-Erling Smørgrav { 504003e7e49SMikolaj Golub size_t len, olen; 505ca007d91SDag-Erling Smørgrav 506003e7e49SMikolaj Golub olen = len = sizeof *xfiles; 507003e7e49SMikolaj Golub if ((xfiles = malloc(len)) == NULL) 508ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 509ca007d91SDag-Erling Smørgrav while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 510003e7e49SMikolaj Golub if (errno != ENOMEM || len != olen) 511ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 512003e7e49SMikolaj Golub olen = len *= 2; 513ca007d91SDag-Erling Smørgrav if ((xfiles = realloc(xfiles, len)) == NULL) 514ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 515ca007d91SDag-Erling Smørgrav } 516ca007d91SDag-Erling Smørgrav if (len > 0 && xfiles->xf_size != sizeof *xfiles) 517ca007d91SDag-Erling Smørgrav errx(1, "struct xfile size mismatch"); 518ca007d91SDag-Erling Smørgrav nxfiles = len / sizeof *xfiles; 519ca007d91SDag-Erling Smørgrav } 520ca007d91SDag-Erling Smørgrav 521ca007d91SDag-Erling Smørgrav static int 522baa7f281SMichael Tuexen printaddr(struct sockaddr_storage *ss) 523ca007d91SDag-Erling Smørgrav { 524ca007d91SDag-Erling Smørgrav char addrstr[INET6_ADDRSTRLEN] = { '\0', '\0' }; 525ca007d91SDag-Erling Smørgrav struct sockaddr_un *sun; 52601cc221bSEd Schouten void *addr = NULL; /* Keep compiler happy. */ 52701cc221bSEd Schouten int off, port = 0; 528ca007d91SDag-Erling Smørgrav 529baa7f281SMichael Tuexen switch (ss->ss_family) { 530ca007d91SDag-Erling Smørgrav case AF_INET: 531ca007d91SDag-Erling Smørgrav addr = &((struct sockaddr_in *)ss)->sin_addr; 532ca007d91SDag-Erling Smørgrav if (inet_lnaof(*(struct in_addr *)addr) == INADDR_ANY) 533ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 534ca007d91SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in *)ss)->sin_port); 535ca007d91SDag-Erling Smørgrav break; 536ca007d91SDag-Erling Smørgrav case AF_INET6: 537ca007d91SDag-Erling Smørgrav addr = &((struct sockaddr_in6 *)ss)->sin6_addr; 538ca007d91SDag-Erling Smørgrav if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)addr)) 539ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 540ca007d91SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in6 *)ss)->sin6_port); 541ca007d91SDag-Erling Smørgrav break; 542ca007d91SDag-Erling Smørgrav case AF_UNIX: 543ca007d91SDag-Erling Smørgrav sun = (struct sockaddr_un *)ss; 544ca007d91SDag-Erling Smørgrav off = (int)((char *)&sun->sun_path - (char *)sun); 545ca007d91SDag-Erling Smørgrav return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 546ca007d91SDag-Erling Smørgrav } 547ca007d91SDag-Erling Smørgrav if (addrstr[0] == '\0') 548baa7f281SMichael Tuexen inet_ntop(ss->ss_family, addr, addrstr, sizeof addrstr); 549ca007d91SDag-Erling Smørgrav if (port == 0) 550ca007d91SDag-Erling Smørgrav return xprintf("%s:*", addrstr); 551ca007d91SDag-Erling Smørgrav else 552ca007d91SDag-Erling Smørgrav return xprintf("%s:%d", addrstr, port); 553ca007d91SDag-Erling Smørgrav } 554ca007d91SDag-Erling Smørgrav 555ca007d91SDag-Erling Smørgrav static const char * 556ca007d91SDag-Erling Smørgrav getprocname(pid_t pid) 557ca007d91SDag-Erling Smørgrav { 558ca007d91SDag-Erling Smørgrav static struct kinfo_proc proc; 559ca007d91SDag-Erling Smørgrav size_t len; 560ca007d91SDag-Erling Smørgrav int mib[4]; 561ca007d91SDag-Erling Smørgrav 562ca007d91SDag-Erling Smørgrav mib[0] = CTL_KERN; 563ca007d91SDag-Erling Smørgrav mib[1] = KERN_PROC; 564ca007d91SDag-Erling Smørgrav mib[2] = KERN_PROC_PID; 565ca007d91SDag-Erling Smørgrav mib[3] = (int)pid; 566ca007d91SDag-Erling Smørgrav len = sizeof proc; 567ca007d91SDag-Erling Smørgrav if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { 56848c513e0SMaxim Konovalov /* Do not warn if the process exits before we get its name. */ 56948c513e0SMaxim Konovalov if (errno != ESRCH) 570ca007d91SDag-Erling Smørgrav warn("sysctl()"); 571ca007d91SDag-Erling Smørgrav return ("??"); 572ca007d91SDag-Erling Smørgrav } 573f487a6a8SEd Maste return (proc.ki_comm); 574ca007d91SDag-Erling Smørgrav } 575ca007d91SDag-Erling Smørgrav 576ae94787dSMaxime Henrion static int 57700feaafdSAndrew Thompson getprocjid(pid_t pid) 57800feaafdSAndrew Thompson { 57900feaafdSAndrew Thompson static struct kinfo_proc proc; 58000feaafdSAndrew Thompson size_t len; 58100feaafdSAndrew Thompson int mib[4]; 58200feaafdSAndrew Thompson 58300feaafdSAndrew Thompson mib[0] = CTL_KERN; 58400feaafdSAndrew Thompson mib[1] = KERN_PROC; 58500feaafdSAndrew Thompson mib[2] = KERN_PROC_PID; 58600feaafdSAndrew Thompson mib[3] = (int)pid; 58700feaafdSAndrew Thompson len = sizeof proc; 58800feaafdSAndrew Thompson if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { 58900feaafdSAndrew Thompson /* Do not warn if the process exits before we get its jid. */ 59000feaafdSAndrew Thompson if (errno != ESRCH) 59100feaafdSAndrew Thompson warn("sysctl()"); 59200feaafdSAndrew Thompson return (-1); 59300feaafdSAndrew Thompson } 59400feaafdSAndrew Thompson return (proc.ki_jid); 59500feaafdSAndrew Thompson } 59600feaafdSAndrew Thompson 59700feaafdSAndrew Thompson static int 598ae94787dSMaxime Henrion check_ports(struct sock *s) 599ae94787dSMaxime Henrion { 600ae94787dSMaxime Henrion int port; 601*e6f718c7SMichael Tuexen struct addr *addr; 602ae94787dSMaxime Henrion 603ae94787dSMaxime Henrion if (ports == NULL) 604ae94787dSMaxime Henrion return (1); 605ae94787dSMaxime Henrion if ((s->family != AF_INET) && (s->family != AF_INET6)) 606ae94787dSMaxime Henrion return (1); 607*e6f718c7SMichael Tuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 608*e6f718c7SMichael Tuexen if (addr->address.ss_family == AF_INET) 609*e6f718c7SMichael Tuexen port = ntohs(((struct sockaddr_in *)(&addr->address))->sin_port); 610ae94787dSMaxime Henrion else 611*e6f718c7SMichael Tuexen port = ntohs(((struct sockaddr_in6 *)(&addr->address))->sin6_port); 612ae94787dSMaxime Henrion if (CHK_PORT(port)) 613ae94787dSMaxime Henrion return (1); 614*e6f718c7SMichael Tuexen } 615*e6f718c7SMichael Tuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 616*e6f718c7SMichael Tuexen if (addr->address.ss_family == AF_INET) 617*e6f718c7SMichael Tuexen port = ntohs(((struct sockaddr_in *)&(addr->address))->sin_port); 618ae94787dSMaxime Henrion else 619*e6f718c7SMichael Tuexen port = ntohs(((struct sockaddr_in6 *)&(addr->address))->sin6_port); 620ae94787dSMaxime Henrion if (CHK_PORT(port)) 621ae94787dSMaxime Henrion return (1); 622*e6f718c7SMichael Tuexen } 623ae94787dSMaxime Henrion return (0); 624ae94787dSMaxime Henrion } 625ae94787dSMaxime Henrion 626ca007d91SDag-Erling Smørgrav static void 62761149f8dSJilles Tjoelker displaysock(struct sock *s, int pos) 628ca007d91SDag-Erling Smørgrav { 629ca007d91SDag-Erling Smørgrav void *p; 63061149f8dSJilles Tjoelker int hash; 631*e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 632ca007d91SDag-Erling Smørgrav 633ca007d91SDag-Erling Smørgrav while (pos < 29) 634ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 635ca007d91SDag-Erling Smørgrav pos += xprintf("%s", s->protoname); 636ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV4) 637ca007d91SDag-Erling Smørgrav pos += xprintf("4 "); 638ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV6) 639ca007d91SDag-Erling Smørgrav pos += xprintf("6 "); 640*e6f718c7SMichael Tuexen laddr = s->laddr; 641*e6f718c7SMichael Tuexen faddr = s->faddr; 642*e6f718c7SMichael Tuexen while (laddr != NULL || faddr != NULL) { 643ca007d91SDag-Erling Smørgrav while (pos < 36) 644ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 645ca007d91SDag-Erling Smørgrav switch (s->family) { 646ca007d91SDag-Erling Smørgrav case AF_INET: 647ca007d91SDag-Erling Smørgrav case AF_INET6: 648*e6f718c7SMichael Tuexen if (laddr != NULL) { 649*e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 65009bbda21SMaxim Konovalov if (s->family == AF_INET6 && pos >= 58) 65109bbda21SMaxim Konovalov pos += xprintf(" "); 652*e6f718c7SMichael Tuexen } 653ca007d91SDag-Erling Smørgrav while (pos < 58) 654ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 655*e6f718c7SMichael Tuexen if (faddr != NULL) 656*e6f718c7SMichael Tuexen pos += printaddr(&faddr->address); 657ca007d91SDag-Erling Smørgrav break; 658ca007d91SDag-Erling Smørgrav case AF_UNIX: 659*e6f718c7SMichael Tuexen if ((laddr == NULL) || (faddr == NULL)) 660*e6f718c7SMichael Tuexen errx(1, "laddr = %p or faddr = %p is NULL", 661*e6f718c7SMichael Tuexen (void *)laddr, (void *)faddr); 662ca007d91SDag-Erling Smørgrav /* server */ 663*e6f718c7SMichael Tuexen if (laddr->address.ss_len > 0) { 664*e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 665ca007d91SDag-Erling Smørgrav break; 666ca007d91SDag-Erling Smørgrav } 667ca007d91SDag-Erling Smørgrav /* client */ 668*e6f718c7SMichael Tuexen p = *(void **)&(faddr->address); 669b4eb37c6SJohn-Mark Gurney if (p == NULL) { 670b4eb37c6SJohn-Mark Gurney pos += xprintf("(not connected)"); 671b4eb37c6SJohn-Mark Gurney break; 672b4eb37c6SJohn-Mark Gurney } 673b4eb37c6SJohn-Mark Gurney pos += xprintf("-> "); 674ca007d91SDag-Erling Smørgrav for (hash = 0; hash < HASHSIZE; ++hash) { 675ca007d91SDag-Erling Smørgrav for (s = sockhash[hash]; s != NULL; s = s->next) 676ca007d91SDag-Erling Smørgrav if (s->pcb == p) 677ca007d91SDag-Erling Smørgrav break; 678ca007d91SDag-Erling Smørgrav if (s != NULL) 679ca007d91SDag-Erling Smørgrav break; 680ca007d91SDag-Erling Smørgrav } 681*e6f718c7SMichael Tuexen if (s == NULL || 682*e6f718c7SMichael Tuexen s->laddr == NULL || 683*e6f718c7SMichael Tuexen s->laddr->address.ss_len == 0) 684ca007d91SDag-Erling Smørgrav pos += xprintf("??"); 685ca007d91SDag-Erling Smørgrav else 686*e6f718c7SMichael Tuexen pos += printaddr(&s->laddr->address); 687ca007d91SDag-Erling Smørgrav break; 688ca007d91SDag-Erling Smørgrav default: 689ca007d91SDag-Erling Smørgrav abort(); 690ca007d91SDag-Erling Smørgrav } 691*e6f718c7SMichael Tuexen if (laddr != NULL) 692*e6f718c7SMichael Tuexen laddr = laddr->next; 693*e6f718c7SMichael Tuexen if (faddr != NULL) 694*e6f718c7SMichael Tuexen faddr = faddr->next; 695*e6f718c7SMichael Tuexen if ((laddr != NULL) || (faddr != NULL)) { 696*e6f718c7SMichael Tuexen xprintf("\n"); 697*e6f718c7SMichael Tuexen pos = 0; 698*e6f718c7SMichael Tuexen } 699*e6f718c7SMichael Tuexen } 700ca007d91SDag-Erling Smørgrav xprintf("\n"); 701ca007d91SDag-Erling Smørgrav } 70261149f8dSJilles Tjoelker 70361149f8dSJilles Tjoelker static void 70461149f8dSJilles Tjoelker display(void) 70561149f8dSJilles Tjoelker { 70661149f8dSJilles Tjoelker struct passwd *pwd; 70761149f8dSJilles Tjoelker struct xfile *xf; 70861149f8dSJilles Tjoelker struct sock *s; 70961149f8dSJilles Tjoelker int hash, n, pos; 71061149f8dSJilles Tjoelker 71161149f8dSJilles Tjoelker printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s\n", 71261149f8dSJilles Tjoelker "USER", "COMMAND", "PID", "FD", "PROTO", 71361149f8dSJilles Tjoelker "LOCAL ADDRESS", "FOREIGN ADDRESS"); 71461149f8dSJilles Tjoelker setpassent(1); 71561149f8dSJilles Tjoelker for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 71661149f8dSJilles Tjoelker if (xf->xf_data == NULL) 71761149f8dSJilles Tjoelker continue; 71800feaafdSAndrew Thompson if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 71900feaafdSAndrew Thompson continue; 72061149f8dSJilles Tjoelker hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 7217e80c6b0SMichael Tuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 7227e80c6b0SMichael Tuexen if ((void *)s->socket != xf->xf_data) 72361149f8dSJilles Tjoelker continue; 72461149f8dSJilles Tjoelker if (!check_ports(s)) 72561149f8dSJilles Tjoelker continue; 72661149f8dSJilles Tjoelker s->shown = 1; 72761149f8dSJilles Tjoelker pos = 0; 72861149f8dSJilles Tjoelker if ((pwd = getpwuid(xf->xf_uid)) == NULL) 72961149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_uid); 73061149f8dSJilles Tjoelker else 73161149f8dSJilles Tjoelker pos += xprintf("%s ", pwd->pw_name); 73261149f8dSJilles Tjoelker while (pos < 9) 73361149f8dSJilles Tjoelker pos += xprintf(" "); 73461149f8dSJilles Tjoelker pos += xprintf("%.10s", getprocname(xf->xf_pid)); 73561149f8dSJilles Tjoelker while (pos < 20) 73661149f8dSJilles Tjoelker pos += xprintf(" "); 73761149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_pid); 73861149f8dSJilles Tjoelker while (pos < 26) 73961149f8dSJilles Tjoelker pos += xprintf(" "); 74061149f8dSJilles Tjoelker pos += xprintf("%d ", xf->xf_fd); 74161149f8dSJilles Tjoelker displaysock(s, pos); 74261149f8dSJilles Tjoelker } 7437e80c6b0SMichael Tuexen } 74400feaafdSAndrew Thompson if (opt_j >= 0) 74500feaafdSAndrew Thompson return; 74661149f8dSJilles Tjoelker for (hash = 0; hash < HASHSIZE; hash++) { 74761149f8dSJilles Tjoelker for (s = sockhash[hash]; s != NULL; s = s->next) { 74861149f8dSJilles Tjoelker if (s->shown) 74961149f8dSJilles Tjoelker continue; 75061149f8dSJilles Tjoelker if (!check_ports(s)) 75161149f8dSJilles Tjoelker continue; 75261149f8dSJilles Tjoelker pos = 0; 75361149f8dSJilles Tjoelker pos += xprintf("%-8s %-10s %-5s %-2s ", 75461149f8dSJilles Tjoelker "?", "?", "?", "?"); 75561149f8dSJilles Tjoelker displaysock(s, pos); 75661149f8dSJilles Tjoelker } 75761149f8dSJilles Tjoelker } 758ca007d91SDag-Erling Smørgrav } 759ca007d91SDag-Erling Smørgrav 7601f3d67aaSGiorgos Keramidas static int set_default_protos(void) 7611f3d67aaSGiorgos Keramidas { 7621f3d67aaSGiorgos Keramidas struct protoent *prot; 7631f3d67aaSGiorgos Keramidas const char *pname; 7641f3d67aaSGiorgos Keramidas size_t pindex; 7651f3d67aaSGiorgos Keramidas 7661f3d67aaSGiorgos Keramidas init_protos(default_numprotos); 7671f3d67aaSGiorgos Keramidas 7681f3d67aaSGiorgos Keramidas for (pindex = 0; pindex < default_numprotos; pindex++) { 7691f3d67aaSGiorgos Keramidas pname = default_protos[pindex]; 7701f3d67aaSGiorgos Keramidas prot = getprotobyname(pname); 7711f3d67aaSGiorgos Keramidas if (prot == NULL) 7721f3d67aaSGiorgos Keramidas err(1, "getprotobyname: %s", pname); 7731f3d67aaSGiorgos Keramidas protos[pindex] = prot->p_proto; 7741f3d67aaSGiorgos Keramidas } 7751f3d67aaSGiorgos Keramidas numprotos = pindex; 7761f3d67aaSGiorgos Keramidas return (pindex); 7771f3d67aaSGiorgos Keramidas } 7781f3d67aaSGiorgos Keramidas 7791f3d67aaSGiorgos Keramidas 780ca007d91SDag-Erling Smørgrav static void 781ca007d91SDag-Erling Smørgrav usage(void) 782ca007d91SDag-Erling Smørgrav { 7831f3d67aaSGiorgos Keramidas fprintf(stderr, 784c7bec96bSAndrew Thompson "Usage: sockstat [-46cLlu] [-j jid] [-p ports] [-P protocols]\n"); 785ca007d91SDag-Erling Smørgrav exit(1); 786ca007d91SDag-Erling Smørgrav } 787ca007d91SDag-Erling Smørgrav 788ca007d91SDag-Erling Smørgrav int 789ca007d91SDag-Erling Smørgrav main(int argc, char *argv[]) 790ca007d91SDag-Erling Smørgrav { 7911f3d67aaSGiorgos Keramidas int protos_defined = -1; 7921f3d67aaSGiorgos Keramidas int o, i; 793ca007d91SDag-Erling Smørgrav 79400feaafdSAndrew Thompson opt_j = -1; 79500feaafdSAndrew Thompson while ((o = getopt(argc, argv, "46cj:Llp:P:uv")) != -1) 796ca007d91SDag-Erling Smørgrav switch (o) { 797ca007d91SDag-Erling Smørgrav case '4': 798ca007d91SDag-Erling Smørgrav opt_4 = 1; 799ca007d91SDag-Erling Smørgrav break; 800ca007d91SDag-Erling Smørgrav case '6': 801ca007d91SDag-Erling Smørgrav opt_6 = 1; 802ca007d91SDag-Erling Smørgrav break; 803ca007d91SDag-Erling Smørgrav case 'c': 804ca007d91SDag-Erling Smørgrav opt_c = 1; 805ca007d91SDag-Erling Smørgrav break; 80600feaafdSAndrew Thompson case 'j': 80700feaafdSAndrew Thompson opt_j = atoi(optarg); 80800feaafdSAndrew Thompson break; 8099b6ca892SBruce M Simpson case 'L': 8109b6ca892SBruce M Simpson opt_L = 1; 8119b6ca892SBruce M Simpson break; 812ca007d91SDag-Erling Smørgrav case 'l': 813ca007d91SDag-Erling Smørgrav opt_l = 1; 814ca007d91SDag-Erling Smørgrav break; 815ca007d91SDag-Erling Smørgrav case 'p': 816ca007d91SDag-Erling Smørgrav parse_ports(optarg); 817ca007d91SDag-Erling Smørgrav break; 8181f3d67aaSGiorgos Keramidas case 'P': 8191f3d67aaSGiorgos Keramidas protos_defined = parse_protos(optarg); 8201f3d67aaSGiorgos Keramidas break; 821ca007d91SDag-Erling Smørgrav case 'u': 822ca007d91SDag-Erling Smørgrav opt_u = 1; 823ca007d91SDag-Erling Smørgrav break; 824ca007d91SDag-Erling Smørgrav case 'v': 825ca007d91SDag-Erling Smørgrav ++opt_v; 826ca007d91SDag-Erling Smørgrav break; 827ca007d91SDag-Erling Smørgrav default: 828ca007d91SDag-Erling Smørgrav usage(); 829ca007d91SDag-Erling Smørgrav } 830ca007d91SDag-Erling Smørgrav 831ca007d91SDag-Erling Smørgrav argc -= optind; 832ca007d91SDag-Erling Smørgrav argv += optind; 833ca007d91SDag-Erling Smørgrav 834ca007d91SDag-Erling Smørgrav if (argc > 0) 835ca007d91SDag-Erling Smørgrav usage(); 836ca007d91SDag-Erling Smørgrav 837d2d77d2aSGiorgos Keramidas if ((!opt_4 && !opt_6) && protos_defined != -1) 8381f3d67aaSGiorgos Keramidas opt_4 = opt_6 = 1; 839d2d77d2aSGiorgos Keramidas if (!opt_4 && !opt_6 && !opt_u) 840d2d77d2aSGiorgos Keramidas opt_4 = opt_6 = opt_u = 1; 841d2d77d2aSGiorgos Keramidas if ((opt_4 || opt_6) && protos_defined == -1) 842d2d77d2aSGiorgos Keramidas protos_defined = set_default_protos(); 843ca007d91SDag-Erling Smørgrav if (!opt_c && !opt_l) 844ca007d91SDag-Erling Smørgrav opt_c = opt_l = 1; 845ca007d91SDag-Erling Smørgrav 846ca007d91SDag-Erling Smørgrav if (opt_4 || opt_6) { 8471f3d67aaSGiorgos Keramidas for (i = 0; i < protos_defined; i++) 8481f3d67aaSGiorgos Keramidas gather_inet(protos[i]); 849ca007d91SDag-Erling Smørgrav } 8501f3d67aaSGiorgos Keramidas 8511f3d67aaSGiorgos Keramidas if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 852ca007d91SDag-Erling Smørgrav gather_unix(SOCK_STREAM); 853ca007d91SDag-Erling Smørgrav gather_unix(SOCK_DGRAM); 854ca007d91SDag-Erling Smørgrav } 855ca007d91SDag-Erling Smørgrav getfiles(); 856ca007d91SDag-Erling Smørgrav display(); 857ca007d91SDag-Erling Smørgrav exit(0); 858ca007d91SDag-Erling Smørgrav } 859