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: stable/10/usr.bin/sockstat/sockstat.c 336039 2018-07-06 19:10:07Z jamie $"); 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> 57336039Sjamie#include <jail.h> 58101043Sdes#include <netdb.h> 59101043Sdes#include <pwd.h> 60101043Sdes#include <stdarg.h> 61101043Sdes#include <stdio.h> 62101043Sdes#include <stdlib.h> 63101043Sdes#include <string.h> 64101043Sdes#include <unistd.h> 65101043Sdes 66285826Shrs#define sstosin(ss) ((struct sockaddr_in *)(ss)) 67285826Shrs#define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) 68285826Shrs#define sstosun(ss) ((struct sockaddr_un *)(ss)) 69285826Shrs#define sstosa(ss) ((struct sockaddr *)(ss)) 70285826Shrs 71101043Sdesstatic int opt_4; /* Show IPv4 sockets */ 72101043Sdesstatic int opt_6; /* Show IPv6 sockets */ 73101043Sdesstatic int opt_c; /* Show connected sockets */ 74235870Sthompsastatic int opt_j; /* Show specified jail */ 75179115Sbmsstatic int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 76101043Sdesstatic int opt_l; /* Show listening sockets */ 77294225Stuexenstatic int opt_s; /* Show protocol state if applicable */ 78101043Sdesstatic int opt_u; /* Show Unix domain sockets */ 79101043Sdesstatic int opt_v; /* Verbose mode */ 80101043Sdes 81164201Skeramida/* 82164201Skeramida * Default protocols to use if no -P was defined. 83164201Skeramida */ 84284441Stuexenstatic const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 85285826Shrsstatic size_t default_numprotos = nitems(default_protos); 86164201Skeramida 87164201Skeramidastatic int *protos; /* protocols to use */ 88164201Skeramidastatic size_t numprotos; /* allocated size of protos[] */ 89164201Skeramida 90101043Sdesstatic int *ports; 91101043Sdes 92101043Sdes#define INT_BIT (sizeof(int)*CHAR_BIT) 93101043Sdes#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 94101043Sdes#define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 95101043Sdes 96284441Stuexenstruct addr { 97284441Stuexen struct sockaddr_storage address; 98284441Stuexen struct addr *next; 99284441Stuexen}; 100284441Stuexen 101101043Sdesstruct sock { 102101043Sdes void *socket; 103101043Sdes void *pcb; 104230512Sjilles int shown; 105101043Sdes int vflag; 106101043Sdes int family; 107101043Sdes int proto; 108294225Stuexen int state; 109101043Sdes const char *protoname; 110284441Stuexen struct addr *laddr; 111284441Stuexen struct addr *faddr; 112101043Sdes struct sock *next; 113101043Sdes}; 114101043Sdes 115101043Sdes#define HASHSIZE 1009 116101043Sdesstatic struct sock *sockhash[HASHSIZE]; 117101043Sdes 118101043Sdesstatic struct xfile *xfiles; 119101043Sdesstatic int nxfiles; 120101043Sdes 121101043Sdesstatic int 122101043Sdesxprintf(const char *fmt, ...) 123101043Sdes{ 124101043Sdes va_list ap; 125101043Sdes int len; 126101043Sdes 127101043Sdes va_start(ap, fmt); 128101043Sdes len = vprintf(fmt, ap); 129101043Sdes va_end(ap); 130101043Sdes if (len < 0) 131101043Sdes err(1, "printf()"); 132101043Sdes return (len); 133101043Sdes} 134101043Sdes 135164201Skeramida 136164201Skeramidastatic int 137164201Skeramidaget_proto_type(const char *proto) 138164201Skeramida{ 139164201Skeramida struct protoent *pent; 140164201Skeramida 141164201Skeramida if (strlen(proto) == 0) 142164201Skeramida return (0); 143164201Skeramida pent = getprotobyname(proto); 144164201Skeramida if (pent == NULL) { 145164201Skeramida warn("getprotobyname"); 146164201Skeramida return (-1); 147164201Skeramida } 148164201Skeramida return (pent->p_proto); 149164201Skeramida} 150164201Skeramida 151164201Skeramida 152285826Shrsstatic void 153285826Shrsinit_protos(int num) 154164201Skeramida{ 155164201Skeramida int proto_count = 0; 156164201Skeramida 157164201Skeramida if (num > 0) { 158164201Skeramida proto_count = num; 159164201Skeramida } else { 160164201Skeramida /* Find the maximum number of possible protocols. */ 161164201Skeramida while (getprotoent() != NULL) 162164201Skeramida proto_count++; 163164201Skeramida endprotoent(); 164164201Skeramida } 165164201Skeramida 166164201Skeramida if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 167164201Skeramida err(1, "malloc"); 168164201Skeramida numprotos = proto_count; 169164201Skeramida} 170164201Skeramida 171164201Skeramida 172164201Skeramidastatic int 173164201Skeramidaparse_protos(char *protospec) 174164201Skeramida{ 175164201Skeramida char *prot; 176164201Skeramida int proto_type, proto_index; 177164201Skeramida 178164201Skeramida if (protospec == NULL) 179164201Skeramida return (-1); 180164201Skeramida 181164201Skeramida init_protos(0); 182164201Skeramida proto_index = 0; 183285826Shrs while ((prot = strsep(&protospec, ",")) != NULL) { 184164201Skeramida if (strlen(prot) == 0) 185164201Skeramida continue; 186164201Skeramida proto_type = get_proto_type(prot); 187164201Skeramida if (proto_type != -1) 188164201Skeramida protos[proto_index++] = proto_type; 189164201Skeramida } 190164201Skeramida numprotos = proto_index; 191164201Skeramida return (proto_index); 192164201Skeramida} 193164201Skeramida 194164201Skeramida 195101043Sdesstatic void 196101043Sdesparse_ports(const char *portspec) 197101043Sdes{ 198101043Sdes const char *p, *q; 199101043Sdes int port, end; 200101043Sdes 201101043Sdes if (ports == NULL) 202114853Srobert if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 203101043Sdes err(1, "calloc()"); 204101043Sdes p = portspec; 205101043Sdes while (*p != '\0') { 206101043Sdes if (!isdigit(*p)) 207101043Sdes errx(1, "syntax error in port range"); 208101043Sdes for (q = p; *q != '\0' && isdigit(*q); ++q) 209101043Sdes /* nothing */ ; 210101043Sdes for (port = 0; p < q; ++p) 211101043Sdes port = port * 10 + digittoint(*p); 212101043Sdes if (port < 0 || port > 65535) 213101043Sdes errx(1, "invalid port number"); 214101043Sdes SET_PORT(port); 215101043Sdes switch (*p) { 216101043Sdes case '-': 217101043Sdes ++p; 218101043Sdes break; 219101043Sdes case ',': 220101043Sdes ++p; 221101043Sdes /* fall through */ 222101043Sdes case '\0': 223101043Sdes default: 224101043Sdes continue; 225101043Sdes } 226101043Sdes for (q = p; *q != '\0' && isdigit(*q); ++q) 227101043Sdes /* nothing */ ; 228101043Sdes for (end = 0; p < q; ++p) 229101043Sdes end = end * 10 + digittoint(*p); 230101043Sdes if (end < port || end > 65535) 231101043Sdes errx(1, "invalid port number"); 232101043Sdes while (port++ < end) 233101043Sdes SET_PORT(port); 234101043Sdes if (*p == ',') 235101043Sdes ++p; 236101043Sdes } 237101043Sdes} 238101043Sdes 239101043Sdesstatic void 240285826Shrssockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 241101043Sdes{ 242101043Sdes struct sockaddr_in *sin4; 243101043Sdes struct sockaddr_in6 *sin6; 244101043Sdes 245285826Shrs bzero(ss, sizeof(*ss)); 246101043Sdes switch (af) { 247101043Sdes case AF_INET: 248285826Shrs sin4 = sstosin(ss); 249285826Shrs sin4->sin_len = sizeof(*sin4); 250101043Sdes sin4->sin_family = af; 251101043Sdes sin4->sin_port = port; 252101043Sdes sin4->sin_addr = *(struct in_addr *)addr; 253101043Sdes break; 254101043Sdes case AF_INET6: 255285826Shrs sin6 = sstosin6(ss); 256285826Shrs sin6->sin6_len = sizeof(*sin6); 257101043Sdes sin6->sin6_family = af; 258101043Sdes sin6->sin6_port = port; 259101043Sdes sin6->sin6_addr = *(struct in6_addr *)addr; 260285826Shrs#define s6_addr16 __u6_addr.__u6_addr16 261285826Shrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 262285826Shrs sin6->sin6_scope_id = 263285826Shrs ntohs(sin6->sin6_addr.s6_addr16[1]); 264285826Shrs sin6->sin6_addr.s6_addr16[1] = 0; 265285826Shrs } 266101043Sdes break; 267101043Sdes default: 268101043Sdes abort(); 269101043Sdes } 270101043Sdes} 271101043Sdes 272101043Sdesstatic void 273284694Stuexenfree_socket(struct sock *sock) 274284694Stuexen{ 275284694Stuexen struct addr *cur, *next; 276284694Stuexen 277284694Stuexen cur = sock->laddr; 278284694Stuexen while (cur != NULL) { 279284694Stuexen next = cur->next; 280284694Stuexen free(cur); 281284694Stuexen cur = next; 282284694Stuexen } 283284694Stuexen cur = sock->faddr; 284284694Stuexen while (cur != NULL) { 285284694Stuexen next = cur->next; 286284694Stuexen free(cur); 287284694Stuexen cur = next; 288284694Stuexen } 289284694Stuexen free(sock); 290284694Stuexen} 291284694Stuexen 292284694Stuexenstatic void 293284441Stuexengather_sctp(void) 294284441Stuexen{ 295284441Stuexen struct sock *sock; 296284441Stuexen struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 297284441Stuexen struct xsctp_inpcb *xinpcb; 298284441Stuexen struct xsctp_tcb *xstcb; 299284441Stuexen struct xsctp_raddr *xraddr; 300284441Stuexen struct xsctp_laddr *xladdr; 301284441Stuexen const char *varname; 302284441Stuexen size_t len, offset; 303284441Stuexen char *buf; 304284441Stuexen int hash, vflag; 305284441Stuexen int no_stcb, local_all_loopback, foreign_all_loopback; 306284441Stuexen 307284441Stuexen vflag = 0; 308284441Stuexen if (opt_4) 309284441Stuexen vflag |= INP_IPV4; 310284441Stuexen if (opt_6) 311284441Stuexen vflag |= INP_IPV6; 312284441Stuexen 313284441Stuexen varname = "net.inet.sctp.assoclist"; 314284441Stuexen if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { 315284441Stuexen if (errno != ENOENT) 316284441Stuexen err(1, "sysctlbyname()"); 317284441Stuexen return; 318284441Stuexen } 319284441Stuexen if ((buf = (char *)malloc(len)) == NULL) { 320284441Stuexen err(1, "malloc()"); 321284441Stuexen return; 322284441Stuexen } 323284441Stuexen if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { 324284441Stuexen err(1, "sysctlbyname()"); 325284441Stuexen free(buf); 326284441Stuexen return; 327284441Stuexen } 328284441Stuexen xinpcb = (struct xsctp_inpcb *)(void *)buf; 329284441Stuexen offset = sizeof(struct xsctp_inpcb); 330284441Stuexen while ((offset < len) && (xinpcb->last == 0)) { 331284441Stuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 332284441Stuexen err(1, "malloc()"); 333284441Stuexen sock->socket = xinpcb->socket; 334284441Stuexen sock->proto = IPPROTO_SCTP; 335284441Stuexen sock->protoname = "sctp"; 336294232Stuexen if (xinpcb->maxqlen == 0) 337294231Stuexen sock->state = SCTP_CLOSED; 338294231Stuexen else 339294231Stuexen sock->state = SCTP_LISTEN; 340284441Stuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 341284441Stuexen sock->family = AF_INET6; 342284441Stuexen sock->vflag = INP_IPV6; 343284441Stuexen } else { 344284441Stuexen sock->family = AF_INET; 345284441Stuexen sock->vflag = INP_IPV4; 346284441Stuexen } 347284441Stuexen prev_laddr = NULL; 348284441Stuexen local_all_loopback = 1; 349284441Stuexen while (offset < len) { 350284441Stuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 351284441Stuexen offset += sizeof(struct xsctp_laddr); 352284441Stuexen if (xladdr->last == 1) 353284441Stuexen break; 354284441Stuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 355284441Stuexen err(1, "malloc()"); 356284441Stuexen switch (xladdr->address.sa.sa_family) { 357284441Stuexen case AF_INET: 358284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 359284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 360284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 361284441Stuexen local_all_loopback = 0; 362284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 363284441Stuexen sockaddr(&laddr->address, 364284441Stuexen AF_INET, 365284441Stuexen &xladdr->address.sin.sin_addr, 366284441Stuexen htons(xinpcb->local_port)); 367284441Stuexen break; 368284441Stuexen case AF_INET6: 369284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 370284441Stuexen local_all_loopback = 0; 371284441Stuexen sockaddr(&laddr->address, 372284441Stuexen AF_INET6, 373284441Stuexen &xladdr->address.sin6.sin6_addr, 374284441Stuexen htons(xinpcb->local_port)); 375284441Stuexen break; 376284441Stuexen default: 377293290Sbdrewery errx(1, "address family %d not supported", 378284441Stuexen xladdr->address.sa.sa_family); 379284441Stuexen } 380284441Stuexen laddr->next = NULL; 381284441Stuexen if (prev_laddr == NULL) 382284441Stuexen sock->laddr = laddr; 383284441Stuexen else 384284441Stuexen prev_laddr->next = laddr; 385284441Stuexen prev_laddr = laddr; 386284441Stuexen } 387284441Stuexen if (sock->laddr == NULL) { 388284441Stuexen if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) 389284441Stuexen err(1, "malloc()"); 390284441Stuexen sock->laddr->address.ss_family = sock->family; 391284441Stuexen if (sock->family == AF_INET) 392284441Stuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 393284441Stuexen else 394284441Stuexen sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 395284441Stuexen local_all_loopback = 0; 396284441Stuexen } 397284441Stuexen if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 398284441Stuexen err(1, "malloc()"); 399284441Stuexen sock->faddr->address.ss_family = sock->family; 400284441Stuexen if (sock->family == AF_INET) 401284441Stuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 402284441Stuexen else 403284441Stuexen sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 404284441Stuexen no_stcb = 1; 405284441Stuexen while (offset < len) { 406284441Stuexen xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 407284441Stuexen offset += sizeof(struct xsctp_tcb); 408284694Stuexen if (no_stcb) { 409284694Stuexen if (opt_l && 410284694Stuexen (!opt_L || !local_all_loopback) && 411284694Stuexen ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 412284694Stuexen (xstcb->last == 1))) { 413284694Stuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 414284694Stuexen sock->next = sockhash[hash]; 415284694Stuexen sockhash[hash] = sock; 416284694Stuexen } else { 417284694Stuexen free_socket(sock); 418284694Stuexen } 419284441Stuexen } 420284441Stuexen if (xstcb->last == 1) 421284441Stuexen break; 422284441Stuexen no_stcb = 0; 423284441Stuexen if (opt_c) { 424284441Stuexen if ((sock = calloc(1, sizeof *sock)) == NULL) 425284441Stuexen err(1, "malloc()"); 426284441Stuexen sock->socket = xinpcb->socket; 427284441Stuexen sock->proto = IPPROTO_SCTP; 428284441Stuexen sock->protoname = "sctp"; 429294231Stuexen sock->state = (int)xstcb->state; 430284441Stuexen if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 431284441Stuexen sock->family = AF_INET6; 432284441Stuexen sock->vflag = INP_IPV6; 433284441Stuexen } else { 434284441Stuexen sock->family = AF_INET; 435284441Stuexen sock->vflag = INP_IPV4; 436284441Stuexen } 437284441Stuexen } 438284441Stuexen prev_laddr = NULL; 439284441Stuexen local_all_loopback = 1; 440284441Stuexen while (offset < len) { 441284441Stuexen xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 442284441Stuexen offset += sizeof(struct xsctp_laddr); 443284441Stuexen if (xladdr->last == 1) 444284441Stuexen break; 445284441Stuexen if (!opt_c) 446284441Stuexen continue; 447284441Stuexen if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 448284441Stuexen err(1, "malloc()"); 449284441Stuexen switch (xladdr->address.sa.sa_family) { 450284441Stuexen case AF_INET: 451284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 452284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 453284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 454284441Stuexen local_all_loopback = 0; 455284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 456284441Stuexen sockaddr(&laddr->address, 457284441Stuexen AF_INET, 458284441Stuexen &xladdr->address.sin.sin_addr, 459284441Stuexen htons(xstcb->local_port)); 460284441Stuexen break; 461284441Stuexen case AF_INET6: 462284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 463284441Stuexen local_all_loopback = 0; 464284441Stuexen sockaddr(&laddr->address, 465284441Stuexen AF_INET6, 466284441Stuexen &xladdr->address.sin6.sin6_addr, 467284441Stuexen htons(xstcb->local_port)); 468284441Stuexen break; 469284441Stuexen default: 470293290Sbdrewery errx(1, "address family %d not supported", 471284441Stuexen xladdr->address.sa.sa_family); 472284441Stuexen } 473284441Stuexen laddr->next = NULL; 474284441Stuexen if (prev_laddr == NULL) 475284441Stuexen sock->laddr = laddr; 476284441Stuexen else 477284441Stuexen prev_laddr->next = laddr; 478284441Stuexen prev_laddr = laddr; 479284441Stuexen } 480284441Stuexen prev_faddr = NULL; 481284441Stuexen foreign_all_loopback = 1; 482284441Stuexen while (offset < len) { 483284441Stuexen xraddr = (struct xsctp_raddr *)(void *)(buf + offset); 484284441Stuexen offset += sizeof(struct xsctp_raddr); 485284441Stuexen if (xraddr->last == 1) 486284441Stuexen break; 487284441Stuexen if (!opt_c) 488284441Stuexen continue; 489284441Stuexen if ((faddr = calloc(1, sizeof(struct addr))) == NULL) 490284441Stuexen err(1, "malloc()"); 491284441Stuexen switch (xraddr->address.sa.sa_family) { 492284441Stuexen case AF_INET: 493284441Stuexen#define __IN_IS_ADDR_LOOPBACK(pina) \ 494284441Stuexen ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 495284441Stuexen if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) 496284441Stuexen foreign_all_loopback = 0; 497284441Stuexen#undef __IN_IS_ADDR_LOOPBACK 498284441Stuexen sockaddr(&faddr->address, 499284441Stuexen AF_INET, 500284441Stuexen &xraddr->address.sin.sin_addr, 501284441Stuexen htons(xstcb->remote_port)); 502284441Stuexen break; 503284441Stuexen case AF_INET6: 504284441Stuexen if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) 505284441Stuexen foreign_all_loopback = 0; 506284441Stuexen sockaddr(&faddr->address, 507284441Stuexen AF_INET6, 508284441Stuexen &xraddr->address.sin6.sin6_addr, 509284441Stuexen htons(xstcb->remote_port)); 510284441Stuexen break; 511284441Stuexen default: 512293290Sbdrewery errx(1, "address family %d not supported", 513284441Stuexen xraddr->address.sa.sa_family); 514284441Stuexen } 515284441Stuexen faddr->next = NULL; 516284441Stuexen if (prev_faddr == NULL) 517284441Stuexen sock->faddr = faddr; 518284441Stuexen else 519284441Stuexen prev_faddr->next = faddr; 520284441Stuexen prev_faddr = faddr; 521284441Stuexen } 522284694Stuexen if (opt_c) { 523284694Stuexen if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { 524284694Stuexen hash = (int)((uintptr_t)sock->socket % HASHSIZE); 525284694Stuexen sock->next = sockhash[hash]; 526284694Stuexen sockhash[hash] = sock; 527284694Stuexen } else { 528284694Stuexen free_socket(sock); 529284694Stuexen } 530284441Stuexen } 531284441Stuexen } 532284441Stuexen xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 533284441Stuexen offset += sizeof(struct xsctp_inpcb); 534284441Stuexen } 535284441Stuexen free(buf); 536284441Stuexen} 537284441Stuexen 538284441Stuexenstatic void 539101043Sdesgather_inet(int proto) 540101043Sdes{ 541101043Sdes struct xinpgen *xig, *exig; 542101043Sdes struct xinpcb *xip; 543101043Sdes struct xtcpcb *xtp; 544101043Sdes struct inpcb *inp; 545101043Sdes struct xsocket *so; 546101043Sdes struct sock *sock; 547284441Stuexen struct addr *laddr, *faddr; 548101043Sdes const char *varname, *protoname; 549101043Sdes size_t len, bufsize; 550101043Sdes void *buf; 551294230Stuexen int hash, retry, vflag; 552101043Sdes 553294230Stuexen vflag = 0; 554101043Sdes if (opt_4) 555101043Sdes vflag |= INP_IPV4; 556101043Sdes if (opt_6) 557101043Sdes vflag |= INP_IPV6; 558101043Sdes 559101043Sdes switch (proto) { 560101043Sdes case IPPROTO_TCP: 561101043Sdes varname = "net.inet.tcp.pcblist"; 562101043Sdes protoname = "tcp"; 563101043Sdes break; 564101043Sdes case IPPROTO_UDP: 565101043Sdes varname = "net.inet.udp.pcblist"; 566101043Sdes protoname = "udp"; 567101043Sdes break; 568138391Sru case IPPROTO_DIVERT: 569138391Sru varname = "net.inet.divert.pcblist"; 570138391Sru protoname = "div"; 571138391Sru break; 572101043Sdes default: 573164201Skeramida errx(1, "protocol %d not supported", proto); 574101043Sdes } 575101043Sdes 576101043Sdes buf = NULL; 577101043Sdes bufsize = 8192; 578101043Sdes retry = 5; 579101043Sdes do { 580101043Sdes for (;;) { 581101043Sdes if ((buf = realloc(buf, bufsize)) == NULL) 582101043Sdes err(1, "realloc()"); 583101043Sdes len = bufsize; 584101043Sdes if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 585101043Sdes break; 586138437Sru if (errno == ENOENT) 587138437Sru goto out; 588230874Strociny if (errno != ENOMEM || len != bufsize) 589101043Sdes err(1, "sysctlbyname()"); 590101043Sdes bufsize *= 2; 591101043Sdes } 592101043Sdes xig = (struct xinpgen *)buf; 593101220Srobert exig = (struct xinpgen *)(void *) 594101220Srobert ((char *)buf + len - sizeof *exig); 595101043Sdes if (xig->xig_len != sizeof *xig || 596101043Sdes exig->xig_len != sizeof *exig) 597101043Sdes errx(1, "struct xinpgen size mismatch"); 598101043Sdes } while (xig->xig_gen != exig->xig_gen && retry--); 599101043Sdes 600101043Sdes if (xig->xig_gen != exig->xig_gen && opt_v) 601101043Sdes warnx("warning: data may be inconsistent"); 602101043Sdes 603101043Sdes for (;;) { 604101220Srobert xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 605101043Sdes if (xig >= exig) 606101043Sdes break; 607294226Stuexen xip = (struct xinpcb *)xig; 608294226Stuexen xtp = (struct xtcpcb *)xig; 609101043Sdes switch (proto) { 610101043Sdes case IPPROTO_TCP: 611285826Shrs if (xtp->xt_len != sizeof(*xtp)) { 612101043Sdes warnx("struct xtcpcb size mismatch"); 613101043Sdes goto out; 614101043Sdes } 615101043Sdes inp = &xtp->xt_inp; 616101043Sdes so = &xtp->xt_socket; 617237263Snp protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; 618101043Sdes break; 619101043Sdes case IPPROTO_UDP: 620138391Sru case IPPROTO_DIVERT: 621285826Shrs if (xip->xi_len != sizeof(*xip)) { 622101043Sdes warnx("struct xinpcb size mismatch"); 623101043Sdes goto out; 624101043Sdes } 625101043Sdes inp = &xip->xi_inp; 626101043Sdes so = &xip->xi_socket; 627101043Sdes break; 628101043Sdes default: 629164201Skeramida errx(1, "protocol %d not supported", proto); 630101043Sdes } 631101043Sdes if ((inp->inp_vflag & vflag) == 0) 632101043Sdes continue; 633101144Sdes if (inp->inp_vflag & INP_IPV4) { 634101144Sdes if ((inp->inp_fport == 0 && !opt_l) || 635101144Sdes (inp->inp_fport != 0 && !opt_c)) 636101144Sdes continue; 637179115Sbms#define __IN_IS_ADDR_LOOPBACK(pina) \ 638179115Sbms ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 639179115Sbms if (opt_L && 640179115Sbms (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || 641179115Sbms __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) 642179115Sbms continue; 643179115Sbms#undef __IN_IS_ADDR_LOOPBACK 644101144Sdes } else if (inp->inp_vflag & INP_IPV6) { 645189637Srwatson if ((inp->inp_fport == 0 && !opt_l) || 646189637Srwatson (inp->inp_fport != 0 && !opt_c)) 647101144Sdes continue; 648179115Sbms if (opt_L && 649179115Sbms (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || 650179115Sbms IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) 651179115Sbms continue; 652101144Sdes } else { 653101144Sdes if (opt_v) 654101144Sdes warnx("invalid vflag 0x%x", inp->inp_vflag); 655101144Sdes continue; 656101144Sdes } 657285826Shrs if ((sock = calloc(1, sizeof(*sock))) == NULL) 658101043Sdes err(1, "malloc()"); 659284441Stuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 660284441Stuexen err(1, "malloc()"); 661284441Stuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 662284441Stuexen err(1, "malloc()"); 663101043Sdes sock->socket = so->xso_so; 664101043Sdes sock->proto = proto; 665101043Sdes if (inp->inp_vflag & INP_IPV4) { 666101043Sdes sock->family = AF_INET; 667284441Stuexen sockaddr(&laddr->address, sock->family, 668101043Sdes &inp->inp_laddr, inp->inp_lport); 669284441Stuexen sockaddr(&faddr->address, sock->family, 670101043Sdes &inp->inp_faddr, inp->inp_fport); 671101043Sdes } else if (inp->inp_vflag & INP_IPV6) { 672101043Sdes sock->family = AF_INET6; 673284441Stuexen sockaddr(&laddr->address, sock->family, 674189637Srwatson &inp->in6p_laddr, inp->inp_lport); 675284441Stuexen sockaddr(&faddr->address, sock->family, 676189637Srwatson &inp->in6p_faddr, inp->inp_fport); 677101043Sdes } 678284441Stuexen laddr->next = NULL; 679284441Stuexen faddr->next = NULL; 680284441Stuexen sock->laddr = laddr; 681284441Stuexen sock->faddr = faddr; 682101043Sdes sock->vflag = inp->inp_vflag; 683294225Stuexen if (proto == IPPROTO_TCP) 684294225Stuexen sock->state = xtp->xt_tp.t_state; 685101043Sdes sock->protoname = protoname; 686101043Sdes hash = (int)((uintptr_t)sock->socket % HASHSIZE); 687101043Sdes sock->next = sockhash[hash]; 688101043Sdes sockhash[hash] = sock; 689101043Sdes } 690101043Sdesout: 691101043Sdes free(buf); 692101043Sdes} 693101043Sdes 694101043Sdesstatic void 695101043Sdesgather_unix(int proto) 696101043Sdes{ 697101043Sdes struct xunpgen *xug, *exug; 698101043Sdes struct xunpcb *xup; 699101043Sdes struct sock *sock; 700284441Stuexen struct addr *laddr, *faddr; 701101043Sdes const char *varname, *protoname; 702101043Sdes size_t len, bufsize; 703101043Sdes void *buf; 704101043Sdes int hash, retry; 705101043Sdes 706101043Sdes switch (proto) { 707101043Sdes case SOCK_STREAM: 708101043Sdes varname = "net.local.stream.pcblist"; 709101043Sdes protoname = "stream"; 710101043Sdes break; 711101043Sdes case SOCK_DGRAM: 712101043Sdes varname = "net.local.dgram.pcblist"; 713101043Sdes protoname = "dgram"; 714101043Sdes break; 715285826Shrs case SOCK_SEQPACKET: 716285826Shrs varname = "net.local.seqpacket.pcblist"; 717285826Shrs protoname = "seqpac"; 718285826Shrs break; 719101043Sdes default: 720101043Sdes abort(); 721101043Sdes } 722101043Sdes buf = NULL; 723101043Sdes bufsize = 8192; 724101043Sdes retry = 5; 725101043Sdes do { 726101043Sdes for (;;) { 727101043Sdes if ((buf = realloc(buf, bufsize)) == NULL) 728101043Sdes err(1, "realloc()"); 729101043Sdes len = bufsize; 730101043Sdes if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 731101043Sdes break; 732230874Strociny if (errno != ENOMEM || len != bufsize) 733101043Sdes err(1, "sysctlbyname()"); 734101043Sdes bufsize *= 2; 735101043Sdes } 736101043Sdes xug = (struct xunpgen *)buf; 737101220Srobert exug = (struct xunpgen *)(void *) 738285826Shrs ((char *)buf + len - sizeof(*exug)); 739285826Shrs if (xug->xug_len != sizeof(*xug) || 740285826Shrs exug->xug_len != sizeof(*exug)) { 741101043Sdes warnx("struct xinpgen size mismatch"); 742101043Sdes goto out; 743101043Sdes } 744101043Sdes } while (xug->xug_gen != exug->xug_gen && retry--); 745101043Sdes 746101043Sdes if (xug->xug_gen != exug->xug_gen && opt_v) 747101043Sdes warnx("warning: data may be inconsistent"); 748101043Sdes 749101043Sdes for (;;) { 750101220Srobert xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 751101043Sdes if (xug >= exug) 752101043Sdes break; 753101043Sdes xup = (struct xunpcb *)xug; 754285826Shrs if (xup->xu_len != sizeof(*xup)) { 755101043Sdes warnx("struct xunpcb size mismatch"); 756101043Sdes goto out; 757101043Sdes } 758101144Sdes if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 759101144Sdes (xup->xu_unp.unp_conn != NULL && !opt_c)) 760101144Sdes continue; 761285826Shrs if ((sock = calloc(1, sizeof(*sock))) == NULL) 762101043Sdes err(1, "malloc()"); 763284441Stuexen if ((laddr = calloc(1, sizeof *laddr)) == NULL) 764284441Stuexen err(1, "malloc()"); 765284441Stuexen if ((faddr = calloc(1, sizeof *faddr)) == NULL) 766284441Stuexen err(1, "malloc()"); 767101043Sdes sock->socket = xup->xu_socket.xso_so; 768101043Sdes sock->pcb = xup->xu_unpp; 769101043Sdes sock->proto = proto; 770101043Sdes sock->family = AF_UNIX; 771101043Sdes sock->protoname = protoname; 772101043Sdes if (xup->xu_unp.unp_addr != NULL) 773284441Stuexen laddr->address = 774101220Srobert *(struct sockaddr_storage *)(void *)&xup->xu_addr; 775101043Sdes else if (xup->xu_unp.unp_conn != NULL) 776284441Stuexen *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 777284441Stuexen laddr->next = NULL; 778284441Stuexen faddr->next = NULL; 779284441Stuexen sock->laddr = laddr; 780284441Stuexen sock->faddr = faddr; 781101043Sdes hash = (int)((uintptr_t)sock->socket % HASHSIZE); 782101043Sdes sock->next = sockhash[hash]; 783101043Sdes sockhash[hash] = sock; 784101043Sdes } 785101043Sdesout: 786101043Sdes free(buf); 787101043Sdes} 788101043Sdes 789101043Sdesstatic void 790101043Sdesgetfiles(void) 791101043Sdes{ 792230874Strociny size_t len, olen; 793101043Sdes 794285826Shrs olen = len = sizeof(*xfiles); 795230874Strociny if ((xfiles = malloc(len)) == NULL) 796101043Sdes err(1, "malloc()"); 797101043Sdes while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 798230874Strociny if (errno != ENOMEM || len != olen) 799101043Sdes err(1, "sysctlbyname()"); 800230874Strociny olen = len *= 2; 801101043Sdes if ((xfiles = realloc(xfiles, len)) == NULL) 802101043Sdes err(1, "realloc()"); 803101043Sdes } 804285826Shrs if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 805101043Sdes errx(1, "struct xfile size mismatch"); 806285826Shrs nxfiles = len / sizeof(*xfiles); 807101043Sdes} 808101043Sdes 809101043Sdesstatic int 810284441Stuexenprintaddr(struct sockaddr_storage *ss) 811101043Sdes{ 812101043Sdes struct sockaddr_un *sun; 813285826Shrs char addrstr[NI_MAXHOST] = { '\0', '\0' }; 814285826Shrs int error, off, port = 0; 815101043Sdes 816284441Stuexen switch (ss->ss_family) { 817101043Sdes case AF_INET: 818285826Shrs if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) 819101043Sdes addrstr[0] = '*'; 820285826Shrs port = ntohs(sstosin(ss)->sin_port); 821101043Sdes break; 822101043Sdes case AF_INET6: 823285826Shrs if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 824101043Sdes addrstr[0] = '*'; 825285826Shrs port = ntohs(sstosin6(ss)->sin6_port); 826101043Sdes break; 827101043Sdes case AF_UNIX: 828285826Shrs sun = sstosun(ss); 829101043Sdes off = (int)((char *)&sun->sun_path - (char *)sun); 830101043Sdes return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 831101043Sdes } 832285826Shrs if (addrstr[0] == '\0') { 833285826Shrs error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, 834285826Shrs sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 835285826Shrs if (error) 836285826Shrs errx(1, "getnameinfo()"); 837285826Shrs } 838101043Sdes if (port == 0) 839101043Sdes return xprintf("%s:*", addrstr); 840101043Sdes else 841101043Sdes return xprintf("%s:%d", addrstr, port); 842101043Sdes} 843101043Sdes 844101043Sdesstatic const char * 845101043Sdesgetprocname(pid_t pid) 846101043Sdes{ 847101043Sdes static struct kinfo_proc proc; 848101043Sdes size_t len; 849101043Sdes int mib[4]; 850101043Sdes 851101043Sdes mib[0] = CTL_KERN; 852101043Sdes mib[1] = KERN_PROC; 853101043Sdes mib[2] = KERN_PROC_PID; 854101043Sdes mib[3] = (int)pid; 855285826Shrs len = sizeof(proc); 856285826Shrs if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 857170833Smaxim /* Do not warn if the process exits before we get its name. */ 858170833Smaxim if (errno != ESRCH) 859170833Smaxim warn("sysctl()"); 860101043Sdes return ("??"); 861101043Sdes } 862167810Semaste return (proc.ki_comm); 863101043Sdes} 864101043Sdes 865115955Smuxstatic int 866235870Sthompsagetprocjid(pid_t pid) 867235870Sthompsa{ 868235870Sthompsa static struct kinfo_proc proc; 869235870Sthompsa size_t len; 870235870Sthompsa int mib[4]; 871235870Sthompsa 872235870Sthompsa mib[0] = CTL_KERN; 873235870Sthompsa mib[1] = KERN_PROC; 874235870Sthompsa mib[2] = KERN_PROC_PID; 875235870Sthompsa mib[3] = (int)pid; 876285826Shrs len = sizeof(proc); 877285826Shrs if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 878235870Sthompsa /* Do not warn if the process exits before we get its jid. */ 879235870Sthompsa if (errno != ESRCH) 880235870Sthompsa warn("sysctl()"); 881235870Sthompsa return (-1); 882235870Sthompsa } 883235870Sthompsa return (proc.ki_jid); 884235870Sthompsa} 885235870Sthompsa 886235870Sthompsastatic int 887115955Smuxcheck_ports(struct sock *s) 888115955Smux{ 889115955Smux int port; 890284441Stuexen struct addr *addr; 891115955Smux 892115955Smux if (ports == NULL) 893115955Smux return (1); 894115955Smux if ((s->family != AF_INET) && (s->family != AF_INET6)) 895115955Smux return (1); 896284441Stuexen for (addr = s->laddr; addr != NULL; addr = addr->next) { 897285826Shrs if (s->family == AF_INET) 898285826Shrs port = ntohs(sstosin(&addr->address)->sin_port); 899284441Stuexen else 900285826Shrs port = ntohs(sstosin6(&addr->address)->sin6_port); 901284441Stuexen if (CHK_PORT(port)) 902284441Stuexen return (1); 903284441Stuexen } 904284441Stuexen for (addr = s->faddr; addr != NULL; addr = addr->next) { 905285826Shrs if (s->family == AF_INET) 906285826Shrs port = ntohs(sstosin(&addr->address)->sin_port); 907284441Stuexen else 908285826Shrs port = ntohs(sstosin6(&addr->address)->sin6_port); 909284441Stuexen if (CHK_PORT(port)) 910284441Stuexen return (1); 911284441Stuexen } 912115955Smux return (0); 913115955Smux} 914115955Smux 915294231Stuexenstatic const char * 916294231Stuexensctp_state(int state) 917294231Stuexen{ 918294231Stuexen switch (state) { 919294231Stuexen case SCTP_CLOSED: 920294231Stuexen return "CLOSED"; 921294231Stuexen break; 922294231Stuexen case SCTP_BOUND: 923294231Stuexen return "BOUND"; 924294231Stuexen break; 925294231Stuexen case SCTP_LISTEN: 926294231Stuexen return "LISTEN"; 927294231Stuexen break; 928294231Stuexen case SCTP_COOKIE_WAIT: 929294231Stuexen return "COOKIE_WAIT"; 930294231Stuexen break; 931294231Stuexen case SCTP_COOKIE_ECHOED: 932294231Stuexen return "COOKIE_ECHOED"; 933294231Stuexen break; 934294231Stuexen case SCTP_ESTABLISHED: 935294231Stuexen return "ESTABLISHED"; 936294231Stuexen break; 937294231Stuexen case SCTP_SHUTDOWN_SENT: 938294231Stuexen return "SHUTDOWN_SENT"; 939294231Stuexen break; 940294231Stuexen case SCTP_SHUTDOWN_RECEIVED: 941294231Stuexen return "SHUTDOWN_RECEIVED"; 942294231Stuexen break; 943294231Stuexen case SCTP_SHUTDOWN_ACK_SENT: 944294231Stuexen return "SHUTDOWN_ACK_SENT"; 945294231Stuexen break; 946294231Stuexen case SCTP_SHUTDOWN_PENDING: 947294231Stuexen return "SHUTDOWN_PENDING"; 948294231Stuexen break; 949294231Stuexen default: 950294231Stuexen return "UNKNOWN"; 951294231Stuexen break; 952294231Stuexen } 953294231Stuexen} 954294231Stuexen 955101043Sdesstatic void 956230512Sjillesdisplaysock(struct sock *s, int pos) 957230512Sjilles{ 958230512Sjilles void *p; 959294228Sdes int hash, first; 960284441Stuexen struct addr *laddr, *faddr; 961284692Stuexen struct sock *s_tmp; 962230512Sjilles 963230512Sjilles while (pos < 29) 964230512Sjilles pos += xprintf(" "); 965230512Sjilles pos += xprintf("%s", s->protoname); 966230512Sjilles if (s->vflag & INP_IPV4) 967230512Sjilles pos += xprintf("4 "); 968230512Sjilles if (s->vflag & INP_IPV6) 969230512Sjilles pos += xprintf("6 "); 970284441Stuexen laddr = s->laddr; 971284441Stuexen faddr = s->faddr; 972294228Sdes first = 1; 973284441Stuexen while (laddr != NULL || faddr != NULL) { 974284441Stuexen while (pos < 36) 975230512Sjilles pos += xprintf(" "); 976284441Stuexen switch (s->family) { 977284441Stuexen case AF_INET: 978284441Stuexen case AF_INET6: 979284441Stuexen if (laddr != NULL) { 980284441Stuexen pos += printaddr(&laddr->address); 981284441Stuexen if (s->family == AF_INET6 && pos >= 58) 982284441Stuexen pos += xprintf(" "); 983284441Stuexen } 984284441Stuexen while (pos < 58) 985284441Stuexen pos += xprintf(" "); 986284441Stuexen if (faddr != NULL) 987284441Stuexen pos += printaddr(&faddr->address); 988230512Sjilles break; 989284441Stuexen case AF_UNIX: 990284441Stuexen if ((laddr == NULL) || (faddr == NULL)) 991284441Stuexen errx(1, "laddr = %p or faddr = %p is NULL", 992284441Stuexen (void *)laddr, (void *)faddr); 993284441Stuexen /* server */ 994284441Stuexen if (laddr->address.ss_len > 0) { 995284441Stuexen pos += printaddr(&laddr->address); 996284441Stuexen break; 997284441Stuexen } 998284441Stuexen /* client */ 999284441Stuexen p = *(void **)&(faddr->address); 1000284441Stuexen if (p == NULL) { 1001284441Stuexen pos += xprintf("(not connected)"); 1002284441Stuexen break; 1003284441Stuexen } 1004284441Stuexen pos += xprintf("-> "); 1005284441Stuexen for (hash = 0; hash < HASHSIZE; ++hash) { 1006284692Stuexen for (s_tmp = sockhash[hash]; 1007284692Stuexen s_tmp != NULL; 1008284692Stuexen s_tmp = s_tmp->next) 1009284692Stuexen if (s_tmp->pcb == p) 1010284441Stuexen break; 1011284692Stuexen if (s_tmp != NULL) 1012284441Stuexen break; 1013284441Stuexen } 1014284692Stuexen if (s_tmp == NULL || 1015284692Stuexen s_tmp->laddr == NULL || 1016284692Stuexen s_tmp->laddr->address.ss_len == 0) 1017284441Stuexen pos += xprintf("??"); 1018284441Stuexen else 1019284692Stuexen pos += printaddr(&s_tmp->laddr->address); 1020230512Sjilles break; 1021284441Stuexen default: 1022284441Stuexen abort(); 1023230512Sjilles } 1024294231Stuexen if (first && opt_s && 1025294231Stuexen (s->proto == IPPROTO_SCTP || s->proto == IPPROTO_TCP)) { 1026294228Sdes while (pos < 80) 1027294228Sdes pos += xprintf(" "); 1028294231Stuexen switch (s->proto) { 1029294231Stuexen case IPPROTO_SCTP: 1030294231Stuexen pos += xprintf("%s", sctp_state(s->state)); 1031294231Stuexen break; 1032294231Stuexen case IPPROTO_TCP: 1033294231Stuexen if (s->state >= 0 && s->state < TCP_NSTATES) 1034294231Stuexen pos += 1035294231Stuexen xprintf("%s", tcpstates[s->state]); 1036294231Stuexen else 1037294231Stuexen pos += xprintf("?"); 1038294231Stuexen break; 1039294231Stuexen } 1040294228Sdes } 1041284441Stuexen if (laddr != NULL) 1042284441Stuexen laddr = laddr->next; 1043284441Stuexen if (faddr != NULL) 1044284441Stuexen faddr = faddr->next; 1045284441Stuexen if ((laddr != NULL) || (faddr != NULL)) { 1046284441Stuexen xprintf("\n"); 1047284441Stuexen pos = 0; 1048230512Sjilles } 1049294228Sdes first = 0; 1050230512Sjilles } 1051294228Sdes xprintf("\n"); 1052230512Sjilles} 1053230512Sjilles 1054230512Sjillesstatic void 1055101043Sdesdisplay(void) 1056101043Sdes{ 1057101043Sdes struct passwd *pwd; 1058101043Sdes struct xfile *xf; 1059101043Sdes struct sock *s; 1060101043Sdes int hash, n, pos; 1061101043Sdes 1062294225Stuexen printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", 1063101043Sdes "USER", "COMMAND", "PID", "FD", "PROTO", 1064101043Sdes "LOCAL ADDRESS", "FOREIGN ADDRESS"); 1065294225Stuexen if (opt_s) 1066294225Stuexen printf(" %-12s", "STATE"); 1067294225Stuexen printf("\n"); 1068101043Sdes setpassent(1); 1069101043Sdes for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 1070134295Sroam if (xf->xf_data == NULL) 1071134295Sroam continue; 1072235870Sthompsa if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 1073235870Sthompsa continue; 1074109153Sdillon hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 1075284441Stuexen for (s = sockhash[hash]; s != NULL; s = s->next) { 1076284441Stuexen if ((void *)s->socket != xf->xf_data) 1077284441Stuexen continue; 1078284441Stuexen if (!check_ports(s)) 1079284441Stuexen continue; 1080284441Stuexen s->shown = 1; 1081284441Stuexen pos = 0; 1082284441Stuexen if ((pwd = getpwuid(xf->xf_uid)) == NULL) 1083284441Stuexen pos += xprintf("%lu ", (u_long)xf->xf_uid); 1084284441Stuexen else 1085284441Stuexen pos += xprintf("%s ", pwd->pw_name); 1086284441Stuexen while (pos < 9) 1087284441Stuexen pos += xprintf(" "); 1088284441Stuexen pos += xprintf("%.10s", getprocname(xf->xf_pid)); 1089284441Stuexen while (pos < 20) 1090284441Stuexen pos += xprintf(" "); 1091284441Stuexen pos += xprintf("%lu ", (u_long)xf->xf_pid); 1092284441Stuexen while (pos < 26) 1093284441Stuexen pos += xprintf(" "); 1094284441Stuexen pos += xprintf("%d ", xf->xf_fd); 1095284441Stuexen displaysock(s, pos); 1096284441Stuexen } 1097230512Sjilles } 1098235870Sthompsa if (opt_j >= 0) 1099235870Sthompsa return; 1100230512Sjilles for (hash = 0; hash < HASHSIZE; hash++) { 1101230512Sjilles for (s = sockhash[hash]; s != NULL; s = s->next) { 1102230512Sjilles if (s->shown) 1103230512Sjilles continue; 1104230512Sjilles if (!check_ports(s)) 1105230512Sjilles continue; 1106230512Sjilles pos = 0; 1107230512Sjilles pos += xprintf("%-8s %-10s %-5s %-2s ", 1108230512Sjilles "?", "?", "?", "?"); 1109230512Sjilles displaysock(s, pos); 1110101043Sdes } 1111101043Sdes } 1112101043Sdes} 1113101043Sdes 1114164201Skeramidastatic int set_default_protos(void) 1115164201Skeramida{ 1116164201Skeramida struct protoent *prot; 1117164201Skeramida const char *pname; 1118164201Skeramida size_t pindex; 1119164201Skeramida 1120164201Skeramida init_protos(default_numprotos); 1121164201Skeramida 1122164201Skeramida for (pindex = 0; pindex < default_numprotos; pindex++) { 1123164201Skeramida pname = default_protos[pindex]; 1124164201Skeramida prot = getprotobyname(pname); 1125164201Skeramida if (prot == NULL) 1126164201Skeramida err(1, "getprotobyname: %s", pname); 1127164201Skeramida protos[pindex] = prot->p_proto; 1128164201Skeramida } 1129164201Skeramida numprotos = pindex; 1130164201Skeramida return (pindex); 1131164201Skeramida} 1132164201Skeramida 1133164201Skeramida 1134101043Sdesstatic void 1135101043Sdesusage(void) 1136101043Sdes{ 1137164201Skeramida fprintf(stderr, 1138294225Stuexen "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); 1139101043Sdes exit(1); 1140101043Sdes} 1141101043Sdes 1142101043Sdesint 1143101043Sdesmain(int argc, char *argv[]) 1144101043Sdes{ 1145164201Skeramida int protos_defined = -1; 1146164201Skeramida int o, i; 1147101043Sdes 1148235870Sthompsa opt_j = -1; 1149294225Stuexen while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) 1150101043Sdes switch (o) { 1151101043Sdes case '4': 1152101043Sdes opt_4 = 1; 1153101043Sdes break; 1154101043Sdes case '6': 1155101043Sdes opt_6 = 1; 1156101043Sdes break; 1157101043Sdes case 'c': 1158101043Sdes opt_c = 1; 1159101043Sdes break; 1160235870Sthompsa case 'j': 1161336039Sjamie opt_j = jail_getid(optarg); 1162336039Sjamie if (opt_j < 0) 1163336039Sjamie errx(1, "%s", jail_errmsg); 1164235870Sthompsa break; 1165179115Sbms case 'L': 1166179115Sbms opt_L = 1; 1167179115Sbms break; 1168101043Sdes case 'l': 1169101043Sdes opt_l = 1; 1170101043Sdes break; 1171101043Sdes case 'p': 1172101043Sdes parse_ports(optarg); 1173101043Sdes break; 1174164201Skeramida case 'P': 1175164201Skeramida protos_defined = parse_protos(optarg); 1176164201Skeramida break; 1177294225Stuexen case 's': 1178294225Stuexen opt_s = 1; 1179294225Stuexen break; 1180101043Sdes case 'u': 1181101043Sdes opt_u = 1; 1182101043Sdes break; 1183101043Sdes case 'v': 1184101043Sdes ++opt_v; 1185101043Sdes break; 1186101043Sdes default: 1187101043Sdes usage(); 1188101043Sdes } 1189101043Sdes 1190101043Sdes argc -= optind; 1191101043Sdes argv += optind; 1192101043Sdes 1193101043Sdes if (argc > 0) 1194101043Sdes usage(); 1195101043Sdes 1196164226Skeramida if ((!opt_4 && !opt_6) && protos_defined != -1) 1197164226Skeramida opt_4 = opt_6 = 1; 1198164226Skeramida if (!opt_4 && !opt_6 && !opt_u) 1199164226Skeramida opt_4 = opt_6 = opt_u = 1; 1200164226Skeramida if ((opt_4 || opt_6) && protos_defined == -1) 1201164201Skeramida protos_defined = set_default_protos(); 1202101043Sdes if (!opt_c && !opt_l) 1203101043Sdes opt_c = opt_l = 1; 1204101043Sdes 1205101043Sdes if (opt_4 || opt_6) { 1206164201Skeramida for (i = 0; i < protos_defined; i++) 1207284441Stuexen if (protos[i] == IPPROTO_SCTP) 1208284441Stuexen gather_sctp(); 1209284441Stuexen else 1210284441Stuexen gather_inet(protos[i]); 1211101043Sdes } 1212164201Skeramida 1213164201Skeramida if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1214101043Sdes gather_unix(SOCK_STREAM); 1215101043Sdes gather_unix(SOCK_DGRAM); 1216285826Shrs gather_unix(SOCK_SEQPACKET); 1217101043Sdes } 1218101043Sdes getfiles(); 1219101043Sdes display(); 1220101043Sdes exit(0); 1221101043Sdes} 1222