xref: /openbsd-src/usr.sbin/mopd/otherOS/pf-snit.c (revision 043fbe51c197dbbcd422e917b65f765d8b5f8874)
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)&ifr;
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