]>
git.saurik.com Git - apple/network_cmds.git/blob - rbootd.tproj/bpf.c
ed214808e42b9af421bbdf280e7e6ec2d4ee1e11
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1988, 1992 The University of Utah and the Center
26 * for Software Science (CSS).
27 * Copyright (c) 1992, 1993
28 * The Regents of the University of California. All rights reserved.
30 * This code is derived from software contributed to Berkeley by
31 * the Center for Software Science of the University of Utah Computer
32 * Science Department. CSS requests users of this software to return
33 * to css-dist@cs.utah.edu any improvements that they make and grant
34 * CSS redistribution rights.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * @(#)bpf.c 8.1 (Berkeley) 6/4/93
66 * Utah $Hdr: bpf.c 3.1 92/07/06$
67 * Author: Jeff Forys, University of Utah CSS
71 static char sccsid
[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93";
74 #include <sys/param.h>
75 #include <sys/ioctl.h>
76 #include <sys/socket.h>
90 #include "pathnames.h"
92 static int BpfFd
= -1;
93 static unsigned BpfLen
= 0;
94 static u_char
*BpfPkt
= NULL
;
97 ** BpfOpen -- Open and initialize a BPF device.
103 ** File descriptor of opened BPF device (for select() etc).
106 ** If an error is encountered, the program terminates here.
116 * Open the first available BPF device.
119 (void) sprintf(bpfdev
, _PATH_BPF
, n
++);
120 BpfFd
= open(bpfdev
, O_RDWR
);
121 } while (BpfFd
< 0 && (errno
== EBUSY
|| errno
== EPERM
));
124 syslog(LOG_ERR
, "bpf: no available devices: %m");
129 * Set interface name for bpf device, get data link layer
130 * type and make sure it's type Ethernet.
132 (void) strncpy(ifr
.ifr_name
, IntfName
, sizeof(ifr
.ifr_name
));
133 if (ioctl(BpfFd
, BIOCSETIF
, (caddr_t
)&ifr
) < 0) {
134 syslog(LOG_ERR
, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName
);
139 * Make sure we are dealing with an Ethernet device.
141 if (ioctl(BpfFd
, BIOCGDLT
, (caddr_t
)&n
) < 0) {
142 syslog(LOG_ERR
, "bpf: ioctl(BIOCGDLT): %m");
145 if (n
!= DLT_EN10MB
) {
146 syslog(LOG_ERR
,"bpf: %s: data-link type %d unsupported",
152 * On read(), return packets immediately (do not buffer them).
155 if (ioctl(BpfFd
, BIOCIMMEDIATE
, (caddr_t
)&n
) < 0) {
156 syslog(LOG_ERR
, "bpf: ioctl(BIOCIMMEDIATE): %m");
161 * Try to enable the chip/driver's multicast address filter to
162 * grab our RMP address. If this fails, try promiscuous mode.
163 * If this fails, there's no way we are going to get any RMP
164 * packets so just exit here.
167 ifr
.ifr_addr
.sa_len
= RMP_ADDRLEN
+ 2;
169 ifr
.ifr_addr
.sa_family
= AF_UNSPEC
;
170 bcopy(&RmpMcastAddr
[0], (char *)&ifr
.ifr_addr
.sa_data
[0], RMP_ADDRLEN
);
171 if (ioctl(BpfFd
, SIOCADDMULTI
, (caddr_t
)&ifr
) < 0) {
173 "bpf: can't add mcast addr (%m), setting promiscuous mode");
175 if (ioctl(BpfFd
, BIOCPROMISC
, (caddr_t
)0) < 0) {
176 syslog(LOG_ERR
, "bpf: can't set promiscuous mode: %m");
182 * Ask BPF how much buffer space it requires and allocate one.
184 if (ioctl(BpfFd
, BIOCGBLEN
, (caddr_t
)&BpfLen
) < 0) {
185 syslog(LOG_ERR
, "bpf: ioctl(BIOCGBLEN): %m");
189 BpfPkt
= (u_char
*)malloc(BpfLen
);
191 if (BpfPkt
== NULL
) {
192 syslog(LOG_ERR
, "bpf: out of memory (%u bytes for bpfpkt)",
198 * Write a little program to snarf RMP Boot packets and stuff
199 * it down BPF's throat (i.e. set up the packet filter).
202 #define RMP ((struct rmp_packet *)0)
203 static struct bpf_insn bpf_insn
[] = {
204 { BPF_LD
|BPF_B
|BPF_ABS
, 0, 0, (long)&RMP
->hp_llc
.dsap
},
205 { BPF_JMP
|BPF_JEQ
|BPF_K
, 0, 5, IEEE_DSAP_HP
},
206 { BPF_LD
|BPF_H
|BPF_ABS
, 0, 0, (long)&RMP
->hp_llc
.cntrl
},
207 { BPF_JMP
|BPF_JEQ
|BPF_K
, 0, 3, IEEE_CNTL_HP
},
208 { BPF_LD
|BPF_H
|BPF_ABS
, 0, 0, (long)&RMP
->hp_llc
.dxsap
},
209 { BPF_JMP
|BPF_JEQ
|BPF_K
, 0, 1, HPEXT_DXSAP
},
210 { BPF_RET
|BPF_K
, 0, 0, RMP_MAX_PACKET
},
211 { BPF_RET
|BPF_K
, 0, 0, 0x0 }
214 static struct bpf_program bpf_pgm
= {
215 sizeof(bpf_insn
)/sizeof(bpf_insn
[0]), bpf_insn
218 if (ioctl(BpfFd
, BIOCSETF
, (caddr_t
)&bpf_pgm
) < 0) {
219 syslog(LOG_ERR
, "bpf: ioctl(BIOCSETF): %m");
228 ** BPF GetIntfName -- Return the name of a network interface attached to
229 ** the system, or 0 if none can be found. The interface
230 ** must be configured up; the lowest unit number is
231 ** preferred; loopback is ignored.
234 ** errmsg - if no network interface found, *errmsg explains why.
237 ** A (static) pointer to interface name, or NULL on error.
243 BpfGetIntfName(errmsg
)
246 struct ifreq ibuf
[8], *ifrp
, *ifend
, *mp
;
251 static char device
[sizeof(ifrp
->ifr_name
)];
252 static char errbuf
[128] = "No Error!";
257 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
258 (void) strcpy(errbuf
, "bpf: socket: %m");
261 ifc
.ifc_len
= sizeof ibuf
;
262 ifc
.ifc_buf
= (caddr_t
)ibuf
;
265 if (ioctl(fd
, OSIOCGIFCONF
, (char *)&ifc
) < 0 ||
266 ifc
.ifc_len
< sizeof(struct ifreq
)) {
267 (void) strcpy(errbuf
, "bpf: ioctl(OSIOCGIFCONF): %m");
271 if (ioctl(fd
, SIOCGIFCONF
, (char *)&ifc
) < 0 ||
272 ifc
.ifc_len
< sizeof(struct ifreq
)) {
273 (void) strcpy(errbuf
, "bpf: ioctl(SIOCGIFCONF): %m");
278 ifend
= (struct ifreq
*)((char *)ibuf
+ ifc
.ifc_len
);
282 for (; ifrp
< ifend
; ++ifrp
) {
283 if (ioctl(fd
, SIOCGIFFLAGS
, (char *)ifrp
) < 0) {
284 (void) strcpy(errbuf
, "bpf: ioctl(SIOCGIFFLAGS): %m");
289 * If interface is down or this is the loopback interface,
292 if ((ifrp
->ifr_flags
& IFF_UP
) == 0 ||
294 (ifrp
->ifr_flags
& IFF_LOOPBACK
))
296 (strcmp(ifrp
->ifr_name
, "lo0") == 0))
300 for (cp
= ifrp
->ifr_name
; !isdigit(*cp
); ++cp
)
311 (void) strcpy(errbuf
, "bpf: no interfaces found");
315 (void) strcpy(device
, mp
->ifr_name
);
320 ** BpfRead -- Read packets from a BPF device and fill in `rconn'.
323 ** rconn - filled in with next packet.
324 ** doread - is True if we can issue a read() syscall.
327 ** True if `rconn' contains a new packet, False otherwise.
333 BpfRead(rconn
, doread
)
337 register int datlen
, caplen
, hdrlen
;
338 static u_char
*bp
= NULL
, *ep
= NULL
;
342 * The read() may block, or it may return one or more packets.
343 * We let the caller decide whether or not we can issue a read().
346 if ((cc
= read(BpfFd
, (char *)BpfPkt
, (int)BpfLen
)) < 0) {
347 syslog(LOG_ERR
, "bpf: read: %m");
355 #define bhp ((struct bpf_hdr *)bp)
357 * If there is a new packet in the buffer, stuff it into `rconn'
358 * and return a success indication.
361 datlen
= bhp
->bh_datalen
;
362 caplen
= bhp
->bh_caplen
;
363 hdrlen
= bhp
->bh_hdrlen
;
365 if (caplen
!= datlen
)
367 "bpf: short packet dropped (%d of %d bytes)",
369 else if (caplen
> sizeof(struct rmp_packet
))
370 syslog(LOG_ERR
, "bpf: large packet dropped (%d bytes)",
373 rconn
->rmplen
= caplen
;
374 bcopy((char *)&bhp
->bh_tstamp
, (char *)&rconn
->tstamp
,
375 sizeof(struct timeval
));
376 bcopy((char *)bp
+ hdrlen
, (char *)&rconn
->rmp
, caplen
);
378 bp
+= BPF_WORDALIGN(caplen
+ hdrlen
);
387 ** BpfWrite -- Write packet to BPF device.
390 ** rconn - packet to send.
393 ** True if write succeeded, False otherwise.
402 if (write(BpfFd
, (char *)&rconn
->rmp
, rconn
->rmplen
) < 0) {
403 syslog(LOG_ERR
, "write: %s: %m", EnetStr(rconn
));
411 ** BpfClose -- Close a BPF device.
427 if (BpfPkt
!= NULL
) {
428 free((char *)BpfPkt
);
436 ifr
.ifr_addr
.sa_len
= RMP_ADDRLEN
+ 2;
438 ifr
.ifr_addr
.sa_family
= AF_UNSPEC
;
439 bcopy(&RmpMcastAddr
[0], (char *)&ifr
.ifr_addr
.sa_data
[0], RMP_ADDRLEN
);
440 if (ioctl(BpfFd
, SIOCDELMULTI
, (caddr_t
)&ifr
) < 0)
441 (void) ioctl(BpfFd
, BIOCPROMISC
, (caddr_t
)0);