1*1fc70a08Sozaki-r /* $NetBSD: sockstat.c,v 1.25 2022/10/28 05:24:07 ozaki-r Exp $ */
2724bd019Satatat
3724bd019Satatat /*
4724bd019Satatat * Copyright (c) 2005 The NetBSD Foundation, Inc.
5724bd019Satatat * All rights reserved.
6724bd019Satatat *
7724bd019Satatat * This code is derived from software contributed to The NetBSD Foundation
8724bd019Satatat * by Andrew Brown.
9724bd019Satatat *
10724bd019Satatat * Redistribution and use in source and binary forms, with or without
11724bd019Satatat * modification, are permitted provided that the following conditions
12724bd019Satatat * are met:
13724bd019Satatat * 1. Redistributions of source code must retain the above copyright
14724bd019Satatat * notice, this list of conditions and the following disclaimer.
15724bd019Satatat * 2. Redistributions in binary form must reproduce the above copyright
16724bd019Satatat * notice, this list of conditions and the following disclaimer in the
17724bd019Satatat * documentation and/or other materials provided with the distribution.
18724bd019Satatat *
19724bd019Satatat * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20724bd019Satatat * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21724bd019Satatat * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22724bd019Satatat * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23724bd019Satatat * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24724bd019Satatat * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25724bd019Satatat * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26724bd019Satatat * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27724bd019Satatat * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28724bd019Satatat * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29724bd019Satatat * POSSIBILITY OF SUCH DAMAGE.
30724bd019Satatat */
31724bd019Satatat
32724bd019Satatat #include <sys/cdefs.h>
33724bd019Satatat #ifndef lint
34*1fc70a08Sozaki-r __RCSID("$NetBSD: sockstat.c,v 1.25 2022/10/28 05:24:07 ozaki-r Exp $");
35724bd019Satatat #endif
36724bd019Satatat
3731ed49d5Schristos #define _KMEMUSER
38f4b74dafSad #include <sys/types.h>
3931ed49d5Schristos #undef _KMEMUSER
40724bd019Satatat #include <sys/param.h>
41724bd019Satatat #include <sys/sysctl.h>
42724bd019Satatat #include <sys/socket.h>
43724bd019Satatat #include <sys/socketvar.h>
44724bd019Satatat #include <sys/un.h>
45724bd019Satatat #include <netinet/in.h>
46724bd019Satatat #include <net/route.h>
47724bd019Satatat #include <netinet/in_systm.h>
48724bd019Satatat #include <netinet/ip.h>
49724bd019Satatat #include <netinet/in_pcb.h>
50724bd019Satatat #include <netinet/tcp_fsm.h>
51724bd019Satatat
52ea36f744Schristos #define _KMEMUSER
53724bd019Satatat /* want DTYPE_* defines */
54724bd019Satatat #include <sys/file.h>
55ea36f744Schristos #undef _KMEMUSER
56724bd019Satatat
57724bd019Satatat #include <arpa/inet.h>
58724bd019Satatat
59724bd019Satatat #include <bitstring.h>
60724bd019Satatat #include <ctype.h>
61724bd019Satatat #include <err.h>
62724bd019Satatat #include <errno.h>
63724bd019Satatat #include <netdb.h>
64724bd019Satatat #include <pwd.h>
65724bd019Satatat #include <stdio.h>
66724bd019Satatat #include <strings.h>
67724bd019Satatat #include <stdlib.h>
68724bd019Satatat #include <unistd.h>
69724bd019Satatat #include <util.h>
70724bd019Satatat
716475f125Spooka #include "prog_ops.h"
726475f125Spooka
73724bd019Satatat #define satosun(sa) ((struct sockaddr_un *)(sa))
74724bd019Satatat #define satosin(sa) ((struct sockaddr_in *)(sa))
75cccbf666Srpaulo #ifdef INET6
76724bd019Satatat #define satosin6(sa) ((struct sockaddr_in6 *)(sa))
77cccbf666Srpaulo #endif
78724bd019Satatat
79724bd019Satatat void parse_ports(const char *);
80724bd019Satatat int get_num(const char *, const char **, const char **);
81724bd019Satatat void get_sockets(const char *);
82724bd019Satatat void get_files(void);
83724bd019Satatat int sort_files(const void *, const void *);
84724bd019Satatat void sysctl_sucker(int *, u_int, void **, size_t *);
85724bd019Satatat void socket_add_hash(struct kinfo_pcb *, int);
86724bd019Satatat int isconnected(struct kinfo_pcb *);
87724bd019Satatat int islistening(struct kinfo_pcb *);
88724bd019Satatat struct kinfo_pcb *pick_socket(struct kinfo_file *);
89724bd019Satatat int get_proc(struct kinfo_proc2 *, int);
90724bd019Satatat int print_socket(struct kinfo_file *, struct kinfo_pcb *,
91724bd019Satatat struct kinfo_proc2 *);
92724bd019Satatat void print_addr(int, int, int, struct sockaddr *);
93724bd019Satatat
94724bd019Satatat LIST_HEAD(socklist, sockitem);
95724bd019Satatat #define HASHSIZE 1009
96724bd019Satatat struct socklist sockhash[HASHSIZE];
97724bd019Satatat struct sockitem {
98724bd019Satatat LIST_ENTRY(sockitem) s_list;
99724bd019Satatat struct kinfo_pcb *s_sock;
100724bd019Satatat };
101724bd019Satatat
102724bd019Satatat struct kinfo_file *flist;
103183f6d8aSlukem size_t flistc;
104724bd019Satatat
105724bd019Satatat int pf_list, only, nonames;
106724bd019Satatat bitstr_t *portmap;
107724bd019Satatat
108724bd019Satatat #define PF_LIST_INET 1
109cccbf666Srpaulo #ifdef INET6
110724bd019Satatat #define PF_LIST_INET6 2
111cccbf666Srpaulo #endif
112724bd019Satatat #define PF_LIST_LOCAL 4
113724bd019Satatat #define ONLY_CONNECTED 1
114724bd019Satatat #define ONLY_LISTEN 2
115724bd019Satatat
116724bd019Satatat int
main(int argc,char * argv[])117724bd019Satatat main(int argc, char *argv[])
118724bd019Satatat {
119724bd019Satatat struct kinfo_pcb *kp;
120183f6d8aSlukem int ch;
121183f6d8aSlukem size_t i;
122724bd019Satatat struct kinfo_proc2 p;
123724bd019Satatat
124724bd019Satatat pf_list = only = 0;
125724bd019Satatat
126cccbf666Srpaulo #ifdef INET6
127724bd019Satatat while ((ch = getopt(argc, argv, "46cf:lnp:u")) != - 1) {
128cccbf666Srpaulo #else
129cccbf666Srpaulo while ((ch = getopt(argc, argv, "4cf:lnp:u")) != - 1) {
130cccbf666Srpaulo #endif
131724bd019Satatat switch (ch) {
132724bd019Satatat case '4':
133724bd019Satatat pf_list |= PF_LIST_INET;
134724bd019Satatat break;
135cccbf666Srpaulo #ifdef INET6
136724bd019Satatat case '6':
137724bd019Satatat pf_list |= PF_LIST_INET6;
138724bd019Satatat break;
139cccbf666Srpaulo #endif
140724bd019Satatat case 'c':
141724bd019Satatat only |= ONLY_CONNECTED;
142724bd019Satatat break;
143724bd019Satatat case 'f':
144724bd019Satatat if (strcasecmp(optarg, "inet") == 0)
145724bd019Satatat pf_list |= PF_LIST_INET;
146cccbf666Srpaulo #ifdef INET6
147724bd019Satatat else if (strcasecmp(optarg, "inet6") == 0)
148724bd019Satatat pf_list |= PF_LIST_INET6;
149cccbf666Srpaulo #endif
150724bd019Satatat else if (strcasecmp(optarg, "local") == 0)
151724bd019Satatat pf_list |= PF_LIST_LOCAL;
152724bd019Satatat else if (strcasecmp(optarg, "unix") == 0)
153724bd019Satatat pf_list |= PF_LIST_LOCAL;
154724bd019Satatat else
155cccbf666Srpaulo errx(1, "%s: unsupported protocol family",
156cccbf666Srpaulo optarg);
157724bd019Satatat break;
158724bd019Satatat case 'l':
159724bd019Satatat only |= ONLY_LISTEN;
160724bd019Satatat break;
161724bd019Satatat case 'n':
162724bd019Satatat nonames++;
163724bd019Satatat break;
164724bd019Satatat case 'p':
165724bd019Satatat parse_ports(optarg);
166724bd019Satatat break;
167724bd019Satatat case 'u':
168724bd019Satatat pf_list |= PF_LIST_LOCAL;
169724bd019Satatat break;
170724bd019Satatat default:
171724bd019Satatat /* usage(); */
172724bd019Satatat exit(1);
173724bd019Satatat }
174724bd019Satatat }
175724bd019Satatat argc -= optind;
176724bd019Satatat argv += optind;
177724bd019Satatat
1786475f125Spooka if (prog_init && prog_init() == -1)
1796475f125Spooka err(1, "init");
1806475f125Spooka
181cccbf666Srpaulo if ((portmap != NULL) && (pf_list == 0)) {
182cccbf666Srpaulo pf_list = PF_LIST_INET;
183cccbf666Srpaulo #ifdef INET6
184cccbf666Srpaulo pf_list |= PF_LIST_INET6;
185cccbf666Srpaulo #endif
186cccbf666Srpaulo }
187cccbf666Srpaulo if (pf_list == 0) {
188cccbf666Srpaulo pf_list = PF_LIST_INET | PF_LIST_LOCAL;
189cccbf666Srpaulo #ifdef INET6
190cccbf666Srpaulo pf_list |= PF_LIST_INET6;
191cccbf666Srpaulo #endif
192cccbf666Srpaulo }
193724bd019Satatat if ((portmap != NULL) && (pf_list & PF_LIST_LOCAL))
194c36f9da9Speter errx(1, "local domain sockets do not have ports");
195724bd019Satatat
196724bd019Satatat if (pf_list & PF_LIST_INET) {
197724bd019Satatat get_sockets("net.inet.tcp.pcblist");
198724bd019Satatat get_sockets("net.inet.udp.pcblist");
199724bd019Satatat if (portmap == NULL)
200724bd019Satatat get_sockets("net.inet.raw.pcblist");
201724bd019Satatat }
202724bd019Satatat
203cccbf666Srpaulo #ifdef INET6
204724bd019Satatat if (pf_list & PF_LIST_INET6) {
205724bd019Satatat get_sockets("net.inet6.tcp6.pcblist");
206724bd019Satatat get_sockets("net.inet6.udp6.pcblist");
207724bd019Satatat if (portmap == NULL)
208724bd019Satatat get_sockets("net.inet6.raw6.pcblist");
209724bd019Satatat }
210cccbf666Srpaulo #endif
211724bd019Satatat
212724bd019Satatat if (pf_list & PF_LIST_LOCAL) {
213724bd019Satatat get_sockets("net.local.stream.pcblist");
2141b0d8e31Smanu get_sockets("net.local.seqpacket.pcblist");
215724bd019Satatat get_sockets("net.local.dgram.pcblist");
216724bd019Satatat }
217724bd019Satatat
218724bd019Satatat get_files();
219724bd019Satatat
220900e40a9Satatat p.p_pid = 0;
221183f6d8aSlukem for (i = 0; i < flistc; i++)
222724bd019Satatat if ((kp = pick_socket(&flist[i])) != NULL &&
223724bd019Satatat get_proc(&p, flist[i].ki_pid) == 0)
224724bd019Satatat print_socket(&flist[i], kp, &p);
225724bd019Satatat
226724bd019Satatat return (0);
227724bd019Satatat }
228724bd019Satatat
229724bd019Satatat void
230724bd019Satatat parse_ports(const char *l)
231724bd019Satatat {
232724bd019Satatat struct servent *srv;
233724bd019Satatat const char *s, *e;
234724bd019Satatat long i, j;
235724bd019Satatat
236724bd019Satatat if (portmap == NULL) {
237724bd019Satatat portmap = bit_alloc(65536);
238724bd019Satatat if (portmap == NULL)
239724bd019Satatat err(1, "malloc");
240724bd019Satatat }
241724bd019Satatat
242724bd019Satatat if ((srv = getservbyname(l, NULL)) != NULL) {
243724bd019Satatat bit_set(portmap, ntohs(srv->s_port));
244724bd019Satatat return;
245724bd019Satatat }
246724bd019Satatat
247724bd019Satatat s = e = l;
248724bd019Satatat while (*s != '\0') {
249724bd019Satatat i = get_num(l, &s, &e);
250724bd019Satatat switch (*e) {
251724bd019Satatat case ',':
252724bd019Satatat e++;
253fbffadb9Smrg /* FALLTHROUGH */
254724bd019Satatat case '\0':
255724bd019Satatat bit_set(portmap, i);
256724bd019Satatat s = e;
257724bd019Satatat continue;
258724bd019Satatat case '-':
259724bd019Satatat s = ++e;
260724bd019Satatat j = get_num(l, &s, &e);
261724bd019Satatat for (; i <= j; i++)
262724bd019Satatat bit_set(portmap, i);
263724bd019Satatat break;
264724bd019Satatat default:
265724bd019Satatat errno = EINVAL;
266724bd019Satatat err(1, "%s", l);
267724bd019Satatat }
268724bd019Satatat }
269724bd019Satatat }
270724bd019Satatat
271724bd019Satatat int
272724bd019Satatat get_num(const char *l, const char **s, const char **e)
273724bd019Satatat {
274724bd019Satatat long x;
275724bd019Satatat char *t;
276724bd019Satatat
2770298690dSrillig while (isdigit((unsigned char)**e))
278724bd019Satatat (*e)++;
279724bd019Satatat if (*s != *e) {
280724bd019Satatat errno = 0;
281724bd019Satatat x = strtol(*s, &t, 0);
282724bd019Satatat if (errno == 0 && x >= 0 && x <= 65535 && t == *e)
283724bd019Satatat return (x);
284724bd019Satatat }
285724bd019Satatat
286724bd019Satatat errno = EINVAL;
287724bd019Satatat err(1, "%s", l);
288724bd019Satatat }
289724bd019Satatat
290724bd019Satatat void
291724bd019Satatat get_sockets(const char *mib)
292724bd019Satatat {
293724bd019Satatat void *v;
294724bd019Satatat size_t sz;
295724bd019Satatat int rc, n, name[CTL_MAXNAME];
296724bd019Satatat u_int namelen;
297724bd019Satatat
298724bd019Satatat sz = CTL_MAXNAME;
299774dcce2Skamil rc = prog_sysctlnametomib(mib, &name[0], &sz);
300fcf2b555Srpaulo if (rc == -1) {
301fcf2b555Srpaulo if (errno == ENOENT)
302fcf2b555Srpaulo return;
303724bd019Satatat err(1, "sysctlnametomib: %s", mib);
304fcf2b555Srpaulo }
305724bd019Satatat namelen = sz;
306724bd019Satatat
307724bd019Satatat name[namelen++] = PCB_ALL;
308724bd019Satatat name[namelen++] = 0; /* XXX all pids */
309724bd019Satatat name[namelen++] = sizeof(struct kinfo_pcb);
310724bd019Satatat name[namelen++] = INT_MAX; /* all of them */
311724bd019Satatat
312724bd019Satatat sysctl_sucker(&name[0], namelen, &v, &sz);
313724bd019Satatat n = sz / sizeof(struct kinfo_pcb);
314724bd019Satatat socket_add_hash(v, n);
315724bd019Satatat }
316724bd019Satatat
317724bd019Satatat void
318724bd019Satatat get_files(void)
319724bd019Satatat {
320724bd019Satatat void *v;
321724bd019Satatat size_t sz;
322724bd019Satatat int rc, name[CTL_MAXNAME];
323724bd019Satatat u_int namelen;
324724bd019Satatat
325724bd019Satatat sz = CTL_MAXNAME;
326774dcce2Skamil rc = prog_sysctlnametomib("kern.file2", &name[0], &sz);
327724bd019Satatat if (rc == -1)
328724bd019Satatat err(1, "sysctlnametomib");
329724bd019Satatat namelen = sz;
330724bd019Satatat
331724bd019Satatat name[namelen++] = KERN_FILE_BYPID;
332724bd019Satatat name[namelen++] = 0; /* XXX all pids */
333724bd019Satatat name[namelen++] = sizeof(struct kinfo_file);
334724bd019Satatat name[namelen++] = INT_MAX; /* all of them */
335724bd019Satatat
336724bd019Satatat sysctl_sucker(&name[0], namelen, &v, &sz);
337724bd019Satatat flist = v;
338183f6d8aSlukem flistc = sz / sizeof(struct kinfo_file);
339724bd019Satatat
340183f6d8aSlukem qsort(flist, flistc, sizeof(*flist), sort_files);
341724bd019Satatat }
342724bd019Satatat
343724bd019Satatat int
344724bd019Satatat sort_files(const void *a, const void *b)
345724bd019Satatat {
346724bd019Satatat const struct kinfo_file *ka = a, *kb = b;
347724bd019Satatat
348724bd019Satatat if (ka->ki_pid == kb->ki_pid)
349724bd019Satatat return (ka->ki_fd - kb->ki_fd);
350724bd019Satatat
351724bd019Satatat return (ka->ki_pid - kb->ki_pid);
352724bd019Satatat }
353724bd019Satatat
354724bd019Satatat void
355724bd019Satatat sysctl_sucker(int *name, u_int namelen, void **vp, size_t *szp)
356724bd019Satatat {
357724bd019Satatat int rc;
358724bd019Satatat void *v;
359724bd019Satatat size_t sz;
360724bd019Satatat
361724bd019Satatat /* printf("name %p, namelen %u\n", name, namelen); */
362724bd019Satatat
363724bd019Satatat v = NULL;
364724bd019Satatat sz = 0;
365724bd019Satatat do {
3666475f125Spooka rc = prog_sysctl(&name[0], namelen, v, &sz, NULL, 0);
367724bd019Satatat if (rc == -1 && errno != ENOMEM)
368724bd019Satatat err(1, "sysctl");
369724bd019Satatat if (rc == -1 && v != NULL) {
370724bd019Satatat free(v);
371724bd019Satatat v = NULL;
372724bd019Satatat }
373724bd019Satatat if (v == NULL) {
374724bd019Satatat v = malloc(sz);
375724bd019Satatat rc = -1;
376724bd019Satatat }
377724bd019Satatat if (v == NULL)
378724bd019Satatat err(1, "malloc");
379724bd019Satatat } while (rc == -1);
380724bd019Satatat
381724bd019Satatat *vp = v;
382724bd019Satatat *szp = sz;
383724bd019Satatat /* printf("got %zu at %p\n", sz, v); */
384724bd019Satatat }
385724bd019Satatat
386724bd019Satatat void
387724bd019Satatat socket_add_hash(struct kinfo_pcb *kp, int n)
388724bd019Satatat {
389724bd019Satatat struct sockitem *si;
390724bd019Satatat int hash, i;
391724bd019Satatat
392724bd019Satatat if (n == 0)
393724bd019Satatat return;
394724bd019Satatat
395724bd019Satatat si = malloc(sizeof(*si) * n);
396724bd019Satatat if (si== NULL)
397724bd019Satatat err(1, "malloc");
398724bd019Satatat
399724bd019Satatat for (i = 0; i < n; i++) {
400724bd019Satatat si[i].s_sock = &kp[i];
401724bd019Satatat hash = (int)(kp[i].ki_sockaddr % HASHSIZE);
402724bd019Satatat LIST_INSERT_HEAD(&sockhash[hash], &si[i], s_list);
403724bd019Satatat }
404724bd019Satatat }
405724bd019Satatat
406724bd019Satatat int
407724bd019Satatat isconnected(struct kinfo_pcb *kp)
408724bd019Satatat {
409724bd019Satatat
410724bd019Satatat if ((kp->ki_sostate & SS_ISCONNECTED) ||
411724bd019Satatat (kp->ki_prstate >= INP_CONNECTED) ||
412724bd019Satatat (kp->ki_tstate > TCPS_LISTEN) ||
413724bd019Satatat (kp->ki_conn != 0))
414724bd019Satatat return (1);
415724bd019Satatat
416724bd019Satatat return (0);
417724bd019Satatat }
418724bd019Satatat
419724bd019Satatat int
420724bd019Satatat islistening(struct kinfo_pcb *kp)
421724bd019Satatat {
422724bd019Satatat
423724bd019Satatat if (isconnected(kp))
424724bd019Satatat return (0);
425724bd019Satatat
426724bd019Satatat if (kp->ki_tstate == TCPS_LISTEN)
427724bd019Satatat return (1);
428724bd019Satatat
429724bd019Satatat switch (kp->ki_family) {
430724bd019Satatat case PF_INET:
431724bd019Satatat if (kp->ki_type == SOCK_RAW ||
432724bd019Satatat (kp->ki_type == SOCK_DGRAM &&
43304592855Srpaulo ntohs(satosin(&kp->ki_src)->sin_port) != 0))
434724bd019Satatat return (1);
435724bd019Satatat break;
436cccbf666Srpaulo #ifdef INET6
437724bd019Satatat case PF_INET6:
438724bd019Satatat if (kp->ki_type == SOCK_RAW ||
439724bd019Satatat (kp->ki_type == SOCK_DGRAM &&
44004592855Srpaulo ntohs(satosin6(&kp->ki_src)->sin6_port) != 0))
441724bd019Satatat return (1);
442724bd019Satatat break;
443cccbf666Srpaulo #endif
444724bd019Satatat case PF_LOCAL:
445724bd019Satatat if (satosun(&kp->ki_src)->sun_path[0] != '\0')
446724bd019Satatat return (1);
447724bd019Satatat break;
448724bd019Satatat default:
449724bd019Satatat break;
450724bd019Satatat }
451724bd019Satatat
452724bd019Satatat return (0);
453724bd019Satatat }
454724bd019Satatat
455724bd019Satatat struct kinfo_pcb *
456724bd019Satatat pick_socket(struct kinfo_file *f)
457724bd019Satatat {
458724bd019Satatat struct sockitem *si;
459724bd019Satatat struct kinfo_pcb *kp;
460724bd019Satatat int hash;
461724bd019Satatat
462724bd019Satatat if (f->ki_ftype != DTYPE_SOCKET)
463724bd019Satatat return (NULL);
464724bd019Satatat
465724bd019Satatat hash = (int)(f->ki_fdata % HASHSIZE);
466724bd019Satatat LIST_FOREACH(si, &sockhash[hash], s_list) {
467724bd019Satatat if (si->s_sock->ki_sockaddr == f->ki_fdata)
468724bd019Satatat break;
469724bd019Satatat }
470724bd019Satatat if (si == NULL)
471724bd019Satatat return (NULL);
472724bd019Satatat
473724bd019Satatat kp = si->s_sock;
474724bd019Satatat
475724bd019Satatat if (only) {
476724bd019Satatat if (isconnected(kp)) {
477724bd019Satatat /*
478724bd019Satatat * connected but you didn't say you wanted
479724bd019Satatat * connected sockets
480724bd019Satatat */
481724bd019Satatat if (!(only & ONLY_CONNECTED))
482724bd019Satatat return (NULL);
483724bd019Satatat }
484724bd019Satatat else if (islistening(kp)) {
485724bd019Satatat /*
486724bd019Satatat * listening but you didn't ask for listening
487724bd019Satatat * sockets
488724bd019Satatat */
489724bd019Satatat if (!(only & ONLY_LISTEN))
490724bd019Satatat return (NULL);
491724bd019Satatat }
492724bd019Satatat else
493724bd019Satatat /*
494724bd019Satatat * neither connected nor listening, so you
495724bd019Satatat * don't get it
496724bd019Satatat */
497724bd019Satatat return (NULL);
498724bd019Satatat }
499724bd019Satatat
500724bd019Satatat if (portmap) {
501724bd019Satatat switch (kp->ki_family) {
502724bd019Satatat case AF_INET:
503724bd019Satatat if (!bit_test(portmap,
504724bd019Satatat ntohs(satosin(&kp->ki_src)->sin_port)) &&
505724bd019Satatat !bit_test(portmap,
506724bd019Satatat ntohs(satosin(&kp->ki_dst)->sin_port)))
507724bd019Satatat return (NULL);
508724bd019Satatat break;
509cccbf666Srpaulo #ifdef INET6
510724bd019Satatat case AF_INET6:
511724bd019Satatat if (!bit_test(portmap,
512724bd019Satatat ntohs(satosin6(&kp->ki_src)->sin6_port)) &&
513724bd019Satatat !bit_test(portmap,
514724bd019Satatat ntohs(satosin6(&kp->ki_dst)->sin6_port)))
515724bd019Satatat return (NULL);
516724bd019Satatat break;
517cccbf666Srpaulo #endif
518724bd019Satatat default:
519724bd019Satatat return (NULL);
520724bd019Satatat }
521724bd019Satatat }
522724bd019Satatat
523724bd019Satatat return (kp);
524724bd019Satatat }
525724bd019Satatat
526724bd019Satatat int
527724bd019Satatat get_proc(struct kinfo_proc2 *p, int pid)
528724bd019Satatat {
529724bd019Satatat int name[6];
530724bd019Satatat u_int namelen;
531724bd019Satatat size_t sz;
532724bd019Satatat
533900e40a9Satatat if (p->p_pid == pid)
534900e40a9Satatat return (0);
535900e40a9Satatat
536724bd019Satatat sz = sizeof(*p);
537724bd019Satatat namelen = 0;
538724bd019Satatat name[namelen++] = CTL_KERN;
539724bd019Satatat name[namelen++] = KERN_PROC2;
540724bd019Satatat name[namelen++] = KERN_PROC_PID;
541724bd019Satatat name[namelen++] = pid;
542724bd019Satatat name[namelen++] = sz;
543724bd019Satatat name[namelen++] = 1;
544724bd019Satatat
5456475f125Spooka return (prog_sysctl(&name[0], namelen, p, &sz, NULL, 0));
546724bd019Satatat }
547724bd019Satatat
548724bd019Satatat int
549724bd019Satatat print_socket(struct kinfo_file *kf, struct kinfo_pcb *kp, struct kinfo_proc2 *p)
550724bd019Satatat {
551724bd019Satatat static int first = 1;
552724bd019Satatat struct passwd *pw;
553724bd019Satatat const char *t;
554724bd019Satatat char proto[22];
555724bd019Satatat
556724bd019Satatat if (first) {
557724bd019Satatat printf("%-8s " "%-10s " "%-5s " "%-2s " "%-6s "
558724bd019Satatat "%-21s " "%s\n",
559724bd019Satatat "USER", "COMMAND", "PID", "FD", "PROTO",
560724bd019Satatat "LOCAL ADDRESS", "FOREIGN ADDRESS");
561724bd019Satatat first = 0;
562724bd019Satatat }
563724bd019Satatat
564724bd019Satatat if ((pw = getpwuid(p->p_uid)) != NULL)
565724bd019Satatat printf("%-8s ", pw->pw_name);
566724bd019Satatat else
567724bd019Satatat printf("%-8d ", (int)p->p_uid);
568724bd019Satatat
56904274e48Satatat printf("%-10.10s ", p->p_comm);
570724bd019Satatat printf("%-5d ", (int)kf->ki_pid);
571724bd019Satatat printf("%2d ", (int)kf->ki_fd);
572724bd019Satatat
573724bd019Satatat snprintf(proto, sizeof(proto), "%d/%d", kp->ki_family, kp->ki_protocol);
574724bd019Satatat
575724bd019Satatat switch (kp->ki_family) {
576724bd019Satatat case PF_INET:
577724bd019Satatat switch (kp->ki_protocol) {
578724bd019Satatat case IPPROTO_TCP: t = "tcp"; break;
579724bd019Satatat case IPPROTO_UDP: t = "udp"; break;
580724bd019Satatat case IPPROTO_RAW: t = "raw"; break;
581724bd019Satatat default: t = proto; break;
582724bd019Satatat }
583724bd019Satatat break;
584cccbf666Srpaulo #ifdef INET6
585724bd019Satatat case PF_INET6:
586724bd019Satatat switch (kp->ki_protocol) {
587724bd019Satatat case IPPROTO_TCP: t = "tcp6"; break;
588724bd019Satatat case IPPROTO_UDP: t = "udp6"; break;
589724bd019Satatat case IPPROTO_RAW: t = "raw6"; break;
590724bd019Satatat default: t = proto; break;
591724bd019Satatat }
592724bd019Satatat break;
593cccbf666Srpaulo #endif
594724bd019Satatat case PF_LOCAL:
595724bd019Satatat switch (kp->ki_type) {
596724bd019Satatat case SOCK_STREAM: t = "stream"; break;
597724bd019Satatat case SOCK_DGRAM: t = "dgram"; break;
598724bd019Satatat case SOCK_RAW: t = "raw"; break;
599724bd019Satatat case SOCK_RDM: t = "rdm"; break;
600724bd019Satatat case SOCK_SEQPACKET: t = "seq"; break;
601724bd019Satatat default: t = proto; break;
602724bd019Satatat }
603724bd019Satatat break;
604724bd019Satatat default:
605724bd019Satatat snprintf(proto, sizeof(proto), "%d/%d/%d",
606724bd019Satatat kp->ki_family, kp->ki_type, kp->ki_protocol);
607724bd019Satatat t = proto;
608724bd019Satatat break;
609724bd019Satatat }
610724bd019Satatat
611724bd019Satatat printf("%-6s ", t);
612724bd019Satatat
613724bd019Satatat /*
614724bd019Satatat if (kp->ki_family == PF_LOCAL) {
615724bd019Satatat if (kp->ki_src.sa_len > 2) {
616724bd019Satatat print_addr(0, kp->ki_type, kp->ki_pflags, &kp->ki_src);
617724bd019Satatat if (kp->ki_dst.sa_family == PF_LOCAL)
618724bd019Satatat printf(" ");
619724bd019Satatat }
620724bd019Satatat if (kp->ki_dst.sa_family == PF_LOCAL)
621724bd019Satatat printf("-> ");
622724bd019Satatat }
623724bd019Satatat else */{
624724bd019Satatat print_addr(21, kp->ki_type, kp->ki_pflags, &kp->ki_src);
625724bd019Satatat printf(" ");
626724bd019Satatat }
627724bd019Satatat
628724bd019Satatat if (isconnected(kp))
629724bd019Satatat print_addr(0, kp->ki_type, kp->ki_pflags, &kp->ki_dst);
630cccbf666Srpaulo else if (kp->ki_family == PF_INET
631cccbf666Srpaulo #ifdef INET6
632cccbf666Srpaulo || kp->ki_family == PF_INET6
633cccbf666Srpaulo #endif
634cccbf666Srpaulo )
635724bd019Satatat printf("%-*s", 0, "*.*");
636724bd019Satatat /* else if (kp->ki_src.sa_len == 2)
637724bd019Satatat printf("%-*s", 0, "-"); */
638724bd019Satatat else
639724bd019Satatat printf("-");
640724bd019Satatat
641724bd019Satatat printf("\n");
642724bd019Satatat
643724bd019Satatat return (0);
644724bd019Satatat }
645724bd019Satatat
646724bd019Satatat void
647724bd019Satatat print_addr(int l, int t, int f, struct sockaddr *sa)
648724bd019Satatat {
649724bd019Satatat char sabuf[256], pbuf[32];
650ef454726Slukem int r = 0;
651724bd019Satatat
652724bd019Satatat if (!(f & INP_ANONPORT))
653724bd019Satatat f = 0;
654724bd019Satatat else
655724bd019Satatat f = NI_NUMERICSERV;
656724bd019Satatat if (t == SOCK_DGRAM)
657724bd019Satatat f |= NI_DGRAM;
658724bd019Satatat if (nonames)
659724bd019Satatat f |= NI_NUMERICHOST|NI_NUMERICSERV;
660724bd019Satatat
661724bd019Satatat getnameinfo(sa, sa->sa_len, sabuf, sizeof(sabuf),
662724bd019Satatat pbuf, sizeof(pbuf), f);
663724bd019Satatat
664724bd019Satatat switch (sa->sa_family) {
665724bd019Satatat case PF_UNSPEC:
666724bd019Satatat r = printf("(PF_UNSPEC)");
667724bd019Satatat break;
668724bd019Satatat case PF_INET: {
669724bd019Satatat struct sockaddr_in *si = satosin(sa);
670724bd019Satatat if (si->sin_addr.s_addr != INADDR_ANY)
671724bd019Satatat r = printf("%s.%s", sabuf, pbuf);
672724bd019Satatat else if (ntohs(si->sin_port) != 0)
673724bd019Satatat r = printf("*.%s", pbuf);
674724bd019Satatat else
675724bd019Satatat r = printf("*.*");
676724bd019Satatat break;
677724bd019Satatat }
678cccbf666Srpaulo #ifdef INET6
679724bd019Satatat case PF_INET6: {
680724bd019Satatat struct sockaddr_in6 *si6 = satosin6(sa);
681724bd019Satatat if (!IN6_IS_ADDR_UNSPECIFIED(&si6->sin6_addr))
682724bd019Satatat r = printf("%s.%s", sabuf, pbuf);
683724bd019Satatat else if (ntohs(si6->sin6_port) != 0)
684724bd019Satatat r = printf("*.%s", pbuf);
685724bd019Satatat else
686724bd019Satatat r = printf("*.*");
687724bd019Satatat break;
688724bd019Satatat }
689cccbf666Srpaulo #endif
690724bd019Satatat case PF_LOCAL: {
6911a773e1dSatatat struct sockaddr_un *sun = satosun(sa);
6921a773e1dSatatat r = printf("%s", sun->sun_path);
693724bd019Satatat if (r == 0)
694724bd019Satatat r = printf("-");
695724bd019Satatat break;
696724bd019Satatat }
697724bd019Satatat default:
698724bd019Satatat break;
699724bd019Satatat }
700724bd019Satatat
701724bd019Satatat if (r > 0)
702724bd019Satatat l -= r;
703724bd019Satatat if (l > 0)
704724bd019Satatat printf("%*s", l, "");
705724bd019Satatat }
706