1ca007d91SDag-Erling Smørgrav /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 4fb2ad9d3SUlrich Spörlein * Copyright (c) 2002 Dag-Erling Coïdan Smørgrav 5ca007d91SDag-Erling Smørgrav * All rights reserved. 6ca007d91SDag-Erling Smørgrav * 7ca007d91SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 8ca007d91SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 9ca007d91SDag-Erling Smørgrav * are met: 10ca007d91SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 11ca007d91SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 12ca007d91SDag-Erling Smørgrav * in this position and unchanged. 13ca007d91SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 14ca007d91SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 15ca007d91SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 16ca007d91SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 17ca007d91SDag-Erling Smørgrav * derived from this software without specific prior written permission. 18ca007d91SDag-Erling Smørgrav * 19ca007d91SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20ca007d91SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21ca007d91SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22ca007d91SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23ca007d91SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24ca007d91SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25ca007d91SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26ca007d91SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27ca007d91SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28ca007d91SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29ca007d91SDag-Erling Smørgrav */ 30ca007d91SDag-Erling Smørgrav 31ca007d91SDag-Erling Smørgrav #include <sys/cdefs.h> 32ca007d91SDag-Erling Smørgrav __FBSDID("$FreeBSD$"); 33ca007d91SDag-Erling Smørgrav 34ca007d91SDag-Erling Smørgrav #include <sys/param.h> 35f1cd4902SRyan Moeller #include <sys/file.h> 36ca007d91SDag-Erling Smørgrav #include <sys/socket.h> 37ca007d91SDag-Erling Smørgrav #include <sys/socketvar.h> 38ca007d91SDag-Erling Smørgrav #include <sys/sysctl.h> 39f1cd4902SRyan Moeller #include <sys/jail.h> 40ca007d91SDag-Erling Smørgrav #include <sys/user.h> 41ca007d91SDag-Erling Smørgrav 42ca007d91SDag-Erling Smørgrav #include <sys/un.h> 430e229f34SGleb Smirnoff #define _WANT_UNPCB 44ca007d91SDag-Erling Smørgrav #include <sys/unpcb.h> 45ca007d91SDag-Erling Smørgrav 4602bd9db0SDag-Erling Smørgrav #include <net/route.h> 4702bd9db0SDag-Erling Smørgrav 48ca007d91SDag-Erling Smørgrav #include <netinet/in.h> 49ca007d91SDag-Erling Smørgrav #include <netinet/in_pcb.h> 50d5b4aa90SMichael Tuexen #include <netinet/sctp.h> 51ca007d91SDag-Erling Smørgrav #include <netinet/tcp.h> 527a5642b3SDag-Erling Smørgrav #define TCPSTATES /* load state names */ 537a5642b3SDag-Erling Smørgrav #include <netinet/tcp_fsm.h> 54ca007d91SDag-Erling Smørgrav #include <netinet/tcp_seq.h> 55ca007d91SDag-Erling Smørgrav #include <netinet/tcp_var.h> 56ca007d91SDag-Erling Smørgrav #include <arpa/inet.h> 57ca007d91SDag-Erling Smørgrav 58c5a2d8c5SRyan Moeller #include <capsicum_helpers.h> 59ca007d91SDag-Erling Smørgrav #include <ctype.h> 60ca007d91SDag-Erling Smørgrav #include <err.h> 61ca007d91SDag-Erling Smørgrav #include <errno.h> 62*5f64777aSMichael Tuexen #include <inttypes.h> 63de68a320SJamie Gritton #include <jail.h> 64ca007d91SDag-Erling Smørgrav #include <netdb.h> 65ca007d91SDag-Erling Smørgrav #include <pwd.h> 66ca007d91SDag-Erling Smørgrav #include <stdarg.h> 67ca007d91SDag-Erling Smørgrav #include <stdio.h> 68ca007d91SDag-Erling Smørgrav #include <stdlib.h> 69ca007d91SDag-Erling Smørgrav #include <string.h> 70ca007d91SDag-Erling Smørgrav #include <unistd.h> 71ca007d91SDag-Erling Smørgrav 72c5a2d8c5SRyan Moeller #include <libcasper.h> 73c5a2d8c5SRyan Moeller #include <casper/cap_net.h> 74c5a2d8c5SRyan Moeller #include <casper/cap_netdb.h> 757ad30f58SMariusz Zaborski #include <casper/cap_pwd.h> 76c5a2d8c5SRyan Moeller #include <casper/cap_sysctl.h> 77c5a2d8c5SRyan Moeller 78b8e20e2dSHiroki Sato #define sstosin(ss) ((struct sockaddr_in *)(ss)) 79b8e20e2dSHiroki Sato #define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) 80b8e20e2dSHiroki Sato #define sstosun(ss) ((struct sockaddr_un *)(ss)) 81b8e20e2dSHiroki Sato #define sstosa(ss) ((struct sockaddr *)(ss)) 82b8e20e2dSHiroki Sato 83ca007d91SDag-Erling Smørgrav static int opt_4; /* Show IPv4 sockets */ 84ca007d91SDag-Erling Smørgrav static int opt_6; /* Show IPv6 sockets */ 852ac089d0SMichael Tuexen static int opt_C; /* Show congestion control */ 86ca007d91SDag-Erling Smørgrav static int opt_c; /* Show connected sockets */ 87*5f64777aSMichael Tuexen static int opt_i; /* Show inp_gencnt */ 8800feaafdSAndrew Thompson static int opt_j; /* Show specified jail */ 899b6ca892SBruce M Simpson static int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 90ca007d91SDag-Erling Smørgrav static int opt_l; /* Show listening sockets */ 91ccdd2b2bSAlexander Motin static int opt_n; /* Don't resolve UIDs to user names */ 92ee0afaa9SEmmanuel Vadot static int opt_q; /* Don't show header */ 93e5cccc35SMichael Tuexen static int opt_S; /* Show protocol stack if applicable */ 947a5642b3SDag-Erling Smørgrav static int opt_s; /* Show protocol state if applicable */ 9549b836f2SMichael Tuexen static int opt_U; /* Show remote UDP encapsulation port number */ 96ca007d91SDag-Erling Smørgrav static int opt_u; /* Show Unix domain sockets */ 97ca007d91SDag-Erling Smørgrav static int opt_v; /* Verbose mode */ 9883f60cb2SMichael Tuexen static int opt_w; /* Wide print area for addresses */ 99ca007d91SDag-Erling Smørgrav 1001f3d67aaSGiorgos Keramidas /* 1011f3d67aaSGiorgos Keramidas * Default protocols to use if no -P was defined. 1021f3d67aaSGiorgos Keramidas */ 103d5b4aa90SMichael Tuexen static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 104b8e20e2dSHiroki Sato static size_t default_numprotos = nitems(default_protos); 1051f3d67aaSGiorgos Keramidas 1061f3d67aaSGiorgos Keramidas static int *protos; /* protocols to use */ 1071f3d67aaSGiorgos Keramidas static size_t numprotos; /* allocated size of protos[] */ 1081f3d67aaSGiorgos Keramidas 109ca007d91SDag-Erling Smørgrav static int *ports; 110ca007d91SDag-Erling Smørgrav 111ca007d91SDag-Erling Smørgrav #define INT_BIT (sizeof(int)*CHAR_BIT) 112ca007d91SDag-Erling Smørgrav #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 113ca007d91SDag-Erling Smørgrav #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 114ca007d91SDag-Erling Smørgrav 115e6f718c7SMichael Tuexen struct addr { 116e6f718c7SMichael Tuexen struct sockaddr_storage address; 11749b836f2SMichael Tuexen unsigned int encaps_port; 118e389705eSMichael Tuexen int state; 119e6f718c7SMichael Tuexen struct addr *next; 120e6f718c7SMichael Tuexen }; 121e6f718c7SMichael Tuexen 122ca007d91SDag-Erling Smørgrav struct sock { 123f38b68aeSBrooks Davis kvaddr_t socket; 124f38b68aeSBrooks Davis kvaddr_t pcb; 125*5f64777aSMichael Tuexen uint64_t inp_gencnt; 12661149f8dSJilles Tjoelker int shown; 127ca007d91SDag-Erling Smørgrav int vflag; 128ca007d91SDag-Erling Smørgrav int family; 129ca007d91SDag-Erling Smørgrav int proto; 1307a5642b3SDag-Erling Smørgrav int state; 131ca007d91SDag-Erling Smørgrav const char *protoname; 132e5cccc35SMichael Tuexen char stack[TCP_FUNCTION_NAME_LEN_MAX]; 1332ac089d0SMichael Tuexen char cc[TCP_CA_NAME_MAX]; 134e6f718c7SMichael Tuexen struct addr *laddr; 135e6f718c7SMichael Tuexen struct addr *faddr; 136ca007d91SDag-Erling Smørgrav struct sock *next; 137ca007d91SDag-Erling Smørgrav }; 138ca007d91SDag-Erling Smørgrav 139ca007d91SDag-Erling Smørgrav #define HASHSIZE 1009 140ca007d91SDag-Erling Smørgrav static struct sock *sockhash[HASHSIZE]; 141ca007d91SDag-Erling Smørgrav 142ca007d91SDag-Erling Smørgrav static struct xfile *xfiles; 143ca007d91SDag-Erling Smørgrav static int nxfiles; 144ca007d91SDag-Erling Smørgrav 145c5a2d8c5SRyan Moeller static cap_channel_t *capnet; 146c5a2d8c5SRyan Moeller static cap_channel_t *capnetdb; 147c5a2d8c5SRyan Moeller static cap_channel_t *capsysctl; 1487ad30f58SMariusz Zaborski static cap_channel_t *cappwd; 149c5a2d8c5SRyan Moeller 150ca007d91SDag-Erling Smørgrav static int 151ca007d91SDag-Erling Smørgrav xprintf(const char *fmt, ...) 152ca007d91SDag-Erling Smørgrav { 153ca007d91SDag-Erling Smørgrav va_list ap; 154ca007d91SDag-Erling Smørgrav int len; 155ca007d91SDag-Erling Smørgrav 156ca007d91SDag-Erling Smørgrav va_start(ap, fmt); 157ca007d91SDag-Erling Smørgrav len = vprintf(fmt, ap); 158ca007d91SDag-Erling Smørgrav va_end(ap); 159ca007d91SDag-Erling Smørgrav if (len < 0) 160ca007d91SDag-Erling Smørgrav err(1, "printf()"); 161ca007d91SDag-Erling Smørgrav return (len); 162ca007d91SDag-Erling Smørgrav } 163ca007d91SDag-Erling Smørgrav 1641f3d67aaSGiorgos Keramidas static int 1651f3d67aaSGiorgos Keramidas get_proto_type(const char *proto) 1661f3d67aaSGiorgos Keramidas { 1671f3d67aaSGiorgos Keramidas struct protoent *pent; 1681f3d67aaSGiorgos Keramidas 1691f3d67aaSGiorgos Keramidas if (strlen(proto) == 0) 1701f3d67aaSGiorgos Keramidas return (0); 171bfb5947bSMariusz Zaborski if (capnetdb != NULL) 172c5a2d8c5SRyan Moeller pent = cap_getprotobyname(capnetdb, proto); 173bfb5947bSMariusz Zaborski else 174bfb5947bSMariusz Zaborski pent = getprotobyname(proto); 1751f3d67aaSGiorgos Keramidas if (pent == NULL) { 176c5a2d8c5SRyan Moeller warn("cap_getprotobyname"); 1771f3d67aaSGiorgos Keramidas return (-1); 1781f3d67aaSGiorgos Keramidas } 1791f3d67aaSGiorgos Keramidas return (pent->p_proto); 1801f3d67aaSGiorgos Keramidas } 1811f3d67aaSGiorgos Keramidas 182b8e20e2dSHiroki Sato static void 183b8e20e2dSHiroki Sato init_protos(int num) 1841f3d67aaSGiorgos Keramidas { 1851f3d67aaSGiorgos Keramidas int proto_count = 0; 1861f3d67aaSGiorgos Keramidas 1871f3d67aaSGiorgos Keramidas if (num > 0) { 1881f3d67aaSGiorgos Keramidas proto_count = num; 1891f3d67aaSGiorgos Keramidas } else { 1901f3d67aaSGiorgos Keramidas /* Find the maximum number of possible protocols. */ 1911f3d67aaSGiorgos Keramidas while (getprotoent() != NULL) 1921f3d67aaSGiorgos Keramidas proto_count++; 1931f3d67aaSGiorgos Keramidas endprotoent(); 1941f3d67aaSGiorgos Keramidas } 1951f3d67aaSGiorgos Keramidas 1961f3d67aaSGiorgos Keramidas if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 1971f3d67aaSGiorgos Keramidas err(1, "malloc"); 1981f3d67aaSGiorgos Keramidas numprotos = proto_count; 1991f3d67aaSGiorgos Keramidas } 2001f3d67aaSGiorgos Keramidas 2011f3d67aaSGiorgos Keramidas static int 2021f3d67aaSGiorgos Keramidas parse_protos(char *protospec) 2031f3d67aaSGiorgos Keramidas { 2041f3d67aaSGiorgos Keramidas char *prot; 2051f3d67aaSGiorgos Keramidas int proto_type, proto_index; 2061f3d67aaSGiorgos Keramidas 2071f3d67aaSGiorgos Keramidas if (protospec == NULL) 2081f3d67aaSGiorgos Keramidas return (-1); 2091f3d67aaSGiorgos Keramidas 2101f3d67aaSGiorgos Keramidas init_protos(0); 2111f3d67aaSGiorgos Keramidas proto_index = 0; 212b8e20e2dSHiroki Sato while ((prot = strsep(&protospec, ",")) != NULL) { 2131f3d67aaSGiorgos Keramidas if (strlen(prot) == 0) 2141f3d67aaSGiorgos Keramidas continue; 2151f3d67aaSGiorgos Keramidas proto_type = get_proto_type(prot); 2161f3d67aaSGiorgos Keramidas if (proto_type != -1) 2171f3d67aaSGiorgos Keramidas protos[proto_index++] = proto_type; 2181f3d67aaSGiorgos Keramidas } 2191f3d67aaSGiorgos Keramidas numprotos = proto_index; 2201f3d67aaSGiorgos Keramidas return (proto_index); 2211f3d67aaSGiorgos Keramidas } 2221f3d67aaSGiorgos Keramidas 223ca007d91SDag-Erling Smørgrav static void 224ca007d91SDag-Erling Smørgrav parse_ports(const char *portspec) 225ca007d91SDag-Erling Smørgrav { 226ca007d91SDag-Erling Smørgrav const char *p, *q; 227ca007d91SDag-Erling Smørgrav int port, end; 228ca007d91SDag-Erling Smørgrav 229ca007d91SDag-Erling Smørgrav if (ports == NULL) 2309efed1e6SRobert Drehmel if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 231ca007d91SDag-Erling Smørgrav err(1, "calloc()"); 232ca007d91SDag-Erling Smørgrav p = portspec; 233ca007d91SDag-Erling Smørgrav while (*p != '\0') { 234ca007d91SDag-Erling Smørgrav if (!isdigit(*p)) 235ca007d91SDag-Erling Smørgrav errx(1, "syntax error in port range"); 236ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 237ca007d91SDag-Erling Smørgrav /* nothing */ ; 238ca007d91SDag-Erling Smørgrav for (port = 0; p < q; ++p) 239ca007d91SDag-Erling Smørgrav port = port * 10 + digittoint(*p); 240ca007d91SDag-Erling Smørgrav if (port < 0 || port > 65535) 241ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 242ca007d91SDag-Erling Smørgrav SET_PORT(port); 243ca007d91SDag-Erling Smørgrav switch (*p) { 244ca007d91SDag-Erling Smørgrav case '-': 245ca007d91SDag-Erling Smørgrav ++p; 246ca007d91SDag-Erling Smørgrav break; 247ca007d91SDag-Erling Smørgrav case ',': 248ca007d91SDag-Erling Smørgrav ++p; 249ca007d91SDag-Erling Smørgrav /* fall through */ 250ca007d91SDag-Erling Smørgrav case '\0': 251ca007d91SDag-Erling Smørgrav default: 252ca007d91SDag-Erling Smørgrav continue; 253ca007d91SDag-Erling Smørgrav } 254ca007d91SDag-Erling Smørgrav for (q = p; *q != '\0' && isdigit(*q); ++q) 255ca007d91SDag-Erling Smørgrav /* nothing */ ; 256ca007d91SDag-Erling Smørgrav for (end = 0; p < q; ++p) 257ca007d91SDag-Erling Smørgrav end = end * 10 + digittoint(*p); 258ca007d91SDag-Erling Smørgrav if (end < port || end > 65535) 259ca007d91SDag-Erling Smørgrav errx(1, "invalid port number"); 260ca007d91SDag-Erling Smørgrav while (port++ < end) 261ca007d91SDag-Erling Smørgrav SET_PORT(port); 262ca007d91SDag-Erling Smørgrav if (*p == ',') 263ca007d91SDag-Erling Smørgrav ++p; 264ca007d91SDag-Erling Smørgrav } 265ca007d91SDag-Erling Smørgrav } 266ca007d91SDag-Erling Smørgrav 267ca007d91SDag-Erling Smørgrav static void 268b8e20e2dSHiroki Sato sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 269ca007d91SDag-Erling Smørgrav { 270ca007d91SDag-Erling Smørgrav struct sockaddr_in *sin4; 271ca007d91SDag-Erling Smørgrav struct sockaddr_in6 *sin6; 272ca007d91SDag-Erling Smørgrav 273b8e20e2dSHiroki Sato bzero(ss, sizeof(*ss)); 274ca007d91SDag-Erling Smørgrav switch (af) { 275ca007d91SDag-Erling Smørgrav case AF_INET: 276b8e20e2dSHiroki Sato sin4 = sstosin(ss); 277b8e20e2dSHiroki Sato sin4->sin_len = sizeof(*sin4); 278ca007d91SDag-Erling Smørgrav sin4->sin_family = af; 279ca007d91SDag-Erling Smørgrav sin4->sin_port = port; 280ca007d91SDag-Erling Smørgrav sin4->sin_addr = *(struct in_addr *)addr; 281ca007d91SDag-Erling Smørgrav break; 282ca007d91SDag-Erling Smørgrav case AF_INET6: 283b8e20e2dSHiroki Sato sin6 = sstosin6(ss); 284b8e20e2dSHiroki Sato sin6->sin6_len = sizeof(*sin6); 285ca007d91SDag-Erling Smørgrav sin6->sin6_family = af; 286ca007d91SDag-Erling Smørgrav sin6->sin6_port = port; 287ca007d91SDag-Erling Smørgrav sin6->sin6_addr = *(struct in6_addr *)addr; 288b8e20e2dSHiroki Sato #define s6_addr16 __u6_addr.__u6_addr16 289b8e20e2dSHiroki Sato if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 290b8e20e2dSHiroki Sato sin6->sin6_scope_id = 291b8e20e2dSHiroki Sato ntohs(sin6->sin6_addr.s6_addr16[1]); 292b8e20e2dSHiroki Sato sin6->sin6_addr.s6_addr16[1] = 0; 293b8e20e2dSHiroki Sato } 294ca007d91SDag-Erling Smørgrav break; 295ca007d91SDag-Erling Smørgrav default: 296ca007d91SDag-Erling Smørgrav abort(); 297ca007d91SDag-Erling Smørgrav } 298ca007d91SDag-Erling Smørgrav } 299ca007d91SDag-Erling Smørgrav 300ca007d91SDag-Erling Smørgrav static void 301bedcf91dSMichael Tuexen free_socket(struct sock *sock) 302bedcf91dSMichael Tuexen { 303bedcf91dSMichael Tuexen struct addr *cur, *next; 304bedcf91dSMichael Tuexen 305bedcf91dSMichael Tuexen cur = sock->laddr; 306bedcf91dSMichael Tuexen while (cur != NULL) { 307bedcf91dSMichael Tuexen next = cur->next; 308bedcf91dSMichael Tuexen free(cur); 309bedcf91dSMichael Tuexen cur = next; 310bedcf91dSMichael Tuexen } 311bedcf91dSMichael Tuexen cur = sock->faddr; 312bedcf91dSMichael Tuexen while (cur != NULL) { 313bedcf91dSMichael Tuexen next = cur->next; 314bedcf91dSMichael Tuexen free(cur); 315bedcf91dSMichael Tuexen cur = next; 316bedcf91dSMichael Tuexen } 317bedcf91dSMichael Tuexen free(sock); 318bedcf91dSMichael Tuexen } 319bedcf91dSMichael Tuexen 320bedcf91dSMichael Tuexen static void 321d5b4aa90SMichael Tuexen gather_sctp(void) 322d5b4aa90SMichael Tuexen { 323d5b4aa90SMichael Tuexen struct sock *sock; 324d5b4aa90SMichael Tuexen struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 325d5b4aa90SMichael Tuexen struct xsctp_inpcb *xinpcb; 326d5b4aa90SMichael Tuexen struct xsctp_tcb *xstcb; 327d5b4aa90SMichael Tuexen struct xsctp_raddr *xraddr; 328d5b4aa90SMichael Tuexen struct xsctp_laddr *xladdr; 329d5b4aa90SMichael Tuexen const char *varname; 330d5b4aa90SMichael Tuexen size_t len, offset; 331d5b4aa90SMichael Tuexen char *buf; 332d5b4aa90SMichael Tuexen int hash, vflag; 333d5b4aa90SMichael Tuexen int no_stcb, local_all_loopback, foreign_all_loopback; 334d5b4aa90SMichael Tuexen 335d5b4aa90SMichael Tuexen vflag = 0; 336d5b4aa90SMichael Tuexen if (opt_4) 337d5b4aa90SMichael Tuexen vflag |= INP_IPV4; 338d5b4aa90SMichael Tuexen if (opt_6) 339d5b4aa90SMichael Tuexen vflag |= INP_IPV6; 340d5b4aa90SMichael Tuexen 341d5b4aa90SMichael Tuexen varname = "net.inet.sctp.assoclist"; 342c5a2d8c5SRyan Moeller if (cap_sysctlbyname(capsysctl, varname, 0, &len, 0, 0) < 0) { 343d5b4aa90SMichael Tuexen if (errno != ENOENT) 344c5a2d8c5SRyan Moeller err(1, "cap_sysctlbyname()"); 345d5b4aa90SMichael Tuexen return; 346d5b4aa90SMichael Tuexen } 347d5b4aa90SMichael Tuexen if ((buf = (char *)malloc(len)) == NULL) { 348d5b4aa90SMichael Tuexen err(1, "malloc()"); 349d5b4aa90SMichael Tuexen return; 350d5b4aa90SMichael Tuexen } 351c5a2d8c5SRyan Moeller if (cap_sysctlbyname(capsysctl, varname, buf, &len, 0, 0) < 0) { 352c5a2d8c5SRyan Moeller err(1, "cap_sysctlbyname()"); 353d5b4aa90SMichael Tuexen free(buf); 354d5b4aa90SMichael Tuexen return; 355d5b4aa90SMichael Tuexen } 356d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)buf; 357d5b4aa90SMichael Tuexen offset = sizeof(struct xsctp_inpcb); 358d5b4aa90SMichael Tuexen while ((offset < len) && (xinpcb->last == 0)) { 359d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 360d5b4aa90SMichael Tuexen err(1, "malloc()"); 361d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 362d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 363d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 364c1eb13c7SMichael Tuexen if (xinpcb->maxqlen == 0) 3656414db1bSMichael Tuexen sock->state = SCTP_CLOSED; 3666414db1bSMichael Tuexen else 3676414db1bSMichael Tuexen sock->state = SCTP_LISTEN; 368d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 369d5b4aa90SMichael Tuexen sock->family = AF_INET6; 370edc9c7fcSMichael Tuexen /* 371edc9c7fcSMichael Tuexen * Currently there is no way to distinguish between 372edc9c7fcSMichael Tuexen * IPv6 only sockets or dual family sockets. 373edc9c7fcSMichael Tuexen * So mark it as dual socket. 374edc9c7fcSMichael Tuexen */ 375edc9c7fcSMichael Tuexen sock->vflag = INP_IPV6 | INP_IPV4; 376d5b4aa90SMichael Tuexen } else { 377d5b4aa90SMichael Tuexen sock->family = AF_INET; 378d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 379d5b4aa90SMichael Tuexen } 380d5b4aa90SMichael Tuexen prev_laddr = NULL; 381d5b4aa90SMichael Tuexen local_all_loopback = 1; 382d5b4aa90SMichael Tuexen while (offset < len) { 383d5b4aa90SMichael Tuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 384d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 385d5b4aa90SMichael Tuexen if (xladdr->last == 1) 386d5b4aa90SMichael Tuexen break; 387d5b4aa90SMichael Tuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 388d5b4aa90SMichael Tuexen err(1, "malloc()"); 389d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 390d5b4aa90SMichael Tuexen case AF_INET: 391d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 392d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 39327569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 39427569d01SRenato Botelho &xladdr->address.sin.sin_addr)) 395d5b4aa90SMichael Tuexen local_all_loopback = 0; 396d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 39727569d01SRenato Botelho sockaddr(&laddr->address, AF_INET, 398d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 399d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 400d5b4aa90SMichael Tuexen break; 401d5b4aa90SMichael Tuexen case AF_INET6: 40227569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 40327569d01SRenato Botelho &xladdr->address.sin6.sin6_addr)) 404d5b4aa90SMichael Tuexen local_all_loopback = 0; 40527569d01SRenato Botelho sockaddr(&laddr->address, AF_INET6, 406d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 407d5b4aa90SMichael Tuexen htons(xinpcb->local_port)); 408d5b4aa90SMichael Tuexen break; 409d5b4aa90SMichael Tuexen default: 410463a577bSEitan Adler errx(1, "address family %d not supported", 411d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 412d5b4aa90SMichael Tuexen } 413d5b4aa90SMichael Tuexen laddr->next = NULL; 414d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 415d5b4aa90SMichael Tuexen sock->laddr = laddr; 416d5b4aa90SMichael Tuexen else 417d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 418d5b4aa90SMichael Tuexen prev_laddr = laddr; 419d5b4aa90SMichael Tuexen } 420d5b4aa90SMichael Tuexen if (sock->laddr == NULL) { 42127569d01SRenato Botelho if ((sock->laddr = 42227569d01SRenato Botelho calloc(1, sizeof(struct addr))) == NULL) 423d5b4aa90SMichael Tuexen err(1, "malloc()"); 424d5b4aa90SMichael Tuexen sock->laddr->address.ss_family = sock->family; 425d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 42627569d01SRenato Botelho sock->laddr->address.ss_len = 42727569d01SRenato Botelho sizeof(struct sockaddr_in); 428d5b4aa90SMichael Tuexen else 42927569d01SRenato Botelho sock->laddr->address.ss_len = 43027569d01SRenato Botelho sizeof(struct sockaddr_in6); 431d5b4aa90SMichael Tuexen local_all_loopback = 0; 432d5b4aa90SMichael Tuexen } 433d5b4aa90SMichael Tuexen if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 434d5b4aa90SMichael Tuexen err(1, "malloc()"); 435d5b4aa90SMichael Tuexen sock->faddr->address.ss_family = sock->family; 436d5b4aa90SMichael Tuexen if (sock->family == AF_INET) 43727569d01SRenato Botelho sock->faddr->address.ss_len = 43827569d01SRenato Botelho sizeof(struct sockaddr_in); 439d5b4aa90SMichael Tuexen else 44027569d01SRenato Botelho sock->faddr->address.ss_len = 44127569d01SRenato Botelho sizeof(struct sockaddr_in6); 442d5b4aa90SMichael Tuexen no_stcb = 1; 443d5b4aa90SMichael Tuexen while (offset < len) { 444d5b4aa90SMichael Tuexen xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 445d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_tcb); 446bedcf91dSMichael Tuexen if (no_stcb) { 44727569d01SRenato Botelho if (opt_l && (sock->vflag & vflag) && 448d5b4aa90SMichael Tuexen (!opt_L || !local_all_loopback) && 449d5b4aa90SMichael Tuexen ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 450d5b4aa90SMichael Tuexen (xstcb->last == 1))) { 45127569d01SRenato Botelho hash = (int)((uintptr_t)sock->socket % 45227569d01SRenato Botelho HASHSIZE); 453d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 454d5b4aa90SMichael Tuexen sockhash[hash] = sock; 455bedcf91dSMichael Tuexen } else { 456bedcf91dSMichael Tuexen free_socket(sock); 457bedcf91dSMichael Tuexen } 458d5b4aa90SMichael Tuexen } 459d5b4aa90SMichael Tuexen if (xstcb->last == 1) 460d5b4aa90SMichael Tuexen break; 461d5b4aa90SMichael Tuexen no_stcb = 0; 462d5b4aa90SMichael Tuexen if (opt_c) { 463d5b4aa90SMichael Tuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 464d5b4aa90SMichael Tuexen err(1, "malloc()"); 465d5b4aa90SMichael Tuexen sock->socket = xinpcb->socket; 466d5b4aa90SMichael Tuexen sock->proto = IPPROTO_SCTP; 467d5b4aa90SMichael Tuexen sock->protoname = "sctp"; 4686414db1bSMichael Tuexen sock->state = (int)xstcb->state; 469d5b4aa90SMichael Tuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 470d5b4aa90SMichael Tuexen sock->family = AF_INET6; 471edc9c7fcSMichael Tuexen /* 472edc9c7fcSMichael Tuexen * Currently there is no way to distinguish 473edc9c7fcSMichael Tuexen * between IPv6 only sockets or dual family 474edc9c7fcSMichael Tuexen * sockets. So mark it as dual socket. 475edc9c7fcSMichael Tuexen */ 476edc9c7fcSMichael Tuexen sock->vflag = INP_IPV6 | INP_IPV4; 477d5b4aa90SMichael Tuexen } else { 478d5b4aa90SMichael Tuexen sock->family = AF_INET; 479d5b4aa90SMichael Tuexen sock->vflag = INP_IPV4; 480d5b4aa90SMichael Tuexen } 481d5b4aa90SMichael Tuexen } 482d5b4aa90SMichael Tuexen prev_laddr = NULL; 483d5b4aa90SMichael Tuexen local_all_loopback = 1; 484d5b4aa90SMichael Tuexen while (offset < len) { 48527569d01SRenato Botelho xladdr = (struct xsctp_laddr *)(void *)(buf + 48627569d01SRenato Botelho offset); 487d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_laddr); 488d5b4aa90SMichael Tuexen if (xladdr->last == 1) 489d5b4aa90SMichael Tuexen break; 490d5b4aa90SMichael Tuexen if (!opt_c) 491d5b4aa90SMichael Tuexen continue; 49227569d01SRenato Botelho laddr = calloc(1, sizeof(struct addr)); 49327569d01SRenato Botelho if (laddr == NULL) 494d5b4aa90SMichael Tuexen err(1, "malloc()"); 495d5b4aa90SMichael Tuexen switch (xladdr->address.sa.sa_family) { 496d5b4aa90SMichael Tuexen case AF_INET: 497d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 498d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 49927569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 50027569d01SRenato Botelho &xladdr->address.sin.sin_addr)) 501d5b4aa90SMichael Tuexen local_all_loopback = 0; 502d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 50327569d01SRenato Botelho sockaddr(&laddr->address, AF_INET, 504d5b4aa90SMichael Tuexen &xladdr->address.sin.sin_addr, 505d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 506d5b4aa90SMichael Tuexen break; 507d5b4aa90SMichael Tuexen case AF_INET6: 50827569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 50927569d01SRenato Botelho &xladdr->address.sin6.sin6_addr)) 510d5b4aa90SMichael Tuexen local_all_loopback = 0; 51127569d01SRenato Botelho sockaddr(&laddr->address, AF_INET6, 512d5b4aa90SMichael Tuexen &xladdr->address.sin6.sin6_addr, 513d5b4aa90SMichael Tuexen htons(xstcb->local_port)); 514d5b4aa90SMichael Tuexen break; 515d5b4aa90SMichael Tuexen default: 51627569d01SRenato Botelho errx(1, 51727569d01SRenato Botelho "address family %d not supported", 518d5b4aa90SMichael Tuexen xladdr->address.sa.sa_family); 519d5b4aa90SMichael Tuexen } 520d5b4aa90SMichael Tuexen laddr->next = NULL; 521d5b4aa90SMichael Tuexen if (prev_laddr == NULL) 522d5b4aa90SMichael Tuexen sock->laddr = laddr; 523d5b4aa90SMichael Tuexen else 524d5b4aa90SMichael Tuexen prev_laddr->next = laddr; 525d5b4aa90SMichael Tuexen prev_laddr = laddr; 526d5b4aa90SMichael Tuexen } 527d5b4aa90SMichael Tuexen prev_faddr = NULL; 528d5b4aa90SMichael Tuexen foreign_all_loopback = 1; 529d5b4aa90SMichael Tuexen while (offset < len) { 53027569d01SRenato Botelho xraddr = (struct xsctp_raddr *)(void *)(buf + 53127569d01SRenato Botelho offset); 532d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_raddr); 533d5b4aa90SMichael Tuexen if (xraddr->last == 1) 534d5b4aa90SMichael Tuexen break; 535d5b4aa90SMichael Tuexen if (!opt_c) 536d5b4aa90SMichael Tuexen continue; 53727569d01SRenato Botelho faddr = calloc(1, sizeof(struct addr)); 53827569d01SRenato Botelho if (faddr == NULL) 539d5b4aa90SMichael Tuexen err(1, "malloc()"); 540d5b4aa90SMichael Tuexen switch (xraddr->address.sa.sa_family) { 541d5b4aa90SMichael Tuexen case AF_INET: 542d5b4aa90SMichael Tuexen #define __IN_IS_ADDR_LOOPBACK(pina) \ 543d5b4aa90SMichael Tuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 54427569d01SRenato Botelho if (!__IN_IS_ADDR_LOOPBACK( 54527569d01SRenato Botelho &xraddr->address.sin.sin_addr)) 546d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 547d5b4aa90SMichael Tuexen #undef __IN_IS_ADDR_LOOPBACK 54827569d01SRenato Botelho sockaddr(&faddr->address, AF_INET, 549d5b4aa90SMichael Tuexen &xraddr->address.sin.sin_addr, 550d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 551d5b4aa90SMichael Tuexen break; 552d5b4aa90SMichael Tuexen case AF_INET6: 55327569d01SRenato Botelho if (!IN6_IS_ADDR_LOOPBACK( 55427569d01SRenato Botelho &xraddr->address.sin6.sin6_addr)) 555d5b4aa90SMichael Tuexen foreign_all_loopback = 0; 55627569d01SRenato Botelho sockaddr(&faddr->address, AF_INET6, 557d5b4aa90SMichael Tuexen &xraddr->address.sin6.sin6_addr, 558d5b4aa90SMichael Tuexen htons(xstcb->remote_port)); 559d5b4aa90SMichael Tuexen break; 560d5b4aa90SMichael Tuexen default: 56127569d01SRenato Botelho errx(1, 56227569d01SRenato Botelho "address family %d not supported", 563d5b4aa90SMichael Tuexen xraddr->address.sa.sa_family); 564d5b4aa90SMichael Tuexen } 56549b836f2SMichael Tuexen faddr->encaps_port = xraddr->encaps_port; 566e389705eSMichael Tuexen faddr->state = xraddr->state; 567d5b4aa90SMichael Tuexen faddr->next = NULL; 568d5b4aa90SMichael Tuexen if (prev_faddr == NULL) 569d5b4aa90SMichael Tuexen sock->faddr = faddr; 570d5b4aa90SMichael Tuexen else 571d5b4aa90SMichael Tuexen prev_faddr->next = faddr; 572d5b4aa90SMichael Tuexen prev_faddr = faddr; 573d5b4aa90SMichael Tuexen } 574bedcf91dSMichael Tuexen if (opt_c) { 575edc9c7fcSMichael Tuexen if ((sock->vflag & vflag) && 576edc9c7fcSMichael Tuexen (!opt_L || 57727569d01SRenato Botelho !(local_all_loopback || 57827569d01SRenato Botelho foreign_all_loopback))) { 57927569d01SRenato Botelho hash = (int)((uintptr_t)sock->socket % 58027569d01SRenato Botelho HASHSIZE); 581d5b4aa90SMichael Tuexen sock->next = sockhash[hash]; 582d5b4aa90SMichael Tuexen sockhash[hash] = sock; 583bedcf91dSMichael Tuexen } else { 584bedcf91dSMichael Tuexen free_socket(sock); 585bedcf91dSMichael Tuexen } 586d5b4aa90SMichael Tuexen } 587d5b4aa90SMichael Tuexen } 588d5b4aa90SMichael Tuexen xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 589d5b4aa90SMichael Tuexen offset += sizeof(struct xsctp_inpcb); 590d5b4aa90SMichael Tuexen } 591d5b4aa90SMichael Tuexen free(buf); 592d5b4aa90SMichael Tuexen } 593d5b4aa90SMichael Tuexen 594d5b4aa90SMichael Tuexen static void 595ca007d91SDag-Erling Smørgrav gather_inet(int proto) 596ca007d91SDag-Erling Smørgrav { 597ca007d91SDag-Erling Smørgrav struct xinpgen *xig, *exig; 598ca007d91SDag-Erling Smørgrav struct xinpcb *xip; 599bf40d2caSGleb Smirnoff struct xtcpcb *xtp = NULL; 600ca007d91SDag-Erling Smørgrav struct xsocket *so; 601ca007d91SDag-Erling Smørgrav struct sock *sock; 602e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 603ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 604ca007d91SDag-Erling Smørgrav size_t len, bufsize; 605ca007d91SDag-Erling Smørgrav void *buf; 6066eb1d5baSMichael Tuexen int hash, retry, vflag; 607ca007d91SDag-Erling Smørgrav 6086eb1d5baSMichael Tuexen vflag = 0; 609ca007d91SDag-Erling Smørgrav if (opt_4) 610ca007d91SDag-Erling Smørgrav vflag |= INP_IPV4; 611ca007d91SDag-Erling Smørgrav if (opt_6) 612ca007d91SDag-Erling Smørgrav vflag |= INP_IPV6; 613ca007d91SDag-Erling Smørgrav 614ca007d91SDag-Erling Smørgrav switch (proto) { 615ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 616ca007d91SDag-Erling Smørgrav varname = "net.inet.tcp.pcblist"; 617ca007d91SDag-Erling Smørgrav protoname = "tcp"; 618ca007d91SDag-Erling Smørgrav break; 619ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 620ca007d91SDag-Erling Smørgrav varname = "net.inet.udp.pcblist"; 621ca007d91SDag-Erling Smørgrav protoname = "udp"; 622ca007d91SDag-Erling Smørgrav break; 6232cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 6242cfbdf89SRuslan Ermilov varname = "net.inet.divert.pcblist"; 6252cfbdf89SRuslan Ermilov protoname = "div"; 6262cfbdf89SRuslan Ermilov break; 627ca007d91SDag-Erling Smørgrav default: 6281f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 629ca007d91SDag-Erling Smørgrav } 630ca007d91SDag-Erling Smørgrav 631ca007d91SDag-Erling Smørgrav buf = NULL; 632ca007d91SDag-Erling Smørgrav bufsize = 8192; 633ca007d91SDag-Erling Smørgrav retry = 5; 634ca007d91SDag-Erling Smørgrav do { 635ca007d91SDag-Erling Smørgrav for (;;) { 636ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 637ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 638ca007d91SDag-Erling Smørgrav len = bufsize; 639c5a2d8c5SRyan Moeller if (cap_sysctlbyname(capsysctl, varname, buf, &len, 640c5a2d8c5SRyan Moeller NULL, 0) == 0) 641ca007d91SDag-Erling Smørgrav break; 6424b2a3d41SRuslan Ermilov if (errno == ENOENT) 6434b2a3d41SRuslan Ermilov goto out; 644003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 645c5a2d8c5SRyan Moeller err(1, "cap_sysctlbyname()"); 646ca007d91SDag-Erling Smørgrav bufsize *= 2; 647ca007d91SDag-Erling Smørgrav } 648ca007d91SDag-Erling Smørgrav xig = (struct xinpgen *)buf; 6496dbe8d53SRobert Drehmel exig = (struct xinpgen *)(void *) 6506dbe8d53SRobert Drehmel ((char *)buf + len - sizeof *exig); 651ca007d91SDag-Erling Smørgrav if (xig->xig_len != sizeof *xig || 652ca007d91SDag-Erling Smørgrav exig->xig_len != sizeof *exig) 653ca007d91SDag-Erling Smørgrav errx(1, "struct xinpgen size mismatch"); 654ca007d91SDag-Erling Smørgrav } while (xig->xig_gen != exig->xig_gen && retry--); 655ca007d91SDag-Erling Smørgrav 656ca007d91SDag-Erling Smørgrav if (xig->xig_gen != exig->xig_gen && opt_v) 657ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 658ca007d91SDag-Erling Smørgrav 659ca007d91SDag-Erling Smørgrav for (;;) { 6606dbe8d53SRobert Drehmel xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 661ca007d91SDag-Erling Smørgrav if (xig >= exig) 662ca007d91SDag-Erling Smørgrav break; 663ca007d91SDag-Erling Smørgrav switch (proto) { 664ca007d91SDag-Erling Smørgrav case IPPROTO_TCP: 665cc65eb4eSGleb Smirnoff xtp = (struct xtcpcb *)xig; 666cc65eb4eSGleb Smirnoff xip = &xtp->xt_inp; 667b8e20e2dSHiroki Sato if (xtp->xt_len != sizeof(*xtp)) { 668ca007d91SDag-Erling Smørgrav warnx("struct xtcpcb size mismatch"); 669ca007d91SDag-Erling Smørgrav goto out; 670ca007d91SDag-Erling Smørgrav } 671cc65eb4eSGleb Smirnoff protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp"; 672ca007d91SDag-Erling Smørgrav break; 673ca007d91SDag-Erling Smørgrav case IPPROTO_UDP: 6742cfbdf89SRuslan Ermilov case IPPROTO_DIVERT: 675cc65eb4eSGleb Smirnoff xip = (struct xinpcb *)xig; 676b8e20e2dSHiroki Sato if (xip->xi_len != sizeof(*xip)) { 677ca007d91SDag-Erling Smørgrav warnx("struct xinpcb size mismatch"); 678ca007d91SDag-Erling Smørgrav goto out; 679ca007d91SDag-Erling Smørgrav } 680ca007d91SDag-Erling Smørgrav break; 681ca007d91SDag-Erling Smørgrav default: 6821f3d67aaSGiorgos Keramidas errx(1, "protocol %d not supported", proto); 683ca007d91SDag-Erling Smørgrav } 684cc65eb4eSGleb Smirnoff so = &xip->xi_socket; 685cc65eb4eSGleb Smirnoff if ((xip->inp_vflag & vflag) == 0) 686ca007d91SDag-Erling Smørgrav continue; 687cc65eb4eSGleb Smirnoff if (xip->inp_vflag & INP_IPV4) { 688cc65eb4eSGleb Smirnoff if ((xip->inp_fport == 0 && !opt_l) || 689cc65eb4eSGleb Smirnoff (xip->inp_fport != 0 && !opt_c)) 6901e6690e5SDag-Erling Smørgrav continue; 6919b6ca892SBruce M Simpson #define __IN_IS_ADDR_LOOPBACK(pina) \ 6929b6ca892SBruce M Simpson ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 6939b6ca892SBruce M Simpson if (opt_L && 694cc65eb4eSGleb Smirnoff (__IN_IS_ADDR_LOOPBACK(&xip->inp_faddr) || 695cc65eb4eSGleb Smirnoff __IN_IS_ADDR_LOOPBACK(&xip->inp_laddr))) 6969b6ca892SBruce M Simpson continue; 6979b6ca892SBruce M Simpson #undef __IN_IS_ADDR_LOOPBACK 698cc65eb4eSGleb Smirnoff } else if (xip->inp_vflag & INP_IPV6) { 699cc65eb4eSGleb Smirnoff if ((xip->inp_fport == 0 && !opt_l) || 700cc65eb4eSGleb Smirnoff (xip->inp_fport != 0 && !opt_c)) 7011e6690e5SDag-Erling Smørgrav continue; 7029b6ca892SBruce M Simpson if (opt_L && 703cc65eb4eSGleb Smirnoff (IN6_IS_ADDR_LOOPBACK(&xip->in6p_faddr) || 704cc65eb4eSGleb Smirnoff IN6_IS_ADDR_LOOPBACK(&xip->in6p_laddr))) 7059b6ca892SBruce M Simpson continue; 7061e6690e5SDag-Erling Smørgrav } else { 7071e6690e5SDag-Erling Smørgrav if (opt_v) 708cc65eb4eSGleb Smirnoff warnx("invalid vflag 0x%x", xip->inp_vflag); 7091e6690e5SDag-Erling Smørgrav continue; 7101e6690e5SDag-Erling Smørgrav } 711b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 712ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 713e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 714e6f718c7SMichael Tuexen err(1, "malloc()"); 715e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 716e6f718c7SMichael Tuexen err(1, "malloc()"); 717ca007d91SDag-Erling Smørgrav sock->socket = so->xso_so; 718ca007d91SDag-Erling Smørgrav sock->proto = proto; 719*5f64777aSMichael Tuexen sock->inp_gencnt = xip->inp_gencnt; 720cc65eb4eSGleb Smirnoff if (xip->inp_vflag & INP_IPV4) { 721ca007d91SDag-Erling Smørgrav sock->family = AF_INET; 722e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 723cc65eb4eSGleb Smirnoff &xip->inp_laddr, xip->inp_lport); 724e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 725cc65eb4eSGleb Smirnoff &xip->inp_faddr, xip->inp_fport); 726cc65eb4eSGleb Smirnoff } else if (xip->inp_vflag & INP_IPV6) { 727ca007d91SDag-Erling Smørgrav sock->family = AF_INET6; 728e6f718c7SMichael Tuexen sockaddr(&laddr->address, sock->family, 729cc65eb4eSGleb Smirnoff &xip->in6p_laddr, xip->inp_lport); 730e6f718c7SMichael Tuexen sockaddr(&faddr->address, sock->family, 731cc65eb4eSGleb Smirnoff &xip->in6p_faddr, xip->inp_fport); 732ca007d91SDag-Erling Smørgrav } 7339e644c23SMichael Tuexen if (proto == IPPROTO_TCP) 7349e644c23SMichael Tuexen faddr->encaps_port = xtp->xt_encaps_port; 735e6f718c7SMichael Tuexen laddr->next = NULL; 736e6f718c7SMichael Tuexen faddr->next = NULL; 737e6f718c7SMichael Tuexen sock->laddr = laddr; 738e6f718c7SMichael Tuexen sock->faddr = faddr; 739cc65eb4eSGleb Smirnoff sock->vflag = xip->inp_vflag; 740e5cccc35SMichael Tuexen if (proto == IPPROTO_TCP) { 741cc65eb4eSGleb Smirnoff sock->state = xtp->t_state; 742e5cccc35SMichael Tuexen memcpy(sock->stack, xtp->xt_stack, 743e5cccc35SMichael Tuexen TCP_FUNCTION_NAME_LEN_MAX); 7442ac089d0SMichael Tuexen memcpy(sock->cc, xtp->xt_cc, TCP_CA_NAME_MAX); 745e5cccc35SMichael Tuexen } 746ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 747ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 748ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 749ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 750ca007d91SDag-Erling Smørgrav } 751ca007d91SDag-Erling Smørgrav out: 752ca007d91SDag-Erling Smørgrav free(buf); 753ca007d91SDag-Erling Smørgrav } 754ca007d91SDag-Erling Smørgrav 755ca007d91SDag-Erling Smørgrav static void 756ca007d91SDag-Erling Smørgrav gather_unix(int proto) 757ca007d91SDag-Erling Smørgrav { 758ca007d91SDag-Erling Smørgrav struct xunpgen *xug, *exug; 759ca007d91SDag-Erling Smørgrav struct xunpcb *xup; 760ca007d91SDag-Erling Smørgrav struct sock *sock; 761e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 762ca007d91SDag-Erling Smørgrav const char *varname, *protoname; 763ca007d91SDag-Erling Smørgrav size_t len, bufsize; 764ca007d91SDag-Erling Smørgrav void *buf; 765ca007d91SDag-Erling Smørgrav int hash, retry; 766ca007d91SDag-Erling Smørgrav 767ca007d91SDag-Erling Smørgrav switch (proto) { 768ca007d91SDag-Erling Smørgrav case SOCK_STREAM: 769ca007d91SDag-Erling Smørgrav varname = "net.local.stream.pcblist"; 770ca007d91SDag-Erling Smørgrav protoname = "stream"; 771ca007d91SDag-Erling Smørgrav break; 772ca007d91SDag-Erling Smørgrav case SOCK_DGRAM: 773ca007d91SDag-Erling Smørgrav varname = "net.local.dgram.pcblist"; 774ca007d91SDag-Erling Smørgrav protoname = "dgram"; 775ca007d91SDag-Erling Smørgrav break; 776b8e20e2dSHiroki Sato case SOCK_SEQPACKET: 777b8e20e2dSHiroki Sato varname = "net.local.seqpacket.pcblist"; 778b8e20e2dSHiroki Sato protoname = "seqpac"; 779b8e20e2dSHiroki Sato break; 780ca007d91SDag-Erling Smørgrav default: 781ca007d91SDag-Erling Smørgrav abort(); 782ca007d91SDag-Erling Smørgrav } 783ca007d91SDag-Erling Smørgrav buf = NULL; 784ca007d91SDag-Erling Smørgrav bufsize = 8192; 785ca007d91SDag-Erling Smørgrav retry = 5; 786ca007d91SDag-Erling Smørgrav do { 787ca007d91SDag-Erling Smørgrav for (;;) { 788ca007d91SDag-Erling Smørgrav if ((buf = realloc(buf, bufsize)) == NULL) 789ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 790ca007d91SDag-Erling Smørgrav len = bufsize; 791c5a2d8c5SRyan Moeller if (cap_sysctlbyname(capsysctl, varname, buf, &len, 792c5a2d8c5SRyan Moeller NULL, 0) == 0) 793ca007d91SDag-Erling Smørgrav break; 794003e7e49SMikolaj Golub if (errno != ENOMEM || len != bufsize) 795c5a2d8c5SRyan Moeller err(1, "cap_sysctlbyname()"); 796ca007d91SDag-Erling Smørgrav bufsize *= 2; 797ca007d91SDag-Erling Smørgrav } 798ca007d91SDag-Erling Smørgrav xug = (struct xunpgen *)buf; 7996dbe8d53SRobert Drehmel exug = (struct xunpgen *)(void *) 800b8e20e2dSHiroki Sato ((char *)buf + len - sizeof(*exug)); 801b8e20e2dSHiroki Sato if (xug->xug_len != sizeof(*xug) || 802b8e20e2dSHiroki Sato exug->xug_len != sizeof(*exug)) { 803ca007d91SDag-Erling Smørgrav warnx("struct xinpgen size mismatch"); 804ca007d91SDag-Erling Smørgrav goto out; 805ca007d91SDag-Erling Smørgrav } 806ca007d91SDag-Erling Smørgrav } while (xug->xug_gen != exug->xug_gen && retry--); 807ca007d91SDag-Erling Smørgrav 808ca007d91SDag-Erling Smørgrav if (xug->xug_gen != exug->xug_gen && opt_v) 809ca007d91SDag-Erling Smørgrav warnx("warning: data may be inconsistent"); 810ca007d91SDag-Erling Smørgrav 811ca007d91SDag-Erling Smørgrav for (;;) { 8126dbe8d53SRobert Drehmel xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 813ca007d91SDag-Erling Smørgrav if (xug >= exug) 814ca007d91SDag-Erling Smørgrav break; 815ca007d91SDag-Erling Smørgrav xup = (struct xunpcb *)xug; 816b8e20e2dSHiroki Sato if (xup->xu_len != sizeof(*xup)) { 817ca007d91SDag-Erling Smørgrav warnx("struct xunpcb size mismatch"); 818ca007d91SDag-Erling Smørgrav goto out; 819ca007d91SDag-Erling Smørgrav } 820f38b68aeSBrooks Davis if ((xup->unp_conn == 0 && !opt_l) || 821f38b68aeSBrooks Davis (xup->unp_conn != 0 && !opt_c)) 8221e6690e5SDag-Erling Smørgrav continue; 823b8e20e2dSHiroki Sato if ((sock = calloc(1, sizeof(*sock))) == NULL) 824ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 825e6f718c7SMichael Tuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 826e6f718c7SMichael Tuexen err(1, "malloc()"); 827e6f718c7SMichael Tuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 828e6f718c7SMichael Tuexen err(1, "malloc()"); 829ca007d91SDag-Erling Smørgrav sock->socket = xup->xu_socket.xso_so; 830ca007d91SDag-Erling Smørgrav sock->pcb = xup->xu_unpp; 831ca007d91SDag-Erling Smørgrav sock->proto = proto; 832ca007d91SDag-Erling Smørgrav sock->family = AF_UNIX; 833ca007d91SDag-Erling Smørgrav sock->protoname = protoname; 8340e229f34SGleb Smirnoff if (xup->xu_addr.sun_family == AF_UNIX) 835e6f718c7SMichael Tuexen laddr->address = 8366dbe8d53SRobert Drehmel *(struct sockaddr_storage *)(void *)&xup->xu_addr; 837f38b68aeSBrooks Davis else if (xup->unp_conn != 0) 838f38b68aeSBrooks Davis *(kvaddr_t*)&(faddr->address) = xup->unp_conn; 839e6f718c7SMichael Tuexen laddr->next = NULL; 840e6f718c7SMichael Tuexen faddr->next = NULL; 841e6f718c7SMichael Tuexen sock->laddr = laddr; 842e6f718c7SMichael Tuexen sock->faddr = faddr; 843ca007d91SDag-Erling Smørgrav hash = (int)((uintptr_t)sock->socket % HASHSIZE); 844ca007d91SDag-Erling Smørgrav sock->next = sockhash[hash]; 845ca007d91SDag-Erling Smørgrav sockhash[hash] = sock; 846ca007d91SDag-Erling Smørgrav } 847ca007d91SDag-Erling Smørgrav out: 848ca007d91SDag-Erling Smørgrav free(buf); 849ca007d91SDag-Erling Smørgrav } 850ca007d91SDag-Erling Smørgrav 851ca007d91SDag-Erling Smørgrav static void 852ca007d91SDag-Erling Smørgrav getfiles(void) 853ca007d91SDag-Erling Smørgrav { 854003e7e49SMikolaj Golub size_t len, olen; 855ca007d91SDag-Erling Smørgrav 856b8e20e2dSHiroki Sato olen = len = sizeof(*xfiles); 857003e7e49SMikolaj Golub if ((xfiles = malloc(len)) == NULL) 858ca007d91SDag-Erling Smørgrav err(1, "malloc()"); 859c5a2d8c5SRyan Moeller while (cap_sysctlbyname(capsysctl, "kern.file", xfiles, &len, 0, 0) 860c5a2d8c5SRyan Moeller == -1) { 861003e7e49SMikolaj Golub if (errno != ENOMEM || len != olen) 862c5a2d8c5SRyan Moeller err(1, "cap_sysctlbyname()"); 863003e7e49SMikolaj Golub olen = len *= 2; 864ca007d91SDag-Erling Smørgrav if ((xfiles = realloc(xfiles, len)) == NULL) 865ca007d91SDag-Erling Smørgrav err(1, "realloc()"); 866ca007d91SDag-Erling Smørgrav } 867b8e20e2dSHiroki Sato if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 868ca007d91SDag-Erling Smørgrav errx(1, "struct xfile size mismatch"); 869b8e20e2dSHiroki Sato nxfiles = len / sizeof(*xfiles); 870ca007d91SDag-Erling Smørgrav } 871ca007d91SDag-Erling Smørgrav 872ca007d91SDag-Erling Smørgrav static int 873baa7f281SMichael Tuexen printaddr(struct sockaddr_storage *ss) 874ca007d91SDag-Erling Smørgrav { 875ca007d91SDag-Erling Smørgrav struct sockaddr_un *sun; 876b8e20e2dSHiroki Sato char addrstr[NI_MAXHOST] = { '\0', '\0' }; 877b8e20e2dSHiroki Sato int error, off, port = 0; 878ca007d91SDag-Erling Smørgrav 879baa7f281SMichael Tuexen switch (ss->ss_family) { 880ca007d91SDag-Erling Smørgrav case AF_INET: 88164acb29bSMike Karels if (sstosin(ss)->sin_addr.s_addr == INADDR_ANY) 882ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 883b8e20e2dSHiroki Sato port = ntohs(sstosin(ss)->sin_port); 884ca007d91SDag-Erling Smørgrav break; 885ca007d91SDag-Erling Smørgrav case AF_INET6: 886b8e20e2dSHiroki Sato if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 887ca007d91SDag-Erling Smørgrav addrstr[0] = '*'; 888b8e20e2dSHiroki Sato port = ntohs(sstosin6(ss)->sin6_port); 889ca007d91SDag-Erling Smørgrav break; 890ca007d91SDag-Erling Smørgrav case AF_UNIX: 891b8e20e2dSHiroki Sato sun = sstosun(ss); 892ca007d91SDag-Erling Smørgrav off = (int)((char *)&sun->sun_path - (char *)sun); 893ca007d91SDag-Erling Smørgrav return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 894ca007d91SDag-Erling Smørgrav } 895b8e20e2dSHiroki Sato if (addrstr[0] == '\0') { 896c5a2d8c5SRyan Moeller error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len, 897c5a2d8c5SRyan Moeller addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 898b8e20e2dSHiroki Sato if (error) 899c5a2d8c5SRyan Moeller errx(1, "cap_getnameinfo()"); 900b8e20e2dSHiroki Sato } 901ca007d91SDag-Erling Smørgrav if (port == 0) 902ca007d91SDag-Erling Smørgrav return xprintf("%s:*", addrstr); 903ca007d91SDag-Erling Smørgrav else 904ca007d91SDag-Erling Smørgrav return xprintf("%s:%d", addrstr, port); 905ca007d91SDag-Erling Smørgrav } 906ca007d91SDag-Erling Smørgrav 907ca007d91SDag-Erling Smørgrav static const char * 908ca007d91SDag-Erling Smørgrav getprocname(pid_t pid) 909ca007d91SDag-Erling Smørgrav { 910ca007d91SDag-Erling Smørgrav static struct kinfo_proc proc; 911ca007d91SDag-Erling Smørgrav size_t len; 912ca007d91SDag-Erling Smørgrav int mib[4]; 913ca007d91SDag-Erling Smørgrav 914ca007d91SDag-Erling Smørgrav mib[0] = CTL_KERN; 915ca007d91SDag-Erling Smørgrav mib[1] = KERN_PROC; 916ca007d91SDag-Erling Smørgrav mib[2] = KERN_PROC_PID; 917ca007d91SDag-Erling Smørgrav mib[3] = (int)pid; 918b8e20e2dSHiroki Sato len = sizeof(proc); 919c5a2d8c5SRyan Moeller if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0) 920c5a2d8c5SRyan Moeller == -1) { 92148c513e0SMaxim Konovalov /* Do not warn if the process exits before we get its name. */ 92248c513e0SMaxim Konovalov if (errno != ESRCH) 923c5a2d8c5SRyan Moeller warn("cap_sysctl()"); 924ca007d91SDag-Erling Smørgrav return ("??"); 925ca007d91SDag-Erling Smørgrav } 926f487a6a8SEd Maste return (proc.ki_comm); 927ca007d91SDag-Erling Smørgrav } 928ca007d91SDag-Erling Smørgrav 929ae94787dSMaxime Henrion static int 93000feaafdSAndrew Thompson getprocjid(pid_t pid) 93100feaafdSAndrew Thompson { 93200feaafdSAndrew Thompson static struct kinfo_proc proc; 93300feaafdSAndrew Thompson size_t len; 93400feaafdSAndrew Thompson int mib[4]; 93500feaafdSAndrew Thompson 93600feaafdSAndrew Thompson mib[0] = CTL_KERN; 93700feaafdSAndrew Thompson mib[1] = KERN_PROC; 93800feaafdSAndrew Thompson mib[2] = KERN_PROC_PID; 93900feaafdSAndrew Thompson mib[3] = (int)pid; 940b8e20e2dSHiroki Sato len = sizeof(proc); 941c5a2d8c5SRyan Moeller if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0) 942c5a2d8c5SRyan Moeller == -1) { 94300feaafdSAndrew Thompson /* Do not warn if the process exits before we get its jid. */ 94400feaafdSAndrew Thompson if (errno != ESRCH) 945c5a2d8c5SRyan Moeller warn("cap_sysctl()"); 94600feaafdSAndrew Thompson return (-1); 94700feaafdSAndrew Thompson } 94800feaafdSAndrew Thompson return (proc.ki_jid); 94900feaafdSAndrew Thompson } 95000feaafdSAndrew Thompson 95100feaafdSAndrew Thompson static int 952ae94787dSMaxime Henrion check_ports(struct sock *s) 953ae94787dSMaxime Henrion { 954ae94787dSMaxime Henrion int port; 955e6f718c7SMichael Tuexen struct addr *addr; 956ae94787dSMaxime Henrion 957ae94787dSMaxime Henrion if (ports == NULL) 958ae94787dSMaxime Henrion return (1); 959ae94787dSMaxime Henrion if ((s->family != AF_INET) && (s->family != AF_INET6)) 960ae94787dSMaxime Henrion return (1); 961e6f718c7SMichael Tuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 962b8e20e2dSHiroki Sato if (s->family == AF_INET) 963b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 964ae94787dSMaxime Henrion else 965b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 966ae94787dSMaxime Henrion if (CHK_PORT(port)) 967ae94787dSMaxime Henrion return (1); 968e6f718c7SMichael Tuexen } 969e6f718c7SMichael Tuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 970b8e20e2dSHiroki Sato if (s->family == AF_INET) 971b8e20e2dSHiroki Sato port = ntohs(sstosin(&addr->address)->sin_port); 972ae94787dSMaxime Henrion else 973b8e20e2dSHiroki Sato port = ntohs(sstosin6(&addr->address)->sin6_port); 974ae94787dSMaxime Henrion if (CHK_PORT(port)) 975ae94787dSMaxime Henrion return (1); 976e6f718c7SMichael Tuexen } 977ae94787dSMaxime Henrion return (0); 978ae94787dSMaxime Henrion } 979ae94787dSMaxime Henrion 9806414db1bSMichael Tuexen static const char * 981e389705eSMichael Tuexen sctp_conn_state(int state) 9826414db1bSMichael Tuexen { 9836414db1bSMichael Tuexen switch (state) { 9846414db1bSMichael Tuexen case SCTP_CLOSED: 9856414db1bSMichael Tuexen return "CLOSED"; 9866414db1bSMichael Tuexen break; 9876414db1bSMichael Tuexen case SCTP_BOUND: 9886414db1bSMichael Tuexen return "BOUND"; 9896414db1bSMichael Tuexen break; 9906414db1bSMichael Tuexen case SCTP_LISTEN: 9916414db1bSMichael Tuexen return "LISTEN"; 9926414db1bSMichael Tuexen break; 9936414db1bSMichael Tuexen case SCTP_COOKIE_WAIT: 9946414db1bSMichael Tuexen return "COOKIE_WAIT"; 9956414db1bSMichael Tuexen break; 9966414db1bSMichael Tuexen case SCTP_COOKIE_ECHOED: 9976414db1bSMichael Tuexen return "COOKIE_ECHOED"; 9986414db1bSMichael Tuexen break; 9996414db1bSMichael Tuexen case SCTP_ESTABLISHED: 10006414db1bSMichael Tuexen return "ESTABLISHED"; 10016414db1bSMichael Tuexen break; 10026414db1bSMichael Tuexen case SCTP_SHUTDOWN_SENT: 10036414db1bSMichael Tuexen return "SHUTDOWN_SENT"; 10046414db1bSMichael Tuexen break; 10056414db1bSMichael Tuexen case SCTP_SHUTDOWN_RECEIVED: 10066414db1bSMichael Tuexen return "SHUTDOWN_RECEIVED"; 10076414db1bSMichael Tuexen break; 10086414db1bSMichael Tuexen case SCTP_SHUTDOWN_ACK_SENT: 10096414db1bSMichael Tuexen return "SHUTDOWN_ACK_SENT"; 10106414db1bSMichael Tuexen break; 10116414db1bSMichael Tuexen case SCTP_SHUTDOWN_PENDING: 10126414db1bSMichael Tuexen return "SHUTDOWN_PENDING"; 10136414db1bSMichael Tuexen break; 10146414db1bSMichael Tuexen default: 10156414db1bSMichael Tuexen return "UNKNOWN"; 10166414db1bSMichael Tuexen break; 10176414db1bSMichael Tuexen } 10186414db1bSMichael Tuexen } 10196414db1bSMichael Tuexen 1020e389705eSMichael Tuexen static const char * 1021e389705eSMichael Tuexen sctp_path_state(int state) 1022e389705eSMichael Tuexen { 1023e389705eSMichael Tuexen switch (state) { 1024e389705eSMichael Tuexen case SCTP_UNCONFIRMED: 1025e389705eSMichael Tuexen return "UNCONFIRMED"; 1026e389705eSMichael Tuexen break; 1027e389705eSMichael Tuexen case SCTP_ACTIVE: 1028e389705eSMichael Tuexen return "ACTIVE"; 1029e389705eSMichael Tuexen break; 1030e389705eSMichael Tuexen case SCTP_INACTIVE: 1031e389705eSMichael Tuexen return "INACTIVE"; 1032e389705eSMichael Tuexen break; 1033e389705eSMichael Tuexen default: 1034e389705eSMichael Tuexen return "UNKNOWN"; 1035e389705eSMichael Tuexen break; 1036e389705eSMichael Tuexen } 1037e389705eSMichael Tuexen } 1038e389705eSMichael Tuexen 1039ca007d91SDag-Erling Smørgrav static void 104061149f8dSJilles Tjoelker displaysock(struct sock *s, int pos) 1041ca007d91SDag-Erling Smørgrav { 1042f38b68aeSBrooks Davis kvaddr_t p; 104349b836f2SMichael Tuexen int hash, first, offset; 1044e6f718c7SMichael Tuexen struct addr *laddr, *faddr; 104581091202SMichael Tuexen struct sock *s_tmp; 1046ca007d91SDag-Erling Smørgrav 1047ca007d91SDag-Erling Smørgrav while (pos < 29) 1048ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 1049ca007d91SDag-Erling Smørgrav pos += xprintf("%s", s->protoname); 1050ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV4) 1051ca007d91SDag-Erling Smørgrav pos += xprintf("4"); 1052ca007d91SDag-Erling Smørgrav if (s->vflag & INP_IPV6) 1053ca007d91SDag-Erling Smørgrav pos += xprintf("6"); 1054edc9c7fcSMichael Tuexen if (s->vflag & (INP_IPV4 | INP_IPV6)) 1055edc9c7fcSMichael Tuexen pos += xprintf(" "); 1056e6f718c7SMichael Tuexen laddr = s->laddr; 1057e6f718c7SMichael Tuexen faddr = s->faddr; 10584e13a5b0SMichael Tuexen first = 1; 1059e6f718c7SMichael Tuexen while (laddr != NULL || faddr != NULL) { 106083f60cb2SMichael Tuexen offset = 36; 106183f60cb2SMichael Tuexen while (pos < offset) 1062ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 1063ca007d91SDag-Erling Smørgrav switch (s->family) { 1064ca007d91SDag-Erling Smørgrav case AF_INET: 1065ca007d91SDag-Erling Smørgrav case AF_INET6: 1066e6f718c7SMichael Tuexen if (laddr != NULL) { 1067e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 106809bbda21SMaxim Konovalov if (s->family == AF_INET6 && pos >= 58) 106909bbda21SMaxim Konovalov pos += xprintf(" "); 1070e6f718c7SMichael Tuexen } 107183f60cb2SMichael Tuexen offset += opt_w ? 46 : 22; 107283f60cb2SMichael Tuexen while (pos < offset) 1073ca007d91SDag-Erling Smørgrav pos += xprintf(" "); 1074e6f718c7SMichael Tuexen if (faddr != NULL) 1075e6f718c7SMichael Tuexen pos += printaddr(&faddr->address); 107683f60cb2SMichael Tuexen offset += opt_w ? 46 : 22; 1077ca007d91SDag-Erling Smørgrav break; 1078ca007d91SDag-Erling Smørgrav case AF_UNIX: 1079e6f718c7SMichael Tuexen if ((laddr == NULL) || (faddr == NULL)) 1080e6f718c7SMichael Tuexen errx(1, "laddr = %p or faddr = %p is NULL", 1081e6f718c7SMichael Tuexen (void *)laddr, (void *)faddr); 1082ca007d91SDag-Erling Smørgrav /* server */ 1083e6f718c7SMichael Tuexen if (laddr->address.ss_len > 0) { 1084e6f718c7SMichael Tuexen pos += printaddr(&laddr->address); 1085ca007d91SDag-Erling Smørgrav break; 1086ca007d91SDag-Erling Smørgrav } 1087ca007d91SDag-Erling Smørgrav /* client */ 1088f38b68aeSBrooks Davis p = *(kvaddr_t*)&(faddr->address); 1089f38b68aeSBrooks Davis if (p == 0) { 1090b4eb37c6SJohn-Mark Gurney pos += xprintf("(not connected)"); 109183f60cb2SMichael Tuexen offset += opt_w ? 92 : 44; 1092b4eb37c6SJohn-Mark Gurney break; 1093b4eb37c6SJohn-Mark Gurney } 1094b4eb37c6SJohn-Mark Gurney pos += xprintf("-> "); 1095ca007d91SDag-Erling Smørgrav for (hash = 0; hash < HASHSIZE; ++hash) { 109681091202SMichael Tuexen for (s_tmp = sockhash[hash]; 109781091202SMichael Tuexen s_tmp != NULL; 109881091202SMichael Tuexen s_tmp = s_tmp->next) 109981091202SMichael Tuexen if (s_tmp->pcb == p) 1100ca007d91SDag-Erling Smørgrav break; 110181091202SMichael Tuexen if (s_tmp != NULL) 1102ca007d91SDag-Erling Smørgrav break; 1103ca007d91SDag-Erling Smørgrav } 110427569d01SRenato Botelho if (s_tmp == NULL || s_tmp->laddr == NULL || 110581091202SMichael Tuexen s_tmp->laddr->address.ss_len == 0) 1106ca007d91SDag-Erling Smørgrav pos += xprintf("??"); 1107ca007d91SDag-Erling Smørgrav else 110881091202SMichael Tuexen pos += printaddr(&s_tmp->laddr->address); 110983f60cb2SMichael Tuexen offset += opt_w ? 92 : 44; 1110ca007d91SDag-Erling Smørgrav break; 1111ca007d91SDag-Erling Smørgrav default: 1112ca007d91SDag-Erling Smørgrav abort(); 1113ca007d91SDag-Erling Smørgrav } 1114*5f64777aSMichael Tuexen if (opt_i) { 1115*5f64777aSMichael Tuexen if (s->proto == IPPROTO_TCP || 1116*5f64777aSMichael Tuexen s->proto == IPPROTO_UDP) { 1117*5f64777aSMichael Tuexen while (pos < offset) 1118*5f64777aSMichael Tuexen pos += xprintf(" "); 1119*5f64777aSMichael Tuexen pos += xprintf("%" PRIu64, s->inp_gencnt); 1120*5f64777aSMichael Tuexen } 1121*5f64777aSMichael Tuexen offset += 9; 1122*5f64777aSMichael Tuexen } 112349b836f2SMichael Tuexen if (opt_U) { 112449b836f2SMichael Tuexen if (faddr != NULL && 11259e644c23SMichael Tuexen ((s->proto == IPPROTO_SCTP && 112649b836f2SMichael Tuexen s->state != SCTP_CLOSED && 112749b836f2SMichael Tuexen s->state != SCTP_BOUND && 11289e644c23SMichael Tuexen s->state != SCTP_LISTEN) || 11299e644c23SMichael Tuexen (s->proto == IPPROTO_TCP && 11309e644c23SMichael Tuexen s->state != TCPS_CLOSED && 11319e644c23SMichael Tuexen s->state != TCPS_LISTEN))) { 113249b836f2SMichael Tuexen while (pos < offset) 113349b836f2SMichael Tuexen pos += xprintf(" "); 113449b836f2SMichael Tuexen pos += xprintf("%u", 113549b836f2SMichael Tuexen ntohs(faddr->encaps_port)); 113649b836f2SMichael Tuexen } 113749b836f2SMichael Tuexen offset += 7; 113849b836f2SMichael Tuexen } 1139e389705eSMichael Tuexen if (opt_s) { 1140e389705eSMichael Tuexen if (faddr != NULL && 1141e389705eSMichael Tuexen s->proto == IPPROTO_SCTP && 1142e389705eSMichael Tuexen s->state != SCTP_CLOSED && 1143e389705eSMichael Tuexen s->state != SCTP_BOUND && 1144e389705eSMichael Tuexen s->state != SCTP_LISTEN) { 1145e389705eSMichael Tuexen while (pos < offset) 1146e389705eSMichael Tuexen pos += xprintf(" "); 1147e389705eSMichael Tuexen pos += xprintf("%s", 1148e389705eSMichael Tuexen sctp_path_state(faddr->state)); 1149e389705eSMichael Tuexen } 1150e389705eSMichael Tuexen offset += 13; 1151e389705eSMichael Tuexen } 1152e5cccc35SMichael Tuexen if (first) { 115349b836f2SMichael Tuexen if (opt_s) { 115449b836f2SMichael Tuexen if (s->proto == IPPROTO_SCTP || 115549b836f2SMichael Tuexen s->proto == IPPROTO_TCP) { 115649b836f2SMichael Tuexen while (pos < offset) 11574e13a5b0SMichael Tuexen pos += xprintf(" "); 11586414db1bSMichael Tuexen switch (s->proto) { 11596414db1bSMichael Tuexen case IPPROTO_SCTP: 1160e5cccc35SMichael Tuexen pos += xprintf("%s", 1161e389705eSMichael Tuexen sctp_conn_state(s->state)); 11626414db1bSMichael Tuexen break; 11636414db1bSMichael Tuexen case IPPROTO_TCP: 1164e5cccc35SMichael Tuexen if (s->state >= 0 && 1165e5cccc35SMichael Tuexen s->state < TCP_NSTATES) 116649b836f2SMichael Tuexen pos += xprintf("%s", 1167e5cccc35SMichael Tuexen tcpstates[s->state]); 11684e13a5b0SMichael Tuexen else 11694e13a5b0SMichael Tuexen pos += xprintf("?"); 11706414db1bSMichael Tuexen break; 11716414db1bSMichael Tuexen } 11724e13a5b0SMichael Tuexen } 117349b836f2SMichael Tuexen offset += 13; 117449b836f2SMichael Tuexen } 11752ac089d0SMichael Tuexen if (opt_S) { 11762ac089d0SMichael Tuexen if (s->proto == IPPROTO_TCP) { 117749b836f2SMichael Tuexen while (pos < offset) 1178e5cccc35SMichael Tuexen pos += xprintf(" "); 11792ac089d0SMichael Tuexen pos += xprintf("%.*s", 11802ac089d0SMichael Tuexen TCP_FUNCTION_NAME_LEN_MAX, 1181e5cccc35SMichael Tuexen s->stack); 1182e5cccc35SMichael Tuexen } 11832ac089d0SMichael Tuexen offset += TCP_FUNCTION_NAME_LEN_MAX + 1; 11842ac089d0SMichael Tuexen } 11852ac089d0SMichael Tuexen if (opt_C) { 11862ac089d0SMichael Tuexen if (s->proto == IPPROTO_TCP) { 11872ac089d0SMichael Tuexen while (pos < offset) 11882ac089d0SMichael Tuexen pos += xprintf(" "); 11892ac089d0SMichael Tuexen xprintf("%.*s", TCP_CA_NAME_MAX, s->cc); 11902ac089d0SMichael Tuexen } 11912ac089d0SMichael Tuexen offset += TCP_CA_NAME_MAX + 1; 11922ac089d0SMichael Tuexen } 1193e5cccc35SMichael Tuexen } 1194e6f718c7SMichael Tuexen if (laddr != NULL) 1195e6f718c7SMichael Tuexen laddr = laddr->next; 1196e6f718c7SMichael Tuexen if (faddr != NULL) 1197e6f718c7SMichael Tuexen faddr = faddr->next; 1198e6f718c7SMichael Tuexen if ((laddr != NULL) || (faddr != NULL)) { 1199e6f718c7SMichael Tuexen xprintf("\n"); 1200e6f718c7SMichael Tuexen pos = 0; 1201e6f718c7SMichael Tuexen } 12024e13a5b0SMichael Tuexen first = 0; 1203e6f718c7SMichael Tuexen } 12044e13a5b0SMichael Tuexen xprintf("\n"); 1205ca007d91SDag-Erling Smørgrav } 120661149f8dSJilles Tjoelker 120761149f8dSJilles Tjoelker static void 120861149f8dSJilles Tjoelker display(void) 120961149f8dSJilles Tjoelker { 121061149f8dSJilles Tjoelker struct passwd *pwd; 121161149f8dSJilles Tjoelker struct xfile *xf; 121261149f8dSJilles Tjoelker struct sock *s; 121361149f8dSJilles Tjoelker int hash, n, pos; 121461149f8dSJilles Tjoelker 1215ee0afaa9SEmmanuel Vadot if (opt_q != 1) { 121683f60cb2SMichael Tuexen printf("%-8s %-10s %-5s %-2s %-6s %-*s %-*s", 121761149f8dSJilles Tjoelker "USER", "COMMAND", "PID", "FD", "PROTO", 121883f60cb2SMichael Tuexen opt_w ? 45 : 21, "LOCAL ADDRESS", 121983f60cb2SMichael Tuexen opt_w ? 45 : 21, "FOREIGN ADDRESS"); 1220*5f64777aSMichael Tuexen if (opt_i) 1221*5f64777aSMichael Tuexen printf(" %-8s", "ID"); 122249b836f2SMichael Tuexen if (opt_U) 122349b836f2SMichael Tuexen printf(" %-6s", "ENCAPS"); 1224e389705eSMichael Tuexen if (opt_s) { 1225e389705eSMichael Tuexen printf(" %-12s", "PATH STATE"); 1226e389705eSMichael Tuexen printf(" %-12s", "CONN STATE"); 1227e389705eSMichael Tuexen } 1228e5cccc35SMichael Tuexen if (opt_S) 12292ac089d0SMichael Tuexen printf(" %-*.*s", TCP_FUNCTION_NAME_LEN_MAX, 12302ac089d0SMichael Tuexen TCP_FUNCTION_NAME_LEN_MAX, "STACK"); 12312ac089d0SMichael Tuexen if (opt_C) 12322ac089d0SMichael Tuexen printf(" %-.*s", TCP_CA_NAME_MAX, "CC"); 12337a5642b3SDag-Erling Smørgrav printf("\n"); 1234ee0afaa9SEmmanuel Vadot } 12357ad30f58SMariusz Zaborski cap_setpassent(cappwd, 1); 123661149f8dSJilles Tjoelker for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 1237f38b68aeSBrooks Davis if (xf->xf_data == 0) 123861149f8dSJilles Tjoelker continue; 123900feaafdSAndrew Thompson if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 124000feaafdSAndrew Thompson continue; 124161149f8dSJilles Tjoelker hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 12427e80c6b0SMichael Tuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 1243f38b68aeSBrooks Davis if (s->socket != xf->xf_data) 124461149f8dSJilles Tjoelker continue; 124561149f8dSJilles Tjoelker if (!check_ports(s)) 124661149f8dSJilles Tjoelker continue; 124761149f8dSJilles Tjoelker s->shown = 1; 124861149f8dSJilles Tjoelker pos = 0; 12497ad30f58SMariusz Zaborski if (opt_n || 12507ad30f58SMariusz Zaborski (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL) 125161149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_uid); 125261149f8dSJilles Tjoelker else 125361149f8dSJilles Tjoelker pos += xprintf("%s ", pwd->pw_name); 125461149f8dSJilles Tjoelker while (pos < 9) 125561149f8dSJilles Tjoelker pos += xprintf(" "); 125661149f8dSJilles Tjoelker pos += xprintf("%.10s", getprocname(xf->xf_pid)); 125761149f8dSJilles Tjoelker while (pos < 20) 125861149f8dSJilles Tjoelker pos += xprintf(" "); 125961149f8dSJilles Tjoelker pos += xprintf("%lu ", (u_long)xf->xf_pid); 126061149f8dSJilles Tjoelker while (pos < 26) 126161149f8dSJilles Tjoelker pos += xprintf(" "); 126261149f8dSJilles Tjoelker pos += xprintf("%d ", xf->xf_fd); 126361149f8dSJilles Tjoelker displaysock(s, pos); 126461149f8dSJilles Tjoelker } 12657e80c6b0SMichael Tuexen } 126600feaafdSAndrew Thompson if (opt_j >= 0) 126700feaafdSAndrew Thompson return; 126861149f8dSJilles Tjoelker for (hash = 0; hash < HASHSIZE; hash++) { 126961149f8dSJilles Tjoelker for (s = sockhash[hash]; s != NULL; s = s->next) { 127061149f8dSJilles Tjoelker if (s->shown) 127161149f8dSJilles Tjoelker continue; 127261149f8dSJilles Tjoelker if (!check_ports(s)) 127361149f8dSJilles Tjoelker continue; 127461149f8dSJilles Tjoelker pos = 0; 127561149f8dSJilles Tjoelker pos += xprintf("%-8s %-10s %-5s %-2s ", 127661149f8dSJilles Tjoelker "?", "?", "?", "?"); 127761149f8dSJilles Tjoelker displaysock(s, pos); 127861149f8dSJilles Tjoelker } 127961149f8dSJilles Tjoelker } 1280ca007d91SDag-Erling Smørgrav } 1281ca007d91SDag-Erling Smørgrav 1282f1cd4902SRyan Moeller static int 1283f1cd4902SRyan Moeller set_default_protos(void) 12841f3d67aaSGiorgos Keramidas { 12851f3d67aaSGiorgos Keramidas struct protoent *prot; 12861f3d67aaSGiorgos Keramidas const char *pname; 12871f3d67aaSGiorgos Keramidas size_t pindex; 12881f3d67aaSGiorgos Keramidas 12891f3d67aaSGiorgos Keramidas init_protos(default_numprotos); 12901f3d67aaSGiorgos Keramidas 12911f3d67aaSGiorgos Keramidas for (pindex = 0; pindex < default_numprotos; pindex++) { 12921f3d67aaSGiorgos Keramidas pname = default_protos[pindex]; 1293c5a2d8c5SRyan Moeller prot = cap_getprotobyname(capnetdb, pname); 12941f3d67aaSGiorgos Keramidas if (prot == NULL) 1295c5a2d8c5SRyan Moeller err(1, "cap_getprotobyname: %s", pname); 12961f3d67aaSGiorgos Keramidas protos[pindex] = prot->p_proto; 12971f3d67aaSGiorgos Keramidas } 12981f3d67aaSGiorgos Keramidas numprotos = pindex; 12991f3d67aaSGiorgos Keramidas return (pindex); 13001f3d67aaSGiorgos Keramidas } 13011f3d67aaSGiorgos Keramidas 1302f1cd4902SRyan Moeller /* 1303f1cd4902SRyan Moeller * Return the vnet property of the jail, or -1 on error. 1304f1cd4902SRyan Moeller */ 1305f1cd4902SRyan Moeller static int 1306f1cd4902SRyan Moeller jail_getvnet(int jid) 1307f1cd4902SRyan Moeller { 1308f1cd4902SRyan Moeller struct iovec jiov[6]; 1309f1cd4902SRyan Moeller int vnet; 13101fec1fa8SGleb Smirnoff size_t len = sizeof(vnet); 13111fec1fa8SGleb Smirnoff 13121fec1fa8SGleb Smirnoff if (sysctlbyname("kern.features.vimage", &vnet, &len, NULL, 0) != 0) 13131fec1fa8SGleb Smirnoff return (0); 1314f1cd4902SRyan Moeller 1315f1cd4902SRyan Moeller vnet = -1; 1316f1cd4902SRyan Moeller jiov[0].iov_base = __DECONST(char *, "jid"); 1317f1cd4902SRyan Moeller jiov[0].iov_len = sizeof("jid"); 1318f1cd4902SRyan Moeller jiov[1].iov_base = &jid; 1319f1cd4902SRyan Moeller jiov[1].iov_len = sizeof(jid); 1320f1cd4902SRyan Moeller jiov[2].iov_base = __DECONST(char *, "vnet"); 1321f1cd4902SRyan Moeller jiov[2].iov_len = sizeof("vnet"); 1322f1cd4902SRyan Moeller jiov[3].iov_base = &vnet; 1323f1cd4902SRyan Moeller jiov[3].iov_len = sizeof(vnet); 1324f1cd4902SRyan Moeller jiov[4].iov_base = __DECONST(char *, "errmsg"); 1325f1cd4902SRyan Moeller jiov[4].iov_len = sizeof("errmsg"); 1326f1cd4902SRyan Moeller jiov[5].iov_base = jail_errmsg; 1327f1cd4902SRyan Moeller jiov[5].iov_len = JAIL_ERRMSGLEN; 1328f1cd4902SRyan Moeller jail_errmsg[0] = '\0'; 1329f1cd4902SRyan Moeller if (jail_get(jiov, nitems(jiov), 0) < 0) { 1330f1cd4902SRyan Moeller if (!jail_errmsg[0]) 1331f1cd4902SRyan Moeller snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1332f1cd4902SRyan Moeller "jail_get: %s", strerror(errno)); 1333f1cd4902SRyan Moeller return (-1); 1334f1cd4902SRyan Moeller } 1335f1cd4902SRyan Moeller return (vnet); 1336f1cd4902SRyan Moeller } 1337f1cd4902SRyan Moeller 1338ca007d91SDag-Erling Smørgrav static void 1339ca007d91SDag-Erling Smørgrav usage(void) 1340ca007d91SDag-Erling Smørgrav { 13411f3d67aaSGiorgos Keramidas fprintf(stderr, 1342*5f64777aSMichael Tuexen "usage: sockstat [-46ciLlSsUuvw] [-j jid] [-p ports] [-P protocols]\n"); 1343ca007d91SDag-Erling Smørgrav exit(1); 1344ca007d91SDag-Erling Smørgrav } 1345ca007d91SDag-Erling Smørgrav 1346ca007d91SDag-Erling Smørgrav int 1347ca007d91SDag-Erling Smørgrav main(int argc, char *argv[]) 1348ca007d91SDag-Erling Smørgrav { 1349c5a2d8c5SRyan Moeller cap_channel_t *capcas; 1350c5a2d8c5SRyan Moeller cap_net_limit_t *limit; 13517ad30f58SMariusz Zaborski const char *pwdcmds[] = { "setpassent", "getpwuid" }; 13527ad30f58SMariusz Zaborski const char *pwdfields[] = { "pw_name" }; 13531f3d67aaSGiorgos Keramidas int protos_defined = -1; 13541f3d67aaSGiorgos Keramidas int o, i; 1355ca007d91SDag-Erling Smørgrav 135600feaafdSAndrew Thompson opt_j = -1; 1357*5f64777aSMichael Tuexen while ((o = getopt(argc, argv, "46Ccij:Llnp:P:qSsUuvw")) != -1) 1358ca007d91SDag-Erling Smørgrav switch (o) { 1359ca007d91SDag-Erling Smørgrav case '4': 1360ca007d91SDag-Erling Smørgrav opt_4 = 1; 1361ca007d91SDag-Erling Smørgrav break; 1362ca007d91SDag-Erling Smørgrav case '6': 1363ca007d91SDag-Erling Smørgrav opt_6 = 1; 1364ca007d91SDag-Erling Smørgrav break; 13652ac089d0SMichael Tuexen case 'C': 13662ac089d0SMichael Tuexen opt_C = 1; 13672ac089d0SMichael Tuexen break; 1368ca007d91SDag-Erling Smørgrav case 'c': 1369ca007d91SDag-Erling Smørgrav opt_c = 1; 1370ca007d91SDag-Erling Smørgrav break; 1371*5f64777aSMichael Tuexen case 'i': 1372*5f64777aSMichael Tuexen opt_i = 1; 1373*5f64777aSMichael Tuexen break; 137400feaafdSAndrew Thompson case 'j': 1375de68a320SJamie Gritton opt_j = jail_getid(optarg); 1376de68a320SJamie Gritton if (opt_j < 0) 137732723a3bSGleb Smirnoff errx(1, "jail_getid: %s", jail_errmsg); 137800feaafdSAndrew Thompson break; 13799b6ca892SBruce M Simpson case 'L': 13809b6ca892SBruce M Simpson opt_L = 1; 13819b6ca892SBruce M Simpson break; 1382ca007d91SDag-Erling Smørgrav case 'l': 1383ca007d91SDag-Erling Smørgrav opt_l = 1; 1384ca007d91SDag-Erling Smørgrav break; 1385ccdd2b2bSAlexander Motin case 'n': 1386ccdd2b2bSAlexander Motin opt_n = 1; 1387ccdd2b2bSAlexander Motin break; 1388ca007d91SDag-Erling Smørgrav case 'p': 1389ca007d91SDag-Erling Smørgrav parse_ports(optarg); 1390ca007d91SDag-Erling Smørgrav break; 13911f3d67aaSGiorgos Keramidas case 'P': 13921f3d67aaSGiorgos Keramidas protos_defined = parse_protos(optarg); 13931f3d67aaSGiorgos Keramidas break; 1394ee0afaa9SEmmanuel Vadot case 'q': 1395ee0afaa9SEmmanuel Vadot opt_q = 1; 139662de7037SEmmanuel Vadot break; 1397e5cccc35SMichael Tuexen case 'S': 1398e5cccc35SMichael Tuexen opt_S = 1; 1399e5cccc35SMichael Tuexen break; 14007a5642b3SDag-Erling Smørgrav case 's': 14017a5642b3SDag-Erling Smørgrav opt_s = 1; 14027a5642b3SDag-Erling Smørgrav break; 140349b836f2SMichael Tuexen case 'U': 140449b836f2SMichael Tuexen opt_U = 1; 140549b836f2SMichael Tuexen break; 1406ca007d91SDag-Erling Smørgrav case 'u': 1407ca007d91SDag-Erling Smørgrav opt_u = 1; 1408ca007d91SDag-Erling Smørgrav break; 1409ca007d91SDag-Erling Smørgrav case 'v': 1410ca007d91SDag-Erling Smørgrav ++opt_v; 1411ca007d91SDag-Erling Smørgrav break; 141283f60cb2SMichael Tuexen case 'w': 141383f60cb2SMichael Tuexen opt_w = 1; 141483f60cb2SMichael Tuexen break; 1415ca007d91SDag-Erling Smørgrav default: 1416ca007d91SDag-Erling Smørgrav usage(); 1417ca007d91SDag-Erling Smørgrav } 1418ca007d91SDag-Erling Smørgrav 1419ca007d91SDag-Erling Smørgrav argc -= optind; 1420ca007d91SDag-Erling Smørgrav argv += optind; 1421ca007d91SDag-Erling Smørgrav 1422ca007d91SDag-Erling Smørgrav if (argc > 0) 1423ca007d91SDag-Erling Smørgrav usage(); 1424ca007d91SDag-Erling Smørgrav 1425f1cd4902SRyan Moeller if (opt_j > 0) { 1426f1cd4902SRyan Moeller switch (jail_getvnet(opt_j)) { 1427f1cd4902SRyan Moeller case -1: 142832723a3bSGleb Smirnoff errx(2, "jail_getvnet: %s", jail_errmsg); 1429f1cd4902SRyan Moeller case JAIL_SYS_NEW: 1430f1cd4902SRyan Moeller if (jail_attach(opt_j) < 0) 1431ae37905bSRyan Moeller err(3, "jail_attach()"); 1432f1cd4902SRyan Moeller /* Set back to -1 for normal output in vnet jail. */ 1433f1cd4902SRyan Moeller opt_j = -1; 1434f1cd4902SRyan Moeller break; 1435f1cd4902SRyan Moeller default: 1436f1cd4902SRyan Moeller break; 1437f1cd4902SRyan Moeller } 1438f1cd4902SRyan Moeller } 1439f1cd4902SRyan Moeller 1440c5a2d8c5SRyan Moeller capcas = cap_init(); 1441c5a2d8c5SRyan Moeller if (capcas == NULL) 1442c5a2d8c5SRyan Moeller err(1, "Unable to contact Casper"); 1443c5a2d8c5SRyan Moeller if (caph_enter_casper() < 0) 1444c5a2d8c5SRyan Moeller err(1, "Unable to enter capability mode"); 1445c5a2d8c5SRyan Moeller capnet = cap_service_open(capcas, "system.net"); 1446c5a2d8c5SRyan Moeller if (capnet == NULL) 1447c5a2d8c5SRyan Moeller err(1, "Unable to open system.net service"); 1448c5a2d8c5SRyan Moeller capnetdb = cap_service_open(capcas, "system.netdb"); 1449c5a2d8c5SRyan Moeller if (capnetdb == NULL) 1450c5a2d8c5SRyan Moeller err(1, "Unable to open system.netdb service"); 1451c5a2d8c5SRyan Moeller capsysctl = cap_service_open(capcas, "system.sysctl"); 1452c5a2d8c5SRyan Moeller if (capsysctl == NULL) 1453c5a2d8c5SRyan Moeller err(1, "Unable to open system.sysctl service"); 14547ad30f58SMariusz Zaborski cappwd = cap_service_open(capcas, "system.pwd"); 14557ad30f58SMariusz Zaborski if (cappwd == NULL) 14567ad30f58SMariusz Zaborski err(1, "Unable to open system.pwd service"); 1457c5a2d8c5SRyan Moeller cap_close(capcas); 1458c5a2d8c5SRyan Moeller limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); 1459c5a2d8c5SRyan Moeller if (limit == NULL) 1460c5a2d8c5SRyan Moeller err(1, "Unable to init cap_net limits"); 1461c5a2d8c5SRyan Moeller if (cap_net_limit(limit) < 0) 1462c5a2d8c5SRyan Moeller err(1, "Unable to apply limits"); 14637ad30f58SMariusz Zaborski if (cap_pwd_limit_cmds(cappwd, pwdcmds, nitems(pwdcmds)) < 0) 14647ad30f58SMariusz Zaborski err(1, "Unable to apply pwd commands limits"); 14657ad30f58SMariusz Zaborski if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0) 14667ad30f58SMariusz Zaborski err(1, "Unable to apply pwd commands limits"); 1467c5a2d8c5SRyan Moeller 1468d2d77d2aSGiorgos Keramidas if ((!opt_4 && !opt_6) && protos_defined != -1) 14691f3d67aaSGiorgos Keramidas opt_4 = opt_6 = 1; 1470d2d77d2aSGiorgos Keramidas if (!opt_4 && !opt_6 && !opt_u) 1471d2d77d2aSGiorgos Keramidas opt_4 = opt_6 = opt_u = 1; 1472d2d77d2aSGiorgos Keramidas if ((opt_4 || opt_6) && protos_defined == -1) 1473d2d77d2aSGiorgos Keramidas protos_defined = set_default_protos(); 1474ca007d91SDag-Erling Smørgrav if (!opt_c && !opt_l) 1475ca007d91SDag-Erling Smørgrav opt_c = opt_l = 1; 1476ca007d91SDag-Erling Smørgrav 1477ca007d91SDag-Erling Smørgrav if (opt_4 || opt_6) { 14781f3d67aaSGiorgos Keramidas for (i = 0; i < protos_defined; i++) 1479d5b4aa90SMichael Tuexen if (protos[i] == IPPROTO_SCTP) 1480d5b4aa90SMichael Tuexen gather_sctp(); 1481d5b4aa90SMichael Tuexen else 14821f3d67aaSGiorgos Keramidas gather_inet(protos[i]); 1483ca007d91SDag-Erling Smørgrav } 14841f3d67aaSGiorgos Keramidas 14851f3d67aaSGiorgos Keramidas if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1486ca007d91SDag-Erling Smørgrav gather_unix(SOCK_STREAM); 1487ca007d91SDag-Erling Smørgrav gather_unix(SOCK_DGRAM); 1488b8e20e2dSHiroki Sato gather_unix(SOCK_SEQPACKET); 1489ca007d91SDag-Erling Smørgrav } 1490ca007d91SDag-Erling Smørgrav getfiles(); 1491ca007d91SDag-Erling Smørgrav display(); 1492ca007d91SDag-Erling Smørgrav exit(0); 1493ca007d91SDag-Erling Smørgrav } 1494