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