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