1 /* $NetBSD: pf.c,v 1.11 2009/10/20 00:51:13 snj Exp $ */
4 * Copyright (c) 1993-95 Mats O Jansson. All rights reserved.
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is partly derived from rarpd.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: pf.c,v 1.11 2009/10/20 00:51:13 snj Exp $");
55 * Return information to device.c how to open device.
56 * In this case the driver can handle both Ethernet type II and
57 * IEEE 802.3 frames (SNAP) in a single pfOpen.
61 pfTrans(const char *interface
)
63 return TRANS_ETHER
+TRANS_8023
+TRANS_AND
;
67 * Open and initialize packet filter.
71 pfInit(const char *interface
, int mode
, u_short protocol
, int typ
)
78 const char *device
= _PATH_BPF
;
80 static struct bpf_insn insns
[] = {
81 BPF_STMT(BPF_LD
| BPF_H
| BPF_ABS
, 12),
82 BPF_JUMP(BPF_JMP
| BPF_JEQ
| BPF_K
, 0x4711, 4, 0),
83 BPF_STMT(BPF_LD
| BPF_H
| BPF_ABS
, 20),
84 BPF_JUMP(BPF_JMP
| BPF_JEQ
| BPF_K
, 0x4711, 0, 3),
85 BPF_STMT(BPF_LD
| BPF_H
| BPF_ABS
, 14),
86 BPF_JUMP(BPF_JMP
| BPF_JEQ
| BPF_K
, 0xaaaa, 0, 1),
87 BPF_STMT(BPF_RET
| BPF_K
, 1520),
88 BPF_STMT(BPF_RET
| BPF_K
, 0),
90 static struct bpf_program filter
= {
91 sizeof insns
/ sizeof(insns
[0]),
95 fd
= open(device
, mode
);
97 mopLogWarn("pfInit: open %s", device
);
101 /* Set immediate mode so packets are processed as they arrive. */
103 if (ioctl(fd
, BIOCIMMEDIATE
, &immediate
) < 0) {
104 mopLogWarn("pfInit: BIOCIMMEDIATE");
108 if (ioctl(fd
, BIOCSBLEN
, &bufsize
) < 0) {
109 mopLogWarn("pfInit: BIOCSBLEN(%d)", bufsize
);
111 (void) strncpy(ifr
.ifr_name
, interface
, sizeof ifr
.ifr_name
);
112 if (ioctl(fd
, BIOCSETIF
, (caddr_t
) & ifr
) < 0) {
113 mopLogWarn("pfInit: BIOCSETIF");
116 /* Check that the data link layer is an Ethernet; this code won't work
117 * with anything else. */
118 if (ioctl(fd
, BIOCGDLT
, (caddr_t
) & dlt
) < 0) {
119 mopLogWarn("pfInit: BIOCGDLT");
122 if (dlt
!= DLT_EN10MB
) {
123 mopLogWarnX("pfInit: %s is not ethernet", device
);
127 /* Set promiscuous mode. */
128 if (ioctl(fd
, BIOCPROMISC
, (caddr_t
)0) < 0) {
129 mopLogWarn("pfInit: BIOCPROMISC");
133 /* Set filter program. */
134 insns
[1].k
= protocol
;
135 insns
[3].k
= protocol
;
137 if (ioctl(fd
, BIOCSETF
, (caddr_t
) & filter
) < 0) {
138 mopLogWarn("pfInit: BIOCSETF");
145 * Add a Multicast address to the interface
149 pfAddMulti(int s
, const char *interface
, const char *addr
)
154 strncpy(ifr
.ifr_name
, interface
, sizeof(ifr
.ifr_name
));
156 ifr
.ifr_addr
.sa_family
= AF_UNSPEC
;
157 memmove(ifr
.ifr_addr
.sa_data
, addr
, 6);
160 * open a socket, temporarily, to use for SIOC* ioctls
163 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
164 mopLogWarn("pfAddMulti: socket");
167 if (ioctl(fd
, SIOCADDMULTI
, (caddr_t
)&ifr
) < 0) {
168 mopLogWarn("pfAddMulti: SIOCADDMULTI");
178 * Delete a Multicast address from the interface
182 pfDelMulti(int s
, const char *interface
, const char *addr
)
187 strncpy(ifr
.ifr_name
, interface
, sizeof(ifr
.ifr_name
));
189 ifr
.ifr_addr
.sa_family
= AF_UNSPEC
;
190 memmove(ifr
.ifr_addr
.sa_data
, addr
, 6);
193 * open a socket, temporarily, to use for SIOC* ioctls
196 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
197 mopLogWarn("pfDelMulti: socket");
200 if (ioctl(fd
, SIOCDELMULTI
, (caddr_t
)&ifr
) < 0) {
201 mopLogWarn("pfAddMulti: SIOCDELMULTI");
215 pfRead(int fd
, u_char
*buf
, int len
)
217 return(read(fd
, buf
, len
));
225 pfWrite(int fd
, const u_char
*buf
, int len
, int trans
)
232 iov
[0].iov_base
= (caddr_t
)__UNCONST(buf
);
234 iov
[1].iov_base
= (caddr_t
)__UNCONST(buf
+22);
235 iov
[1].iov_len
= len
-22;
238 iov
[0].iov_base
= (caddr_t
)__UNCONST(buf
);
240 iov
[1].iov_base
= (caddr_t
)__UNCONST(buf
+14);
241 iov
[1].iov_len
= len
-14;
245 if (writev(fd
, iov
, 2) == len
)