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