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