1*043fbe51Sderaadt /* $OpenBSD: pf-snit.c,v 1.8 2009/10/27 23:59:53 deraadt Exp $ */
2e08c8b61Smaja
3bff609efSmaja /*
4bff609efSmaja * Copyright (c) 1993-96 Mats O Jansson. All rights reserved.
5bff609efSmaja *
6bff609efSmaja * Redistribution and use in source and binary forms, with or without
7bff609efSmaja * modification, are permitted provided that the following conditions
8bff609efSmaja * are met:
9bff609efSmaja * 1. Redistributions of source code must retain the above copyright
10bff609efSmaja * notice, this list of conditions and the following disclaimer.
11bff609efSmaja * 2. Redistributions in binary form must reproduce the above copyright
12bff609efSmaja * notice, this list of conditions and the following disclaimer in the
13bff609efSmaja * documentation and/or other materials provided with the distribution.
14bff609efSmaja *
15bff609efSmaja * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16bff609efSmaja * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17bff609efSmaja * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18bff609efSmaja * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19bff609efSmaja * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20bff609efSmaja * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21bff609efSmaja * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22bff609efSmaja * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23bff609efSmaja * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24bff609efSmaja * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25bff609efSmaja */
26bff609efSmaja
27bff609efSmaja #include <stdio.h>
28bff609efSmaja #include <sys/types.h>
29bff609efSmaja #include <sys/time.h>
30bff609efSmaja #include <sys/ioctl.h>
31bff609efSmaja #include <sys/file.h>
32bff609efSmaja #include <sys/socket.h>
33bff609efSmaja #include <sys/uio.h>
34bff609efSmaja #include <net/if.h>
35bff609efSmaja
36bff609efSmaja #define DEV_NIT "/dev/nit"
37bff609efSmaja #include <net/nit.h>
38bff609efSmaja #include <net/nit_if.h>
39bff609efSmaja #include <net/nit_pf.h>
40bff609efSmaja #include <net/nit_buf.h>
41bff609efSmaja #include <net/packetfilt.h>
42bff609efSmaja #include <stropts.h>
43bff609efSmaja
44bff609efSmaja #include <netinet/in.h>
45bff609efSmaja #include <netinet/if_ether.h>
46bff609efSmaja
47bff609efSmaja #include <netdb.h>
48bff609efSmaja #include <ctype.h>
49bff609efSmaja #include <syslog.h>
50bff609efSmaja
51bff609efSmaja #include "common/mopdef.h"
52bff609efSmaja
53bff609efSmaja /*
54bff609efSmaja * Variables
55bff609efSmaja */
56bff609efSmaja
57bff609efSmaja /* struct ifreq ifr; */
58bff609efSmaja extern int errno;
59bff609efSmaja extern int promisc;
60bff609efSmaja
61bff609efSmaja /*
62bff609efSmaja * Return information to device.c how to open device.
63bff609efSmaja * In this case the driver can handle both Ethernet type II and
64bff609efSmaja * IEEE 802.3 frames (SNAP) in a single pfOpen.
65bff609efSmaja */
66bff609efSmaja
67bff609efSmaja int
pfTrans(interface)68bff609efSmaja pfTrans(interface)
69bff609efSmaja char *interface;
70bff609efSmaja {
71bff609efSmaja return TRANS_ETHER+TRANS_8023+TRANS_AND;
72bff609efSmaja }
73bff609efSmaja
74bff609efSmaja /*
75bff609efSmaja * Open and initialize packet filter.
76bff609efSmaja */
77bff609efSmaja
78bff609efSmaja int
pfInit(interface,mode,protocol,trans)79bff609efSmaja pfInit(interface, mode, protocol, trans)
80bff609efSmaja char *interface;
81bff609efSmaja u_short protocol;
82bff609efSmaja int trans, mode;
83bff609efSmaja {
84bff609efSmaja int fd;
85bff609efSmaja int ioarg;
86bff609efSmaja char device[64];
87bff609efSmaja unsigned long if_flags;
88bff609efSmaja
89bff609efSmaja struct ifreq ifr;
90bff609efSmaja struct strioctl si;
91bff609efSmaja
92bff609efSmaja /* get clone */
93bff609efSmaja if ((fd = open(DEV_NIT, mode)) < 0) {
94bff609efSmaja syslog(LOG_ERR,"pfInit: open nit %m");
95bff609efSmaja return(-1);
96bff609efSmaja }
97bff609efSmaja
98bff609efSmaja /*
99bff609efSmaja * set filter for protocol
100bff609efSmaja */
101bff609efSmaja
102bff609efSmaja if (setup_pf(fd, protocol, trans) < 0)
103bff609efSmaja return(-1);
104bff609efSmaja
105bff609efSmaja /*
106bff609efSmaja * set options, bind to underlying interface
107bff609efSmaja */
108bff609efSmaja
109bff609efSmaja strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
110bff609efSmaja
111bff609efSmaja /* bind */
112bff609efSmaja si.ic_cmd = NIOCBIND; /* bind to underlying interface */
113bff609efSmaja si.ic_timout = 10;
114bff609efSmaja si.ic_len = sizeof(ifr);
115bff609efSmaja si.ic_dp = (caddr_t)𝔦
116bff609efSmaja if (ioctl(fd, I_STR, (caddr_t)&si) < 0) {
117bff609efSmaja syslog(LOG_ERR,"pfinit: I_STR %m");
118bff609efSmaja return(-1);
119bff609efSmaja }
120bff609efSmaja
121bff609efSmaja if (promisc) {
122bff609efSmaja if_flags = NI_PROMISC;
123bff609efSmaja si.ic_cmd = NIOCSFLAGS;
124bff609efSmaja si.ic_timout = 10;
125bff609efSmaja si.ic_len = sizeof(if_flags);
126bff609efSmaja si.ic_dp = (caddr_t)&if_flags;
127bff609efSmaja if (ioctl(fd, I_STR, (caddr_t)&si) < 0) {
128bff609efSmaja syslog(LOG_ERR,"pfInit: I_STR (promisc) %m");
129bff609efSmaja return(-1);
130bff609efSmaja }
131bff609efSmaja }
132bff609efSmaja
133bff609efSmaja /* set up messages */
134bff609efSmaja if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { /* want messages */
135bff609efSmaja syslog(LOG_ERR,"pfInit: I_SRDOPT %m");
136bff609efSmaja return(-1);
137bff609efSmaja }
138bff609efSmaja
139bff609efSmaja /* flush read queue */
140bff609efSmaja if (ioctl(fd, I_FLUSH, (char *)FLUSHR) < 0) {
141bff609efSmaja syslog(LOG_ERR,"pfInit: I_FLUSH %m");
142bff609efSmaja return(-1);
143bff609efSmaja }
144bff609efSmaja
145bff609efSmaja return(fd);
146bff609efSmaja }
147bff609efSmaja
148bff609efSmaja /*
149bff609efSmaja * establish protocol filter
150bff609efSmaja */
151bff609efSmaja
152bff609efSmaja int
setup_pf(s,prot,trans)153bff609efSmaja setup_pf(s, prot, trans)
154bff609efSmaja int s, trans;
155bff609efSmaja u_short prot;
156bff609efSmaja {
157bff609efSmaja int ioarg;
158bff609efSmaja u_short offset;
159bff609efSmaja
160bff609efSmaja struct packetfilt pf;
1610ac0d02eSmpech u_short *fwp = pf.Pf_Filter;
162bff609efSmaja struct strioctl si;
163bff609efSmaja
164bff609efSmaja #define s_offset(structp, element) (&(((structp)0)->element))
165bff609efSmaja
166bff609efSmaja bzero(&pf, sizeof(pf));
167bff609efSmaja pf.Pf_Priority = 128;
168bff609efSmaja
169bff609efSmaja offset = ((int)s_offset(struct ether_header *, ether_type))/sizeof(u_short);
170bff609efSmaja *fwp++ = ENF_PUSHWORD + offset; /* Check Ethernet type II */
171bff609efSmaja *fwp++ = ENF_PUSHLIT | ENF_EQ; /* protocol prot */
172bff609efSmaja *fwp++ = htons(prot);
173bff609efSmaja *fwp++ = ENF_PUSHWORD + offset + 4; /* Check 802.3 protocol prot */
174bff609efSmaja *fwp++ = ENF_PUSHLIT | ENF_EQ;
175bff609efSmaja *fwp++ = htons(prot);
176bff609efSmaja *fwp++ = ENF_PUSHWORD + offset + 1; /* Check for SSAP and DSAP */
177bff609efSmaja *fwp++ = ENF_PUSHLIT | ENF_EQ;
178bff609efSmaja *fwp++ = htons(0xaaaa);
179bff609efSmaja *fwp++ = ENF_AND;
180bff609efSmaja *fwp++ = ENF_OR;
181bff609efSmaja pf.Pf_FilterLen = 11;
182bff609efSmaja
183bff609efSmaja si.ic_cmd = NIOCSETF;
184bff609efSmaja si.ic_timout = 10;
185bff609efSmaja si.ic_len = sizeof(pf);
186bff609efSmaja si.ic_dp = (char *)&pf;
187bff609efSmaja if (ioctl(s, I_PUSH, "pf") < 0) {
188bff609efSmaja syslog(LOG_ERR,"setup_pf: I_PUSH %m");
189bff609efSmaja return(-1);
190bff609efSmaja }
191bff609efSmaja if (ioctl(s, I_STR, (char *)&si) < 0) {
192bff609efSmaja syslog(LOG_ERR,"setup_pf: I_STR %m");
193bff609efSmaja return(-1);
194bff609efSmaja }
195bff609efSmaja
196bff609efSmaja return(0);
197bff609efSmaja }
198bff609efSmaja
199bff609efSmaja /*
200bff609efSmaja * Get the interface ethernet address
201bff609efSmaja */
202bff609efSmaja
203bff609efSmaja int
pfEthAddr(fd,addr)204bff609efSmaja pfEthAddr(fd, addr)
205bff609efSmaja int fd;
206bff609efSmaja u_char *addr;
207bff609efSmaja {
208bff609efSmaja struct ifreq ifr;
209bff609efSmaja struct sockaddr *sa;
210bff609efSmaja
211bff609efSmaja if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
212bff609efSmaja syslog(LOG_ERR,"pfEthAddr: SIOCGIFADDR %m");
213bff609efSmaja return(-1);
214bff609efSmaja }
215bff609efSmaja sa = (struct sockaddr *)ifr.ifr_data;
216bff609efSmaja bcopy((char *)sa->sa_data, (char *)addr, 6);
217bff609efSmaja
218bff609efSmaja return(0);
219bff609efSmaja }
220bff609efSmaja
221bff609efSmaja /*
222bff609efSmaja * Add a Multicast address to the interface
223bff609efSmaja */
224bff609efSmaja
225bff609efSmaja int
pfAddMulti(s,interface,addr)226bff609efSmaja pfAddMulti(s, interface, addr)
227bff609efSmaja int s;
228bff609efSmaja char *interface, *addr;
229bff609efSmaja {
230bff609efSmaja struct ifreq ifr;
231bff609efSmaja int fd;
232bff609efSmaja
23307db2e42Sbitblt strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) -1);
23407db2e42Sbitblt ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
235bff609efSmaja
236bff609efSmaja ifr.ifr_addr.sa_family = AF_UNSPEC;
237bff609efSmaja bcopy(addr, ifr.ifr_addr.sa_data, 6);
238bff609efSmaja
239bff609efSmaja /*
240bff609efSmaja * open a socket, temporarily, to use for SIOC* ioctls
241bff609efSmaja */
242bff609efSmaja
243bff609efSmaja if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
244bff609efSmaja syslog(LOG_ERR,"pfAddMulti: socket() %m");
245bff609efSmaja return(-1);
246bff609efSmaja }
247bff609efSmaja if (ioctl(fd, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
248bff609efSmaja syslog(LOG_ERR,"pfAddMulti: SIOCADDMULTI %m");
249bff609efSmaja close(fd);
250bff609efSmaja return(-1);
251bff609efSmaja }
252bff609efSmaja close(fd);
253bff609efSmaja
254bff609efSmaja return(0);
255bff609efSmaja }
256bff609efSmaja
257bff609efSmaja /*
258bff609efSmaja * delete a multicast address from the interface
259bff609efSmaja */
260bff609efSmaja
261bff609efSmaja int
pfDelMulti(s,interface,addr)262bff609efSmaja pfDelMulti(s, interface, addr)
263bff609efSmaja int s;
264bff609efSmaja char *interface, *addr;
265bff609efSmaja {
266bff609efSmaja struct ifreq ifr;
267bff609efSmaja int fd;
268bff609efSmaja
26907db2e42Sbitblt strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) -1);
27007db2e42Sbitblt ifr.ifr_name[sizeof(ifr.ifr_name)] = 0;
271bff609efSmaja
272bff609efSmaja ifr.ifr_addr.sa_family = AF_UNSPEC;
273bff609efSmaja bcopy(addr, ifr.ifr_addr.sa_data, 6);
274bff609efSmaja
275bff609efSmaja /*
276bff609efSmaja * open a socket, temporarily, to use for SIOC* ioctls
277bff609efSmaja *
278bff609efSmaja */
279bff609efSmaja if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
280bff609efSmaja syslog(LOG_ERR,"pfDelMulti: socket() %m");
281bff609efSmaja return(-1);
282bff609efSmaja }
283bff609efSmaja
284bff609efSmaja if (ioctl(fd, SIOCDELMULTI, (caddr_t)&ifr) < 0) {
285bff609efSmaja syslog(LOG_ERR,"pfDelMulti: SIOCDELMULTI %m");
286bff609efSmaja close(fd);
287bff609efSmaja return(-1);
288bff609efSmaja }
289bff609efSmaja close(fd);
290bff609efSmaja
291bff609efSmaja return(0);
292bff609efSmaja }
293bff609efSmaja
294bff609efSmaja /*
295bff609efSmaja * read a packet
296bff609efSmaja */
297bff609efSmaja
298bff609efSmaja int
pfRead(fd,buf,len)299bff609efSmaja pfRead(fd, buf, len)
300bff609efSmaja int fd, len;
301bff609efSmaja u_char *buf;
302bff609efSmaja {
303bff609efSmaja return(read(fd, buf, len));
304bff609efSmaja }
305bff609efSmaja
306bff609efSmaja /*
307bff609efSmaja * write a packet
308bff609efSmaja */
309bff609efSmaja
310bff609efSmaja int
pfWrite(fd,buf,len,trans)311bff609efSmaja pfWrite(fd, buf, len, trans)
312bff609efSmaja int fd, len, trans;
313bff609efSmaja u_char *buf;
314bff609efSmaja {
315bff609efSmaja
316bff609efSmaja struct sockaddr sa;
317bff609efSmaja struct strbuf pbuf, dbuf;
318bff609efSmaja
319bff609efSmaja sa.sa_family = AF_UNSPEC;
320bff609efSmaja bcopy(buf, sa.sa_data, sizeof(sa.sa_data));
321bff609efSmaja
322bff609efSmaja switch (trans) {
323bff609efSmaja default:
324bff609efSmaja pbuf.len = sizeof(struct sockaddr);
325bff609efSmaja pbuf.buf = (char *) &sa;
326bff609efSmaja dbuf.len = len-14;
327bff609efSmaja dbuf.buf = (char *)buf+14;
328bff609efSmaja break;
329bff609efSmaja }
330bff609efSmaja
331bff609efSmaja if (putmsg(fd, &pbuf, &dbuf, 0) == 0)
332bff609efSmaja return(len);
333bff609efSmaja
334bff609efSmaja return(-1);
335bff609efSmaja }
336