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