xref: /minix3/sys/arch/i386/stand/lib/test/ether_bpf.c (revision 58a2b0008e28f606a7f7f5faaeaba4faac57a1ea)
1*58a2b000SEvgeniy Ivanov /*	$NetBSD: ether_bpf.c,v 1.10 2008/12/14 18:46:33 christos Exp $	*/
2*58a2b000SEvgeniy Ivanov 
3*58a2b000SEvgeniy Ivanov /*
4*58a2b000SEvgeniy Ivanov  * Copyright (c) 1998
5*58a2b000SEvgeniy Ivanov  *	Matthias Drochner.  All rights reserved.
6*58a2b000SEvgeniy Ivanov  *
7*58a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
8*58a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
9*58a2b000SEvgeniy Ivanov  * are met:
10*58a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
11*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
12*58a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
13*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
14*58a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
15*58a2b000SEvgeniy Ivanov  *
16*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*58a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*58a2b000SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*58a2b000SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*58a2b000SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*58a2b000SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*58a2b000SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*58a2b000SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*58a2b000SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*58a2b000SEvgeniy Ivanov  *
27*58a2b000SEvgeniy Ivanov  */
28*58a2b000SEvgeniy Ivanov 
29*58a2b000SEvgeniy Ivanov #include "sanamespace.h"
30*58a2b000SEvgeniy Ivanov 
31*58a2b000SEvgeniy Ivanov #include <stdio.h>
32*58a2b000SEvgeniy Ivanov #include <fcntl.h>
33*58a2b000SEvgeniy Ivanov #include <unistd.h>
34*58a2b000SEvgeniy Ivanov #include <stdlib.h>
35*58a2b000SEvgeniy Ivanov #include <limits.h>
36*58a2b000SEvgeniy Ivanov #include <sys/ioctl.h>
37*58a2b000SEvgeniy Ivanov #include <sys/queue.h>
38*58a2b000SEvgeniy Ivanov #include <sys/socket.h>
39*58a2b000SEvgeniy Ivanov #include <net/if.h>
40*58a2b000SEvgeniy Ivanov #include <net/bpf.h>
41*58a2b000SEvgeniy Ivanov #include <net/if_dl.h>
42*58a2b000SEvgeniy Ivanov #include <netinet/in.h>
43*58a2b000SEvgeniy Ivanov #include <kvm.h>
44*58a2b000SEvgeniy Ivanov #include <nlist.h>
45*58a2b000SEvgeniy Ivanov #include <string.h>
46*58a2b000SEvgeniy Ivanov #include <err.h>
47*58a2b000SEvgeniy Ivanov #include <errno.h>
48*58a2b000SEvgeniy Ivanov 
49*58a2b000SEvgeniy Ivanov #include <netif/netif_small.h>
50*58a2b000SEvgeniy Ivanov #include <netif/etherdrv.h>
51*58a2b000SEvgeniy Ivanov 
52*58a2b000SEvgeniy Ivanov #define BPFDEV "/dev/bpf0"
53*58a2b000SEvgeniy Ivanov 
54*58a2b000SEvgeniy Ivanov #define MAXPKT 1536
55*58a2b000SEvgeniy Ivanov 
56*58a2b000SEvgeniy Ivanov /*
57*58a2b000SEvgeniy Ivanov  * Allows to use any configured interface with
58*58a2b000SEvgeniy Ivanov  * standalone network code. Provides the interface used
59*58a2b000SEvgeniy Ivanov  * by i386/stand/lib/netif/netif_small.c.
60*58a2b000SEvgeniy Ivanov  */
61*58a2b000SEvgeniy Ivanov 
62*58a2b000SEvgeniy Ivanov static int bpf = -1;
63*58a2b000SEvgeniy Ivanov 
64*58a2b000SEvgeniy Ivanov static struct nlist nl[] = {
65*58a2b000SEvgeniy Ivanov 	{"_ifnet"},
66*58a2b000SEvgeniy Ivanov 	{NULL}
67*58a2b000SEvgeniy Ivanov };
68*58a2b000SEvgeniy Ivanov 
69*58a2b000SEvgeniy Ivanov int
EtherInit(char * ha)70*58a2b000SEvgeniy Ivanov EtherInit(char *ha)
71*58a2b000SEvgeniy Ivanov {
72*58a2b000SEvgeniy Ivanov 	int res;
73*58a2b000SEvgeniy Ivanov 	u_int val;
74*58a2b000SEvgeniy Ivanov 	struct ifreq ifr;
75*58a2b000SEvgeniy Ivanov 	kvm_t *kvm;
76*58a2b000SEvgeniy Ivanov 	char errbuf[_POSIX2_LINE_MAX];
77*58a2b000SEvgeniy Ivanov 	struct ifnet_head ifh;
78*58a2b000SEvgeniy Ivanov 	struct ifnet *ifp;
79*58a2b000SEvgeniy Ivanov 	struct ifaddr *ifap = 0;
80*58a2b000SEvgeniy Ivanov 	struct sockaddr_dl *sdlp;
81*58a2b000SEvgeniy Ivanov 	int sdllen;
82*58a2b000SEvgeniy Ivanov 
83*58a2b000SEvgeniy Ivanov 	bpf = open(BPFDEV, O_RDWR, 0);
84*58a2b000SEvgeniy Ivanov 	if (bpf < 0) {
85*58a2b000SEvgeniy Ivanov 		warn("open %s", BPFDEV);
86*58a2b000SEvgeniy Ivanov 		return 0;
87*58a2b000SEvgeniy Ivanov 	}
88*58a2b000SEvgeniy Ivanov 
89*58a2b000SEvgeniy Ivanov 	val = MAXPKT;
90*58a2b000SEvgeniy Ivanov 	res = ioctl(bpf, BIOCSBLEN, &val);
91*58a2b000SEvgeniy Ivanov 	if (res < 0) {
92*58a2b000SEvgeniy Ivanov 		warn("ioctl BIOCSBLEN");
93*58a2b000SEvgeniy Ivanov 		return 0;
94*58a2b000SEvgeniy Ivanov 	}
95*58a2b000SEvgeniy Ivanov 
96*58a2b000SEvgeniy Ivanov 	val = 1;
97*58a2b000SEvgeniy Ivanov 	res = ioctl(bpf, BIOCIMMEDIATE, &val);
98*58a2b000SEvgeniy Ivanov 	if (res < 0) {
99*58a2b000SEvgeniy Ivanov 		warn("ioctl BIOCIMMEDIATE");
100*58a2b000SEvgeniy Ivanov 		return 0;
101*58a2b000SEvgeniy Ivanov 	}
102*58a2b000SEvgeniy Ivanov 
103*58a2b000SEvgeniy Ivanov 	val = 1;
104*58a2b000SEvgeniy Ivanov 	res = ioctl(bpf, FIONBIO, &val);
105*58a2b000SEvgeniy Ivanov 	if (res < 0) {
106*58a2b000SEvgeniy Ivanov 		warn("ioctl FIONBIO");
107*58a2b000SEvgeniy Ivanov 		return 0;
108*58a2b000SEvgeniy Ivanov 	}
109*58a2b000SEvgeniy Ivanov 
110*58a2b000SEvgeniy Ivanov 	memcpy(ifr.ifr_name, BPF_IFNAME, IFNAMSIZ);
111*58a2b000SEvgeniy Ivanov 	res = ioctl(bpf, BIOCSETIF, &ifr);
112*58a2b000SEvgeniy Ivanov 	if (res < 0) {
113*58a2b000SEvgeniy Ivanov 		warn("ioctl BIOCSETIF %s", BPF_IFNAME);
114*58a2b000SEvgeniy Ivanov 		return 0;
115*58a2b000SEvgeniy Ivanov 	}
116*58a2b000SEvgeniy Ivanov 
117*58a2b000SEvgeniy Ivanov 	kvm = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
118*58a2b000SEvgeniy Ivanov 	if (!kvm) {
119*58a2b000SEvgeniy Ivanov 		warnx(errbuf);
120*58a2b000SEvgeniy Ivanov 		return 0;
121*58a2b000SEvgeniy Ivanov 	}
122*58a2b000SEvgeniy Ivanov 	if (kvm_nlist(kvm, nl) < 0) {
123*58a2b000SEvgeniy Ivanov 		warnx("nlist failed (%s)", kvm_geterr(kvm));
124*58a2b000SEvgeniy Ivanov 		kvm_close(kvm);
125*58a2b000SEvgeniy Ivanov 		return 0;
126*58a2b000SEvgeniy Ivanov 	}
127*58a2b000SEvgeniy Ivanov 
128*58a2b000SEvgeniy Ivanov 	kvm_read(kvm, nl[0].n_value, &ifh, sizeof(struct ifnet_head));
129*58a2b000SEvgeniy Ivanov 	ifp = TAILQ_FIRST(&ifh);
130*58a2b000SEvgeniy Ivanov 	while (ifp) {
131*58a2b000SEvgeniy Ivanov 		struct ifnet ifnet;
132*58a2b000SEvgeniy Ivanov 		kvm_read(kvm, (u_long)ifp, &ifnet, sizeof(struct ifnet));
133*58a2b000SEvgeniy Ivanov 		if (!strcmp(ifnet.if_xname, BPF_IFNAME)) {
134*58a2b000SEvgeniy Ivanov 			ifap = IFADDR_FIRST(&ifnet);
135*58a2b000SEvgeniy Ivanov 			break;
136*58a2b000SEvgeniy Ivanov 		}
137*58a2b000SEvgeniy Ivanov 		ifp = IFNET_NEXT(&ifnet);
138*58a2b000SEvgeniy Ivanov 	}
139*58a2b000SEvgeniy Ivanov 	if (!ifp) {
140*58a2b000SEvgeniy Ivanov 		warnx("interface not found");
141*58a2b000SEvgeniy Ivanov 		kvm_close(kvm);
142*58a2b000SEvgeniy Ivanov 		return 0;
143*58a2b000SEvgeniy Ivanov 	}
144*58a2b000SEvgeniy Ivanov 
145*58a2b000SEvgeniy Ivanov #define _offsetof(t, m) ((int)((void *)&((t *)0)->m))
146*58a2b000SEvgeniy Ivanov 	sdllen = _offsetof(struct sockaddr_dl,
147*58a2b000SEvgeniy Ivanov 			   sdl_data[0]) + strlen(BPF_IFNAME) + 6;
148*58a2b000SEvgeniy Ivanov 	sdlp = malloc(sdllen);
149*58a2b000SEvgeniy Ivanov 
150*58a2b000SEvgeniy Ivanov 	while (ifap) {
151*58a2b000SEvgeniy Ivanov 		struct ifaddr ifaddr;
152*58a2b000SEvgeniy Ivanov 		kvm_read(kvm, (u_long)ifap, &ifaddr, sizeof(struct ifaddr));
153*58a2b000SEvgeniy Ivanov 		kvm_read(kvm, (u_long)ifaddr.ifa_addr, sdlp, sdllen);
154*58a2b000SEvgeniy Ivanov 		if (sdlp->sdl_family == AF_LINK) {
155*58a2b000SEvgeniy Ivanov 			memcpy(ha, CLLADDR(sdlp), 6);
156*58a2b000SEvgeniy Ivanov 			break;
157*58a2b000SEvgeniy Ivanov 		}
158*58a2b000SEvgeniy Ivanov 		ifap = IFADDR_NEXT(&ifaddr);
159*58a2b000SEvgeniy Ivanov 	}
160*58a2b000SEvgeniy Ivanov 	free(sdlp);
161*58a2b000SEvgeniy Ivanov 	kvm_close(kvm);
162*58a2b000SEvgeniy Ivanov 	if (!ifap) {
163*58a2b000SEvgeniy Ivanov 		warnx("interface hw addr not found");
164*58a2b000SEvgeniy Ivanov 		return 0;
165*58a2b000SEvgeniy Ivanov 	}
166*58a2b000SEvgeniy Ivanov 	return 1;
167*58a2b000SEvgeniy Ivanov }
168*58a2b000SEvgeniy Ivanov 
169*58a2b000SEvgeniy Ivanov void
EtherStop(void)170*58a2b000SEvgeniy Ivanov EtherStop(void)
171*58a2b000SEvgeniy Ivanov {
172*58a2b000SEvgeniy Ivanov 
173*58a2b000SEvgeniy Ivanov 	if (bpf != -1)
174*58a2b000SEvgeniy Ivanov 		close(bpf);
175*58a2b000SEvgeniy Ivanov }
176*58a2b000SEvgeniy Ivanov 
177*58a2b000SEvgeniy Ivanov int
EtherSend(char * pkt,int len)178*58a2b000SEvgeniy Ivanov EtherSend(char *pkt, int len)
179*58a2b000SEvgeniy Ivanov {
180*58a2b000SEvgeniy Ivanov 
181*58a2b000SEvgeniy Ivanov 	if (write(bpf, pkt, len) != len) {
182*58a2b000SEvgeniy Ivanov 		warn("EtherSend");
183*58a2b000SEvgeniy Ivanov 		return -1;
184*58a2b000SEvgeniy Ivanov 	}
185*58a2b000SEvgeniy Ivanov 	return len;
186*58a2b000SEvgeniy Ivanov }
187*58a2b000SEvgeniy Ivanov 
188*58a2b000SEvgeniy Ivanov static union {
189*58a2b000SEvgeniy Ivanov 	struct bpf_hdr h;
190*58a2b000SEvgeniy Ivanov 	u_char buf[MAXPKT];
191*58a2b000SEvgeniy Ivanov } rbuf;
192*58a2b000SEvgeniy Ivanov 
193*58a2b000SEvgeniy Ivanov int
EtherReceive(char * pkt,int maxlen)194*58a2b000SEvgeniy Ivanov EtherReceive(char *pkt, int maxlen)
195*58a2b000SEvgeniy Ivanov {
196*58a2b000SEvgeniy Ivanov 	int res;
197*58a2b000SEvgeniy Ivanov 
198*58a2b000SEvgeniy Ivanov 	res = read(bpf, &rbuf, MAXPKT);
199*58a2b000SEvgeniy Ivanov 	if (res > 0) {
200*58a2b000SEvgeniy Ivanov #if 0
201*58a2b000SEvgeniy Ivanov 		int i;
202*58a2b000SEvgeniy Ivanov 		fprintf(stderr, "got packet, len=%d\n", rbuf.h.bh_caplen);
203*58a2b000SEvgeniy Ivanov 		if (rbuf.h.bh_caplen < rbuf.h.bh_datalen)
204*58a2b000SEvgeniy Ivanov 			printf("(truncated)\n");
205*58a2b000SEvgeniy Ivanov 		for (i = 0; i < 20; i++)
206*58a2b000SEvgeniy Ivanov 			fprintf(stderr, "%02x ", rbuf.buf[rbuf.h.bh_hdrlen + i]);
207*58a2b000SEvgeniy Ivanov 		fprintf(stderr, "\n");
208*58a2b000SEvgeniy Ivanov #endif
209*58a2b000SEvgeniy Ivanov 		if (rbuf.h.bh_caplen > maxlen)
210*58a2b000SEvgeniy Ivanov 			return 0;
211*58a2b000SEvgeniy Ivanov 		memcpy(pkt, &rbuf.buf[rbuf.h.bh_hdrlen], rbuf.h.bh_caplen);
212*58a2b000SEvgeniy Ivanov 		return rbuf.h.bh_caplen;
213*58a2b000SEvgeniy Ivanov 	}
214*58a2b000SEvgeniy Ivanov 
215*58a2b000SEvgeniy Ivanov 	return 0;
216*58a2b000SEvgeniy Ivanov }
217