1101043Sdes/*- 2228991Suqs * Copyright (c) 2002 Dag-Erling Co��dan Sm��rgrav 3101043Sdes * All rights reserved. 4101043Sdes * 5101043Sdes * Redistribution and use in source and binary forms, with or without 6101043Sdes * modification, are permitted provided that the following conditions 7101043Sdes * are met: 8101043Sdes * 1. Redistributions of source code must retain the above copyright 9101043Sdes * notice, this list of conditions and the following disclaimer 10101043Sdes * in this position and unchanged. 11101043Sdes * 2. Redistributions in binary form must reproduce the above copyright 12101043Sdes * notice, this list of conditions and the following disclaimer in the 13101043Sdes * documentation and/or other materials provided with the distribution. 14101043Sdes * 3. The name of the author may not be used to endorse or promote products 15101043Sdes * derived from this software without specific prior written permission. 16101043Sdes * 17101043Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18101043Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19101043Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20101043Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21101043Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22101043Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23101043Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24101043Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25101043Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26101043Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27101043Sdes */ 28101043Sdes 29101043Sdes#include <sys/cdefs.h> 30101043Sdes__FBSDID("$FreeBSD: releng/10.3/usr.bin/sockstat/sockstat.c 294232 2016-01-17 18:39:01Z tuexen $"); 31101043Sdes 32101043Sdes#include <sys/param.h> 33101043Sdes#include <sys/socket.h> 34101043Sdes#include <sys/socketvar.h> 35101043Sdes#include <sys/sysctl.h> 36101043Sdes#include <sys/file.h> 37101043Sdes#include <sys/user.h> 38101043Sdes 39101043Sdes#include <sys/un.h> 40101043Sdes#include <sys/unpcb.h> 41101043Sdes 42101163Sdes#include <net/route.h> 43101163Sdes 44101043Sdes#include <netinet/in.h> 45101043Sdes#include <netinet/in_pcb.h> 46284441Stuexen#include <netinet/sctp.h> 47101043Sdes#include <netinet/tcp.h> 48294225Stuexen#define TCPSTATES /* load state names */ 49294225Stuexen#include <netinet/tcp_fsm.h> 50101043Sdes#include <netinet/tcp_seq.h> 51101043Sdes#include <netinet/tcp_var.h> 52101043Sdes#include <arpa/inet.h> 53101043Sdes 54101043Sdes#include <ctype.h> 55101043Sdes#include <err.h> 56101043Sdes#include <errno.h> 57101043Sdes#include <netdb.h> 58101043Sdes#include <pwd.h> 59101043Sdes#include <stdarg.h> 60101043Sdes#include <stdio.h> 61101043Sdes#include <stdlib.h> 62101043Sdes#include <string.h> 63101043Sdes#include <unistd.h> 64101043Sdes 65285826Shrs#define sstosin(ss) ((struct sockaddr_in *)(ss)) 66285826Shrs#define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) 67285826Shrs#define sstosun(ss) ((struct sockaddr_un *)(ss)) 68285826Shrs#define sstosa(ss) ((struct sockaddr *)(ss)) 69285826Shrs 70101043Sdesstatic int opt_4; /* Show IPv4 sockets */ 71101043Sdesstatic int opt_6; /* Show IPv6 sockets */ 72101043Sdesstatic int opt_c; /* Show connected sockets */ 73235870Sthompsastatic int opt_j; /* Show specified jail */ 74179115Sbmsstatic int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 75101043Sdesstatic int opt_l; /* Show listening sockets */ 76294225Stuexenstatic int opt_s; /* Show protocol state if applicable */ 77101043Sdesstatic int opt_u; /* Show Unix domain sockets */ 78101043Sdesstatic int opt_v; /* Verbose mode */ 79101043Sdes 80164201Skeramida/* 81164201Skeramida * Default protocols to use if no -P was defined. 82164201Skeramida */ 83284441Stuexenstatic const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 84285826Shrsstatic size_t default_numprotos = nitems(default_protos); 85164201Skeramida 86164201Skeramidastatic int *protos; /* protocols to use */ 87164201Skeramidastatic size_t numprotos; /* allocated size of protos[] */ 88164201Skeramida 89101043Sdesstatic int *ports; 90101043Sdes 91101043Sdes#define INT_BIT (sizeof(int)*CHAR_BIT) 92101043Sdes#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 93101043Sdes#define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 94101043Sdes 95284441Stuexenstruct addr { 96284441Stuexen struct sockaddr_storage address; 97284441Stuexen struct addr *next; 98284441Stuexen}; 99284441Stuexen 100101043Sdesstruct sock { 101101043Sdes void *socket; 102101043Sdes void *pcb; 103230512Sjilles int shown; 104101043Sdes int vflag; 105101043Sdes int family; 106101043Sdes int proto; 107294225Stuexen int state; 108101043Sdes const char *protoname; 109284441Stuexen struct addr *laddr; 110284441Stuexen struct addr *faddr; 111101043Sdes struct sock *next; 112101043Sdes}; 113101043Sdes 114101043Sdes#define HASHSIZE 1009 115101043Sdesstatic struct sock *sockhash[HASHSIZE]; 116101043Sdes 117101043Sdesstatic struct xfile *xfiles; 118101043Sdesstatic int nxfiles; 119101043Sdes 120101043Sdesstatic int 121101043Sdesxprintf(const char *fmt, ...) 122101043Sdes{ 123101043Sdes va_list ap; 124101043Sdes int len; 125101043Sdes 126101043Sdes va_start(ap, fmt); 127101043Sdes len = vprintf(fmt, ap); 128101043Sdes va_end(ap); 129101043Sdes if (len < 0) 130101043Sdes err(1, "printf()"); 131101043Sdes return (len); 132101043Sdes} 133101043Sdes 134164201Skeramida 135164201Skeramidastatic int 136164201Skeramidaget_proto_type(const char *proto) 137164201Skeramida{ 138164201Skeramida struct protoent *pent; 139164201Skeramida 140164201Skeramida if (strlen(proto) == 0) 141164201Skeramida return (0); 142164201Skeramida pent = getprotobyname(proto); 143164201Skeramida if (pent == NULL) { 144164201Skeramida warn("getprotobyname"); 145164201Skeramida return (-1); 146164201Skeramida } 147164201Skeramida return (pent->p_proto); 148164201Skeramida} 149164201Skeramida 150164201Skeramida 151285826Shrsstatic void 152285826Shrsinit_protos(int num) 153164201Skeramida{ 154164201Skeramida int proto_count = 0; 155164201Skeramida 156164201Skeramida if (num > 0) { 157164201Skeramida proto_count = num; 158164201Skeramida } else { 159164201Skeramida /* Find the maximum number of possible protocols. */ 160164201Skeramida while (getprotoent() != NULL) 161164201Skeramida proto_count++; 162164201Skeramida endprotoent(); 163164201Skeramida } 164164201Skeramida 165164201Skeramida if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 166164201Skeramida err(1, "malloc"); 167164201Skeramida numprotos = proto_count; 168164201Skeramida} 169164201Skeramida 170164201Skeramida 171164201Skeramidastatic int 172164201Skeramidaparse_protos(char *protospec) 173164201Skeramida{ 174164201Skeramida char *prot; 175164201Skeramida int proto_type, proto_index; 176164201Skeramida 177164201Skeramida if (protospec == NULL) 178164201Skeramida return (-1); 179164201Skeramida 180164201Skeramida init_protos(0); 181164201Skeramida proto_index = 0; 182285826Shrs while ((prot = strsep(&protospec, ",")) != NULL) { 183164201Skeramida if (strlen(prot) == 0) 184164201Skeramida continue; 185164201Skeramida proto_type = get_proto_type(prot); 186164201Skeramida if (proto_type != -1) 187164201Skeramida protos[proto_index++] = proto_type; 188164201Skeramida } 189164201Skeramida numprotos = proto_index; 190164201Skeramida return (proto_index); 191164201Skeramida} 192164201Skeramida 193164201Skeramida 194101043Sdesstatic void 195101043Sdesparse_ports(const char *portspec) 196101043Sdes{ 197101043Sdes const char *p, *q; 198101043Sdes int port, end; 199101043Sdes 200101043Sdes if (ports == NULL) 201114853Srobert if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 202101043Sdes err(1, "calloc()"); 203101043Sdes p = portspec; 204101043Sdes while (*p != '\0') { 205101043Sdes if (!isdigit(*p)) 206101043Sdes errx(1, "syntax error in port range"); 207101043Sdes for (q = p; *q != '\0' && isdigit(*q); ++q) 208101043Sdes /* nothing */ ; 209101043Sdes for (port = 0; p < q; ++p) 210101043Sdes port = port * 10 + digittoint(*p); 211101043Sdes if (port < 0 || port > 65535) 212101043Sdes errx(1, "invalid port number"); 213101043Sdes SET_PORT(port); 214101043Sdes switch (*p) { 215101043Sdes case '-': 216101043Sdes ++p; 217101043Sdes break; 218101043Sdes case ',': 219101043Sdes ++p; 220101043Sdes /* fall through */ 221101043Sdes case '\0': 222101043Sdes default: 223101043Sdes continue; 224101043Sdes } 225101043Sdes for (q = p; *q != '\0' && isdigit(*q); ++q) 226101043Sdes /* nothing */ ; 227101043Sdes for (end = 0; p < q; ++p) 228101043Sdes end = end * 10 + digittoint(*p); 229101043Sdes if (end < port || end > 65535) 230101043Sdes errx(1, "invalid port number"); 231101043Sdes while (port++ < end) 232101043Sdes SET_PORT(port); 233101043Sdes if (*p == ',') 234101043Sdes ++p; 235101043Sdes } 236101043Sdes} 237101043Sdes 238101043Sdesstatic void 239285826Shrssockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 240101043Sdes{ 241101043Sdes struct sockaddr_in *sin4; 242101043Sdes struct sockaddr_in6 *sin6; 243101043Sdes 244285826Shrs bzero(ss, sizeof(*ss)); 245101043Sdes switch (af) { 246101043Sdes case AF_INET: 247285826Shrs sin4 = sstosin(ss); 248285826Shrs sin4->sin_len = sizeof(*sin4); 249101043Sdes sin4->sin_family = af; 250101043Sdes sin4->sin_port = port; 251101043Sdes sin4->sin_addr = *(struct in_addr *)addr; 252101043Sdes break; 253101043Sdes case AF_INET6: 254285826Shrs sin6 = sstosin6(ss); 255285826Shrs sin6->sin6_len = sizeof(*sin6); 256101043Sdes sin6->sin6_family = af; 257101043Sdes sin6->sin6_port = port; 258101043Sdes sin6->sin6_addr = *(struct in6_addr *)addr; 259285826Shrs#define s6_addr16 __u6_addr.__u6_addr16 260285826Shrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 261285826Shrs sin6->sin6_scope_id = 262285826Shrs ntohs(sin6->sin6_addr.s6_addr16[1]); 263285826Shrs sin6->sin6_addr.s6_addr16[1] = 0; 264285826Shrs } 265101043Sdes break; 266101043Sdes default: 267101043Sdes abort(); 268101043Sdes } 269101043Sdes} 270101043Sdes 271101043Sdesstatic void 272284694Stuexenfree_socket(struct sock *sock) 273284694Stuexen{ 274284694Stuexen struct addr *cur, *next; 275284694Stuexen 276284694Stuexen cur = sock->laddr; 277284694Stuexen while (cur != NULL) { 278284694Stuexen next = cur->next; 279284694Stuexen free(cur); 280284694Stuexen cur = next; 281284694Stuexen } 282284694Stuexen cur = sock->faddr; 283284694Stuexen while (cur != NULL) { 284284694Stuexen next = cur->next; 285284694Stuexen free(cur); 286284694Stuexen cur = next; 287284694Stuexen } 288284694Stuexen free(sock); 289284694Stuexen} 290284694Stuexen 291284694Stuexenstatic void 292284441Stuexengather_sctp(void) 293284441Stuexen{ 294284441Stuexen struct sock *sock; 295284441Stuexen struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 296284441Stuexen struct xsctp_inpcb *xinpcb; 297284441Stuexen struct xsctp_tcb *xstcb; 298284441Stuexen struct xsctp_raddr *xraddr; 299284441Stuexen struct xsctp_laddr *xladdr; 300284441Stuexen const char *varname; 301284441Stuexen size_t len, offset; 302284441Stuexen char *buf; 303284441Stuexen int hash, vflag; 304284441Stuexen int no_stcb, local_all_loopback, foreign_all_loopback; 305284441Stuexen 306284441Stuexen vflag = 0; 307284441Stuexen if (opt_4) 308284441Stuexen vflag |= INP_IPV4; 309284441Stuexen if (opt_6) 310284441Stuexen vflag |= INP_IPV6; 311284441Stuexen 312284441Stuexen varname = "net.inet.sctp.assoclist"; 313284441Stuexen if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { 314284441Stuexen if (errno != ENOENT) 315284441Stuexen err(1, "sysctlbyname()"); 316284441Stuexen return; 317284441Stuexen } 318284441Stuexen if ((buf = (char *)malloc(len)) == NULL) { 319284441Stuexen err(1, "malloc()"); 320284441Stuexen return; 321284441Stuexen } 322284441Stuexen if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { 323284441Stuexen err(1, "sysctlbyname()"); 324284441Stuexen free(buf); 325284441Stuexen return; 326284441Stuexen } 327284441Stuexen xinpcb = (struct xsctp_inpcb *)(void *)buf; 328284441Stuexen offset = sizeof(struct xsctp_inpcb); 329284441Stuexen while ((offset < len) && (xinpcb->last == 0)) { 330284441Stuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 331284441Stuexen err(1, "malloc()"); 332284441Stuexen sock->socket = xinpcb->socket; 333284441Stuexen sock->proto = IPPROTO_SCTP; 334284441Stuexen sock->protoname = "sctp"; 335294232Stuexen if (xinpcb->maxqlen == 0) 336294231Stuexen sock->state = SCTP_CLOSED; 337294231Stuexen else 338294231Stuexen sock->state = SCTP_LISTEN; 339284441Stuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 340284441Stuexen sock->family = AF_INET6; 341284441Stuexen sock->vflag = INP_IPV6; 342284441Stuexen } else { 343284441Stuexen sock->family = AF_INET; 344284441Stuexen sock->vflag = INP_IPV4; 345284441Stuexen } 346284441Stuexen prev_laddr = NULL; 347284441Stuexen local_all_loopback = 1; 348284441Stuexen while (offset < len) { 349284441Stuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 350284441Stuexen offset += sizeof(struct xsctp_laddr); 351284441Stuexen if (xladdr->last == 1) 352284441Stuexen break; 353284441Stuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 354284441Stuexen err(1, "malloc()"); 355284441Stuexen switch (xladdr->address.sa.sa_family) { 356284441Stuexen case AF_INET: 357284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 358284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 359284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 360284441Stuexen local_all_loopback = 0; 361284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 362284441Stuexen sockaddr(&laddr->address, 363284441Stuexen AF_INET, 364284441Stuexen &xladdr->address.sin.sin_addr, 365284441Stuexen htons(xinpcb->local_port)); 366284441Stuexen break; 367284441Stuexen case AF_INET6: 368284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 369284441Stuexen local_all_loopback = 0; 370284441Stuexen sockaddr(&laddr->address, 371284441Stuexen AF_INET6, 372284441Stuexen &xladdr->address.sin6.sin6_addr, 373284441Stuexen htons(xinpcb->local_port)); 374284441Stuexen break; 375284441Stuexen default: 376293290Sbdrewery errx(1, "address family %d not supported", 377284441Stuexen xladdr->address.sa.sa_family); 378284441Stuexen } 379284441Stuexen laddr->next = NULL; 380284441Stuexen if (prev_laddr == NULL) 381284441Stuexen sock->laddr = laddr; 382284441Stuexen else 383284441Stuexen prev_laddr->next = laddr; 384284441Stuexen prev_laddr = laddr; 385284441Stuexen } 386284441Stuexen if (sock->laddr == NULL) { 387284441Stuexen if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) 388284441Stuexen err(1, "malloc()"); 389284441Stuexen sock->laddr->address.ss_family = sock->family; 390284441Stuexen if (sock->family == AF_INET) 391284441Stuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 392284441Stuexen else 393284441Stuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 394284441Stuexen local_all_loopback = 0; 395284441Stuexen } 396284441Stuexen if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 397284441Stuexen err(1, "malloc()"); 398284441Stuexen sock->faddr->address.ss_family = sock->family; 399284441Stuexen if (sock->family == AF_INET) 400284441Stuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 401284441Stuexen else 402284441Stuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 403284441Stuexen no_stcb = 1; 404284441Stuexen while (offset < len) { 405284441Stuexen xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 406284441Stuexen offset += sizeof(struct xsctp_tcb); 407284694Stuexen if (no_stcb) { 408284694Stuexen if (opt_l && 409284694Stuexen (!opt_L || !local_all_loopback) && 410284694Stuexen ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 411284694Stuexen (xstcb->last == 1))) { 412284694Stuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 413284694Stuexen sock->next = sockhash[hash]; 414284694Stuexen sockhash[hash] = sock; 415284694Stuexen } else { 416284694Stuexen free_socket(sock); 417284694Stuexen } 418284441Stuexen } 419284441Stuexen if (xstcb->last == 1) 420284441Stuexen break; 421284441Stuexen no_stcb = 0; 422284441Stuexen if (opt_c) { 423284441Stuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 424284441Stuexen err(1, "malloc()"); 425284441Stuexen sock->socket = xinpcb->socket; 426284441Stuexen sock->proto = IPPROTO_SCTP; 427284441Stuexen sock->protoname = "sctp"; 428294231Stuexen sock->state = (int)xstcb->state; 429284441Stuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 430284441Stuexen sock->family = AF_INET6; 431284441Stuexen sock->vflag = INP_IPV6; 432284441Stuexen } else { 433284441Stuexen sock->family = AF_INET; 434284441Stuexen sock->vflag = INP_IPV4; 435284441Stuexen } 436284441Stuexen } 437284441Stuexen prev_laddr = NULL; 438284441Stuexen local_all_loopback = 1; 439284441Stuexen while (offset < len) { 440284441Stuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 441284441Stuexen offset += sizeof(struct xsctp_laddr); 442284441Stuexen if (xladdr->last == 1) 443284441Stuexen break; 444284441Stuexen if (!opt_c) 445284441Stuexen continue; 446284441Stuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 447284441Stuexen err(1, "malloc()"); 448284441Stuexen switch (xladdr->address.sa.sa_family) { 449284441Stuexen case AF_INET: 450284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 451284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 452284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 453284441Stuexen local_all_loopback = 0; 454284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 455284441Stuexen sockaddr(&laddr->address, 456284441Stuexen AF_INET, 457284441Stuexen &xladdr->address.sin.sin_addr, 458284441Stuexen htons(xstcb->local_port)); 459284441Stuexen break; 460284441Stuexen case AF_INET6: 461284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 462284441Stuexen local_all_loopback = 0; 463284441Stuexen sockaddr(&laddr->address, 464284441Stuexen AF_INET6, 465284441Stuexen &xladdr->address.sin6.sin6_addr, 466284441Stuexen htons(xstcb->local_port)); 467284441Stuexen break; 468284441Stuexen default: 469293290Sbdrewery errx(1, "address family %d not supported", 470284441Stuexen xladdr->address.sa.sa_family); 471284441Stuexen } 472284441Stuexen laddr->next = NULL; 473284441Stuexen if (prev_laddr == NULL) 474284441Stuexen sock->laddr = laddr; 475284441Stuexen else 476284441Stuexen prev_laddr->next = laddr; 477284441Stuexen prev_laddr = laddr; 478284441Stuexen } 479284441Stuexen prev_faddr = NULL; 480284441Stuexen foreign_all_loopback = 1; 481284441Stuexen while (offset < len) { 482284441Stuexen xraddr = (struct xsctp_raddr *)(void *)(buf + offset); 483284441Stuexen offset += sizeof(struct xsctp_raddr); 484284441Stuexen if (xraddr->last == 1) 485284441Stuexen break; 486284441Stuexen if (!opt_c) 487284441Stuexen continue; 488284441Stuexen if ((faddr = calloc(1, sizeof(struct addr))) == NULL) 489284441Stuexen err(1, "malloc()"); 490284441Stuexen switch (xraddr->address.sa.sa_family) { 491284441Stuexen case AF_INET: 492284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 493284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 494284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) 495284441Stuexen foreign_all_loopback = 0; 496284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 497284441Stuexen sockaddr(&faddr->address, 498284441Stuexen AF_INET, 499284441Stuexen &xraddr->address.sin.sin_addr, 500284441Stuexen htons(xstcb->remote_port)); 501284441Stuexen break; 502284441Stuexen case AF_INET6: 503284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) 504284441Stuexen foreign_all_loopback = 0; 505284441Stuexen sockaddr(&faddr->address, 506284441Stuexen AF_INET6, 507284441Stuexen &xraddr->address.sin6.sin6_addr, 508284441Stuexen htons(xstcb->remote_port)); 509284441Stuexen break; 510284441Stuexen default: 511293290Sbdrewery errx(1, "address family %d not supported", 512284441Stuexen xraddr->address.sa.sa_family); 513284441Stuexen } 514284441Stuexen faddr->next = NULL; 515284441Stuexen if (prev_faddr == NULL) 516284441Stuexen sock->faddr = faddr; 517284441Stuexen else 518284441Stuexen prev_faddr->next = faddr; 519284441Stuexen prev_faddr = faddr; 520284441Stuexen } 521284694Stuexen if (opt_c) { 522284694Stuexen if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { 523284694Stuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 524284694Stuexen sock->next = sockhash[hash]; 525284694Stuexen sockhash[hash] = sock; 526284694Stuexen } else { 527284694Stuexen free_socket(sock); 528284694Stuexen } 529284441Stuexen } 530284441Stuexen } 531284441Stuexen xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 532284441Stuexen offset += sizeof(struct xsctp_inpcb); 533284441Stuexen } 534284441Stuexen free(buf); 535284441Stuexen} 536284441Stuexen 537284441Stuexenstatic void 538101043Sdesgather_inet(int proto) 539101043Sdes{ 540101043Sdes struct xinpgen *xig, *exig; 541101043Sdes struct xinpcb *xip; 542101043Sdes struct xtcpcb *xtp; 543101043Sdes struct inpcb *inp; 544101043Sdes struct xsocket *so; 545101043Sdes struct sock *sock; 546284441Stuexen struct addr *laddr, *faddr; 547101043Sdes const char *varname, *protoname; 548101043Sdes size_t len, bufsize; 549101043Sdes void *buf; 550294230Stuexen int hash, retry, vflag; 551101043Sdes 552294230Stuexen vflag = 0; 553101043Sdes if (opt_4) 554101043Sdes vflag |= INP_IPV4; 555101043Sdes if (opt_6) 556101043Sdes vflag |= INP_IPV6; 557101043Sdes 558101043Sdes switch (proto) { 559101043Sdes case IPPROTO_TCP: 560101043Sdes varname = "net.inet.tcp.pcblist"; 561101043Sdes protoname = "tcp"; 562101043Sdes break; 563101043Sdes case IPPROTO_UDP: 564101043Sdes varname = "net.inet.udp.pcblist"; 565101043Sdes protoname = "udp"; 566101043Sdes break; 567138391Sru case IPPROTO_DIVERT: 568138391Sru varname = "net.inet.divert.pcblist"; 569138391Sru protoname = "div"; 570138391Sru break; 571101043Sdes default: 572164201Skeramida errx(1, "protocol %d not supported", proto); 573101043Sdes } 574101043Sdes 575101043Sdes buf = NULL; 576101043Sdes bufsize = 8192; 577101043Sdes retry = 5; 578101043Sdes do { 579101043Sdes for (;;) { 580101043Sdes if ((buf = realloc(buf, bufsize)) == NULL) 581101043Sdes err(1, "realloc()"); 582101043Sdes len = bufsize; 583101043Sdes if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 584101043Sdes break; 585138437Sru if (errno == ENOENT) 586138437Sru goto out; 587230874Strociny if (errno != ENOMEM || len != bufsize) 588101043Sdes err(1, "sysctlbyname()"); 589101043Sdes bufsize *= 2; 590101043Sdes } 591101043Sdes xig = (struct xinpgen *)buf; 592101220Srobert exig = (struct xinpgen *)(void *) 593101220Srobert ((char *)buf + len - sizeof *exig); 594101043Sdes if (xig->xig_len != sizeof *xig || 595101043Sdes exig->xig_len != sizeof *exig) 596101043Sdes errx(1, "struct xinpgen size mismatch"); 597101043Sdes } while (xig->xig_gen != exig->xig_gen && retry--); 598101043Sdes 599101043Sdes if (xig->xig_gen != exig->xig_gen && opt_v) 600101043Sdes warnx("warning: data may be inconsistent"); 601101043Sdes 602101043Sdes for (;;) { 603101220Srobert xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 604101043Sdes if (xig >= exig) 605101043Sdes break; 606294226Stuexen xip = (struct xinpcb *)xig; 607294226Stuexen xtp = (struct xtcpcb *)xig; 608101043Sdes switch (proto) { 609101043Sdes case IPPROTO_TCP: 610285826Shrs if (xtp->xt_len != sizeof(*xtp)) { 611101043Sdes warnx("struct xtcpcb size mismatch"); 612101043Sdes goto out; 613101043Sdes } 614101043Sdes inp = &xtp->xt_inp; 615101043Sdes so = &xtp->xt_socket; 616237263Snp protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; 617101043Sdes break; 618101043Sdes case IPPROTO_UDP: 619138391Sru case IPPROTO_DIVERT: 620285826Shrs if (xip->xi_len != sizeof(*xip)) { 621101043Sdes warnx("struct xinpcb size mismatch"); 622101043Sdes goto out; 623101043Sdes } 624101043Sdes inp = &xip->xi_inp; 625101043Sdes so = &xip->xi_socket; 626101043Sdes break; 627101043Sdes default: 628164201Skeramida errx(1, "protocol %d not supported", proto); 629101043Sdes } 630101043Sdes if ((inp->inp_vflag & vflag) == 0) 631101043Sdes continue; 632101144Sdes if (inp->inp_vflag & INP_IPV4) { 633101144Sdes if ((inp->inp_fport == 0 && !opt_l) || 634101144Sdes (inp->inp_fport != 0 && !opt_c)) 635101144Sdes continue; 636179115Sbms#define __IN_IS_ADDR_LOOPBACK(pina) \ 637179115Sbms ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 638179115Sbms if (opt_L && 639179115Sbms (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || 640179115Sbms __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) 641179115Sbms continue; 642179115Sbms#undef __IN_IS_ADDR_LOOPBACK 643101144Sdes } else if (inp->inp_vflag & INP_IPV6) { 644189637Srwatson if ((inp->inp_fport == 0 && !opt_l) || 645189637Srwatson (inp->inp_fport != 0 && !opt_c)) 646101144Sdes continue; 647179115Sbms if (opt_L && 648179115Sbms (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || 649179115Sbms IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) 650179115Sbms continue; 651101144Sdes } else { 652101144Sdes if (opt_v) 653101144Sdes warnx("invalid vflag 0x%x", inp->inp_vflag); 654101144Sdes continue; 655101144Sdes } 656285826Shrs if ((sock = calloc(1, sizeof(*sock))) == NULL) 657101043Sdes err(1, "malloc()"); 658284441Stuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 659284441Stuexen err(1, "malloc()"); 660284441Stuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 661284441Stuexen err(1, "malloc()"); 662101043Sdes sock->socket = so->xso_so; 663101043Sdes sock->proto = proto; 664101043Sdes if (inp->inp_vflag & INP_IPV4) { 665101043Sdes sock->family = AF_INET; 666284441Stuexen sockaddr(&laddr->address, sock->family, 667101043Sdes &inp->inp_laddr, inp->inp_lport); 668284441Stuexen sockaddr(&faddr->address, sock->family, 669101043Sdes &inp->inp_faddr, inp->inp_fport); 670101043Sdes } else if (inp->inp_vflag & INP_IPV6) { 671101043Sdes sock->family = AF_INET6; 672284441Stuexen sockaddr(&laddr->address, sock->family, 673189637Srwatson &inp->in6p_laddr, inp->inp_lport); 674284441Stuexen sockaddr(&faddr->address, sock->family, 675189637Srwatson &inp->in6p_faddr, inp->inp_fport); 676101043Sdes } 677284441Stuexen laddr->next = NULL; 678284441Stuexen faddr->next = NULL; 679284441Stuexen sock->laddr = laddr; 680284441Stuexen sock->faddr = faddr; 681101043Sdes sock->vflag = inp->inp_vflag; 682294225Stuexen if (proto == IPPROTO_TCP) 683294225Stuexen sock->state = xtp->xt_tp.t_state; 684101043Sdes sock->protoname = protoname; 685101043Sdes hash = (int)((uintptr_t)sock->socket % HASHSIZE); 686101043Sdes sock->next = sockhash[hash]; 687101043Sdes sockhash[hash] = sock; 688101043Sdes } 689101043Sdesout: 690101043Sdes free(buf); 691101043Sdes} 692101043Sdes 693101043Sdesstatic void 694101043Sdesgather_unix(int proto) 695101043Sdes{ 696101043Sdes struct xunpgen *xug, *exug; 697101043Sdes struct xunpcb *xup; 698101043Sdes struct sock *sock; 699284441Stuexen struct addr *laddr, *faddr; 700101043Sdes const char *varname, *protoname; 701101043Sdes size_t len, bufsize; 702101043Sdes void *buf; 703101043Sdes int hash, retry; 704101043Sdes 705101043Sdes switch (proto) { 706101043Sdes case SOCK_STREAM: 707101043Sdes varname = "net.local.stream.pcblist"; 708101043Sdes protoname = "stream"; 709101043Sdes break; 710101043Sdes case SOCK_DGRAM: 711101043Sdes varname = "net.local.dgram.pcblist"; 712101043Sdes protoname = "dgram"; 713101043Sdes break; 714285826Shrs case SOCK_SEQPACKET: 715285826Shrs varname = "net.local.seqpacket.pcblist"; 716285826Shrs protoname = "seqpac"; 717285826Shrs break; 718101043Sdes default: 719101043Sdes abort(); 720101043Sdes } 721101043Sdes buf = NULL; 722101043Sdes bufsize = 8192; 723101043Sdes retry = 5; 724101043Sdes do { 725101043Sdes for (;;) { 726101043Sdes if ((buf = realloc(buf, bufsize)) == NULL) 727101043Sdes err(1, "realloc()"); 728101043Sdes len = bufsize; 729101043Sdes if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 730101043Sdes break; 731230874Strociny if (errno != ENOMEM || len != bufsize) 732101043Sdes err(1, "sysctlbyname()"); 733101043Sdes bufsize *= 2; 734101043Sdes } 735101043Sdes xug = (struct xunpgen *)buf; 736101220Srobert exug = (struct xunpgen *)(void *) 737285826Shrs ((char *)buf + len - sizeof(*exug)); 738285826Shrs if (xug->xug_len != sizeof(*xug) || 739285826Shrs exug->xug_len != sizeof(*exug)) { 740101043Sdes warnx("struct xinpgen size mismatch"); 741101043Sdes goto out; 742101043Sdes } 743101043Sdes } while (xug->xug_gen != exug->xug_gen && retry--); 744101043Sdes 745101043Sdes if (xug->xug_gen != exug->xug_gen && opt_v) 746101043Sdes warnx("warning: data may be inconsistent"); 747101043Sdes 748101043Sdes for (;;) { 749101220Srobert xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 750101043Sdes if (xug >= exug) 751101043Sdes break; 752101043Sdes xup = (struct xunpcb *)xug; 753285826Shrs if (xup->xu_len != sizeof(*xup)) { 754101043Sdes warnx("struct xunpcb size mismatch"); 755101043Sdes goto out; 756101043Sdes } 757101144Sdes if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 758101144Sdes (xup->xu_unp.unp_conn != NULL && !opt_c)) 759101144Sdes continue; 760285826Shrs if ((sock = calloc(1, sizeof(*sock))) == NULL) 761101043Sdes err(1, "malloc()"); 762284441Stuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 763284441Stuexen err(1, "malloc()"); 764284441Stuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 765284441Stuexen err(1, "malloc()"); 766101043Sdes sock->socket = xup->xu_socket.xso_so; 767101043Sdes sock->pcb = xup->xu_unpp; 768101043Sdes sock->proto = proto; 769101043Sdes sock->family = AF_UNIX; 770101043Sdes sock->protoname = protoname; 771101043Sdes if (xup->xu_unp.unp_addr != NULL) 772284441Stuexen laddr->address = 773101220Srobert *(struct sockaddr_storage *)(void *)&xup->xu_addr; 774101043Sdes else if (xup->xu_unp.unp_conn != NULL) 775284441Stuexen *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 776284441Stuexen laddr->next = NULL; 777284441Stuexen faddr->next = NULL; 778284441Stuexen sock->laddr = laddr; 779284441Stuexen sock->faddr = faddr; 780101043Sdes hash = (int)((uintptr_t)sock->socket % HASHSIZE); 781101043Sdes sock->next = sockhash[hash]; 782101043Sdes sockhash[hash] = sock; 783101043Sdes } 784101043Sdesout: 785101043Sdes free(buf); 786101043Sdes} 787101043Sdes 788101043Sdesstatic void 789101043Sdesgetfiles(void) 790101043Sdes{ 791230874Strociny size_t len, olen; 792101043Sdes 793285826Shrs olen = len = sizeof(*xfiles); 794230874Strociny if ((xfiles = malloc(len)) == NULL) 795101043Sdes err(1, "malloc()"); 796101043Sdes while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 797230874Strociny if (errno != ENOMEM || len != olen) 798101043Sdes err(1, "sysctlbyname()"); 799230874Strociny olen = len *= 2; 800101043Sdes if ((xfiles = realloc(xfiles, len)) == NULL) 801101043Sdes err(1, "realloc()"); 802101043Sdes } 803285826Shrs if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 804101043Sdes errx(1, "struct xfile size mismatch"); 805285826Shrs nxfiles = len / sizeof(*xfiles); 806101043Sdes} 807101043Sdes 808101043Sdesstatic int 809284441Stuexenprintaddr(struct sockaddr_storage *ss) 810101043Sdes{ 811101043Sdes struct sockaddr_un *sun; 812285826Shrs char addrstr[NI_MAXHOST] = { '\0', '\0' }; 813285826Shrs int error, off, port = 0; 814101043Sdes 815284441Stuexen switch (ss->ss_family) { 816101043Sdes case AF_INET: 817285826Shrs if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) 818101043Sdes addrstr[0] = '*'; 819285826Shrs port = ntohs(sstosin(ss)->sin_port); 820101043Sdes break; 821101043Sdes case AF_INET6: 822285826Shrs if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 823101043Sdes addrstr[0] = '*'; 824285826Shrs port = ntohs(sstosin6(ss)->sin6_port); 825101043Sdes break; 826101043Sdes case AF_UNIX: 827285826Shrs sun = sstosun(ss); 828101043Sdes off = (int)((char *)&sun->sun_path - (char *)sun); 829101043Sdes return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 830101043Sdes } 831285826Shrs if (addrstr[0] == '\0') { 832285826Shrs error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, 833285826Shrs sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 834285826Shrs if (error) 835285826Shrs errx(1, "getnameinfo()"); 836285826Shrs } 837101043Sdes if (port == 0) 838101043Sdes return xprintf("%s:*", addrstr); 839101043Sdes else 840101043Sdes return xprintf("%s:%d", addrstr, port); 841101043Sdes} 842101043Sdes 843101043Sdesstatic const char * 844101043Sdesgetprocname(pid_t pid) 845101043Sdes{ 846101043Sdes static struct kinfo_proc proc; 847101043Sdes size_t len; 848101043Sdes int mib[4]; 849101043Sdes 850101043Sdes mib[0] = CTL_KERN; 851101043Sdes mib[1] = KERN_PROC; 852101043Sdes mib[2] = KERN_PROC_PID; 853101043Sdes mib[3] = (int)pid; 854285826Shrs len = sizeof(proc); 855285826Shrs if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 856170833Smaxim /* Do not warn if the process exits before we get its name. */ 857170833Smaxim if (errno != ESRCH) 858170833Smaxim warn("sysctl()"); 859101043Sdes return ("??"); 860101043Sdes } 861167810Semaste return (proc.ki_comm); 862101043Sdes} 863101043Sdes 864115955Smuxstatic int 865235870Sthompsagetprocjid(pid_t pid) 866235870Sthompsa{ 867235870Sthompsa static struct kinfo_proc proc; 868235870Sthompsa size_t len; 869235870Sthompsa int mib[4]; 870235870Sthompsa 871235870Sthompsa mib[0] = CTL_KERN; 872235870Sthompsa mib[1] = KERN_PROC; 873235870Sthompsa mib[2] = KERN_PROC_PID; 874235870Sthompsa mib[3] = (int)pid; 875285826Shrs len = sizeof(proc); 876285826Shrs if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 877235870Sthompsa /* Do not warn if the process exits before we get its jid. */ 878235870Sthompsa if (errno != ESRCH) 879235870Sthompsa warn("sysctl()"); 880235870Sthompsa return (-1); 881235870Sthompsa } 882235870Sthompsa return (proc.ki_jid); 883235870Sthompsa} 884235870Sthompsa 885235870Sthompsastatic int 886115955Smuxcheck_ports(struct sock *s) 887115955Smux{ 888115955Smux int port; 889284441Stuexen struct addr *addr; 890115955Smux 891115955Smux if (ports == NULL) 892115955Smux return (1); 893115955Smux if ((s->family != AF_INET) && (s->family != AF_INET6)) 894115955Smux return (1); 895284441Stuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 896285826Shrs if (s->family == AF_INET) 897285826Shrs port = ntohs(sstosin(&addr->address)->sin_port); 898284441Stuexen else 899285826Shrs port = ntohs(sstosin6(&addr->address)->sin6_port); 900284441Stuexen if (CHK_PORT(port)) 901284441Stuexen return (1); 902284441Stuexen } 903284441Stuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 904285826Shrs if (s->family == AF_INET) 905285826Shrs port = ntohs(sstosin(&addr->address)->sin_port); 906284441Stuexen else 907285826Shrs port = ntohs(sstosin6(&addr->address)->sin6_port); 908284441Stuexen if (CHK_PORT(port)) 909284441Stuexen return (1); 910284441Stuexen } 911115955Smux return (0); 912115955Smux} 913115955Smux 914294231Stuexenstatic const char * 915294231Stuexensctp_state(int state) 916294231Stuexen{ 917294231Stuexen switch (state) { 918294231Stuexen case SCTP_CLOSED: 919294231Stuexen return "CLOSED"; 920294231Stuexen break; 921294231Stuexen case SCTP_BOUND: 922294231Stuexen return "BOUND"; 923294231Stuexen break; 924294231Stuexen case SCTP_LISTEN: 925294231Stuexen return "LISTEN"; 926294231Stuexen break; 927294231Stuexen case SCTP_COOKIE_WAIT: 928294231Stuexen return "COOKIE_WAIT"; 929294231Stuexen break; 930294231Stuexen case SCTP_COOKIE_ECHOED: 931294231Stuexen return "COOKIE_ECHOED"; 932294231Stuexen break; 933294231Stuexen case SCTP_ESTABLISHED: 934294231Stuexen return "ESTABLISHED"; 935294231Stuexen break; 936294231Stuexen case SCTP_SHUTDOWN_SENT: 937294231Stuexen return "SHUTDOWN_SENT"; 938294231Stuexen break; 939294231Stuexen case SCTP_SHUTDOWN_RECEIVED: 940294231Stuexen return "SHUTDOWN_RECEIVED"; 941294231Stuexen break; 942294231Stuexen case SCTP_SHUTDOWN_ACK_SENT: 943294231Stuexen return "SHUTDOWN_ACK_SENT"; 944294231Stuexen break; 945294231Stuexen case SCTP_SHUTDOWN_PENDING: 946294231Stuexen return "SHUTDOWN_PENDING"; 947294231Stuexen break; 948294231Stuexen default: 949294231Stuexen return "UNKNOWN"; 950294231Stuexen break; 951294231Stuexen } 952294231Stuexen} 953294231Stuexen 954101043Sdesstatic void 955230512Sjillesdisplaysock(struct sock *s, int pos) 956230512Sjilles{ 957230512Sjilles void *p; 958294228Sdes int hash, first; 959284441Stuexen struct addr *laddr, *faddr; 960284692Stuexen struct sock *s_tmp; 961230512Sjilles 962230512Sjilles while (pos < 29) 963230512Sjilles pos += xprintf(" "); 964230512Sjilles pos += xprintf("%s", s->protoname); 965230512Sjilles if (s->vflag & INP_IPV4) 966230512Sjilles pos += xprintf("4 "); 967230512Sjilles if (s->vflag & INP_IPV6) 968230512Sjilles pos += xprintf("6 "); 969284441Stuexen laddr = s->laddr; 970284441Stuexen faddr = s->faddr; 971294228Sdes first = 1; 972284441Stuexen while (laddr != NULL || faddr != NULL) { 973284441Stuexen while (pos < 36) 974230512Sjilles pos += xprintf(" "); 975284441Stuexen switch (s->family) { 976284441Stuexen case AF_INET: 977284441Stuexen case AF_INET6: 978284441Stuexen if (laddr != NULL) { 979284441Stuexen pos += printaddr(&laddr->address); 980284441Stuexen if (s->family == AF_INET6 && pos >= 58) 981284441Stuexen pos += xprintf(" "); 982284441Stuexen } 983284441Stuexen while (pos < 58) 984284441Stuexen pos += xprintf(" "); 985284441Stuexen if (faddr != NULL) 986284441Stuexen pos += printaddr(&faddr->address); 987230512Sjilles break; 988284441Stuexen case AF_UNIX: 989284441Stuexen if ((laddr == NULL) || (faddr == NULL)) 990284441Stuexen errx(1, "laddr = %p or faddr = %p is NULL", 991284441Stuexen (void *)laddr, (void *)faddr); 992284441Stuexen /* server */ 993284441Stuexen if (laddr->address.ss_len > 0) { 994284441Stuexen pos += printaddr(&laddr->address); 995284441Stuexen break; 996284441Stuexen } 997284441Stuexen /* client */ 998284441Stuexen p = *(void **)&(faddr->address); 999284441Stuexen if (p == NULL) { 1000284441Stuexen pos += xprintf("(not connected)"); 1001284441Stuexen break; 1002284441Stuexen } 1003284441Stuexen pos += xprintf("-> "); 1004284441Stuexen for (hash = 0; hash < HASHSIZE; ++hash) { 1005284692Stuexen for (s_tmp = sockhash[hash]; 1006284692Stuexen s_tmp != NULL; 1007284692Stuexen s_tmp = s_tmp->next) 1008284692Stuexen if (s_tmp->pcb == p) 1009284441Stuexen break; 1010284692Stuexen if (s_tmp != NULL) 1011284441Stuexen break; 1012284441Stuexen } 1013284692Stuexen if (s_tmp == NULL || 1014284692Stuexen s_tmp->laddr == NULL || 1015284692Stuexen s_tmp->laddr->address.ss_len == 0) 1016284441Stuexen pos += xprintf("??"); 1017284441Stuexen else 1018284692Stuexen pos += printaddr(&s_tmp->laddr->address); 1019230512Sjilles break; 1020284441Stuexen default: 1021284441Stuexen abort(); 1022230512Sjilles } 1023294231Stuexen if (first && opt_s && 1024294231Stuexen (s->proto == IPPROTO_SCTP || s->proto == IPPROTO_TCP)) { 1025294228Sdes while (pos < 80) 1026294228Sdes pos += xprintf(" "); 1027294231Stuexen switch (s->proto) { 1028294231Stuexen case IPPROTO_SCTP: 1029294231Stuexen pos += xprintf("%s", sctp_state(s->state)); 1030294231Stuexen break; 1031294231Stuexen case IPPROTO_TCP: 1032294231Stuexen if (s->state >= 0 && s->state < TCP_NSTATES) 1033294231Stuexen pos += 1034294231Stuexen xprintf("%s", tcpstates[s->state]); 1035294231Stuexen else 1036294231Stuexen pos += xprintf("?"); 1037294231Stuexen break; 1038294231Stuexen } 1039294228Sdes } 1040284441Stuexen if (laddr != NULL) 1041284441Stuexen laddr = laddr->next; 1042284441Stuexen if (faddr != NULL) 1043284441Stuexen faddr = faddr->next; 1044284441Stuexen if ((laddr != NULL) || (faddr != NULL)) { 1045284441Stuexen xprintf("\n"); 1046284441Stuexen pos = 0; 1047230512Sjilles } 1048294228Sdes first = 0; 1049230512Sjilles } 1050294228Sdes xprintf("\n"); 1051230512Sjilles} 1052230512Sjilles 1053230512Sjillesstatic void 1054101043Sdesdisplay(void) 1055101043Sdes{ 1056101043Sdes struct passwd *pwd; 1057101043Sdes struct xfile *xf; 1058101043Sdes struct sock *s; 1059101043Sdes int hash, n, pos; 1060101043Sdes 1061294225Stuexen printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", 1062101043Sdes "USER", "COMMAND", "PID", "FD", "PROTO", 1063101043Sdes "LOCAL ADDRESS", "FOREIGN ADDRESS"); 1064294225Stuexen if (opt_s) 1065294225Stuexen printf(" %-12s", "STATE"); 1066294225Stuexen printf("\n"); 1067101043Sdes setpassent(1); 1068101043Sdes for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 1069134295Sroam if (xf->xf_data == NULL) 1070134295Sroam continue; 1071235870Sthompsa if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 1072235870Sthompsa continue; 1073109153Sdillon hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 1074284441Stuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 1075284441Stuexen if ((void *)s->socket != xf->xf_data) 1076284441Stuexen continue; 1077284441Stuexen if (!check_ports(s)) 1078284441Stuexen continue; 1079284441Stuexen s->shown = 1; 1080284441Stuexen pos = 0; 1081284441Stuexen if ((pwd = getpwuid(xf->xf_uid)) == NULL) 1082284441Stuexen pos += xprintf("%lu ", (u_long)xf->xf_uid); 1083284441Stuexen else 1084284441Stuexen pos += xprintf("%s ", pwd->pw_name); 1085284441Stuexen while (pos < 9) 1086284441Stuexen pos += xprintf(" "); 1087284441Stuexen pos += xprintf("%.10s", getprocname(xf->xf_pid)); 1088284441Stuexen while (pos < 20) 1089284441Stuexen pos += xprintf(" "); 1090284441Stuexen pos += xprintf("%lu ", (u_long)xf->xf_pid); 1091284441Stuexen while (pos < 26) 1092284441Stuexen pos += xprintf(" "); 1093284441Stuexen pos += xprintf("%d ", xf->xf_fd); 1094284441Stuexen displaysock(s, pos); 1095284441Stuexen } 1096230512Sjilles } 1097235870Sthompsa if (opt_j >= 0) 1098235870Sthompsa return; 1099230512Sjilles for (hash = 0; hash < HASHSIZE; hash++) { 1100230512Sjilles for (s = sockhash[hash]; s != NULL; s = s->next) { 1101230512Sjilles if (s->shown) 1102230512Sjilles continue; 1103230512Sjilles if (!check_ports(s)) 1104230512Sjilles continue; 1105230512Sjilles pos = 0; 1106230512Sjilles pos += xprintf("%-8s %-10s %-5s %-2s ", 1107230512Sjilles "?", "?", "?", "?"); 1108230512Sjilles displaysock(s, pos); 1109101043Sdes } 1110101043Sdes } 1111101043Sdes} 1112101043Sdes 1113164201Skeramidastatic int set_default_protos(void) 1114164201Skeramida{ 1115164201Skeramida struct protoent *prot; 1116164201Skeramida const char *pname; 1117164201Skeramida size_t pindex; 1118164201Skeramida 1119164201Skeramida init_protos(default_numprotos); 1120164201Skeramida 1121164201Skeramida for (pindex = 0; pindex < default_numprotos; pindex++) { 1122164201Skeramida pname = default_protos[pindex]; 1123164201Skeramida prot = getprotobyname(pname); 1124164201Skeramida if (prot == NULL) 1125164201Skeramida err(1, "getprotobyname: %s", pname); 1126164201Skeramida protos[pindex] = prot->p_proto; 1127164201Skeramida } 1128164201Skeramida numprotos = pindex; 1129164201Skeramida return (pindex); 1130164201Skeramida} 1131164201Skeramida 1132164201Skeramida 1133101043Sdesstatic void 1134101043Sdesusage(void) 1135101043Sdes{ 1136164201Skeramida fprintf(stderr, 1137294225Stuexen "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); 1138101043Sdes exit(1); 1139101043Sdes} 1140101043Sdes 1141101043Sdesint 1142101043Sdesmain(int argc, char *argv[]) 1143101043Sdes{ 1144164201Skeramida int protos_defined = -1; 1145164201Skeramida int o, i; 1146101043Sdes 1147235870Sthompsa opt_j = -1; 1148294225Stuexen while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) 1149101043Sdes switch (o) { 1150101043Sdes case '4': 1151101043Sdes opt_4 = 1; 1152101043Sdes break; 1153101043Sdes case '6': 1154101043Sdes opt_6 = 1; 1155101043Sdes break; 1156101043Sdes case 'c': 1157101043Sdes opt_c = 1; 1158101043Sdes break; 1159235870Sthompsa case 'j': 1160235870Sthompsa opt_j = atoi(optarg); 1161235870Sthompsa break; 1162179115Sbms case 'L': 1163179115Sbms opt_L = 1; 1164179115Sbms break; 1165101043Sdes case 'l': 1166101043Sdes opt_l = 1; 1167101043Sdes break; 1168101043Sdes case 'p': 1169101043Sdes parse_ports(optarg); 1170101043Sdes break; 1171164201Skeramida case 'P': 1172164201Skeramida protos_defined = parse_protos(optarg); 1173164201Skeramida break; 1174294225Stuexen case 's': 1175294225Stuexen opt_s = 1; 1176294225Stuexen break; 1177101043Sdes case 'u': 1178101043Sdes opt_u = 1; 1179101043Sdes break; 1180101043Sdes case 'v': 1181101043Sdes ++opt_v; 1182101043Sdes break; 1183101043Sdes default: 1184101043Sdes usage(); 1185101043Sdes } 1186101043Sdes 1187101043Sdes argc -= optind; 1188101043Sdes argv += optind; 1189101043Sdes 1190101043Sdes if (argc > 0) 1191101043Sdes usage(); 1192101043Sdes 1193164226Skeramida if ((!opt_4 && !opt_6) && protos_defined != -1) 1194164226Skeramida opt_4 = opt_6 = 1; 1195164226Skeramida if (!opt_4 && !opt_6 && !opt_u) 1196164226Skeramida opt_4 = opt_6 = opt_u = 1; 1197164226Skeramida if ((opt_4 || opt_6) && protos_defined == -1) 1198164201Skeramida protos_defined = set_default_protos(); 1199101043Sdes if (!opt_c && !opt_l) 1200101043Sdes opt_c = opt_l = 1; 1201101043Sdes 1202101043Sdes if (opt_4 || opt_6) { 1203164201Skeramida for (i = 0; i < protos_defined; i++) 1204284441Stuexen if (protos[i] == IPPROTO_SCTP) 1205284441Stuexen gather_sctp(); 1206284441Stuexen else 1207284441Stuexen gather_inet(protos[i]); 1208101043Sdes } 1209164201Skeramida 1210164201Skeramida if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1211101043Sdes gather_unix(SOCK_STREAM); 1212101043Sdes gather_unix(SOCK_DGRAM); 1213285826Shrs gather_unix(SOCK_SEQPACKET); 1214101043Sdes } 1215101043Sdes getfiles(); 1216101043Sdes display(); 1217101043Sdes exit(0); 1218101043Sdes} 1219