xref: /freebsd/usr.bin/netstat/unix.c (revision f856af0466c076beef4ea9b15d088e1119a945b8)
1 /*-
2  * Copyright (c) 1983, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #if 0
35 #ifndef lint
36 static char sccsid[] = "@(#)unix.c	8.1 (Berkeley) 6/6/93";
37 #endif /* not lint */
38 #endif
39 
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42 
43 /*
44  * Display protocol blocks in the unix domain.
45  */
46 #include <sys/param.h>
47 #include <sys/queue.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/mbuf.h>
52 #include <sys/sysctl.h>
53 #include <sys/un.h>
54 #include <sys/unpcb.h>
55 
56 #include <netinet/in.h>
57 
58 #include <errno.h>
59 #include <err.h>
60 #include <stddef.h>
61 #include <stdint.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <kvm.h>
65 #include "netstat.h"
66 
67 static	void unixdomainpr (struct xunpcb *, struct xsocket *);
68 
69 static	const char *const socktype[] =
70     { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
71 
72 void
73 unixpr(void)
74 {
75 	char 	*buf;
76 	int	type;
77 	size_t	len;
78 	struct	xsocket *so;
79 	struct	xunpgen *xug, *oxug;
80 	struct	xunpcb *xunp;
81 	char mibvar[sizeof "net.local.seqpacket.pcblist"];
82 
83 	for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
84 		sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
85 
86 		len = 0;
87 		if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
88 			if (errno != ENOENT)
89 				warn("sysctl: %s", mibvar);
90 			continue;
91 		}
92 		if ((buf = malloc(len)) == 0) {
93 			warnx("malloc %lu bytes", (u_long)len);
94 			return;
95 		}
96 		if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
97 			warn("sysctl: %s", mibvar);
98 			free(buf);
99 			return;
100 		}
101 
102 		oxug = xug = (struct xunpgen *)buf;
103 		for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
104 		     xug->xug_len > sizeof(struct xunpgen);
105 		     xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
106 			xunp = (struct xunpcb *)xug;
107 			so = &xunp->xu_socket;
108 
109 			/* Ignore PCBs which were freed during copyout. */
110 			if (xunp->xu_unp.unp_gencnt > oxug->xug_gen)
111 				continue;
112 			unixdomainpr(xunp, so);
113 		}
114 		if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
115 			if (oxug->xug_count > xug->xug_count) {
116 				printf("Some %s sockets may have been deleted.\n",
117 				       socktype[type]);
118 			} else if (oxug->xug_count < xug->xug_count) {
119 				printf("Some %s sockets may have been created.\n",
120 			       socktype[type]);
121 			} else {
122 				printf("Some %s sockets may have been created or deleted",
123 			       socktype[type]);
124 			}
125 		}
126 		free(buf);
127 	}
128 }
129 
130 static void
131 unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
132 {
133 	struct unpcb *unp;
134 	struct sockaddr_un *sa;
135 	static int first = 1;
136 
137 	unp = &xunp->xu_unp;
138 	if (unp->unp_addr)
139 		sa = &xunp->xu_addr;
140 	else
141 		sa = (struct sockaddr_un *)0;
142 
143 	if (first) {
144 		printf("Active UNIX domain sockets\n");
145 		printf(
146 "%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n",
147 		    "Address", "Type", "Recv-Q", "Send-Q",
148 		    "Inode", "Conn", "Refs", "Nextref");
149 		first = 0;
150 	}
151 	printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx",
152 	       (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
153 	       so->so_snd.sb_cc,
154 	       (long)unp->unp_vnode, (long)unp->unp_conn,
155 	       (long)LIST_FIRST(&unp->unp_refs), (long)LIST_NEXT(unp, unp_reflink));
156 	if (sa)
157 		printf(" %.*s",
158 		    (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
159 		    sa->sun_path);
160 	putchar('\n');
161 }
162