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