1ca007d91SDag-Erling Smørgrav /*- 2ca007d91SDag-Erling Smørgrav * 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 */ 65ca007d91SDag-Erling Smørgrav static int opt_l; /* Show listening sockets */ 66ca007d91SDag-Erling Smørgrav static int opt_u; /* Show Unix domain sockets */ 67ca007d91SDag-Erling Smørgrav static int opt_v; /* Verbose mode */ 68ca007d91SDag-Erling Smørgrav 69ca007d91SDag-Erling Smørgrav static int *ports; 70ca007d91SDag-Erling Smørgrav 71ca007d91SDag-Erling Smørgrav #define INT_BIT (sizeof(int)*CHAR_BIT) 72ca007d91SDag-Erling Smørgrav #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 73ca007d91SDag-Erling Smørgrav #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 74ca007d91SDag-Erling Smørgrav 75ca007d91SDag-Erling Smørgrav struct sock { 76ca007d91SDag-Erling Smørgrav void *socket; 77ca007d91SDag-Erling Smørgrav void *pcb; 78ca007d91SDag-Erling Smørgrav int vflag; 79ca007d91SDag-Erling Smørgrav int family; 80ca007d91SDag-Erling Smørgrav int proto; 81ca007d91SDag-Erling Smørgrav const char *protoname; 82ca007d91SDag-Erling Smørgrav struct sockaddr_storage laddr; 83ca007d91SDag-Erling Smørgrav struct sockaddr_storage faddr; 84ca007d91SDag-Erling Smørgrav struct sock *next; 85ca007d91SDag-Erling Smørgrav }; 86ca007d91SDag-Erling Smørgrav 87ca007d91SDag-Erling Smørgrav #define HASHSIZE 1009 88ca007d91SDag-Erling Smørgrav static struct sock *sockhash[HASHSIZE]; 89ca007d91SDag-Erling Smørgrav 90ca007d91SDag-Erling Smørgrav static struct xfile *xfiles; 91ca007d91SDag-Erling Smørgrav static int nxfiles; 92ca007d91SDag-Erling Smørgrav 93ca007d91SDag-Erling Smørgrav static int 94ca007d91SDag-Erling Smørgrav xprintf(const char *fmt, ...) 95ca007d91SDag-Erling Smørgrav { 96ca007d91SDag-Erling Smørgrav va_list ap; 97ca007d91SDag-Erling Smørgrav int len; 98ca007d91SDag-Erling Smørgrav 99ca007d91SDag-Erling Smørgrav va_start(ap, fmt); 100ca007d91SDag-Erling Smørgrav len = vprintf(fmt, ap); 101ca007d91SDag-Erling Smørgrav va_end(ap); 102ca007d91SDag-Erling Smørgrav if (len < 0) 103ca007d91SDag-Erling Smørgrav err(1, "printf()"); 104ca007d91SDag-Erling Smørgrav return (len); 105ca007d91SDag-Erling Smørgrav } 106ca007d91SDag-Erling Smørgrav 107ca007d91SDag-Erling Smørgrav static void 108ca007d91SDag-Erling Smørgrav parse_ports(const char *portspec) 109ca007d91SDag-Erling Smørgrav { 110ca007d91SDag-Erling Smørgrav const char *p, *q; 111ca007d91SDag-Erling Smørgrav int port, end; 112ca007d91SDag-Erling Smørgrav 113ca007d91SDag-Erling Smørgrav if (ports == NULL) 1149efed1e6SRobert Drehmel if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 115ca007d91SDag-Erling Smørgrav err(1, "calloc()"); 116ca007d91SDag-Erling Smørgrav p = portspec; 117ca007d91SDag-Erling Smørgrav while (*p != '\0') { 118ca007d91SDag-Erling Smørgrav if (!isdigit(*p)) 119ca007d91SDag-Erling Smørgrav errx(1, "syntax error in port range"); 120ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 121ca007d91SDag-Erling Smørgrav /* nothing */ ; 122ca007d91SDag-Erling Smørgrav for (port = 0; p < q; ++p) 123ca007d91SDag-Erling Smørgrav port = port * 10 + digittoint(*p); 124ca007d91SDag-Erling Smørgrav if (port < 0 || port > 65535) 125ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 126ca007d91SDag-Erling Smørgrav SET_PORT(port); 127ca007d91SDag-Erling Smørgrav switch (*p) { 128ca007d91SDag-Erling Smørgrav case '-': 129ca007d91SDag-Erling Smørgrav ++p; 130ca007d91SDag-Erling Smørgrav break; 131ca007d91SDag-Erling Smørgrav case ',': 132ca007d91SDag-Erling Smørgrav ++p; 133ca007d91SDag-Erling Smørgrav /* fall through */ 134ca007d91SDag-Erling Smørgrav case '\0': 135ca007d91SDag-Erling Smørgrav default: 136ca007d91SDag-Erling Smørgrav continue; 137ca007d91SDag-Erling Smørgrav } 138ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 139ca007d91SDag-Erling Smørgrav /* nothing */ ; 140ca007d91SDag-Erling Smørgrav for (end = 0; p < q; ++p) 141ca007d91SDag-Erling Smørgrav end = end * 10 + digittoint(*p); 142ca007d91SDag-Erling Smørgrav if (end < port || end > 65535) 143ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 144ca007d91SDag-Erling Smørgrav while (port++ < end) 145ca007d91SDag-Erling Smørgrav SET_PORT(port); 146ca007d91SDag-Erling Smørgrav if (*p == ',') 147ca007d91SDag-Erling Smørgrav ++p; 148ca007d91SDag-Erling Smørgrav } 149ca007d91SDag-Erling Smørgrav } 150ca007d91SDag-Erling Smørgrav 151ca007d91SDag-Erling Smørgrav static void 152ca007d91SDag-Erling Smørgrav sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port) 153ca007d91SDag-Erling Smørgrav { 154ca007d91SDag-Erling Smørgrav struct sockaddr_in *sin4; 155ca007d91SDag-Erling Smørgrav struct sockaddr_in6 *sin6; 156ca007d91SDag-Erling Smørgrav 157ca007d91SDag-Erling Smørgrav bzero(sa, sizeof *sa); 158ca007d91SDag-Erling Smørgrav switch (af) { 159ca007d91SDag-Erling Smørgrav case AF_INET: 160ca007d91SDag-Erling Smørgrav sin4 = (struct sockaddr_in *)sa; 161ca007d91SDag-Erling Smørgrav sin4->sin_len = sizeof *sin4; 162ca007d91SDag-Erling Smørgrav sin4->sin_family = af; 163ca007d91SDag-Erling Smørgrav sin4->sin_port = port; 164ca007d91SDag-Erling Smørgrav sin4->sin_addr = *(struct in_addr *)addr; 165ca007d91SDag-Erling Smørgrav break; 166ca007d91SDag-Erling Smørgrav case AF_INET6: 167ca007d91SDag-Erling Smørgrav sin6 = (struct sockaddr_in6 *)sa; 168ca007d91SDag-Erling Smørgrav sin6->sin6_len = sizeof *sin6; 169ca007d91SDag-Erling Smørgrav sin6->sin6_family = af; 170ca007d91SDag-Erling Smørgrav sin6->sin6_port = port; 171ca007d91SDag-Erling Smørgrav sin6->sin6_addr = *(struct in6_addr *)addr; 172ca007d91SDag-Erling Smørgrav break; 173ca007d91SDag-Erling Smørgrav default: 174ca007d91SDag-Erling Smørgrav abort(); 175ca007d91SDag-Erling Smørgrav } 176ca007d91SDag-Erling Smørgrav } 177ca007d91SDag-Erling Smørgrav 178ca007d91SDag-Erling Smørgrav static void 179ca007d91SDag-Erling Smørgrav gather_inet(int proto) 180ca007d91SDag-Erling Smørgrav { 181ca007d91SDag-Erling Smørgrav struct xinpgen *xig, *exig; 182ca007d91SDag-Erling Smørgrav struct xinpcb *xip; 183ca007d91SDag-Erling Smørgrav struct xtcpcb *xtp; 184ca007d91SDag-Erling Smørgrav struct inpcb *inp; 185ca007d91SDag-Erling Smørgrav struct xsocket *so; 186ca007d91SDag-Erling Smørgrav struct sock *sock; 187ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 188ca007d91SDag-Erling Smørgrav size_t len, bufsize; 189ca007d91SDag-Erling Smørgrav void *buf; 190ca007d91SDag-Erling Smørgrav int hash, retry, vflag; 191ca007d91SDag-Erling Smørgrav 192ca007d91SDag-Erling Smørgrav vflag = 0; 193ca007d91SDag-Erling Smørgrav if (opt_4) 194ca007d91SDag-Erling Smørgrav vflag |= INP_IPV4; 195ca007d91SDag-Erling Smørgrav if (opt_6) 196ca007d91SDag-Erling Smørgrav vflag |= INP_IPV6; 197ca007d91SDag-Erling Smørgrav 198ca007d91SDag-Erling Smørgrav switch (proto) { 199ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 200ca007d91SDag-Erling Smørgrav varname = "net.inet.tcp.pcblist"; 201ca007d91SDag-Erling Smørgrav protoname = "tcp"; 202ca007d91SDag-Erling Smørgrav break; 203ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 204ca007d91SDag-Erling Smørgrav varname = "net.inet.udp.pcblist"; 205ca007d91SDag-Erling Smørgrav protoname = "udp"; 206ca007d91SDag-Erling Smørgrav break; 2072cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 2082cfbdf89SRuslan Ermilov varname = "net.inet.divert.pcblist"; 2092cfbdf89SRuslan Ermilov protoname = "div"; 2102cfbdf89SRuslan Ermilov break; 211ca007d91SDag-Erling Smørgrav default: 212ca007d91SDag-Erling Smørgrav abort(); 213ca007d91SDag-Erling Smørgrav } 214ca007d91SDag-Erling Smørgrav 215ca007d91SDag-Erling Smørgrav buf = NULL; 216ca007d91SDag-Erling Smørgrav bufsize = 8192; 217ca007d91SDag-Erling Smørgrav retry = 5; 218ca007d91SDag-Erling Smørgrav do { 219ca007d91SDag-Erling Smørgrav for (;;) { 220ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 221ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 222ca007d91SDag-Erling Smørgrav len = bufsize; 223ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 224ca007d91SDag-Erling Smørgrav break; 225ca007d91SDag-Erling Smørgrav if (errno != ENOMEM) 226ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 227ca007d91SDag-Erling Smørgrav bufsize *= 2; 228ca007d91SDag-Erling Smørgrav } 229ca007d91SDag-Erling Smørgrav xig = (struct xinpgen *)buf; 2306dbe8d53SRobert Drehmel exig = (struct xinpgen *)(void *) 2316dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exig); 232ca007d91SDag-Erling Smørgrav if (xig->xig_len != sizeof *xig || 233ca007d91SDag-Erling Smørgrav exig->xig_len != sizeof *exig) 234ca007d91SDag-Erling Smørgrav errx(1, "struct xinpgen size mismatch"); 235ca007d91SDag-Erling Smørgrav } while (xig->xig_gen != exig->xig_gen && retry--); 236ca007d91SDag-Erling Smørgrav 237ca007d91SDag-Erling Smørgrav if (xig->xig_gen != exig->xig_gen && opt_v) 238ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 239ca007d91SDag-Erling Smørgrav 240ca007d91SDag-Erling Smørgrav for (;;) { 2416dbe8d53SRobert Drehmel xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 242ca007d91SDag-Erling Smørgrav if (xig >= exig) 243ca007d91SDag-Erling Smørgrav break; 244ca007d91SDag-Erling Smørgrav switch (proto) { 245ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 246ca007d91SDag-Erling Smørgrav xtp = (struct xtcpcb *)xig; 247ca007d91SDag-Erling Smørgrav if (xtp->xt_len != sizeof *xtp) { 248ca007d91SDag-Erling Smørgrav warnx("struct xtcpcb size mismatch"); 249ca007d91SDag-Erling Smørgrav goto out; 250ca007d91SDag-Erling Smørgrav } 251ca007d91SDag-Erling Smørgrav inp = &xtp->xt_inp; 252ca007d91SDag-Erling Smørgrav so = &xtp->xt_socket; 253ca007d91SDag-Erling Smørgrav break; 254ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 2552cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 256ca007d91SDag-Erling Smørgrav xip = (struct xinpcb *)xig; 257ca007d91SDag-Erling Smørgrav if (xip->xi_len != sizeof *xip) { 258ca007d91SDag-Erling Smørgrav warnx("struct xinpcb size mismatch"); 259ca007d91SDag-Erling Smørgrav goto out; 260ca007d91SDag-Erling Smørgrav } 261ca007d91SDag-Erling Smørgrav inp = &xip->xi_inp; 262ca007d91SDag-Erling Smørgrav so = &xip->xi_socket; 263ca007d91SDag-Erling Smørgrav break; 264ca007d91SDag-Erling Smørgrav default: 265ca007d91SDag-Erling Smørgrav abort(); 266ca007d91SDag-Erling Smørgrav } 267ca007d91SDag-Erling Smørgrav if ((inp->inp_vflag & vflag) == 0) 268ca007d91SDag-Erling Smørgrav continue; 2691e6690e5SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 2701e6690e5SDag-Erling Smørgrav if ((inp->inp_fport == 0 && !opt_l) || 2711e6690e5SDag-Erling Smørgrav (inp->inp_fport != 0 && !opt_c)) 2721e6690e5SDag-Erling Smørgrav continue; 2731e6690e5SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 2741e6690e5SDag-Erling Smørgrav if ((inp->in6p_fport == 0 && !opt_l) || 2751e6690e5SDag-Erling Smørgrav (inp->in6p_fport != 0 && !opt_c)) 2761e6690e5SDag-Erling Smørgrav continue; 2771e6690e5SDag-Erling Smørgrav } else { 2781e6690e5SDag-Erling Smørgrav if (opt_v) 2791e6690e5SDag-Erling Smørgrav warnx("invalid vflag 0x%x", inp->inp_vflag); 2801e6690e5SDag-Erling Smørgrav free(sock); 2811e6690e5SDag-Erling Smørgrav continue; 2821e6690e5SDag-Erling Smørgrav } 283ca007d91SDag-Erling Smørgrav if ((sock = calloc(1, sizeof *sock)) == NULL) 284ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 285ca007d91SDag-Erling Smørgrav sock->socket = so->xso_so; 286ca007d91SDag-Erling Smørgrav sock->proto = proto; 287ca007d91SDag-Erling Smørgrav if (inp->inp_vflag & INP_IPV4) { 288ca007d91SDag-Erling Smørgrav sock->family = AF_INET; 289ca007d91SDag-Erling Smørgrav sockaddr(&sock->laddr, sock->family, 290ca007d91SDag-Erling Smørgrav &inp->inp_laddr, inp->inp_lport); 291ca007d91SDag-Erling Smørgrav sockaddr(&sock->faddr, sock->family, 292ca007d91SDag-Erling Smørgrav &inp->inp_faddr, inp->inp_fport); 293ca007d91SDag-Erling Smørgrav } else if (inp->inp_vflag & INP_IPV6) { 294ca007d91SDag-Erling Smørgrav sock->family = AF_INET6; 295ca007d91SDag-Erling Smørgrav sockaddr(&sock->laddr, sock->family, 296ca007d91SDag-Erling Smørgrav &inp->in6p_laddr, inp->in6p_lport); 297ca007d91SDag-Erling Smørgrav sockaddr(&sock->faddr, sock->family, 298ca007d91SDag-Erling Smørgrav &inp->in6p_faddr, inp->in6p_fport); 299ca007d91SDag-Erling Smørgrav } 300ca007d91SDag-Erling Smørgrav sock->vflag = inp->inp_vflag; 301ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 302ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 303ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 304ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 305ca007d91SDag-Erling Smørgrav } 306ca007d91SDag-Erling Smørgrav out: 307ca007d91SDag-Erling Smørgrav free(buf); 308ca007d91SDag-Erling Smørgrav } 309ca007d91SDag-Erling Smørgrav 310ca007d91SDag-Erling Smørgrav static void 311ca007d91SDag-Erling Smørgrav gather_unix(int proto) 312ca007d91SDag-Erling Smørgrav { 313ca007d91SDag-Erling Smørgrav struct xunpgen *xug, *exug; 314ca007d91SDag-Erling Smørgrav struct xunpcb *xup; 315ca007d91SDag-Erling Smørgrav struct sock *sock; 316ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 317ca007d91SDag-Erling Smørgrav size_t len, bufsize; 318ca007d91SDag-Erling Smørgrav void *buf; 319ca007d91SDag-Erling Smørgrav int hash, retry; 320ca007d91SDag-Erling Smørgrav 321ca007d91SDag-Erling Smørgrav switch (proto) { 322ca007d91SDag-Erling Smørgrav case SOCK_STREAM: 323ca007d91SDag-Erling Smørgrav varname = "net.local.stream.pcblist"; 324ca007d91SDag-Erling Smørgrav protoname = "stream"; 325ca007d91SDag-Erling Smørgrav break; 326ca007d91SDag-Erling Smørgrav case SOCK_DGRAM: 327ca007d91SDag-Erling Smørgrav varname = "net.local.dgram.pcblist"; 328ca007d91SDag-Erling Smørgrav protoname = "dgram"; 329ca007d91SDag-Erling Smørgrav break; 330ca007d91SDag-Erling Smørgrav default: 331ca007d91SDag-Erling Smørgrav abort(); 332ca007d91SDag-Erling Smørgrav } 333ca007d91SDag-Erling Smørgrav buf = NULL; 334ca007d91SDag-Erling Smørgrav bufsize = 8192; 335ca007d91SDag-Erling Smørgrav retry = 5; 336ca007d91SDag-Erling Smørgrav do { 337ca007d91SDag-Erling Smørgrav for (;;) { 338ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 339ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 340ca007d91SDag-Erling Smørgrav len = bufsize; 341ca007d91SDag-Erling Smørgrav if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 342ca007d91SDag-Erling Smørgrav break; 343ca007d91SDag-Erling Smørgrav if (errno != ENOMEM) 344ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 345ca007d91SDag-Erling Smørgrav bufsize *= 2; 346ca007d91SDag-Erling Smørgrav } 347ca007d91SDag-Erling Smørgrav xug = (struct xunpgen *)buf; 3486dbe8d53SRobert Drehmel exug = (struct xunpgen *)(void *) 3496dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exug); 350ca007d91SDag-Erling Smørgrav if (xug->xug_len != sizeof *xug || 351ca007d91SDag-Erling Smørgrav exug->xug_len != sizeof *exug) { 352ca007d91SDag-Erling Smørgrav warnx("struct xinpgen size mismatch"); 353ca007d91SDag-Erling Smørgrav goto out; 354ca007d91SDag-Erling Smørgrav } 355ca007d91SDag-Erling Smørgrav } while (xug->xug_gen != exug->xug_gen && retry--); 356ca007d91SDag-Erling Smørgrav 357ca007d91SDag-Erling Smørgrav if (xug->xug_gen != exug->xug_gen && opt_v) 358ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 359ca007d91SDag-Erling Smørgrav 360ca007d91SDag-Erling Smørgrav for (;;) { 3616dbe8d53SRobert Drehmel xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 362ca007d91SDag-Erling Smørgrav if (xug >= exug) 363ca007d91SDag-Erling Smørgrav break; 364ca007d91SDag-Erling Smørgrav xup = (struct xunpcb *)xug; 365ca007d91SDag-Erling Smørgrav if (xup->xu_len != sizeof *xup) { 366ca007d91SDag-Erling Smørgrav warnx("struct xunpcb size mismatch"); 367ca007d91SDag-Erling Smørgrav goto out; 368ca007d91SDag-Erling Smørgrav } 3691e6690e5SDag-Erling Smørgrav if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 3701e6690e5SDag-Erling Smørgrav (xup->xu_unp.unp_conn != NULL && !opt_c)) 3711e6690e5SDag-Erling Smørgrav continue; 372ca007d91SDag-Erling Smørgrav if ((sock = calloc(1, sizeof *sock)) == NULL) 373ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 374ca007d91SDag-Erling Smørgrav sock->socket = xup->xu_socket.xso_so; 375ca007d91SDag-Erling Smørgrav sock->pcb = xup->xu_unpp; 376ca007d91SDag-Erling Smørgrav sock->proto = proto; 377ca007d91SDag-Erling Smørgrav sock->family = AF_UNIX; 378ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 379ca007d91SDag-Erling Smørgrav if (xup->xu_unp.unp_addr != NULL) 3806dbe8d53SRobert Drehmel sock->laddr = 3816dbe8d53SRobert Drehmel *(struct sockaddr_storage *)(void *)&xup->xu_addr; 382ca007d91SDag-Erling Smørgrav else if (xup->xu_unp.unp_conn != NULL) 383ca007d91SDag-Erling Smørgrav *(void **)&sock->faddr = xup->xu_unp.unp_conn; 384ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 385ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 386ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 387ca007d91SDag-Erling Smørgrav } 388ca007d91SDag-Erling Smørgrav out: 389ca007d91SDag-Erling Smørgrav free(buf); 390ca007d91SDag-Erling Smørgrav } 391ca007d91SDag-Erling Smørgrav 392ca007d91SDag-Erling Smørgrav static void 393ca007d91SDag-Erling Smørgrav getfiles(void) 394ca007d91SDag-Erling Smørgrav { 395ca007d91SDag-Erling Smørgrav size_t len; 396ca007d91SDag-Erling Smørgrav 397ca007d91SDag-Erling Smørgrav if ((xfiles = malloc(len = sizeof *xfiles)) == NULL) 398ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 399ca007d91SDag-Erling Smørgrav while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 400ca007d91SDag-Erling Smørgrav if (errno != ENOMEM) 401ca007d91SDag-Erling Smørgrav err(1, "sysctlbyname()"); 402ca007d91SDag-Erling Smørgrav len *= 2; 403ca007d91SDag-Erling Smørgrav if ((xfiles = realloc(xfiles, len)) == NULL) 404ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 405ca007d91SDag-Erling Smørgrav } 406ca007d91SDag-Erling Smørgrav if (len > 0 && xfiles->xf_size != sizeof *xfiles) 407ca007d91SDag-Erling Smørgrav errx(1, "struct xfile size mismatch"); 408ca007d91SDag-Erling Smørgrav nxfiles = len / sizeof *xfiles; 409ca007d91SDag-Erling Smørgrav } 410ca007d91SDag-Erling Smørgrav 411ca007d91SDag-Erling Smørgrav static int 412ca007d91SDag-Erling Smørgrav printaddr(int af, struct sockaddr_storage *ss) 413ca007d91SDag-Erling Smørgrav { 414ca007d91SDag-Erling Smørgrav char addrstr[INET6_ADDRSTRLEN] = { '\0', '\0' }; 415ca007d91SDag-Erling Smørgrav struct sockaddr_un *sun; 416ca007d91SDag-Erling Smørgrav void *addr; 417ca007d91SDag-Erling Smørgrav int off, port; 418ca007d91SDag-Erling Smørgrav 419ca007d91SDag-Erling Smørgrav switch (af) { 420ca007d91SDag-Erling Smørgrav case AF_INET: 421ca007d91SDag-Erling Smørgrav addr = &((struct sockaddr_in *)ss)->sin_addr; 422ca007d91SDag-Erling Smørgrav if (inet_lnaof(*(struct in_addr *)addr) == INADDR_ANY) 423ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 424ca007d91SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in *)ss)->sin_port); 425ca007d91SDag-Erling Smørgrav break; 426ca007d91SDag-Erling Smørgrav case AF_INET6: 427ca007d91SDag-Erling Smørgrav addr = &((struct sockaddr_in6 *)ss)->sin6_addr; 428ca007d91SDag-Erling Smørgrav if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)addr)) 429ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 430ca007d91SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in6 *)ss)->sin6_port); 431ca007d91SDag-Erling Smørgrav break; 432ca007d91SDag-Erling Smørgrav case AF_UNIX: 433ca007d91SDag-Erling Smørgrav sun = (struct sockaddr_un *)ss; 434ca007d91SDag-Erling Smørgrav off = (int)((char *)&sun->sun_path - (char *)sun); 435ca007d91SDag-Erling Smørgrav return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 436ca007d91SDag-Erling Smørgrav } 437ca007d91SDag-Erling Smørgrav if (addrstr[0] == '\0') 438ca007d91SDag-Erling Smørgrav inet_ntop(af, addr, addrstr, sizeof addrstr); 439ca007d91SDag-Erling Smørgrav if (port == 0) 440ca007d91SDag-Erling Smørgrav return xprintf("%s:*", addrstr); 441ca007d91SDag-Erling Smørgrav else 442ca007d91SDag-Erling Smørgrav return xprintf("%s:%d", addrstr, port); 443ca007d91SDag-Erling Smørgrav } 444ca007d91SDag-Erling Smørgrav 445ca007d91SDag-Erling Smørgrav static const char * 446ca007d91SDag-Erling Smørgrav getprocname(pid_t pid) 447ca007d91SDag-Erling Smørgrav { 448ca007d91SDag-Erling Smørgrav static struct kinfo_proc proc; 449ca007d91SDag-Erling Smørgrav size_t len; 450ca007d91SDag-Erling Smørgrav int mib[4]; 451ca007d91SDag-Erling Smørgrav 452ca007d91SDag-Erling Smørgrav mib[0] = CTL_KERN; 453ca007d91SDag-Erling Smørgrav mib[1] = KERN_PROC; 454ca007d91SDag-Erling Smørgrav mib[2] = KERN_PROC_PID; 455ca007d91SDag-Erling Smørgrav mib[3] = (int)pid; 456ca007d91SDag-Erling Smørgrav len = sizeof proc; 457ca007d91SDag-Erling Smørgrav if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { 458ca007d91SDag-Erling Smørgrav warn("sysctl()"); 459ca007d91SDag-Erling Smørgrav return ("??"); 460ca007d91SDag-Erling Smørgrav } 461ca007d91SDag-Erling Smørgrav return (proc.ki_ocomm); 462ca007d91SDag-Erling Smørgrav } 463ca007d91SDag-Erling Smørgrav 464ae94787dSMaxime Henrion static int 465ae94787dSMaxime Henrion check_ports(struct sock *s) 466ae94787dSMaxime Henrion { 467ae94787dSMaxime Henrion int port; 468ae94787dSMaxime Henrion 469ae94787dSMaxime Henrion if (ports == NULL) 470ae94787dSMaxime Henrion return (1); 471ae94787dSMaxime Henrion if ((s->family != AF_INET) && (s->family != AF_INET6)) 472ae94787dSMaxime Henrion return (1); 473ae94787dSMaxime Henrion if (s->family == AF_INET) 474ae94787dSMaxime Henrion port = ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port); 475ae94787dSMaxime Henrion else 476ae94787dSMaxime Henrion port = ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port); 477ae94787dSMaxime Henrion if (CHK_PORT(port)) 478ae94787dSMaxime Henrion return (1); 479ae94787dSMaxime Henrion if (s->family == AF_INET) 480ae94787dSMaxime Henrion port = ntohs(((struct sockaddr_in *)(&s->faddr))->sin_port); 481ae94787dSMaxime Henrion else 482ae94787dSMaxime Henrion port = ntohs(((struct sockaddr_in6 *)(&s->faddr))->sin6_port); 483ae94787dSMaxime Henrion if (CHK_PORT(port)) 484ae94787dSMaxime Henrion return (1); 485ae94787dSMaxime Henrion return (0); 486ae94787dSMaxime Henrion } 487ae94787dSMaxime Henrion 488ca007d91SDag-Erling Smørgrav static void 489ca007d91SDag-Erling Smørgrav display(void) 490ca007d91SDag-Erling Smørgrav { 491ca007d91SDag-Erling Smørgrav struct passwd *pwd; 492ca007d91SDag-Erling Smørgrav struct xfile *xf; 493ca007d91SDag-Erling Smørgrav struct sock *s; 494ca007d91SDag-Erling Smørgrav void *p; 495ca007d91SDag-Erling Smørgrav int hash, n, pos; 496ca007d91SDag-Erling Smørgrav 497ca007d91SDag-Erling Smørgrav printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s\n", 498ca007d91SDag-Erling Smørgrav "USER", "COMMAND", "PID", "FD", "PROTO", 499ca007d91SDag-Erling Smørgrav "LOCAL ADDRESS", "FOREIGN ADDRESS"); 500ca007d91SDag-Erling Smørgrav setpassent(1); 501ca007d91SDag-Erling Smørgrav for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 50297c6143cSPeter Pentchev if (xf->xf_data == NULL) 50397c6143cSPeter Pentchev continue; 50448e3128bSMatthew Dillon hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 505ca007d91SDag-Erling Smørgrav for (s = sockhash[hash]; s != NULL; s = s->next) 50648e3128bSMatthew Dillon if ((void *)s->socket == xf->xf_data) 507ca007d91SDag-Erling Smørgrav break; 508ca007d91SDag-Erling Smørgrav if (s == NULL) 509ca007d91SDag-Erling Smørgrav continue; 510ae94787dSMaxime Henrion if (!check_ports(s)) 511ae94787dSMaxime Henrion continue; 512ca007d91SDag-Erling Smørgrav pos = 0; 513ca007d91SDag-Erling Smørgrav if ((pwd = getpwuid(xf->xf_uid)) == NULL) 514ca007d91SDag-Erling Smørgrav pos += xprintf("%lu", (u_long)xf->xf_uid); 515ca007d91SDag-Erling Smørgrav else 516ca007d91SDag-Erling Smørgrav pos += xprintf("%s", pwd->pw_name); 517ca007d91SDag-Erling Smørgrav while (pos < 9) 518ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 519ca007d91SDag-Erling Smørgrav pos += xprintf("%.10s", getprocname(xf->xf_pid)); 520ca007d91SDag-Erling Smørgrav while (pos < 20) 521ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 522ca007d91SDag-Erling Smørgrav pos += xprintf("%lu", (u_long)xf->xf_pid); 523ca007d91SDag-Erling Smørgrav while (pos < 26) 524ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 525ca007d91SDag-Erling Smørgrav pos += xprintf("%d", xf->xf_fd); 526ca007d91SDag-Erling Smørgrav while (pos < 29) 527ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 528ca007d91SDag-Erling Smørgrav pos += xprintf("%s", s->protoname); 529ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV4) 530ca007d91SDag-Erling Smørgrav pos += xprintf("4"); 531ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV6) 532ca007d91SDag-Erling Smørgrav pos += xprintf("6"); 533ca007d91SDag-Erling Smørgrav while (pos < 36) 534ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 535ca007d91SDag-Erling Smørgrav switch (s->family) { 536ca007d91SDag-Erling Smørgrav case AF_INET: 537ca007d91SDag-Erling Smørgrav case AF_INET6: 538ca007d91SDag-Erling Smørgrav pos += printaddr(s->family, &s->laddr); 539ca007d91SDag-Erling Smørgrav while (pos < 58) 540ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 541ca007d91SDag-Erling Smørgrav pos += printaddr(s->family, &s->faddr); 542ca007d91SDag-Erling Smørgrav break; 543ca007d91SDag-Erling Smørgrav case AF_UNIX: 544ca007d91SDag-Erling Smørgrav /* server */ 545ca007d91SDag-Erling Smørgrav if (s->laddr.ss_len > 0) { 546ca007d91SDag-Erling Smørgrav pos += printaddr(s->family, &s->laddr); 547ca007d91SDag-Erling Smørgrav break; 548ca007d91SDag-Erling Smørgrav } 549ca007d91SDag-Erling Smørgrav /* client */ 550ca007d91SDag-Erling Smørgrav p = *(void **)&s->faddr; 551b4eb37c6SJohn-Mark Gurney if (p == NULL) { 552b4eb37c6SJohn-Mark Gurney pos += xprintf("(not connected)"); 553b4eb37c6SJohn-Mark Gurney break; 554b4eb37c6SJohn-Mark Gurney } 555b4eb37c6SJohn-Mark Gurney pos += xprintf("-> "); 556ca007d91SDag-Erling Smørgrav for (hash = 0; hash < HASHSIZE; ++hash) { 557ca007d91SDag-Erling Smørgrav for (s = sockhash[hash]; s != NULL; s = s->next) 558ca007d91SDag-Erling Smørgrav if (s->pcb == p) 559ca007d91SDag-Erling Smørgrav break; 560ca007d91SDag-Erling Smørgrav if (s != NULL) 561ca007d91SDag-Erling Smørgrav break; 562ca007d91SDag-Erling Smørgrav } 563ca007d91SDag-Erling Smørgrav if (s == NULL || s->laddr.ss_len == 0) 564ca007d91SDag-Erling Smørgrav pos += xprintf("??"); 565ca007d91SDag-Erling Smørgrav else 566ca007d91SDag-Erling Smørgrav pos += printaddr(s->family, &s->laddr); 567ca007d91SDag-Erling Smørgrav break; 568ca007d91SDag-Erling Smørgrav default: 569ca007d91SDag-Erling Smørgrav abort(); 570ca007d91SDag-Erling Smørgrav } 571ca007d91SDag-Erling Smørgrav xprintf("\n"); 572ca007d91SDag-Erling Smørgrav } 573ca007d91SDag-Erling Smørgrav } 574ca007d91SDag-Erling Smørgrav 575ca007d91SDag-Erling Smørgrav static void 576ca007d91SDag-Erling Smørgrav usage(void) 577ca007d91SDag-Erling Smørgrav { 578ca007d91SDag-Erling Smørgrav fprintf(stderr, "Usage: sockstat [-46clu] [-p ports]\n"); 579ca007d91SDag-Erling Smørgrav exit(1); 580ca007d91SDag-Erling Smørgrav } 581ca007d91SDag-Erling Smørgrav 582ca007d91SDag-Erling Smørgrav int 583ca007d91SDag-Erling Smørgrav main(int argc, char *argv[]) 584ca007d91SDag-Erling Smørgrav { 585ca007d91SDag-Erling Smørgrav int o; 586ca007d91SDag-Erling Smørgrav 587ca007d91SDag-Erling Smørgrav while ((o = getopt(argc, argv, "46clp:uv")) != -1) 588ca007d91SDag-Erling Smørgrav switch (o) { 589ca007d91SDag-Erling Smørgrav case '4': 590ca007d91SDag-Erling Smørgrav opt_4 = 1; 591ca007d91SDag-Erling Smørgrav break; 592ca007d91SDag-Erling Smørgrav case '6': 593ca007d91SDag-Erling Smørgrav opt_6 = 1; 594ca007d91SDag-Erling Smørgrav break; 595ca007d91SDag-Erling Smørgrav case 'c': 596ca007d91SDag-Erling Smørgrav opt_c = 1; 597ca007d91SDag-Erling Smørgrav break; 598ca007d91SDag-Erling Smørgrav case 'l': 599ca007d91SDag-Erling Smørgrav opt_l = 1; 600ca007d91SDag-Erling Smørgrav break; 601ca007d91SDag-Erling Smørgrav case 'p': 602ca007d91SDag-Erling Smørgrav parse_ports(optarg); 603ca007d91SDag-Erling Smørgrav break; 604ca007d91SDag-Erling Smørgrav case 'u': 605ca007d91SDag-Erling Smørgrav opt_u = 1; 606ca007d91SDag-Erling Smørgrav break; 607ca007d91SDag-Erling Smørgrav case 'v': 608ca007d91SDag-Erling Smørgrav ++opt_v; 609ca007d91SDag-Erling Smørgrav break; 610ca007d91SDag-Erling Smørgrav default: 611ca007d91SDag-Erling Smørgrav usage(); 612ca007d91SDag-Erling Smørgrav } 613ca007d91SDag-Erling Smørgrav 614ca007d91SDag-Erling Smørgrav argc -= optind; 615ca007d91SDag-Erling Smørgrav argv += optind; 616ca007d91SDag-Erling Smørgrav 617ca007d91SDag-Erling Smørgrav if (argc > 0) 618ca007d91SDag-Erling Smørgrav usage(); 619ca007d91SDag-Erling Smørgrav 620ca007d91SDag-Erling Smørgrav if (!opt_4 && !opt_6 && !opt_u) 621ca007d91SDag-Erling Smørgrav opt_4 = opt_6 = opt_u = 1; 622ca007d91SDag-Erling Smørgrav if (!opt_c && !opt_l) 623ca007d91SDag-Erling Smørgrav opt_c = opt_l = 1; 624ca007d91SDag-Erling Smørgrav 625ca007d91SDag-Erling Smørgrav if (opt_4 || opt_6) { 626ca007d91SDag-Erling Smørgrav gather_inet(IPPROTO_TCP); 627ca007d91SDag-Erling Smørgrav gather_inet(IPPROTO_UDP); 6282cfbdf89SRuslan Ermilov gather_inet(IPPROTO_DIVERT); 629ca007d91SDag-Erling Smørgrav } 630ca007d91SDag-Erling Smørgrav if (opt_u) { 631ca007d91SDag-Erling Smørgrav gather_unix(SOCK_STREAM); 632ca007d91SDag-Erling Smørgrav gather_unix(SOCK_DGRAM); 633ca007d91SDag-Erling Smørgrav } 634ca007d91SDag-Erling Smørgrav getfiles(); 635ca007d91SDag-Erling Smørgrav display(); 636ca007d91SDag-Erling Smørgrav 637ca007d91SDag-Erling Smørgrav exit(0); 638ca007d91SDag-Erling Smørgrav } 639