1/*	$NetBSD: bpf.c,v 1.10 2010/12/13 21:15:30 pooka Exp $	*/
2
3/*
4 * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Rui Paulo.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <err.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <kvm.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <net/if.h>
41#include <sys/types.h>
42#include <sys/param.h>
43#include <sys/sysctl.h>
44#include <net/bpfdesc.h>
45#include <net/bpf.h>
46#include "netstat.h"
47#include "prog_ops.h"
48
49void
50bpf_stats(void)
51{
52	struct bpf_stat bpf_s;
53	size_t len = sizeof(bpf_s);
54
55	if (use_sysctl) {
56		if (sysctlbyname("net.bpf.stats", &bpf_s, &len, NULL, 0) == -1)
57			err(1, "net.bpf.stats");
58
59		printf("bpf:\n");
60		printf("\t%" PRIu64 " total packets received\n",
61		    bpf_s.bs_recv);
62		printf("\t%" PRIu64 " total packets captured\n",
63		    bpf_s.bs_capt);
64		printf("\t%" PRIu64 " total packets dropped\n",
65		    bpf_s.bs_drop);
66	} else {
67		warnx("BPF stats not available via KVM.");
68	}
69}
70
71void
72bpf_dump(const char *bpfif)
73{
74	struct bpf_d_ext *dpe;
75
76	if (use_sysctl) {
77		int	name[CTL_MAXNAME], rc;
78		size_t	i, sz, szproc;
79		u_int	namelen;
80		void	*v;
81		struct kinfo_proc2 p;
82
83		/* adapted from sockstat.c by Andrew Brown */
84
85		sz = CTL_MAXNAME;
86		if (sysctlnametomib("net.bpf.peers", &name[0], &sz) == -1)
87			err(1, "sysctlnametomib: net.bpf.peers");
88		namelen = sz;
89
90		name[namelen++] = sizeof(*dpe);
91		name[namelen++] = INT_MAX;
92
93		v = NULL;
94		sz = 0;
95		do {
96			rc = prog_sysctl(&name[0], namelen,
97			    v, &sz, NULL, 0);
98			if (rc == -1 && errno != ENOMEM)
99				err(1, "sysctl: net.bpf.peers");
100			if (rc == -1 && v != NULL) {
101				free(v);
102				v = NULL;
103			}
104			if (v == NULL) {
105				v = malloc(sz);
106				rc = -1;
107			}
108			if (v == NULL)
109				err(1, "malloc");
110		} while (rc == -1);
111
112		dpe = v;
113
114		puts("Active BPF peers\nPID\tInt\tRecv     Drop     Capt" \
115		    "     Flags  Bufsize  Comm");
116
117#define BPFEXT(entry) dpe->entry
118
119		for (i = 0; i < (sz / sizeof(*dpe)); i++, dpe++) {
120			if (bpfif &&
121			    strncmp(BPFEXT(bde_ifname), bpfif, IFNAMSIZ))
122				continue;
123
124			printf("%-7d ", BPFEXT(bde_pid));
125			printf("%-7s ",
126			       (BPFEXT(bde_ifname)[0] == '\0') ? "-" :
127			       BPFEXT(bde_ifname));
128
129			printf("%-8" PRIu64 " %-8" PRIu64 " %-8" PRIu64 " ",
130				BPFEXT(bde_rcount), BPFEXT(bde_dcount),
131				BPFEXT(bde_ccount));
132
133			switch (BPFEXT(bde_state)) {
134			case BPF_IDLE:
135				printf("I");
136				break;
137			case BPF_WAITING:
138				printf("W");
139				break;
140			case BPF_TIMED_OUT:
141				printf("T");
142				break;
143			default:
144				printf("-");
145				break;
146			}
147
148			printf("%c", BPFEXT(bde_promisc) ? 'P' : '-');
149			printf("%c", BPFEXT(bde_immediate) ? 'R' : '-');
150			printf("%c", BPFEXT(bde_seesent) ? 'S' : '-');
151			printf("%c", BPFEXT(bde_hdrcmplt) ? 'H' : '-');
152			printf("  %-8d ", BPFEXT(bde_bufsize));
153
154			szproc = sizeof(p);
155			namelen = 0;
156			name[namelen++] = CTL_KERN;
157			name[namelen++] = KERN_PROC2;
158			name[namelen++] = KERN_PROC_PID;
159			name[namelen++] = BPFEXT(bde_pid);
160			name[namelen++] = szproc;
161			name[namelen++] = 1;
162
163			if (prog_sysctl(&name[0], namelen, &p, &szproc,
164			    NULL, 0) == -1)
165				printf("-\n");
166			else
167				printf("%s\n", p.p_comm);
168#undef BPFEXT
169		}
170		free(v);
171	} else {
172                /* XXX */
173                errx(1, "bpf_dump not implemented using kvm");
174        }
175}
176