xref: /freebsd/usr.bin/sockstat/sockstat.c (revision 7b35b4d196309baf579571e1c1a433a4000d74c9)
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