1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2002 Dag-Erling Smørgrav
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/param.h>
32 #include <sys/file.h>
33 #include <sys/socket.h>
34 #include <sys/socketvar.h>
35 #include <sys/sysctl.h>
36 #include <sys/jail.h>
37 #include <sys/user.h>
38 #include <sys/queue.h>
39 #include <sys/tree.h>
40
41 #include <sys/un.h>
42 #include <sys/unpcb.h>
43
44 #include <net/route.h>
45
46 #include <netinet/in.h>
47 #include <netinet/in_pcb.h>
48 #include <netinet/sctp.h>
49 #include <netinet/tcp.h>
50 #define TCPSTATES /* load state names */
51 #include <netinet/tcp_fsm.h>
52 #include <netinet/tcp_seq.h>
53 #include <netinet/tcp_var.h>
54 #include <arpa/inet.h>
55
56 #include <capsicum_helpers.h>
57 #include <ctype.h>
58 #include <errno.h>
59 #include <inttypes.h>
60 #include <jail.h>
61 #include <netdb.h>
62 #include <pwd.h>
63 #include <stdarg.h>
64 #include <stdbool.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69 #include <libxo/xo.h>
70
71 #include <libcasper.h>
72 #include <casper/cap_net.h>
73 #include <casper/cap_netdb.h>
74 #include <casper/cap_pwd.h>
75 #include <casper/cap_sysctl.h>
76
77 #define SOCKSTAT_XO_VERSION "1"
78 #define sstosin(ss) ((struct sockaddr_in *)(ss))
79 #define sstosin6(ss) ((struct sockaddr_in6 *)(ss))
80 #define sstosun(ss) ((struct sockaddr_un *)(ss))
81 #define sstosa(ss) ((struct sockaddr *)(ss))
82
83 static bool opt_4; /* Show IPv4 sockets */
84 static bool opt_6; /* Show IPv6 sockets */
85 static bool opt_A; /* Show kernel address of pcb */
86 static bool opt_C; /* Show congestion control */
87 static bool opt_c; /* Show connected sockets */
88 static bool opt_f; /* Show FIB numbers */
89 static bool opt_I; /* Show spliced socket addresses */
90 static bool opt_i; /* Show inp_gencnt */
91 static int opt_j; /* Show specified jail */
92 static bool opt_L; /* Don't show IPv4 or IPv6 loopback sockets */
93 static bool opt_l; /* Show listening sockets */
94 static bool opt_n; /* Don't resolve UIDs to user names */
95 static bool opt_q; /* Don't show header */
96 static bool opt_S; /* Show protocol stack if applicable */
97 static bool opt_s; /* Show protocol state if applicable */
98 static bool opt_U; /* Show remote UDP encapsulation port number */
99 static bool opt_u; /* Show Unix domain sockets */
100 static u_int opt_v; /* Verbose mode */
101 static bool opt_w; /* Automatically size the columns */
102
103 /*
104 * Default protocols to use if no -P was defined.
105 */
106 static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" };
107 static size_t default_numprotos = nitems(default_protos);
108
109 static int *protos; /* protocols to use */
110 static size_t numprotos; /* allocated size of protos[] */
111
112 static int *ports;
113
114 #define INT_BIT (sizeof(int)*CHAR_BIT)
115 #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0)
116 #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
117
118 struct addr {
119 union {
120 struct sockaddr_storage address;
121 struct { /* unix(4) faddr */
122 kvaddr_t conn;
123 kvaddr_t firstref;
124 kvaddr_t nextref;
125 };
126 };
127 unsigned int encaps_port;
128 int state;
129 struct addr *next;
130 };
131
132 struct sock {
133 union {
134 RB_ENTRY(sock) socket_tree; /* tree of pcbs with socket */
135 SLIST_ENTRY(sock) socket_list; /* list of pcbs w/o socket */
136 };
137 RB_ENTRY(sock) pcb_tree;
138 kvaddr_t socket;
139 kvaddr_t pcb;
140 kvaddr_t splice_socket;
141 uint64_t inp_gencnt;
142 int shown;
143 int vflag;
144 int family;
145 int proto;
146 int state;
147 int fibnum;
148 const char *protoname;
149 char stack[TCP_FUNCTION_NAME_LEN_MAX];
150 char cc[TCP_CA_NAME_MAX];
151 struct addr *laddr;
152 struct addr *faddr;
153 };
154
155 static RB_HEAD(socks_t, sock) socks = RB_INITIALIZER(&socks);
156 static int64_t
socket_compare(const struct sock * a,const struct sock * b)157 socket_compare(const struct sock *a, const struct sock *b)
158 {
159 return ((int64_t)(a->socket/2 - b->socket/2));
160 }
161 RB_GENERATE_STATIC(socks_t, sock, socket_tree, socket_compare);
162
163 static RB_HEAD(pcbs_t, sock) pcbs = RB_INITIALIZER(&pcbs);
164 static int64_t
pcb_compare(const struct sock * a,const struct sock * b)165 pcb_compare(const struct sock *a, const struct sock *b)
166 {
167 return ((int64_t)(a->pcb/2 - b->pcb/2));
168 }
169 RB_GENERATE_STATIC(pcbs_t, sock, pcb_tree, pcb_compare);
170
171 static SLIST_HEAD(, sock) nosocks = SLIST_HEAD_INITIALIZER(&nosocks);
172
173 struct file {
174 RB_ENTRY(file) file_tree;
175 kvaddr_t xf_data;
176 pid_t xf_pid;
177 uid_t xf_uid;
178 int xf_fd;
179 };
180
181 static RB_HEAD(files_t, file) ftree = RB_INITIALIZER(&ftree);
182 static int64_t
file_compare(const struct file * a,const struct file * b)183 file_compare(const struct file *a, const struct file *b)
184 {
185 return ((int64_t)(a->xf_data/2 - b->xf_data/2));
186 }
187 RB_GENERATE_STATIC(files_t, file, file_tree, file_compare);
188
189 static struct file *files;
190 static int nfiles;
191
192 static cap_channel_t *capnet;
193 static cap_channel_t *capnetdb;
194 static cap_channel_t *capsysctl;
195 static cap_channel_t *cappwd;
196
197 static bool
_check_ksize(size_t received_size,size_t expected_size,const char * struct_name)198 _check_ksize(size_t received_size, size_t expected_size, const char *struct_name)
199 {
200 if (received_size != expected_size) {
201 xo_warnx("%s size mismatch: expected %zd, received %zd",
202 struct_name, expected_size, received_size);
203 return false;
204 }
205 return true;
206 }
207 #define check_ksize(_sz, _struct) (_check_ksize(_sz, sizeof(_struct), #_struct))
208
209 static void
_enforce_ksize(size_t received_size,size_t expected_size,const char * struct_name)210 _enforce_ksize(size_t received_size, size_t expected_size, const char *struct_name)
211 {
212 if (received_size != expected_size) {
213 xo_errx(1, "fatal: struct %s size mismatch: expected %zd, received %zd",
214 struct_name, expected_size, received_size);
215 }
216 }
217 #define enforce_ksize(_sz, _struct) (_enforce_ksize(_sz, sizeof(_struct), #_struct))
218
219 static int
get_proto_type(const char * proto)220 get_proto_type(const char *proto)
221 {
222 struct protoent *pent;
223
224 if (strlen(proto) == 0)
225 return (0);
226 if (capnetdb != NULL)
227 pent = cap_getprotobyname(capnetdb, proto);
228 else
229 pent = getprotobyname(proto);
230 if (pent == NULL) {
231 xo_warn("cap_getprotobyname");
232 return (-1);
233 }
234 return (pent->p_proto);
235 }
236
237 static void
init_protos(int num)238 init_protos(int num)
239 {
240 int proto_count = 0;
241
242 if (num > 0) {
243 proto_count = num;
244 } else {
245 /* Find the maximum number of possible protocols. */
246 while (getprotoent() != NULL)
247 proto_count++;
248 endprotoent();
249 }
250
251 if ((protos = malloc(sizeof(int) * proto_count)) == NULL)
252 xo_err(1, "malloc");
253 numprotos = proto_count;
254 }
255
256 static int
parse_protos(char * protospec)257 parse_protos(char *protospec)
258 {
259 char *prot;
260 int proto_type, proto_index;
261
262 if (protospec == NULL)
263 return (-1);
264
265 init_protos(0);
266 proto_index = 0;
267 while ((prot = strsep(&protospec, ",")) != NULL) {
268 if (strlen(prot) == 0)
269 continue;
270 proto_type = get_proto_type(prot);
271 if (proto_type != -1)
272 protos[proto_index++] = proto_type;
273 }
274 numprotos = proto_index;
275 return (proto_index);
276 }
277
278 static void
parse_ports(const char * portspec)279 parse_ports(const char *portspec)
280 {
281 const char *p, *q;
282 int port, end;
283
284 if (ports == NULL)
285 if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL)
286 xo_err(1, "calloc()");
287 p = portspec;
288 while (*p != '\0') {
289 if (!isdigit(*p))
290 xo_errx(1, "syntax error in port range");
291 for (q = p; *q != '\0' && isdigit(*q); ++q)
292 /* nothing */ ;
293 for (port = 0; p < q; ++p)
294 port = port * 10 + digittoint(*p);
295 if (port < 0 || port > 65535)
296 xo_errx(1, "invalid port number");
297 SET_PORT(port);
298 switch (*p) {
299 case '-':
300 ++p;
301 break;
302 case ',':
303 ++p;
304 /* fall through */
305 case '\0':
306 default:
307 continue;
308 }
309 for (q = p; *q != '\0' && isdigit(*q); ++q)
310 /* nothing */ ;
311 for (end = 0; p < q; ++p)
312 end = end * 10 + digittoint(*p);
313 if (end < port || end > 65535)
314 xo_errx(1, "invalid port number");
315 while (port++ < end)
316 SET_PORT(port);
317 if (*p == ',')
318 ++p;
319 }
320 }
321
322 static void
sockaddr(struct sockaddr_storage * ss,int af,void * addr,int port)323 sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port)
324 {
325 struct sockaddr_in *sin4;
326 struct sockaddr_in6 *sin6;
327
328 bzero(ss, sizeof(*ss));
329 switch (af) {
330 case AF_INET:
331 sin4 = sstosin(ss);
332 sin4->sin_len = sizeof(*sin4);
333 sin4->sin_family = af;
334 sin4->sin_port = port;
335 sin4->sin_addr = *(struct in_addr *)addr;
336 break;
337 case AF_INET6:
338 sin6 = sstosin6(ss);
339 sin6->sin6_len = sizeof(*sin6);
340 sin6->sin6_family = af;
341 sin6->sin6_port = port;
342 sin6->sin6_addr = *(struct in6_addr *)addr;
343 #define s6_addr16 __u6_addr.__u6_addr16
344 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
345 sin6->sin6_scope_id =
346 ntohs(sin6->sin6_addr.s6_addr16[1]);
347 sin6->sin6_addr.s6_addr16[1] = 0;
348 }
349 break;
350 default:
351 abort();
352 }
353 }
354
355 static void
free_socket(struct sock * sock)356 free_socket(struct sock *sock)
357 {
358 struct addr *cur, *next;
359
360 cur = sock->laddr;
361 while (cur != NULL) {
362 next = cur->next;
363 free(cur);
364 cur = next;
365 }
366 cur = sock->faddr;
367 while (cur != NULL) {
368 next = cur->next;
369 free(cur);
370 cur = next;
371 }
372 free(sock);
373 }
374
375 static void
gather_sctp(void)376 gather_sctp(void)
377 {
378 struct sock *sock;
379 struct addr *laddr, *prev_laddr, *faddr, *prev_faddr;
380 struct xsctp_inpcb *xinpcb;
381 struct xsctp_tcb *xstcb;
382 struct xsctp_raddr *xraddr;
383 struct xsctp_laddr *xladdr;
384 const char *varname;
385 size_t len, offset;
386 char *buf;
387 int vflag;
388 int no_stcb, local_all_loopback, foreign_all_loopback;
389
390 vflag = 0;
391 if (opt_4)
392 vflag |= INP_IPV4;
393 if (opt_6)
394 vflag |= INP_IPV6;
395
396 varname = "net.inet.sctp.assoclist";
397 if (cap_sysctlbyname(capsysctl, varname, 0, &len, 0, 0) < 0) {
398 if (errno != ENOENT)
399 xo_err(1, "cap_sysctlbyname()");
400 return;
401 }
402 if ((buf = (char *)malloc(len)) == NULL) {
403 xo_err(1, "malloc()");
404 return;
405 }
406 if (cap_sysctlbyname(capsysctl, varname, buf, &len, 0, 0) < 0) {
407 xo_err(1, "cap_sysctlbyname()");
408 free(buf);
409 return;
410 }
411 xinpcb = (struct xsctp_inpcb *)(void *)buf;
412 offset = sizeof(struct xsctp_inpcb);
413 while ((offset < len) && (xinpcb->last == 0)) {
414 if ((sock = calloc(1, sizeof *sock)) == NULL)
415 xo_err(1, "malloc()");
416 sock->socket = xinpcb->socket;
417 sock->proto = IPPROTO_SCTP;
418 sock->protoname = "sctp";
419 if (xinpcb->maxqlen == 0)
420 sock->state = SCTP_CLOSED;
421 else
422 sock->state = SCTP_LISTEN;
423 if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
424 sock->family = AF_INET6;
425 /*
426 * Currently there is no way to distinguish between
427 * IPv6 only sockets or dual family sockets.
428 * So mark it as dual socket.
429 */
430 sock->vflag = INP_IPV6 | INP_IPV4;
431 } else {
432 sock->family = AF_INET;
433 sock->vflag = INP_IPV4;
434 }
435 prev_laddr = NULL;
436 local_all_loopback = 1;
437 while (offset < len) {
438 xladdr = (struct xsctp_laddr *)(void *)(buf + offset);
439 offset += sizeof(struct xsctp_laddr);
440 if (xladdr->last == 1)
441 break;
442 if ((laddr = calloc(1, sizeof(struct addr))) == NULL)
443 xo_err(1, "malloc()");
444 switch (xladdr->address.sa.sa_family) {
445 case AF_INET:
446 #define __IN_IS_ADDR_LOOPBACK(pina) \
447 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
448 if (!__IN_IS_ADDR_LOOPBACK(
449 &xladdr->address.sin.sin_addr))
450 local_all_loopback = 0;
451 #undef __IN_IS_ADDR_LOOPBACK
452 sockaddr(&laddr->address, AF_INET,
453 &xladdr->address.sin.sin_addr,
454 htons(xinpcb->local_port));
455 break;
456 case AF_INET6:
457 if (!IN6_IS_ADDR_LOOPBACK(
458 &xladdr->address.sin6.sin6_addr))
459 local_all_loopback = 0;
460 sockaddr(&laddr->address, AF_INET6,
461 &xladdr->address.sin6.sin6_addr,
462 htons(xinpcb->local_port));
463 break;
464 default:
465 xo_errx(1, "address family %d not supported",
466 xladdr->address.sa.sa_family);
467 }
468 laddr->next = NULL;
469 if (prev_laddr == NULL)
470 sock->laddr = laddr;
471 else
472 prev_laddr->next = laddr;
473 prev_laddr = laddr;
474 }
475 if (sock->laddr == NULL) {
476 if ((sock->laddr =
477 calloc(1, sizeof(struct addr))) == NULL)
478 xo_err(1, "malloc()");
479 sock->laddr->address.ss_family = sock->family;
480 if (sock->family == AF_INET)
481 sock->laddr->address.ss_len =
482 sizeof(struct sockaddr_in);
483 else
484 sock->laddr->address.ss_len =
485 sizeof(struct sockaddr_in6);
486 local_all_loopback = 0;
487 }
488 if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL)
489 xo_err(1, "malloc()");
490 sock->faddr->address.ss_family = sock->family;
491 if (sock->family == AF_INET)
492 sock->faddr->address.ss_len =
493 sizeof(struct sockaddr_in);
494 else
495 sock->faddr->address.ss_len =
496 sizeof(struct sockaddr_in6);
497 no_stcb = 1;
498 while (offset < len) {
499 xstcb = (struct xsctp_tcb *)(void *)(buf + offset);
500 offset += sizeof(struct xsctp_tcb);
501 if (no_stcb) {
502 if (opt_l && (sock->vflag & vflag) &&
503 (!opt_L || !local_all_loopback) &&
504 ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) ||
505 (xstcb->last == 1))) {
506 RB_INSERT(socks_t, &socks, sock);
507 } else {
508 free_socket(sock);
509 }
510 }
511 if (xstcb->last == 1)
512 break;
513 no_stcb = 0;
514 if (opt_c) {
515 if ((sock = calloc(1, sizeof *sock)) == NULL)
516 xo_err(1, "malloc()");
517 sock->socket = xinpcb->socket;
518 sock->proto = IPPROTO_SCTP;
519 sock->protoname = "sctp";
520 sock->state = (int)xstcb->state;
521 if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
522 sock->family = AF_INET6;
523 /*
524 * Currently there is no way to distinguish
525 * between IPv6 only sockets or dual family
526 * sockets. So mark it as dual socket.
527 */
528 sock->vflag = INP_IPV6 | INP_IPV4;
529 } else {
530 sock->family = AF_INET;
531 sock->vflag = INP_IPV4;
532 }
533 }
534 prev_laddr = NULL;
535 local_all_loopback = 1;
536 while (offset < len) {
537 xladdr = (struct xsctp_laddr *)(void *)(buf +
538 offset);
539 offset += sizeof(struct xsctp_laddr);
540 if (xladdr->last == 1)
541 break;
542 if (!opt_c)
543 continue;
544 laddr = calloc(1, sizeof(struct addr));
545 if (laddr == NULL)
546 xo_err(1, "malloc()");
547 switch (xladdr->address.sa.sa_family) {
548 case AF_INET:
549 #define __IN_IS_ADDR_LOOPBACK(pina) \
550 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
551 if (!__IN_IS_ADDR_LOOPBACK(
552 &xladdr->address.sin.sin_addr))
553 local_all_loopback = 0;
554 #undef __IN_IS_ADDR_LOOPBACK
555 sockaddr(&laddr->address, AF_INET,
556 &xladdr->address.sin.sin_addr,
557 htons(xstcb->local_port));
558 break;
559 case AF_INET6:
560 if (!IN6_IS_ADDR_LOOPBACK(
561 &xladdr->address.sin6.sin6_addr))
562 local_all_loopback = 0;
563 sockaddr(&laddr->address, AF_INET6,
564 &xladdr->address.sin6.sin6_addr,
565 htons(xstcb->local_port));
566 break;
567 default:
568 xo_errx(1,
569 "address family %d not supported",
570 xladdr->address.sa.sa_family);
571 }
572 laddr->next = NULL;
573 if (prev_laddr == NULL)
574 sock->laddr = laddr;
575 else
576 prev_laddr->next = laddr;
577 prev_laddr = laddr;
578 }
579 prev_faddr = NULL;
580 foreign_all_loopback = 1;
581 while (offset < len) {
582 xraddr = (struct xsctp_raddr *)(void *)(buf +
583 offset);
584 offset += sizeof(struct xsctp_raddr);
585 if (xraddr->last == 1)
586 break;
587 if (!opt_c)
588 continue;
589 faddr = calloc(1, sizeof(struct addr));
590 if (faddr == NULL)
591 xo_err(1, "malloc()");
592 switch (xraddr->address.sa.sa_family) {
593 case AF_INET:
594 #define __IN_IS_ADDR_LOOPBACK(pina) \
595 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
596 if (!__IN_IS_ADDR_LOOPBACK(
597 &xraddr->address.sin.sin_addr))
598 foreign_all_loopback = 0;
599 #undef __IN_IS_ADDR_LOOPBACK
600 sockaddr(&faddr->address, AF_INET,
601 &xraddr->address.sin.sin_addr,
602 htons(xstcb->remote_port));
603 break;
604 case AF_INET6:
605 if (!IN6_IS_ADDR_LOOPBACK(
606 &xraddr->address.sin6.sin6_addr))
607 foreign_all_loopback = 0;
608 sockaddr(&faddr->address, AF_INET6,
609 &xraddr->address.sin6.sin6_addr,
610 htons(xstcb->remote_port));
611 break;
612 default:
613 xo_errx(1,
614 "address family %d not supported",
615 xraddr->address.sa.sa_family);
616 }
617 faddr->encaps_port = xraddr->encaps_port;
618 faddr->state = xraddr->state;
619 faddr->next = NULL;
620 if (prev_faddr == NULL)
621 sock->faddr = faddr;
622 else
623 prev_faddr->next = faddr;
624 prev_faddr = faddr;
625 }
626 if (opt_c) {
627 if ((sock->vflag & vflag) &&
628 (!opt_L ||
629 !(local_all_loopback ||
630 foreign_all_loopback))) {
631 RB_INSERT(socks_t, &socks, sock);
632 } else {
633 free_socket(sock);
634 }
635 }
636 }
637 xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset);
638 offset += sizeof(struct xsctp_inpcb);
639 }
640 free(buf);
641 }
642
643 static void
gather_inet(int proto)644 gather_inet(int proto)
645 {
646 struct xinpgen *xig, *exig;
647 struct xinpcb *xip;
648 struct xtcpcb *xtp = NULL;
649 struct xsocket *so;
650 struct sock *sock;
651 struct addr *laddr, *faddr;
652 const char *varname, *protoname;
653 size_t len, bufsize;
654 void *buf;
655 int retry, vflag;
656
657 vflag = 0;
658 if (opt_4)
659 vflag |= INP_IPV4;
660 if (opt_6)
661 vflag |= INP_IPV6;
662
663 switch (proto) {
664 case IPPROTO_TCP:
665 varname = "net.inet.tcp.pcblist";
666 protoname = "tcp";
667 break;
668 case IPPROTO_UDP:
669 varname = "net.inet.udp.pcblist";
670 protoname = "udp";
671 break;
672 case IPPROTO_DIVERT:
673 varname = "net.inet.divert.pcblist";
674 protoname = "div";
675 break;
676 default:
677 xo_errx(1, "protocol %d not supported", proto);
678 }
679
680 buf = NULL;
681 bufsize = 8192;
682 retry = 5;
683 do {
684 for (;;) {
685 if ((buf = realloc(buf, bufsize)) == NULL)
686 xo_err(1, "realloc()");
687 len = bufsize;
688 if (cap_sysctlbyname(capsysctl, varname, buf, &len,
689 NULL, 0) == 0)
690 break;
691 if (errno == ENOENT)
692 goto out;
693 if (errno != ENOMEM || len != bufsize)
694 xo_err(1, "cap_sysctlbyname()");
695 bufsize *= 2;
696 }
697 xig = (struct xinpgen *)buf;
698 exig = (struct xinpgen *)(void *)
699 ((char *)buf + len - sizeof *exig);
700 enforce_ksize(xig->xig_len, struct xinpgen);
701 enforce_ksize(exig->xig_len, struct xinpgen);
702 } while (xig->xig_gen != exig->xig_gen && retry--);
703
704 if (xig->xig_gen != exig->xig_gen && opt_v)
705 xo_warnx("warning: data may be inconsistent");
706
707 for (;;) {
708 xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
709 if (xig >= exig)
710 break;
711 switch (proto) {
712 case IPPROTO_TCP:
713 xtp = (struct xtcpcb *)xig;
714 xip = &xtp->xt_inp;
715 if (!check_ksize(xtp->xt_len, struct xtcpcb))
716 goto out;
717 protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp";
718 break;
719 case IPPROTO_UDP:
720 case IPPROTO_DIVERT:
721 xip = (struct xinpcb *)xig;
722 if (!check_ksize(xip->xi_len, struct xinpcb))
723 goto out;
724 break;
725 default:
726 xo_errx(1, "protocol %d not supported", proto);
727 }
728 so = &xip->xi_socket;
729 if ((xip->inp_vflag & vflag) == 0)
730 continue;
731 if (xip->inp_vflag & INP_IPV4) {
732 if ((xip->inp_fport == 0 && !opt_l) ||
733 (xip->inp_fport != 0 && !opt_c))
734 continue;
735 #define __IN_IS_ADDR_LOOPBACK(pina) \
736 ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
737 if (opt_L &&
738 (__IN_IS_ADDR_LOOPBACK(&xip->inp_faddr) ||
739 __IN_IS_ADDR_LOOPBACK(&xip->inp_laddr)))
740 continue;
741 #undef __IN_IS_ADDR_LOOPBACK
742 } else if (xip->inp_vflag & INP_IPV6) {
743 if ((xip->inp_fport == 0 && !opt_l) ||
744 (xip->inp_fport != 0 && !opt_c))
745 continue;
746 if (opt_L &&
747 (IN6_IS_ADDR_LOOPBACK(&xip->in6p_faddr) ||
748 IN6_IS_ADDR_LOOPBACK(&xip->in6p_laddr)))
749 continue;
750 } else {
751 if (opt_v)
752 xo_warnx("invalid vflag 0x%x", xip->inp_vflag);
753 continue;
754 }
755 if ((sock = calloc(1, sizeof(*sock))) == NULL)
756 xo_err(1, "malloc()");
757 if ((laddr = calloc(1, sizeof *laddr)) == NULL)
758 xo_err(1, "malloc()");
759 if ((faddr = calloc(1, sizeof *faddr)) == NULL)
760 xo_err(1, "malloc()");
761 sock->socket = so->xso_so;
762 sock->pcb = so->so_pcb;
763 sock->splice_socket = so->so_splice_so;
764 sock->proto = proto;
765 sock->inp_gencnt = xip->inp_gencnt;
766 sock->fibnum = so->so_fibnum;
767 if (xip->inp_vflag & INP_IPV4) {
768 sock->family = AF_INET;
769 sockaddr(&laddr->address, sock->family,
770 &xip->inp_laddr, xip->inp_lport);
771 sockaddr(&faddr->address, sock->family,
772 &xip->inp_faddr, xip->inp_fport);
773 } else if (xip->inp_vflag & INP_IPV6) {
774 sock->family = AF_INET6;
775 sockaddr(&laddr->address, sock->family,
776 &xip->in6p_laddr, xip->inp_lport);
777 sockaddr(&faddr->address, sock->family,
778 &xip->in6p_faddr, xip->inp_fport);
779 }
780 if (proto == IPPROTO_TCP)
781 faddr->encaps_port = xtp->xt_encaps_port;
782 laddr->next = NULL;
783 faddr->next = NULL;
784 sock->laddr = laddr;
785 sock->faddr = faddr;
786 sock->vflag = xip->inp_vflag;
787 if (proto == IPPROTO_TCP) {
788 sock->state = xtp->t_state;
789 memcpy(sock->stack, xtp->xt_stack,
790 TCP_FUNCTION_NAME_LEN_MAX);
791 memcpy(sock->cc, xtp->xt_cc, TCP_CA_NAME_MAX);
792 }
793 sock->protoname = protoname;
794 if (sock->socket != 0)
795 RB_INSERT(socks_t, &socks, sock);
796 else
797 SLIST_INSERT_HEAD(&nosocks, sock, socket_list);
798 }
799 out:
800 free(buf);
801 }
802
803 static void
gather_unix(int proto)804 gather_unix(int proto)
805 {
806 struct xunpgen *xug, *exug;
807 struct xunpcb *xup;
808 struct sock *sock;
809 struct addr *laddr, *faddr;
810 const char *varname, *protoname;
811 size_t len, bufsize;
812 void *buf;
813 int retry;
814
815 switch (proto) {
816 case SOCK_STREAM:
817 varname = "net.local.stream.pcblist";
818 protoname = "stream";
819 break;
820 case SOCK_DGRAM:
821 varname = "net.local.dgram.pcblist";
822 protoname = "dgram";
823 break;
824 case SOCK_SEQPACKET:
825 varname = "net.local.seqpacket.pcblist";
826 protoname = (xo_get_style(NULL) == XO_STYLE_TEXT)
827 ? "seqpac"
828 : "seqpacket";
829 break;
830 default:
831 abort();
832 }
833 buf = NULL;
834 bufsize = 8192;
835 retry = 5;
836 do {
837 for (;;) {
838 if ((buf = realloc(buf, bufsize)) == NULL)
839 xo_err(1, "realloc()");
840 len = bufsize;
841 if (cap_sysctlbyname(capsysctl, varname, buf, &len,
842 NULL, 0) == 0)
843 break;
844 if (errno != ENOMEM || len != bufsize)
845 xo_err(1, "cap_sysctlbyname()");
846 bufsize *= 2;
847 }
848 xug = (struct xunpgen *)buf;
849 exug = (struct xunpgen *)(void *)
850 ((char *)buf + len - sizeof(*exug));
851 if (!check_ksize(xug->xug_len, struct xunpgen) ||
852 !check_ksize(exug->xug_len, struct xunpgen))
853 goto out;
854 } while (xug->xug_gen != exug->xug_gen && retry--);
855
856 if (xug->xug_gen != exug->xug_gen && opt_v)
857 xo_warnx("warning: data may be inconsistent");
858
859 for (;;) {
860 xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len);
861 if (xug >= exug)
862 break;
863 xup = (struct xunpcb *)xug;
864 if (!check_ksize(xup->xu_len, struct xunpcb))
865 goto out;
866 if ((xup->unp_conn == 0 && !opt_l) ||
867 (xup->unp_conn != 0 && !opt_c))
868 continue;
869 if ((sock = calloc(1, sizeof(*sock))) == NULL)
870 xo_err(1, "malloc()");
871 if ((laddr = calloc(1, sizeof *laddr)) == NULL)
872 xo_err(1, "malloc()");
873 if ((faddr = calloc(1, sizeof *faddr)) == NULL)
874 xo_err(1, "malloc()");
875 sock->socket = xup->xu_socket.xso_so;
876 sock->pcb = xup->xu_unpp;
877 sock->proto = proto;
878 sock->family = AF_UNIX;
879 sock->protoname = protoname;
880 if (xup->xu_addr.sun_family == AF_UNIX)
881 laddr->address =
882 *(struct sockaddr_storage *)(void *)&xup->xu_addr;
883 faddr->conn = xup->unp_conn;
884 faddr->firstref = xup->xu_firstref;
885 faddr->nextref = xup->xu_nextref;
886 laddr->next = NULL;
887 faddr->next = NULL;
888 sock->laddr = laddr;
889 sock->faddr = faddr;
890 RB_INSERT(socks_t, &socks, sock);
891 RB_INSERT(pcbs_t, &pcbs, sock);
892 }
893 out:
894 free(buf);
895 }
896
897 static void
getfiles(void)898 getfiles(void)
899 {
900 struct xfile *xfiles;
901 size_t len, olen;
902
903 olen = len = sizeof(*xfiles);
904 if ((xfiles = malloc(len)) == NULL)
905 xo_err(1, "malloc()");
906 while (cap_sysctlbyname(capsysctl, "kern.file", xfiles, &len, 0, 0)
907 == -1) {
908 if (errno != ENOMEM || len != olen)
909 xo_err(1, "cap_sysctlbyname()");
910 olen = len *= 2;
911 if ((xfiles = realloc(xfiles, len)) == NULL)
912 xo_err(1, "realloc()");
913 }
914 if (len > 0)
915 enforce_ksize(xfiles->xf_size, struct xfile);
916 nfiles = len / sizeof(*xfiles);
917
918 if ((files = malloc(nfiles * sizeof(struct file))) == NULL)
919 xo_err(1, "malloc()");
920
921 for (int i = 0; i < nfiles; i++) {
922 files[i].xf_data = xfiles[i].xf_data;
923 files[i].xf_pid = xfiles[i].xf_pid;
924 files[i].xf_uid = xfiles[i].xf_uid;
925 files[i].xf_fd = xfiles[i].xf_fd;
926 RB_INSERT(files_t, &ftree, &files[i]);
927 }
928
929 free(xfiles);
930 }
931
932 static int
formataddr(struct sockaddr_storage * ss,char * buf,size_t bufsize)933 formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize)
934 {
935 struct sockaddr_un *sun;
936 char addrstr[NI_MAXHOST] = { '\0', '\0' };
937 int error, off, port = 0;
938 const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
939
940 switch (ss->ss_family) {
941 case AF_INET:
942 if (sstosin(ss)->sin_addr.s_addr == INADDR_ANY)
943 addrstr[0] = '*';
944 port = ntohs(sstosin(ss)->sin_port);
945 break;
946 case AF_INET6:
947 if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr))
948 addrstr[0] = '*';
949 port = ntohs(sstosin6(ss)->sin6_port);
950 break;
951 case AF_UNIX:
952 sun = sstosun(ss);
953 off = (int)((char *)&sun->sun_path - (char *)sun);
954 if (!is_text_style) {
955 xo_emit("{:path/%.*s}", sun->sun_len - off,
956 sun->sun_path);
957 return 0;
958 }
959 return snprintf(buf, bufsize, "%.*s",
960 sun->sun_len - off, sun->sun_path);
961 }
962 if (addrstr[0] == '\0') {
963 error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len,
964 addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
965 if (error)
966 xo_errx(1, "cap_getnameinfo()");
967 }
968 if (!is_text_style) {
969 xo_emit("{:address/%s}", addrstr);
970 xo_emit("{:port/%d}", port);
971 return 0;
972 }
973 if (port == 0)
974 return snprintf(buf, bufsize, "%s:*", addrstr);
975 return snprintf(buf, bufsize, "%s:%d", addrstr, port);
976 }
977
978 static const char *
getprocname(pid_t pid)979 getprocname(pid_t pid)
980 {
981 static struct kinfo_proc proc;
982 size_t len;
983 int mib[4];
984
985 mib[0] = CTL_KERN;
986 mib[1] = KERN_PROC;
987 mib[2] = KERN_PROC_PID;
988 mib[3] = (int)pid;
989 len = sizeof(proc);
990 if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0)
991 == -1) {
992 /* Do not warn if the process exits before we get its name. */
993 if (errno != ESRCH)
994 xo_warn("cap_sysctl()");
995 return ("??");
996 }
997 return (proc.ki_comm);
998 }
999
1000 static int
getprocjid(pid_t pid)1001 getprocjid(pid_t pid)
1002 {
1003 static struct kinfo_proc proc;
1004 size_t len;
1005 int mib[4];
1006
1007 mib[0] = CTL_KERN;
1008 mib[1] = KERN_PROC;
1009 mib[2] = KERN_PROC_PID;
1010 mib[3] = (int)pid;
1011 len = sizeof(proc);
1012 if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0)
1013 == -1) {
1014 /* Do not warn if the process exits before we get its jid. */
1015 if (errno != ESRCH)
1016 xo_warn("cap_sysctl()");
1017 return (-1);
1018 }
1019 return (proc.ki_jid);
1020 }
1021
1022 static int
check_ports(struct sock * s)1023 check_ports(struct sock *s)
1024 {
1025 int port;
1026 struct addr *addr;
1027
1028 if (ports == NULL)
1029 return (1);
1030 if ((s->family != AF_INET) && (s->family != AF_INET6))
1031 return (1);
1032 for (addr = s->laddr; addr != NULL; addr = addr->next) {
1033 if (s->family == AF_INET)
1034 port = ntohs(sstosin(&addr->address)->sin_port);
1035 else
1036 port = ntohs(sstosin6(&addr->address)->sin6_port);
1037 if (CHK_PORT(port))
1038 return (1);
1039 }
1040 for (addr = s->faddr; addr != NULL; addr = addr->next) {
1041 if (s->family == AF_INET)
1042 port = ntohs(sstosin(&addr->address)->sin_port);
1043 else
1044 port = ntohs(sstosin6(&addr->address)->sin6_port);
1045 if (CHK_PORT(port))
1046 return (1);
1047 }
1048 return (0);
1049 }
1050
1051 static const char *
sctp_conn_state(int state)1052 sctp_conn_state(int state)
1053 {
1054 switch (state) {
1055 case SCTP_CLOSED:
1056 return "CLOSED";
1057 break;
1058 case SCTP_BOUND:
1059 return "BOUND";
1060 break;
1061 case SCTP_LISTEN:
1062 return "LISTEN";
1063 break;
1064 case SCTP_COOKIE_WAIT:
1065 return "COOKIE_WAIT";
1066 break;
1067 case SCTP_COOKIE_ECHOED:
1068 return "COOKIE_ECHOED";
1069 break;
1070 case SCTP_ESTABLISHED:
1071 return "ESTABLISHED";
1072 break;
1073 case SCTP_SHUTDOWN_SENT:
1074 return "SHUTDOWN_SENT";
1075 break;
1076 case SCTP_SHUTDOWN_RECEIVED:
1077 return "SHUTDOWN_RECEIVED";
1078 break;
1079 case SCTP_SHUTDOWN_ACK_SENT:
1080 return "SHUTDOWN_ACK_SENT";
1081 break;
1082 case SCTP_SHUTDOWN_PENDING:
1083 return "SHUTDOWN_PENDING";
1084 break;
1085 default:
1086 return "UNKNOWN";
1087 break;
1088 }
1089 }
1090
1091 static const char *
sctp_path_state(int state)1092 sctp_path_state(int state)
1093 {
1094 switch (state) {
1095 case SCTP_UNCONFIRMED:
1096 return "UNCONFIRMED";
1097 break;
1098 case SCTP_ACTIVE:
1099 return "ACTIVE";
1100 break;
1101 case SCTP_INACTIVE:
1102 return "INACTIVE";
1103 break;
1104 default:
1105 return "UNKNOWN";
1106 break;
1107 }
1108 }
1109
1110 static int
format_unix_faddr(struct addr * faddr,char * buf,size_t bufsize)1111 format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) {
1112 #define SAFEBUF (buf == NULL ? NULL : buf + pos)
1113 #define SAFESIZE (buf == NULL ? 0 : bufsize - pos)
1114
1115 size_t pos = 0;
1116 const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
1117 if (faddr->conn != 0) {
1118 /* Remote peer we connect(2) to, if any. */
1119 struct sock *p;
1120 if (is_text_style)
1121 pos += strlcpy(SAFEBUF, "-> ", SAFESIZE);
1122 p = RB_FIND(pcbs_t, &pcbs,
1123 &(struct sock){ .pcb = faddr->conn });
1124 if (__predict_false(p == NULL) && is_text_style) {
1125 /* XXGL: can this happen at all? */
1126 pos += snprintf(SAFEBUF, SAFESIZE, "??");
1127 } else if (p->laddr->address.ss_len == 0) {
1128 struct file *f;
1129 f = RB_FIND(files_t, &ftree,
1130 &(struct file){ .xf_data =
1131 p->socket });
1132 if (f != NULL) {
1133 if (is_text_style) {
1134 pos += snprintf(SAFEBUF, SAFESIZE,
1135 "[%lu %d]", (u_long)f->xf_pid,
1136 f->xf_fd);
1137 } else {
1138 xo_open_list("connections");
1139 xo_open_instance("connections");
1140 xo_emit("{:pid/%lu}", (u_long)f->xf_pid);
1141 xo_emit("{:fd/%d}", f->xf_fd);
1142 xo_close_instance("connections");
1143 xo_close_list("connections");
1144 }
1145 }
1146 } else
1147 pos += formataddr(&p->laddr->address,
1148 SAFEBUF, SAFESIZE);
1149 } else if (faddr->firstref != 0) {
1150 /* Remote peer(s) connect(2)ed to us, if any. */
1151 struct sock *p;
1152 struct file *f;
1153 kvaddr_t ref = faddr->firstref;
1154 bool fref = true;
1155
1156 if (is_text_style)
1157 pos += snprintf(SAFEBUF, SAFESIZE, " <- ");
1158 xo_open_list("connections");
1159 while ((p = RB_FIND(pcbs_t, &pcbs,
1160 &(struct sock){ .pcb = ref })) != 0) {
1161 f = RB_FIND(files_t, &ftree,
1162 &(struct file){ .xf_data = p->socket });
1163 if (f != NULL) {
1164 if (is_text_style) {
1165 pos += snprintf(SAFEBUF, SAFESIZE,
1166 "%s[%lu %d]", fref ? "" : ",",
1167 (u_long)f->xf_pid, f->xf_fd);
1168 } else {
1169 xo_open_instance("connections");
1170 xo_emit("{:pid/%lu}", (u_long)f->xf_pid);
1171 xo_emit("{:fd/%d}", f->xf_fd);
1172 xo_close_instance("connections");
1173 }
1174 }
1175 ref = p->faddr->nextref;
1176 fref = false;
1177 }
1178 xo_close_list("connections");
1179 }
1180 return pos;
1181 }
1182
1183 struct col_widths {
1184 int user;
1185 int command;
1186 int pid;
1187 int fd;
1188 int proto;
1189 int local_addr;
1190 int foreign_addr;
1191 int pcb_kva;
1192 int fib;
1193 int splice_address;
1194 int inp_gencnt;
1195 int encaps;
1196 int path_state;
1197 int conn_state;
1198 int stack;
1199 int cc;
1200 };
1201
1202 static void
calculate_sock_column_widths(struct col_widths * cw,struct sock * s)1203 calculate_sock_column_widths(struct col_widths *cw, struct sock *s)
1204 {
1205 struct addr *laddr, *faddr;
1206 bool first = true;
1207 int len = 0;
1208 laddr = s->laddr;
1209 faddr = s->faddr;
1210 first = true;
1211
1212 len = strlen(s->protoname);
1213 if (s->vflag & (INP_IPV4 | INP_IPV6))
1214 len += 1;
1215 cw->proto = MAX(cw->proto, len);
1216
1217 while (laddr != NULL || faddr != NULL) {
1218 if (opt_w && s->family == AF_UNIX) {
1219 if ((laddr == NULL) || (faddr == NULL))
1220 xo_errx(1, "laddr = %p or faddr = %p is NULL",
1221 (void *)laddr, (void *)faddr);
1222 if (laddr->address.ss_len > 0)
1223 len = formataddr(&laddr->address, NULL, 0);
1224 cw->local_addr = MAX(cw->local_addr, len);
1225 len = format_unix_faddr(faddr, NULL, 0);
1226 cw->foreign_addr = MAX(cw->foreign_addr, len);
1227 } else if (opt_w) {
1228 if (laddr != NULL) {
1229 len = formataddr(&laddr->address, NULL, 0);
1230 cw->local_addr = MAX(cw->local_addr, len);
1231 }
1232 if (faddr != NULL) {
1233 len = formataddr(&faddr->address, NULL, 0);
1234 cw->foreign_addr = MAX(cw->foreign_addr, len);
1235 }
1236 }
1237 if (opt_f) {
1238 len = snprintf(NULL, 0, "%d", s->fibnum);
1239 cw->fib = MAX(cw->fib, len);
1240 }
1241 if (opt_I) {
1242 if (s->splice_socket != 0) {
1243 struct sock *sp;
1244
1245 sp = RB_FIND(socks_t, &socks, &(struct sock)
1246 { .socket = s->splice_socket });
1247 if (sp != NULL) {
1248 len = formataddr(&sp->laddr->address,
1249 NULL, 0);
1250 cw->splice_address = MAX(
1251 cw->splice_address, len);
1252 }
1253 }
1254 }
1255 if (opt_i) {
1256 if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP)
1257 {
1258 len = snprintf(NULL, 0,
1259 "%" PRIu64, s->inp_gencnt);
1260 cw->inp_gencnt = MAX(cw->inp_gencnt, len);
1261 }
1262 }
1263 if (opt_U) {
1264 if (faddr != NULL &&
1265 ((s->proto == IPPROTO_SCTP &&
1266 s->state != SCTP_CLOSED &&
1267 s->state != SCTP_BOUND &&
1268 s->state != SCTP_LISTEN) ||
1269 (s->proto == IPPROTO_TCP &&
1270 s->state != TCPS_CLOSED &&
1271 s->state != TCPS_LISTEN))) {
1272 len = snprintf(NULL, 0, "%u",
1273 ntohs(faddr->encaps_port));
1274 cw->encaps = MAX(cw->encaps, len);
1275 }
1276 }
1277 if (opt_s) {
1278 if (faddr != NULL &&
1279 s->proto == IPPROTO_SCTP &&
1280 s->state != SCTP_CLOSED &&
1281 s->state != SCTP_BOUND &&
1282 s->state != SCTP_LISTEN) {
1283 len = strlen(sctp_path_state(faddr->state));
1284 cw->path_state = MAX(cw->path_state, len);
1285 }
1286 }
1287 if (first) {
1288 if (opt_s) {
1289 if (s->proto == IPPROTO_SCTP ||
1290 s->proto == IPPROTO_TCP) {
1291 switch (s->proto) {
1292 case IPPROTO_SCTP:
1293 len = strlen(
1294 sctp_conn_state(s->state));
1295 cw->conn_state = MAX(
1296 cw->conn_state, len);
1297 break;
1298 case IPPROTO_TCP:
1299 if (s->state >= 0 &&
1300 s->state < TCP_NSTATES) {
1301 len = strlen(
1302 tcpstates[s->state]);
1303 cw->conn_state = MAX(
1304 cw->conn_state, len);
1305 }
1306 break;
1307 }
1308 }
1309 }
1310 if (opt_S && s->proto == IPPROTO_TCP) {
1311 len = strlen(s->stack);
1312 cw->stack = MAX(cw->stack, len);
1313 }
1314 if (opt_C && s->proto == IPPROTO_TCP) {
1315 len = strlen(s->cc);
1316 cw->cc = MAX(cw->cc, len);
1317 }
1318 }
1319 if (laddr != NULL)
1320 laddr = laddr->next;
1321 if (faddr != NULL)
1322 faddr = faddr->next;
1323 first = false;
1324 }
1325 }
1326
1327 static void
calculate_column_widths(struct col_widths * cw)1328 calculate_column_widths(struct col_widths *cw)
1329 {
1330 int n, len;
1331 struct file *xf;
1332 struct sock *s;
1333 struct passwd *pwd;
1334
1335 cap_setpassent(cappwd, 1);
1336 for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
1337 if (xf->xf_data == 0)
1338 continue;
1339 if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
1340 continue;
1341 s = RB_FIND(socks_t, &socks,
1342 &(struct sock){ .socket = xf->xf_data});
1343 if (s == NULL || (!check_ports(s)))
1344 continue;
1345 s->shown = 1;
1346 if (opt_n ||
1347 (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
1348 len = snprintf(NULL, 0, "%lu", (u_long)xf->xf_uid);
1349 else
1350 len = snprintf(NULL, 0, "%s", pwd->pw_name);
1351 cw->user = MAX(cw->user, len);
1352 len = snprintf(NULL, 0, "%lu", (u_long)xf->xf_pid);
1353 cw->pid = MAX(cw->pid, len);
1354 len = snprintf(NULL, 0, "%d", xf->xf_fd);
1355 cw->fd = MAX(cw->fd, len);
1356
1357 calculate_sock_column_widths(cw, s);
1358 }
1359 if (opt_j >= 0)
1360 return;
1361 SLIST_FOREACH(s, &nosocks, socket_list) {
1362 if (!check_ports(s))
1363 continue;
1364 calculate_sock_column_widths(cw, s);
1365 }
1366 RB_FOREACH(s, socks_t, &socks) {
1367 if (s->shown)
1368 continue;
1369 if (!check_ports(s))
1370 continue;
1371 calculate_sock_column_widths(cw, s);
1372 }
1373 }
1374
1375 static void
display_sock(struct sock * s,struct col_widths * cw,char * buf,size_t bufsize)1376 display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
1377 {
1378 struct addr *laddr, *faddr;
1379 bool first;
1380 laddr = s->laddr;
1381 faddr = s->faddr;
1382 first = true;
1383 const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
1384
1385 snprintf(buf, bufsize, "%s%s%s",
1386 s->protoname,
1387 s->vflag & INP_IPV4 ? "4" : "",
1388 s->vflag & INP_IPV6 ? "6" : "");
1389 xo_emit(" {:proto/%-*s}", cw->proto, buf);
1390 while (laddr != NULL || faddr != NULL) {
1391 if (s->family == AF_UNIX) {
1392 if ((laddr == NULL) || (faddr == NULL))
1393 xo_errx(1, "laddr = %p or faddr = %p is NULL",
1394 (void *)laddr, (void *)faddr);
1395 if (laddr->address.ss_len > 0) {
1396 xo_open_container("local");
1397 formataddr(&laddr->address, buf, bufsize);
1398 if (is_text_style) {
1399 xo_emit(" {:/%-*.*s}", cw->local_addr,
1400 cw->local_addr, buf);
1401 }
1402 xo_close_container("local");
1403 } else if (laddr->address.ss_len == 0 &&
1404 faddr->conn == 0 && is_text_style) {
1405 xo_emit(" {:/%-*.*s}", cw->local_addr,
1406 cw->local_addr, "(not connected)");
1407 } else if (is_text_style) {
1408 xo_emit(" {:/%-*.*s}", cw->local_addr,
1409 cw->local_addr, "??");
1410 }
1411 if (faddr->conn != 0 || faddr->firstref != 0) {
1412 xo_open_container("foreign");
1413 int len = format_unix_faddr(faddr, buf,
1414 bufsize);
1415 if (len == 0 && is_text_style)
1416 xo_emit(" {:/%-*s}",
1417 cw->foreign_addr, "??");
1418 else if (is_text_style)
1419 xo_emit(" {:/%-*.*s}", cw->foreign_addr,
1420 cw->foreign_addr, buf);
1421 xo_close_container("foreign");
1422 } else if (is_text_style)
1423 xo_emit(" {:/%-*s}", cw->foreign_addr, "??");
1424 } else {
1425 if (laddr != NULL) {
1426 xo_open_container("local");
1427 formataddr(&laddr->address, buf, bufsize);
1428 if (is_text_style) {
1429 xo_emit(" {:/%-*.*s}", cw->local_addr,
1430 cw->local_addr, buf);
1431 }
1432 xo_close_container("local");
1433 } else if (is_text_style)
1434 xo_emit(" {:/%-*.*s}", cw->local_addr,
1435 cw->local_addr, "??");
1436 if (faddr != NULL) {
1437 xo_open_container("foreign");
1438 formataddr(&faddr->address, buf, bufsize);
1439 if (is_text_style) {
1440 xo_emit(" {:/%-*.*s}", cw->foreign_addr,
1441 cw->foreign_addr, buf);
1442 }
1443 xo_close_container("foreign");
1444 } else if (is_text_style) {
1445 xo_emit(" {:/%-*.*s}", cw->foreign_addr,
1446 cw->foreign_addr, "??");
1447 }
1448 }
1449 if (opt_A) {
1450 snprintf(buf, bufsize, "%#*" PRIx64,
1451 cw->pcb_kva, s->pcb);
1452 xo_emit(" {:pcb-kva/%s}", buf);
1453 }
1454 if (opt_f)
1455 xo_emit(" {:fib/%*d}", cw->fib, s->fibnum);
1456 if (opt_I) {
1457 if (s->splice_socket != 0) {
1458 struct sock *sp;
1459 sp = RB_FIND(socks_t, &socks, &(struct sock)
1460 { .socket = s->splice_socket });
1461 if (sp != NULL) {
1462 xo_open_container("splice");
1463 formataddr(&sp->laddr->address,
1464 buf, bufsize);
1465 xo_close_container("splice");
1466 } else if (is_text_style)
1467 strlcpy(buf, "??", bufsize);
1468 } else if (is_text_style)
1469 strlcpy(buf, "??", bufsize);
1470 if (is_text_style)
1471 xo_emit(" {:/%-*s}", cw->splice_address, buf);
1472 }
1473 if (opt_i) {
1474 if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP)
1475 {
1476 snprintf(buf, bufsize, "%" PRIu64,
1477 s->inp_gencnt);
1478 xo_emit(" {:id/%*s}", cw->inp_gencnt, buf);
1479 } else if (is_text_style)
1480 xo_emit(" {:/%*s}", cw->inp_gencnt, "??");
1481 }
1482 if (opt_U) {
1483 if (faddr != NULL &&
1484 ((s->proto == IPPROTO_SCTP &&
1485 s->state != SCTP_CLOSED &&
1486 s->state != SCTP_BOUND &&
1487 s->state != SCTP_LISTEN) ||
1488 (s->proto == IPPROTO_TCP &&
1489 s->state != TCPS_CLOSED &&
1490 s->state != TCPS_LISTEN))) {
1491 xo_emit(" {:encaps/%*u}", cw->encaps,
1492 ntohs(faddr->encaps_port));
1493 } else if (is_text_style)
1494 xo_emit(" {:/%*s}", cw->encaps, "??");
1495 }
1496 if (opt_s) {
1497 if (faddr != NULL &&
1498 s->proto == IPPROTO_SCTP &&
1499 s->state != SCTP_CLOSED &&
1500 s->state != SCTP_BOUND &&
1501 s->state != SCTP_LISTEN) {
1502 xo_emit(" {:path-state/%-*s}", cw->path_state,
1503 sctp_path_state(faddr->state));
1504 } else if (is_text_style)
1505 xo_emit(" {:/%-*s}", cw->path_state, "??");
1506 }
1507 if (first) {
1508 if (opt_s) {
1509 if (s->proto == IPPROTO_SCTP ||
1510 s->proto == IPPROTO_TCP) {
1511 switch (s->proto) {
1512 case IPPROTO_SCTP:
1513 xo_emit(" {:path-state/%-*s}",
1514 cw->path_state,
1515 sctp_path_state(
1516 faddr->state));
1517 break;
1518 case IPPROTO_TCP:
1519 if (s->state >= 0 &&
1520 s->state < TCP_NSTATES)
1521 xo_emit(" {:conn-state/%-*s}",
1522 cw->conn_state,
1523 tcpstates[s->state]);
1524 else if (is_text_style)
1525 xo_emit(" {:/%-*s}",
1526 cw->conn_state, "??");
1527 break;
1528 }
1529 } else if (is_text_style)
1530 xo_emit(" {:/%-*s}",
1531 cw->conn_state, "??");
1532 }
1533 if (opt_S) {
1534 if (s->proto == IPPROTO_TCP)
1535 xo_emit(" {:stack/%-*s}",
1536 cw->stack, s->stack);
1537 else if (is_text_style)
1538 xo_emit(" {:/%-*s}",
1539 cw->stack, "??");
1540 }
1541 if (opt_C) {
1542 if (s->proto == IPPROTO_TCP)
1543 xo_emit(" {:cc/%-*s}", cw->cc, s->cc);
1544 else if (is_text_style)
1545 xo_emit(" {:/%-*s}", cw->cc, "??");
1546 }
1547 }
1548 if (laddr != NULL)
1549 laddr = laddr->next;
1550 if (faddr != NULL)
1551 faddr = faddr->next;
1552 if (is_text_style && (laddr != NULL || faddr != NULL))
1553 xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
1554 cw->user, "??", cw->command, "??",
1555 cw->pid, "??", cw->fd, "??");
1556 first = false;
1557 }
1558 xo_emit("\n");
1559 }
1560
1561 static void
display(void)1562 display(void)
1563 {
1564 struct passwd *pwd;
1565 struct file *xf;
1566 struct sock *s;
1567 int n;
1568 struct col_widths cw;
1569 const size_t bufsize = 512;
1570 void *buf;
1571 if ((buf = (char *)malloc(bufsize)) == NULL) {
1572 xo_err(1, "malloc()");
1573 return;
1574 }
1575
1576 if (xo_get_style(NULL) == XO_STYLE_TEXT) {
1577 cw = (struct col_widths) {
1578 .user = strlen("USER"),
1579 .command = 10,
1580 .pid = strlen("PID"),
1581 .fd = strlen("FD"),
1582 .proto = strlen("PROTO"),
1583 .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21,
1584 .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21,
1585 .pcb_kva = 18,
1586 .fib = strlen("FIB"),
1587 .splice_address = strlen("SPLICE ADDRESS"),
1588 .inp_gencnt = strlen("ID"),
1589 .encaps = strlen("ENCAPS"),
1590 .path_state = strlen("PATH STATE"),
1591 .conn_state = strlen("CONN STATE"),
1592 .stack = strlen("STACK"),
1593 .cc = strlen("CC"),
1594 };
1595 calculate_column_widths(&cw);
1596 } else
1597 memset(&cw, 0, sizeof(cw));
1598
1599 xo_set_version(SOCKSTAT_XO_VERSION);
1600 xo_open_container("sockstat");
1601 xo_open_list("socket");
1602 if (!opt_q) {
1603 xo_emit("{T:/%-*s} {T:/%-*s} {T:/%*s} {T:/%*s} {T:/%-*s} "
1604 "{T:/%-*s} {T:/%-*s}", cw.user, "USER", cw.command,
1605 "COMMAND", cw.pid, "PID", cw.fd, "FD", cw.proto,
1606 "PROTO", cw.local_addr, "LOCAL ADDRESS",
1607 cw.foreign_addr, "FOREIGN ADDRESS");
1608 if (opt_A)
1609 xo_emit(" {T:/%-*s}", cw.pcb_kva, "PCB KVA");
1610 if (opt_f)
1611 /* RT_MAXFIBS is 65535. */
1612 xo_emit(" {T:/%*s}", cw.fib, "FIB");
1613 if (opt_I)
1614 xo_emit(" {T:/%-*s}", cw.splice_address,
1615 "SPLICE ADDRESS");
1616 if (opt_i)
1617 xo_emit(" {T:/%*s}", cw.inp_gencnt, "ID");
1618 if (opt_U)
1619 xo_emit(" {T:/%*s}", cw.encaps, "ENCAPS");
1620 if (opt_s) {
1621 xo_emit(" {T:/%-*s}", cw.path_state, "PATH STATE");
1622 xo_emit(" {T:/%-*s}", cw.conn_state, "CONN STATE");
1623 }
1624 if (opt_S)
1625 xo_emit(" {T:/%-*s}", cw.stack, "STACK");
1626 if (opt_C)
1627 xo_emit(" {T:/%-*s}", cw.cc, "CC");
1628 xo_emit("\n");
1629 }
1630 cap_setpassent(cappwd, 1);
1631 for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
1632 if (xf->xf_data == 0)
1633 continue;
1634 if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
1635 continue;
1636 s = RB_FIND(socks_t, &socks,
1637 &(struct sock){ .socket = xf->xf_data});
1638 if (s != NULL && check_ports(s)) {
1639 xo_open_instance("socket");
1640 s->shown = 1;
1641 if (opt_n ||
1642 (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
1643 xo_emit("{:user/%-*lu}", cw.user,
1644 (u_long)xf->xf_uid);
1645 else
1646 xo_emit("{:user/%-*s}", cw.user, pwd->pw_name);
1647 if (xo_get_style(NULL) == XO_STYLE_TEXT)
1648 xo_emit(" {:/%-*.10s}", cw.command,
1649 getprocname(xf->xf_pid));
1650 else
1651 xo_emit(" {:command/%-*s}", cw.command,
1652 getprocname(xf->xf_pid));
1653 xo_emit(" {:pid/%*lu}", cw.pid, (u_long)xf->xf_pid);
1654 xo_emit(" {:fd/%*d}", cw.fd, xf->xf_fd);
1655 display_sock(s, &cw, buf, bufsize);
1656 xo_close_instance("socket");
1657 }
1658 }
1659 if (opt_j >= 0)
1660 return;
1661 SLIST_FOREACH(s, &nosocks, socket_list) {
1662 if (!check_ports(s))
1663 continue;
1664 xo_open_instance("socket");
1665 if (xo_get_style(NULL) == XO_STYLE_TEXT)
1666 xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
1667 cw.user, "??", cw.command, "??",
1668 cw.pid, "??", cw.fd, "??");
1669 display_sock(s, &cw, buf, bufsize);
1670 xo_close_instance("socket");
1671 }
1672 RB_FOREACH(s, socks_t, &socks) {
1673 if (s->shown)
1674 continue;
1675 if (!check_ports(s))
1676 continue;
1677 xo_open_instance("socket");
1678 if (xo_get_style(NULL) == XO_STYLE_TEXT)
1679 xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
1680 cw.user, "??", cw.command, "??",
1681 cw.pid, "??", cw.fd, "??");
1682 display_sock(s, &cw, buf, bufsize);
1683 xo_close_instance("socket");
1684 }
1685 xo_close_list("socket");
1686 xo_close_container("sockstat");
1687 if (xo_finish() < 0)
1688 xo_err(1, "stdout");
1689 free(buf);
1690 cap_endpwent(cappwd);
1691 }
1692
1693 static int
set_default_protos(void)1694 set_default_protos(void)
1695 {
1696 struct protoent *prot;
1697 const char *pname;
1698 size_t pindex;
1699
1700 init_protos(default_numprotos);
1701
1702 for (pindex = 0; pindex < default_numprotos; pindex++) {
1703 pname = default_protos[pindex];
1704 prot = cap_getprotobyname(capnetdb, pname);
1705 if (prot == NULL)
1706 xo_err(1, "cap_getprotobyname: %s", pname);
1707 protos[pindex] = prot->p_proto;
1708 }
1709 numprotos = pindex;
1710 return (pindex);
1711 }
1712
1713 /*
1714 * Return the vnet property of the jail, or -1 on error.
1715 */
1716 static int
jail_getvnet(int jid)1717 jail_getvnet(int jid)
1718 {
1719 struct iovec jiov[6];
1720 int vnet;
1721 size_t len = sizeof(vnet);
1722
1723 if (sysctlbyname("kern.features.vimage", &vnet, &len, NULL, 0) != 0)
1724 return (0);
1725
1726 vnet = -1;
1727 jiov[0].iov_base = __DECONST(char *, "jid");
1728 jiov[0].iov_len = sizeof("jid");
1729 jiov[1].iov_base = &jid;
1730 jiov[1].iov_len = sizeof(jid);
1731 jiov[2].iov_base = __DECONST(char *, "vnet");
1732 jiov[2].iov_len = sizeof("vnet");
1733 jiov[3].iov_base = &vnet;
1734 jiov[3].iov_len = sizeof(vnet);
1735 jiov[4].iov_base = __DECONST(char *, "errmsg");
1736 jiov[4].iov_len = sizeof("errmsg");
1737 jiov[5].iov_base = jail_errmsg;
1738 jiov[5].iov_len = JAIL_ERRMSGLEN;
1739 jail_errmsg[0] = '\0';
1740 if (jail_get(jiov, nitems(jiov), 0) < 0) {
1741 if (!jail_errmsg[0])
1742 snprintf(jail_errmsg, JAIL_ERRMSGLEN,
1743 "jail_get: %s", strerror(errno));
1744 return (-1);
1745 }
1746 return (vnet);
1747 }
1748
1749 static void
usage(void)1750 usage(void)
1751 {
1752 xo_error(
1753 "usage: sockstat [--libxo] [-46ACcfIiLlnqSsUuvw] [-j jid] [-p ports]\n"
1754 " [-P protocols]\n");
1755 exit(1);
1756 }
1757
1758 int
main(int argc,char * argv[])1759 main(int argc, char *argv[])
1760 {
1761 cap_channel_t *capcas;
1762 cap_net_limit_t *limit;
1763 const char *pwdcmds[] = { "setpassent", "getpwuid" };
1764 const char *pwdfields[] = { "pw_name" };
1765 int protos_defined = -1;
1766 int o, i;
1767
1768 argc = xo_parse_args(argc, argv);
1769 if (argc < 0)
1770 exit(1);
1771 opt_j = -1;
1772 while ((o = getopt(argc, argv, "46ACcfIij:Llnp:P:qSsUuvw")) != -1)
1773 switch (o) {
1774 case '4':
1775 opt_4 = true;
1776 break;
1777 case '6':
1778 opt_6 = true;
1779 break;
1780 case 'A':
1781 opt_A = true;
1782 break;
1783 case 'C':
1784 opt_C = true;
1785 break;
1786 case 'c':
1787 opt_c = true;
1788 break;
1789 case 'f':
1790 opt_f = true;
1791 break;
1792 case 'I':
1793 opt_I = true;
1794 break;
1795 case 'i':
1796 opt_i = true;
1797 break;
1798 case 'j':
1799 opt_j = jail_getid(optarg);
1800 if (opt_j < 0)
1801 xo_errx(1, "jail_getid: %s", jail_errmsg);
1802 break;
1803 case 'L':
1804 opt_L = true;
1805 break;
1806 case 'l':
1807 opt_l = true;
1808 break;
1809 case 'n':
1810 opt_n = true;
1811 break;
1812 case 'p':
1813 parse_ports(optarg);
1814 break;
1815 case 'P':
1816 protos_defined = parse_protos(optarg);
1817 break;
1818 case 'q':
1819 opt_q = true;
1820 break;
1821 case 'S':
1822 opt_S = true;
1823 break;
1824 case 's':
1825 opt_s = true;
1826 break;
1827 case 'U':
1828 opt_U = true;
1829 break;
1830 case 'u':
1831 opt_u = true;
1832 break;
1833 case 'v':
1834 ++opt_v;
1835 break;
1836 case 'w':
1837 opt_w = true;
1838 break;
1839 default:
1840 usage();
1841 }
1842
1843 argc -= optind;
1844 argv += optind;
1845
1846 if (argc > 0)
1847 usage();
1848
1849 if (opt_j > 0) {
1850 switch (jail_getvnet(opt_j)) {
1851 case -1:
1852 xo_errx(2, "jail_getvnet: %s", jail_errmsg);
1853 case JAIL_SYS_NEW:
1854 if (jail_attach(opt_j) < 0)
1855 xo_err(3, "jail_attach()");
1856 /* Set back to -1 for normal output in vnet jail. */
1857 opt_j = -1;
1858 break;
1859 default:
1860 break;
1861 }
1862 }
1863
1864 capcas = cap_init();
1865 if (capcas == NULL)
1866 xo_err(1, "Unable to contact Casper");
1867 if (caph_enter_casper() < 0)
1868 xo_err(1, "Unable to enter capability mode");
1869 capnet = cap_service_open(capcas, "system.net");
1870 if (capnet == NULL)
1871 xo_err(1, "Unable to open system.net service");
1872 capnetdb = cap_service_open(capcas, "system.netdb");
1873 if (capnetdb == NULL)
1874 xo_err(1, "Unable to open system.netdb service");
1875 capsysctl = cap_service_open(capcas, "system.sysctl");
1876 if (capsysctl == NULL)
1877 xo_err(1, "Unable to open system.sysctl service");
1878 cappwd = cap_service_open(capcas, "system.pwd");
1879 if (cappwd == NULL)
1880 xo_err(1, "Unable to open system.pwd service");
1881 cap_close(capcas);
1882 limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
1883 if (limit == NULL)
1884 xo_err(1, "Unable to init cap_net limits");
1885 if (cap_net_limit(limit) < 0)
1886 xo_err(1, "Unable to apply limits");
1887 if (cap_pwd_limit_cmds(cappwd, pwdcmds, nitems(pwdcmds)) < 0)
1888 xo_err(1, "Unable to apply pwd commands limits");
1889 if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0)
1890 xo_err(1, "Unable to apply pwd commands limits");
1891
1892 if ((!opt_4 && !opt_6) && protos_defined != -1)
1893 opt_4 = opt_6 = true;
1894 if (!opt_4 && !opt_6 && !opt_u)
1895 opt_4 = opt_6 = opt_u = true;
1896 if ((opt_4 || opt_6) && protos_defined == -1)
1897 protos_defined = set_default_protos();
1898 if (!opt_c && !opt_l)
1899 opt_c = opt_l = true;
1900
1901 if (opt_4 || opt_6) {
1902 for (i = 0; i < protos_defined; i++)
1903 if (protos[i] == IPPROTO_SCTP)
1904 gather_sctp();
1905 else
1906 gather_inet(protos[i]);
1907 }
1908
1909 if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) {
1910 gather_unix(SOCK_STREAM);
1911 gather_unix(SOCK_DGRAM);
1912 gather_unix(SOCK_SEQPACKET);
1913 }
1914 getfiles();
1915 display();
1916 exit(0);
1917 }
1918