sockstat.c revision 336039
1/*- 2 * Copyright (c) 2002 Dag-Erling Co��dan Sm��rgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/10/usr.bin/sockstat/sockstat.c 336039 2018-07-06 19:10:07Z jamie $"); 31 32#include <sys/param.h> 33#include <sys/socket.h> 34#include <sys/socketvar.h> 35#include <sys/sysctl.h> 36#include <sys/file.h> 37#include <sys/user.h> 38 39#include <sys/un.h> 40#include <sys/unpcb.h> 41 42#include <net/route.h> 43 44#include <netinet/in.h> 45#include <netinet/in_pcb.h> 46#include <netinet/sctp.h> 47#include <netinet/tcp.h> 48#define TCPSTATES /* load state names */ 49#include <netinet/tcp_fsm.h> 50#include <netinet/tcp_seq.h> 51#include <netinet/tcp_var.h> 52#include <arpa/inet.h> 53 54#include <ctype.h> 55#include <err.h> 56#include <errno.h> 57#include <jail.h> 58#include <netdb.h> 59#include <pwd.h> 60#include <stdarg.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64#include <unistd.h> 65 66#define sstosin(ss) ((struct sockaddr_in *)(ss)) 67#define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) 68#define sstosun(ss) ((struct sockaddr_un *)(ss)) 69#define sstosa(ss) ((struct sockaddr *)(ss)) 70 71static int opt_4; /* Show IPv4 sockets */ 72static int opt_6; /* Show IPv6 sockets */ 73static int opt_c; /* Show connected sockets */ 74static int opt_j; /* Show specified jail */ 75static int opt_L; /* Don't show IPv4 or IPv6 loopback sockets */ 76static int opt_l; /* Show listening sockets */ 77static int opt_s; /* Show protocol state if applicable */ 78static int opt_u; /* Show Unix domain sockets */ 79static int opt_v; /* Verbose mode */ 80 81/* 82 * Default protocols to use if no -P was defined. 83 */ 84static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; 85static size_t default_numprotos = nitems(default_protos); 86 87static int *protos; /* protocols to use */ 88static size_t numprotos; /* allocated size of protos[] */ 89 90static int *ports; 91 92#define INT_BIT (sizeof(int)*CHAR_BIT) 93#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) 94#define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT))) 95 96struct addr { 97 struct sockaddr_storage address; 98 struct addr *next; 99}; 100 101struct sock { 102 void *socket; 103 void *pcb; 104 int shown; 105 int vflag; 106 int family; 107 int proto; 108 int state; 109 const char *protoname; 110 struct addr *laddr; 111 struct addr *faddr; 112 struct sock *next; 113}; 114 115#define HASHSIZE 1009 116static struct sock *sockhash[HASHSIZE]; 117 118static struct xfile *xfiles; 119static int nxfiles; 120 121static int 122xprintf(const char *fmt, ...) 123{ 124 va_list ap; 125 int len; 126 127 va_start(ap, fmt); 128 len = vprintf(fmt, ap); 129 va_end(ap); 130 if (len < 0) 131 err(1, "printf()"); 132 return (len); 133} 134 135 136static int 137get_proto_type(const char *proto) 138{ 139 struct protoent *pent; 140 141 if (strlen(proto) == 0) 142 return (0); 143 pent = getprotobyname(proto); 144 if (pent == NULL) { 145 warn("getprotobyname"); 146 return (-1); 147 } 148 return (pent->p_proto); 149} 150 151 152static void 153init_protos(int num) 154{ 155 int proto_count = 0; 156 157 if (num > 0) { 158 proto_count = num; 159 } else { 160 /* Find the maximum number of possible protocols. */ 161 while (getprotoent() != NULL) 162 proto_count++; 163 endprotoent(); 164 } 165 166 if ((protos = malloc(sizeof(int) * proto_count)) == NULL) 167 err(1, "malloc"); 168 numprotos = proto_count; 169} 170 171 172static int 173parse_protos(char *protospec) 174{ 175 char *prot; 176 int proto_type, proto_index; 177 178 if (protospec == NULL) 179 return (-1); 180 181 init_protos(0); 182 proto_index = 0; 183 while ((prot = strsep(&protospec, ",")) != NULL) { 184 if (strlen(prot) == 0) 185 continue; 186 proto_type = get_proto_type(prot); 187 if (proto_type != -1) 188 protos[proto_index++] = proto_type; 189 } 190 numprotos = proto_index; 191 return (proto_index); 192} 193 194 195static void 196parse_ports(const char *portspec) 197{ 198 const char *p, *q; 199 int port, end; 200 201 if (ports == NULL) 202 if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL) 203 err(1, "calloc()"); 204 p = portspec; 205 while (*p != '\0') { 206 if (!isdigit(*p)) 207 errx(1, "syntax error in port range"); 208 for (q = p; *q != '\0' && isdigit(*q); ++q) 209 /* nothing */ ; 210 for (port = 0; p < q; ++p) 211 port = port * 10 + digittoint(*p); 212 if (port < 0 || port > 65535) 213 errx(1, "invalid port number"); 214 SET_PORT(port); 215 switch (*p) { 216 case '-': 217 ++p; 218 break; 219 case ',': 220 ++p; 221 /* fall through */ 222 case '\0': 223 default: 224 continue; 225 } 226 for (q = p; *q != '\0' && isdigit(*q); ++q) 227 /* nothing */ ; 228 for (end = 0; p < q; ++p) 229 end = end * 10 + digittoint(*p); 230 if (end < port || end > 65535) 231 errx(1, "invalid port number"); 232 while (port++ < end) 233 SET_PORT(port); 234 if (*p == ',') 235 ++p; 236 } 237} 238 239static void 240sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port) 241{ 242 struct sockaddr_in *sin4; 243 struct sockaddr_in6 *sin6; 244 245 bzero(ss, sizeof(*ss)); 246 switch (af) { 247 case AF_INET: 248 sin4 = sstosin(ss); 249 sin4->sin_len = sizeof(*sin4); 250 sin4->sin_family = af; 251 sin4->sin_port = port; 252 sin4->sin_addr = *(struct in_addr *)addr; 253 break; 254 case AF_INET6: 255 sin6 = sstosin6(ss); 256 sin6->sin6_len = sizeof(*sin6); 257 sin6->sin6_family = af; 258 sin6->sin6_port = port; 259 sin6->sin6_addr = *(struct in6_addr *)addr; 260#define s6_addr16 __u6_addr.__u6_addr16 261 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 262 sin6->sin6_scope_id = 263 ntohs(sin6->sin6_addr.s6_addr16[1]); 264 sin6->sin6_addr.s6_addr16[1] = 0; 265 } 266 break; 267 default: 268 abort(); 269 } 270} 271 272static void 273free_socket(struct sock *sock) 274{ 275 struct addr *cur, *next; 276 277 cur = sock->laddr; 278 while (cur != NULL) { 279 next = cur->next; 280 free(cur); 281 cur = next; 282 } 283 cur = sock->faddr; 284 while (cur != NULL) { 285 next = cur->next; 286 free(cur); 287 cur = next; 288 } 289 free(sock); 290} 291 292static void 293gather_sctp(void) 294{ 295 struct sock *sock; 296 struct addr *laddr, *prev_laddr, *faddr, *prev_faddr; 297 struct xsctp_inpcb *xinpcb; 298 struct xsctp_tcb *xstcb; 299 struct xsctp_raddr *xraddr; 300 struct xsctp_laddr *xladdr; 301 const char *varname; 302 size_t len, offset; 303 char *buf; 304 int hash, vflag; 305 int no_stcb, local_all_loopback, foreign_all_loopback; 306 307 vflag = 0; 308 if (opt_4) 309 vflag |= INP_IPV4; 310 if (opt_6) 311 vflag |= INP_IPV6; 312 313 varname = "net.inet.sctp.assoclist"; 314 if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { 315 if (errno != ENOENT) 316 err(1, "sysctlbyname()"); 317 return; 318 } 319 if ((buf = (char *)malloc(len)) == NULL) { 320 err(1, "malloc()"); 321 return; 322 } 323 if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { 324 err(1, "sysctlbyname()"); 325 free(buf); 326 return; 327 } 328 xinpcb = (struct xsctp_inpcb *)(void *)buf; 329 offset = sizeof(struct xsctp_inpcb); 330 while ((offset < len) && (xinpcb->last == 0)) { 331 if ((sock = calloc(1, sizeof *sock)) == NULL) 332 err(1, "malloc()"); 333 sock->socket = xinpcb->socket; 334 sock->proto = IPPROTO_SCTP; 335 sock->protoname = "sctp"; 336 if (xinpcb->maxqlen == 0) 337 sock->state = SCTP_CLOSED; 338 else 339 sock->state = SCTP_LISTEN; 340 if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 341 sock->family = AF_INET6; 342 sock->vflag = INP_IPV6; 343 } else { 344 sock->family = AF_INET; 345 sock->vflag = INP_IPV4; 346 } 347 prev_laddr = NULL; 348 local_all_loopback = 1; 349 while (offset < len) { 350 xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 351 offset += sizeof(struct xsctp_laddr); 352 if (xladdr->last == 1) 353 break; 354 if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 355 err(1, "malloc()"); 356 switch (xladdr->address.sa.sa_family) { 357 case AF_INET: 358#define __IN_IS_ADDR_LOOPBACK(pina) \ 359 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 360 if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 361 local_all_loopback = 0; 362#undef __IN_IS_ADDR_LOOPBACK 363 sockaddr(&laddr->address, 364 AF_INET, 365 &xladdr->address.sin.sin_addr, 366 htons(xinpcb->local_port)); 367 break; 368 case AF_INET6: 369 if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 370 local_all_loopback = 0; 371 sockaddr(&laddr->address, 372 AF_INET6, 373 &xladdr->address.sin6.sin6_addr, 374 htons(xinpcb->local_port)); 375 break; 376 default: 377 errx(1, "address family %d not supported", 378 xladdr->address.sa.sa_family); 379 } 380 laddr->next = NULL; 381 if (prev_laddr == NULL) 382 sock->laddr = laddr; 383 else 384 prev_laddr->next = laddr; 385 prev_laddr = laddr; 386 } 387 if (sock->laddr == NULL) { 388 if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL) 389 err(1, "malloc()"); 390 sock->laddr->address.ss_family = sock->family; 391 if (sock->family == AF_INET) 392 sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 393 else 394 sock->laddr->address.ss_len = sizeof(struct sockaddr_in); 395 local_all_loopback = 0; 396 } 397 if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL) 398 err(1, "malloc()"); 399 sock->faddr->address.ss_family = sock->family; 400 if (sock->family == AF_INET) 401 sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 402 else 403 sock->faddr->address.ss_len = sizeof(struct sockaddr_in); 404 no_stcb = 1; 405 while (offset < len) { 406 xstcb = (struct xsctp_tcb *)(void *)(buf + offset); 407 offset += sizeof(struct xsctp_tcb); 408 if (no_stcb) { 409 if (opt_l && 410 (!opt_L || !local_all_loopback) && 411 ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || 412 (xstcb->last == 1))) { 413 hash = (int)((uintptr_t)sock->socket % HASHSIZE); 414 sock->next = sockhash[hash]; 415 sockhash[hash] = sock; 416 } else { 417 free_socket(sock); 418 } 419 } 420 if (xstcb->last == 1) 421 break; 422 no_stcb = 0; 423 if (opt_c) { 424 if ((sock = calloc(1, sizeof *sock)) == NULL) 425 err(1, "malloc()"); 426 sock->socket = xinpcb->socket; 427 sock->proto = IPPROTO_SCTP; 428 sock->protoname = "sctp"; 429 sock->state = (int)xstcb->state; 430 if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) { 431 sock->family = AF_INET6; 432 sock->vflag = INP_IPV6; 433 } else { 434 sock->family = AF_INET; 435 sock->vflag = INP_IPV4; 436 } 437 } 438 prev_laddr = NULL; 439 local_all_loopback = 1; 440 while (offset < len) { 441 xladdr = (struct xsctp_laddr *)(void *)(buf + offset); 442 offset += sizeof(struct xsctp_laddr); 443 if (xladdr->last == 1) 444 break; 445 if (!opt_c) 446 continue; 447 if ((laddr = calloc(1, sizeof(struct addr))) == NULL) 448 err(1, "malloc()"); 449 switch (xladdr->address.sa.sa_family) { 450 case AF_INET: 451#define __IN_IS_ADDR_LOOPBACK(pina) \ 452 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 453 if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr)) 454 local_all_loopback = 0; 455#undef __IN_IS_ADDR_LOOPBACK 456 sockaddr(&laddr->address, 457 AF_INET, 458 &xladdr->address.sin.sin_addr, 459 htons(xstcb->local_port)); 460 break; 461 case AF_INET6: 462 if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr)) 463 local_all_loopback = 0; 464 sockaddr(&laddr->address, 465 AF_INET6, 466 &xladdr->address.sin6.sin6_addr, 467 htons(xstcb->local_port)); 468 break; 469 default: 470 errx(1, "address family %d not supported", 471 xladdr->address.sa.sa_family); 472 } 473 laddr->next = NULL; 474 if (prev_laddr == NULL) 475 sock->laddr = laddr; 476 else 477 prev_laddr->next = laddr; 478 prev_laddr = laddr; 479 } 480 prev_faddr = NULL; 481 foreign_all_loopback = 1; 482 while (offset < len) { 483 xraddr = (struct xsctp_raddr *)(void *)(buf + offset); 484 offset += sizeof(struct xsctp_raddr); 485 if (xraddr->last == 1) 486 break; 487 if (!opt_c) 488 continue; 489 if ((faddr = calloc(1, sizeof(struct addr))) == NULL) 490 err(1, "malloc()"); 491 switch (xraddr->address.sa.sa_family) { 492 case AF_INET: 493#define __IN_IS_ADDR_LOOPBACK(pina) \ 494 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 495 if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr)) 496 foreign_all_loopback = 0; 497#undef __IN_IS_ADDR_LOOPBACK 498 sockaddr(&faddr->address, 499 AF_INET, 500 &xraddr->address.sin.sin_addr, 501 htons(xstcb->remote_port)); 502 break; 503 case AF_INET6: 504 if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr)) 505 foreign_all_loopback = 0; 506 sockaddr(&faddr->address, 507 AF_INET6, 508 &xraddr->address.sin6.sin6_addr, 509 htons(xstcb->remote_port)); 510 break; 511 default: 512 errx(1, "address family %d not supported", 513 xraddr->address.sa.sa_family); 514 } 515 faddr->next = NULL; 516 if (prev_faddr == NULL) 517 sock->faddr = faddr; 518 else 519 prev_faddr->next = faddr; 520 prev_faddr = faddr; 521 } 522 if (opt_c) { 523 if (!opt_L || !(local_all_loopback || foreign_all_loopback)) { 524 hash = (int)((uintptr_t)sock->socket % HASHSIZE); 525 sock->next = sockhash[hash]; 526 sockhash[hash] = sock; 527 } else { 528 free_socket(sock); 529 } 530 } 531 } 532 xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset); 533 offset += sizeof(struct xsctp_inpcb); 534 } 535 free(buf); 536} 537 538static void 539gather_inet(int proto) 540{ 541 struct xinpgen *xig, *exig; 542 struct xinpcb *xip; 543 struct xtcpcb *xtp; 544 struct inpcb *inp; 545 struct xsocket *so; 546 struct sock *sock; 547 struct addr *laddr, *faddr; 548 const char *varname, *protoname; 549 size_t len, bufsize; 550 void *buf; 551 int hash, retry, vflag; 552 553 vflag = 0; 554 if (opt_4) 555 vflag |= INP_IPV4; 556 if (opt_6) 557 vflag |= INP_IPV6; 558 559 switch (proto) { 560 case IPPROTO_TCP: 561 varname = "net.inet.tcp.pcblist"; 562 protoname = "tcp"; 563 break; 564 case IPPROTO_UDP: 565 varname = "net.inet.udp.pcblist"; 566 protoname = "udp"; 567 break; 568 case IPPROTO_DIVERT: 569 varname = "net.inet.divert.pcblist"; 570 protoname = "div"; 571 break; 572 default: 573 errx(1, "protocol %d not supported", proto); 574 } 575 576 buf = NULL; 577 bufsize = 8192; 578 retry = 5; 579 do { 580 for (;;) { 581 if ((buf = realloc(buf, bufsize)) == NULL) 582 err(1, "realloc()"); 583 len = bufsize; 584 if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 585 break; 586 if (errno == ENOENT) 587 goto out; 588 if (errno != ENOMEM || len != bufsize) 589 err(1, "sysctlbyname()"); 590 bufsize *= 2; 591 } 592 xig = (struct xinpgen *)buf; 593 exig = (struct xinpgen *)(void *) 594 ((char *)buf + len - sizeof *exig); 595 if (xig->xig_len != sizeof *xig || 596 exig->xig_len != sizeof *exig) 597 errx(1, "struct xinpgen size mismatch"); 598 } while (xig->xig_gen != exig->xig_gen && retry--); 599 600 if (xig->xig_gen != exig->xig_gen && opt_v) 601 warnx("warning: data may be inconsistent"); 602 603 for (;;) { 604 xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 605 if (xig >= exig) 606 break; 607 xip = (struct xinpcb *)xig; 608 xtp = (struct xtcpcb *)xig; 609 switch (proto) { 610 case IPPROTO_TCP: 611 if (xtp->xt_len != sizeof(*xtp)) { 612 warnx("struct xtcpcb size mismatch"); 613 goto out; 614 } 615 inp = &xtp->xt_inp; 616 so = &xtp->xt_socket; 617 protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; 618 break; 619 case IPPROTO_UDP: 620 case IPPROTO_DIVERT: 621 if (xip->xi_len != sizeof(*xip)) { 622 warnx("struct xinpcb size mismatch"); 623 goto out; 624 } 625 inp = &xip->xi_inp; 626 so = &xip->xi_socket; 627 break; 628 default: 629 errx(1, "protocol %d not supported", proto); 630 } 631 if ((inp->inp_vflag & vflag) == 0) 632 continue; 633 if (inp->inp_vflag & INP_IPV4) { 634 if ((inp->inp_fport == 0 && !opt_l) || 635 (inp->inp_fport != 0 && !opt_c)) 636 continue; 637#define __IN_IS_ADDR_LOOPBACK(pina) \ 638 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 639 if (opt_L && 640 (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || 641 __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) 642 continue; 643#undef __IN_IS_ADDR_LOOPBACK 644 } else if (inp->inp_vflag & INP_IPV6) { 645 if ((inp->inp_fport == 0 && !opt_l) || 646 (inp->inp_fport != 0 && !opt_c)) 647 continue; 648 if (opt_L && 649 (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || 650 IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) 651 continue; 652 } else { 653 if (opt_v) 654 warnx("invalid vflag 0x%x", inp->inp_vflag); 655 continue; 656 } 657 if ((sock = calloc(1, sizeof(*sock))) == NULL) 658 err(1, "malloc()"); 659 if ((laddr = calloc(1, sizeof *laddr)) == NULL) 660 err(1, "malloc()"); 661 if ((faddr = calloc(1, sizeof *faddr)) == NULL) 662 err(1, "malloc()"); 663 sock->socket = so->xso_so; 664 sock->proto = proto; 665 if (inp->inp_vflag & INP_IPV4) { 666 sock->family = AF_INET; 667 sockaddr(&laddr->address, sock->family, 668 &inp->inp_laddr, inp->inp_lport); 669 sockaddr(&faddr->address, sock->family, 670 &inp->inp_faddr, inp->inp_fport); 671 } else if (inp->inp_vflag & INP_IPV6) { 672 sock->family = AF_INET6; 673 sockaddr(&laddr->address, sock->family, 674 &inp->in6p_laddr, inp->inp_lport); 675 sockaddr(&faddr->address, sock->family, 676 &inp->in6p_faddr, inp->inp_fport); 677 } 678 laddr->next = NULL; 679 faddr->next = NULL; 680 sock->laddr = laddr; 681 sock->faddr = faddr; 682 sock->vflag = inp->inp_vflag; 683 if (proto == IPPROTO_TCP) 684 sock->state = xtp->xt_tp.t_state; 685 sock->protoname = protoname; 686 hash = (int)((uintptr_t)sock->socket % HASHSIZE); 687 sock->next = sockhash[hash]; 688 sockhash[hash] = sock; 689 } 690out: 691 free(buf); 692} 693 694static void 695gather_unix(int proto) 696{ 697 struct xunpgen *xug, *exug; 698 struct xunpcb *xup; 699 struct sock *sock; 700 struct addr *laddr, *faddr; 701 const char *varname, *protoname; 702 size_t len, bufsize; 703 void *buf; 704 int hash, retry; 705 706 switch (proto) { 707 case SOCK_STREAM: 708 varname = "net.local.stream.pcblist"; 709 protoname = "stream"; 710 break; 711 case SOCK_DGRAM: 712 varname = "net.local.dgram.pcblist"; 713 protoname = "dgram"; 714 break; 715 case SOCK_SEQPACKET: 716 varname = "net.local.seqpacket.pcblist"; 717 protoname = "seqpac"; 718 break; 719 default: 720 abort(); 721 } 722 buf = NULL; 723 bufsize = 8192; 724 retry = 5; 725 do { 726 for (;;) { 727 if ((buf = realloc(buf, bufsize)) == NULL) 728 err(1, "realloc()"); 729 len = bufsize; 730 if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 731 break; 732 if (errno != ENOMEM || len != bufsize) 733 err(1, "sysctlbyname()"); 734 bufsize *= 2; 735 } 736 xug = (struct xunpgen *)buf; 737 exug = (struct xunpgen *)(void *) 738 ((char *)buf + len - sizeof(*exug)); 739 if (xug->xug_len != sizeof(*xug) || 740 exug->xug_len != sizeof(*exug)) { 741 warnx("struct xinpgen size mismatch"); 742 goto out; 743 } 744 } while (xug->xug_gen != exug->xug_gen && retry--); 745 746 if (xug->xug_gen != exug->xug_gen && opt_v) 747 warnx("warning: data may be inconsistent"); 748 749 for (;;) { 750 xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); 751 if (xug >= exug) 752 break; 753 xup = (struct xunpcb *)xug; 754 if (xup->xu_len != sizeof(*xup)) { 755 warnx("struct xunpcb size mismatch"); 756 goto out; 757 } 758 if ((xup->xu_unp.unp_conn == NULL && !opt_l) || 759 (xup->xu_unp.unp_conn != NULL && !opt_c)) 760 continue; 761 if ((sock = calloc(1, sizeof(*sock))) == NULL) 762 err(1, "malloc()"); 763 if ((laddr = calloc(1, sizeof *laddr)) == NULL) 764 err(1, "malloc()"); 765 if ((faddr = calloc(1, sizeof *faddr)) == NULL) 766 err(1, "malloc()"); 767 sock->socket = xup->xu_socket.xso_so; 768 sock->pcb = xup->xu_unpp; 769 sock->proto = proto; 770 sock->family = AF_UNIX; 771 sock->protoname = protoname; 772 if (xup->xu_unp.unp_addr != NULL) 773 laddr->address = 774 *(struct sockaddr_storage *)(void *)&xup->xu_addr; 775 else if (xup->xu_unp.unp_conn != NULL) 776 *(void **)&(faddr->address) = xup->xu_unp.unp_conn; 777 laddr->next = NULL; 778 faddr->next = NULL; 779 sock->laddr = laddr; 780 sock->faddr = faddr; 781 hash = (int)((uintptr_t)sock->socket % HASHSIZE); 782 sock->next = sockhash[hash]; 783 sockhash[hash] = sock; 784 } 785out: 786 free(buf); 787} 788 789static void 790getfiles(void) 791{ 792 size_t len, olen; 793 794 olen = len = sizeof(*xfiles); 795 if ((xfiles = malloc(len)) == NULL) 796 err(1, "malloc()"); 797 while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { 798 if (errno != ENOMEM || len != olen) 799 err(1, "sysctlbyname()"); 800 olen = len *= 2; 801 if ((xfiles = realloc(xfiles, len)) == NULL) 802 err(1, "realloc()"); 803 } 804 if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) 805 errx(1, "struct xfile size mismatch"); 806 nxfiles = len / sizeof(*xfiles); 807} 808 809static int 810printaddr(struct sockaddr_storage *ss) 811{ 812 struct sockaddr_un *sun; 813 char addrstr[NI_MAXHOST] = { '\0', '\0' }; 814 int error, off, port = 0; 815 816 switch (ss->ss_family) { 817 case AF_INET: 818 if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY) 819 addrstr[0] = '*'; 820 port = ntohs(sstosin(ss)->sin_port); 821 break; 822 case AF_INET6: 823 if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) 824 addrstr[0] = '*'; 825 port = ntohs(sstosin6(ss)->sin6_port); 826 break; 827 case AF_UNIX: 828 sun = sstosun(ss); 829 off = (int)((char *)&sun->sun_path - (char *)sun); 830 return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); 831 } 832 if (addrstr[0] == '\0') { 833 error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, 834 sizeof(addrstr), NULL, 0, NI_NUMERICHOST); 835 if (error) 836 errx(1, "getnameinfo()"); 837 } 838 if (port == 0) 839 return xprintf("%s:*", addrstr); 840 else 841 return xprintf("%s:%d", addrstr, port); 842} 843 844static const char * 845getprocname(pid_t pid) 846{ 847 static struct kinfo_proc proc; 848 size_t len; 849 int mib[4]; 850 851 mib[0] = CTL_KERN; 852 mib[1] = KERN_PROC; 853 mib[2] = KERN_PROC_PID; 854 mib[3] = (int)pid; 855 len = sizeof(proc); 856 if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 857 /* Do not warn if the process exits before we get its name. */ 858 if (errno != ESRCH) 859 warn("sysctl()"); 860 return ("??"); 861 } 862 return (proc.ki_comm); 863} 864 865static int 866getprocjid(pid_t pid) 867{ 868 static struct kinfo_proc proc; 869 size_t len; 870 int mib[4]; 871 872 mib[0] = CTL_KERN; 873 mib[1] = KERN_PROC; 874 mib[2] = KERN_PROC_PID; 875 mib[3] = (int)pid; 876 len = sizeof(proc); 877 if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { 878 /* Do not warn if the process exits before we get its jid. */ 879 if (errno != ESRCH) 880 warn("sysctl()"); 881 return (-1); 882 } 883 return (proc.ki_jid); 884} 885 886static int 887check_ports(struct sock *s) 888{ 889 int port; 890 struct addr *addr; 891 892 if (ports == NULL) 893 return (1); 894 if ((s->family != AF_INET) && (s->family != AF_INET6)) 895 return (1); 896 for (addr = s->laddr; addr != NULL; addr = addr->next) { 897 if (s->family == AF_INET) 898 port = ntohs(sstosin(&addr->address)->sin_port); 899 else 900 port = ntohs(sstosin6(&addr->address)->sin6_port); 901 if (CHK_PORT(port)) 902 return (1); 903 } 904 for (addr = s->faddr; addr != NULL; addr = addr->next) { 905 if (s->family == AF_INET) 906 port = ntohs(sstosin(&addr->address)->sin_port); 907 else 908 port = ntohs(sstosin6(&addr->address)->sin6_port); 909 if (CHK_PORT(port)) 910 return (1); 911 } 912 return (0); 913} 914 915static const char * 916sctp_state(int state) 917{ 918 switch (state) { 919 case SCTP_CLOSED: 920 return "CLOSED"; 921 break; 922 case SCTP_BOUND: 923 return "BOUND"; 924 break; 925 case SCTP_LISTEN: 926 return "LISTEN"; 927 break; 928 case SCTP_COOKIE_WAIT: 929 return "COOKIE_WAIT"; 930 break; 931 case SCTP_COOKIE_ECHOED: 932 return "COOKIE_ECHOED"; 933 break; 934 case SCTP_ESTABLISHED: 935 return "ESTABLISHED"; 936 break; 937 case SCTP_SHUTDOWN_SENT: 938 return "SHUTDOWN_SENT"; 939 break; 940 case SCTP_SHUTDOWN_RECEIVED: 941 return "SHUTDOWN_RECEIVED"; 942 break; 943 case SCTP_SHUTDOWN_ACK_SENT: 944 return "SHUTDOWN_ACK_SENT"; 945 break; 946 case SCTP_SHUTDOWN_PENDING: 947 return "SHUTDOWN_PENDING"; 948 break; 949 default: 950 return "UNKNOWN"; 951 break; 952 } 953} 954 955static void 956displaysock(struct sock *s, int pos) 957{ 958 void *p; 959 int hash, first; 960 struct addr *laddr, *faddr; 961 struct sock *s_tmp; 962 963 while (pos < 29) 964 pos += xprintf(" "); 965 pos += xprintf("%s", s->protoname); 966 if (s->vflag & INP_IPV4) 967 pos += xprintf("4 "); 968 if (s->vflag & INP_IPV6) 969 pos += xprintf("6 "); 970 laddr = s->laddr; 971 faddr = s->faddr; 972 first = 1; 973 while (laddr != NULL || faddr != NULL) { 974 while (pos < 36) 975 pos += xprintf(" "); 976 switch (s->family) { 977 case AF_INET: 978 case AF_INET6: 979 if (laddr != NULL) { 980 pos += printaddr(&laddr->address); 981 if (s->family == AF_INET6 && pos >= 58) 982 pos += xprintf(" "); 983 } 984 while (pos < 58) 985 pos += xprintf(" "); 986 if (faddr != NULL) 987 pos += printaddr(&faddr->address); 988 break; 989 case AF_UNIX: 990 if ((laddr == NULL) || (faddr == NULL)) 991 errx(1, "laddr = %p or faddr = %p is NULL", 992 (void *)laddr, (void *)faddr); 993 /* server */ 994 if (laddr->address.ss_len > 0) { 995 pos += printaddr(&laddr->address); 996 break; 997 } 998 /* client */ 999 p = *(void **)&(faddr->address); 1000 if (p == NULL) { 1001 pos += xprintf("(not connected)"); 1002 break; 1003 } 1004 pos += xprintf("-> "); 1005 for (hash = 0; hash < HASHSIZE; ++hash) { 1006 for (s_tmp = sockhash[hash]; 1007 s_tmp != NULL; 1008 s_tmp = s_tmp->next) 1009 if (s_tmp->pcb == p) 1010 break; 1011 if (s_tmp != NULL) 1012 break; 1013 } 1014 if (s_tmp == NULL || 1015 s_tmp->laddr == NULL || 1016 s_tmp->laddr->address.ss_len == 0) 1017 pos += xprintf("??"); 1018 else 1019 pos += printaddr(&s_tmp->laddr->address); 1020 break; 1021 default: 1022 abort(); 1023 } 1024 if (first && opt_s && 1025 (s->proto == IPPROTO_SCTP || s->proto == IPPROTO_TCP)) { 1026 while (pos < 80) 1027 pos += xprintf(" "); 1028 switch (s->proto) { 1029 case IPPROTO_SCTP: 1030 pos += xprintf("%s", sctp_state(s->state)); 1031 break; 1032 case IPPROTO_TCP: 1033 if (s->state >= 0 && s->state < TCP_NSTATES) 1034 pos += 1035 xprintf("%s", tcpstates[s->state]); 1036 else 1037 pos += xprintf("?"); 1038 break; 1039 } 1040 } 1041 if (laddr != NULL) 1042 laddr = laddr->next; 1043 if (faddr != NULL) 1044 faddr = faddr->next; 1045 if ((laddr != NULL) || (faddr != NULL)) { 1046 xprintf("\n"); 1047 pos = 0; 1048 } 1049 first = 0; 1050 } 1051 xprintf("\n"); 1052} 1053 1054static void 1055display(void) 1056{ 1057 struct passwd *pwd; 1058 struct xfile *xf; 1059 struct sock *s; 1060 int hash, n, pos; 1061 1062 printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s", 1063 "USER", "COMMAND", "PID", "FD", "PROTO", 1064 "LOCAL ADDRESS", "FOREIGN ADDRESS"); 1065 if (opt_s) 1066 printf(" %-12s", "STATE"); 1067 printf("\n"); 1068 setpassent(1); 1069 for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 1070 if (xf->xf_data == NULL) 1071 continue; 1072 if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid)) 1073 continue; 1074 hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 1075 for (s = sockhash[hash]; s != NULL; s = s->next) { 1076 if ((void *)s->socket != xf->xf_data) 1077 continue; 1078 if (!check_ports(s)) 1079 continue; 1080 s->shown = 1; 1081 pos = 0; 1082 if ((pwd = getpwuid(xf->xf_uid)) == NULL) 1083 pos += xprintf("%lu ", (u_long)xf->xf_uid); 1084 else 1085 pos += xprintf("%s ", pwd->pw_name); 1086 while (pos < 9) 1087 pos += xprintf(" "); 1088 pos += xprintf("%.10s", getprocname(xf->xf_pid)); 1089 while (pos < 20) 1090 pos += xprintf(" "); 1091 pos += xprintf("%lu ", (u_long)xf->xf_pid); 1092 while (pos < 26) 1093 pos += xprintf(" "); 1094 pos += xprintf("%d ", xf->xf_fd); 1095 displaysock(s, pos); 1096 } 1097 } 1098 if (opt_j >= 0) 1099 return; 1100 for (hash = 0; hash < HASHSIZE; hash++) { 1101 for (s = sockhash[hash]; s != NULL; s = s->next) { 1102 if (s->shown) 1103 continue; 1104 if (!check_ports(s)) 1105 continue; 1106 pos = 0; 1107 pos += xprintf("%-8s %-10s %-5s %-2s ", 1108 "?", "?", "?", "?"); 1109 displaysock(s, pos); 1110 } 1111 } 1112} 1113 1114static int set_default_protos(void) 1115{ 1116 struct protoent *prot; 1117 const char *pname; 1118 size_t pindex; 1119 1120 init_protos(default_numprotos); 1121 1122 for (pindex = 0; pindex < default_numprotos; pindex++) { 1123 pname = default_protos[pindex]; 1124 prot = getprotobyname(pname); 1125 if (prot == NULL) 1126 err(1, "getprotobyname: %s", pname); 1127 protos[pindex] = prot->p_proto; 1128 } 1129 numprotos = pindex; 1130 return (pindex); 1131} 1132 1133 1134static void 1135usage(void) 1136{ 1137 fprintf(stderr, 1138 "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n"); 1139 exit(1); 1140} 1141 1142int 1143main(int argc, char *argv[]) 1144{ 1145 int protos_defined = -1; 1146 int o, i; 1147 1148 opt_j = -1; 1149 while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1) 1150 switch (o) { 1151 case '4': 1152 opt_4 = 1; 1153 break; 1154 case '6': 1155 opt_6 = 1; 1156 break; 1157 case 'c': 1158 opt_c = 1; 1159 break; 1160 case 'j': 1161 opt_j = jail_getid(optarg); 1162 if (opt_j < 0) 1163 errx(1, "%s", jail_errmsg); 1164 break; 1165 case 'L': 1166 opt_L = 1; 1167 break; 1168 case 'l': 1169 opt_l = 1; 1170 break; 1171 case 'p': 1172 parse_ports(optarg); 1173 break; 1174 case 'P': 1175 protos_defined = parse_protos(optarg); 1176 break; 1177 case 's': 1178 opt_s = 1; 1179 break; 1180 case 'u': 1181 opt_u = 1; 1182 break; 1183 case 'v': 1184 ++opt_v; 1185 break; 1186 default: 1187 usage(); 1188 } 1189 1190 argc -= optind; 1191 argv += optind; 1192 1193 if (argc > 0) 1194 usage(); 1195 1196 if ((!opt_4 && !opt_6) && protos_defined != -1) 1197 opt_4 = opt_6 = 1; 1198 if (!opt_4 && !opt_6 && !opt_u) 1199 opt_4 = opt_6 = opt_u = 1; 1200 if ((opt_4 || opt_6) && protos_defined == -1) 1201 protos_defined = set_default_protos(); 1202 if (!opt_c && !opt_l) 1203 opt_c = opt_l = 1; 1204 1205 if (opt_4 || opt_6) { 1206 for (i = 0; i < protos_defined; i++) 1207 if (protos[i] == IPPROTO_SCTP) 1208 gather_sctp(); 1209 else 1210 gather_inet(protos[i]); 1211 } 1212 1213 if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) { 1214 gather_unix(SOCK_STREAM); 1215 gather_unix(SOCK_DGRAM); 1216 gather_unix(SOCK_SEQPACKET); 1217 } 1218 getfiles(); 1219 display(); 1220 exit(0); 1221} 1222