1145554Sdarrenr/*	$FreeBSD$	*/
2145554Sdarrenr
3145554Sdarrenr/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5145554Sdarrenr *
6145554Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7255332Scy *
8255332Scy * $Id$
9145554Sdarrenr */
10145554Sdarrenr#if !defined(lint)
11145554Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
12255332Scystatic const char rcsid[] = "@(#)$Id$";
13145554Sdarrenr#endif
14145554Sdarrenr
15255332Scy#include "ipf.h"
16145554Sdarrenr#include "md5.h"
17255332Scy#include "ipt.h"
18145554Sdarrenr
19255332Scyipf_main_softc_t	ipfmain;
20145554Sdarrenr
21145554Sdarrenrstatic	struct	ifnet **ifneta = NULL;
22145554Sdarrenrstatic	int	nifs = 0;
23145554Sdarrenr
24255332Scystruct	rtentry;
25255332Scy
26255332Scystatic	void	ipf_setifpaddr __P((struct ifnet *, char *));
27145554Sdarrenrvoid	init_ifp __P((void));
28145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
29145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
30145554Sdarrenr			       struct sockaddr *));
31145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
32145554Sdarrenr				  struct sockaddr *));
33145554Sdarrenr#else
34145554Sdarrenr# if TRU64 >= 1885
35145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
36145554Sdarrenr			       struct sockaddr *, struct rtentry *, char *));
37145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
38145554Sdarrenr				  struct sockaddr *, struct rtentry *, char *));
39145554Sdarrenr# else
40145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
41145554Sdarrenr			       struct sockaddr *, struct rtentry *));
42145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
43145554Sdarrenr				  struct sockaddr *, struct rtentry *));
44145554Sdarrenr# endif
45145554Sdarrenr#endif
46145554Sdarrenr
47145554Sdarrenr
48255332Scyint
49255332Scyipfattach(softc)
50255332Scy	ipf_main_softc_t *softc;
51145554Sdarrenr{
52145554Sdarrenr	return 0;
53145554Sdarrenr}
54145554Sdarrenr
55145554Sdarrenr
56255332Scyint
57255332Scyipfdetach(softc)
58255332Scy	ipf_main_softc_t *softc;
59145554Sdarrenr{
60145554Sdarrenr	return 0;
61145554Sdarrenr}
62145554Sdarrenr
63145554Sdarrenr
64145554Sdarrenr/*
65145554Sdarrenr * Filter ioctl interface.
66145554Sdarrenr */
67255332Scyint
68255332Scyipfioctl(softc, dev, cmd, data, mode)
69255332Scy	ipf_main_softc_t *softc;
70255332Scy	int dev;
71255332Scy	ioctlcmd_t cmd;
72255332Scy	caddr_t data;
73255332Scy	int mode;
74145554Sdarrenr{
75170268Sdarrenr	int error = 0, unit = 0, uid;
76145554Sdarrenr
77170268Sdarrenr	uid = getuid();
78145554Sdarrenr	unit = dev;
79145554Sdarrenr
80145554Sdarrenr	SPL_NET(s);
81145554Sdarrenr
82255332Scy	error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
83170268Sdarrenr	if (error != -1) {
84145554Sdarrenr		SPL_X(s);
85145554Sdarrenr		return error;
86145554Sdarrenr	}
87145554Sdarrenr	SPL_X(s);
88145554Sdarrenr	return error;
89145554Sdarrenr}
90145554Sdarrenr
91145554Sdarrenr
92255332Scyvoid
93255332Scyipf_forgetifp(softc, ifp)
94255332Scy	ipf_main_softc_t *softc;
95255332Scy	void *ifp;
96145554Sdarrenr{
97145554Sdarrenr	register frentry_t *f;
98145554Sdarrenr
99255332Scy	WRITE_ENTER(&softc->ipf_mutex);
100255332Scy	for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
101255332Scy	     f = f->fr_next)
102145554Sdarrenr		if (f->fr_ifa == ifp)
103145554Sdarrenr			f->fr_ifa = (void *)-1;
104255332Scy	for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
105255332Scy	     f = f->fr_next)
106145554Sdarrenr		if (f->fr_ifa == ifp)
107145554Sdarrenr			f->fr_ifa = (void *)-1;
108255332Scy	for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
109255332Scy	     f = f->fr_next)
110145554Sdarrenr		if (f->fr_ifa == ifp)
111145554Sdarrenr			f->fr_ifa = (void *)-1;
112255332Scy	for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
113255332Scy	     f = f->fr_next)
114145554Sdarrenr		if (f->fr_ifa == ifp)
115145554Sdarrenr			f->fr_ifa = (void *)-1;
116255332Scy	RWLOCK_EXIT(&softc->ipf_mutex);
117255332Scy	ipf_nat_sync(softc, ifp);
118255332Scy	ipf_lookup_sync(softc, ifp);
119145554Sdarrenr}
120145554Sdarrenr
121145554Sdarrenr
122255332Scystatic int
123145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
124255332Scyno_output(ifp, m, s)
125145554Sdarrenr#else
126145554Sdarrenr# if TRU64 >= 1885
127255332Scyno_output (ifp, m, s, rt, cp)
128255332Scy	char *cp;
129145554Sdarrenr# else
130255332Scyno_output(ifp, m, s, rt)
131145554Sdarrenr# endif
132255332Scy	struct rtentry *rt;
133145554Sdarrenr#endif
134255332Scy	struct ifnet *ifp;
135255332Scy	struct mbuf *m;
136255332Scy	struct sockaddr *s;
137145554Sdarrenr{
138145554Sdarrenr	return 0;
139145554Sdarrenr}
140145554Sdarrenr
141145554Sdarrenr
142255332Scystatic int
143145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
144255332Scywrite_output(ifp, m, s)
145145554Sdarrenr#else
146145554Sdarrenr# if TRU64 >= 1885
147255332Scywrite_output (ifp, m, s, rt, cp)
148255332Scy	char *cp;
149145554Sdarrenr# else
150255332Scywrite_output(ifp, m, s, rt)
151145554Sdarrenr# endif
152255332Scy	struct rtentry *rt;
153145554Sdarrenr#endif
154255332Scy	struct ifnet *ifp;
155255332Scy	struct mbuf *m;
156255332Scy	struct sockaddr *s;
157145554Sdarrenr{
158145554Sdarrenr	char fname[32];
159145554Sdarrenr	mb_t *mb;
160145554Sdarrenr	ip_t *ip;
161145554Sdarrenr	int fd;
162145554Sdarrenr
163145554Sdarrenr	mb = (mb_t *)m;
164145554Sdarrenr	ip = MTOD(mb, ip_t *);
165145554Sdarrenr
166145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
167145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
168145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
169145554Sdarrenr	sprintf(fname, "/tmp/%s", ifp->if_xname);
170145554Sdarrenr#else
171145554Sdarrenr	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
172145554Sdarrenr#endif
173145554Sdarrenr	fd = open(fname, O_WRONLY|O_APPEND);
174145554Sdarrenr	if (fd == -1) {
175145554Sdarrenr		perror("open");
176145554Sdarrenr		return -1;
177145554Sdarrenr	}
178145554Sdarrenr	write(fd, (char *)ip, ntohs(ip->ip_len));
179145554Sdarrenr	close(fd);
180145554Sdarrenr	return 0;
181145554Sdarrenr}
182145554Sdarrenr
183145554Sdarrenr
184255332Scystatic void
185255332Scyipf_setifpaddr(ifp, addr)
186255332Scy	struct ifnet *ifp;
187255332Scy	char *addr;
188145554Sdarrenr{
189145554Sdarrenr#ifdef __sgi
190145554Sdarrenr	struct in_ifaddr *ifa;
191145554Sdarrenr#else
192145554Sdarrenr	struct ifaddr *ifa;
193145554Sdarrenr#endif
194145554Sdarrenr
195145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
196145554Sdarrenr	if (ifp->if_addrlist.tqh_first != NULL)
197145554Sdarrenr#else
198145554Sdarrenr# ifdef __sgi
199145554Sdarrenr	if (ifp->in_ifaddr != NULL)
200145554Sdarrenr# else
201145554Sdarrenr	if (ifp->if_addrlist != NULL)
202145554Sdarrenr# endif
203145554Sdarrenr#endif
204145554Sdarrenr		return;
205145554Sdarrenr
206145554Sdarrenr	ifa = (struct ifaddr *)malloc(sizeof(*ifa));
207145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
208145554Sdarrenr	ifp->if_addrlist.tqh_first = ifa;
209145554Sdarrenr#else
210145554Sdarrenr# ifdef __sgi
211145554Sdarrenr	ifp->in_ifaddr = ifa;
212145554Sdarrenr# else
213145554Sdarrenr	ifp->if_addrlist = ifa;
214145554Sdarrenr# endif
215145554Sdarrenr#endif
216145554Sdarrenr
217145554Sdarrenr	if (ifa != NULL) {
218145554Sdarrenr		struct sockaddr_in *sin;
219145554Sdarrenr
220145554Sdarrenr#ifdef __sgi
221145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ia_addr;
222145554Sdarrenr#else
223145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ifa_addr;
224145554Sdarrenr#endif
225255332Scy#ifdef USE_INET6
226255332Scy		if (index(addr, ':') != NULL) {
227255332Scy			struct sockaddr_in6 *sin6;
228255332Scy
229255332Scy			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
230255332Scy			sin6->sin6_family = AF_INET6;
231255761Scy			/* Abort if bad address. */
232255761Scy			switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
233255761Scy			{
234255761Scy			case 1:
235255761Scy				break;
236255761Scy			case -1:
237255761Scy				perror("inet_pton");
238255761Scy				abort();
239255761Scy				break;
240255761Scy			default:
241255761Scy				abort();
242255761Scy				break;
243255761Scy			}
244255332Scy		} else
245255332Scy#endif
246255332Scy		{
247255332Scy			sin->sin_family = AF_INET;
248255332Scy			sin->sin_addr.s_addr = inet_addr(addr);
249255332Scy			if (sin->sin_addr.s_addr == 0)
250255332Scy				abort();
251255332Scy		}
252145554Sdarrenr	}
253145554Sdarrenr}
254145554Sdarrenr
255255332Scystruct ifnet *
256255332Scyget_unit(name, family)
257255332Scy	char *name;
258255332Scy	int family;
259145554Sdarrenr{
260145554Sdarrenr	struct ifnet *ifp, **ifpp, **old_ifneta;
261145554Sdarrenr	char *addr;
262145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
263145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
264145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
265145554Sdarrenr
266255332Scy	if (!*name)
267255332Scy		return NULL;
268255332Scy
269145554Sdarrenr	if (name == NULL)
270145554Sdarrenr		name = "anon0";
271145554Sdarrenr
272145554Sdarrenr	addr = strchr(name, '=');
273145554Sdarrenr	if (addr != NULL)
274145554Sdarrenr		*addr++ = '\0';
275145554Sdarrenr
276145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
277145554Sdarrenr		if (!strcmp(name, ifp->if_xname)) {
278145554Sdarrenr			if (addr != NULL)
279255332Scy				ipf_setifpaddr(ifp, addr);
280145554Sdarrenr			return ifp;
281145554Sdarrenr		}
282145554Sdarrenr	}
283145554Sdarrenr#else
284145554Sdarrenr	char *s, ifname[LIFNAMSIZ+1];
285145554Sdarrenr
286145554Sdarrenr	if (name == NULL)
287145554Sdarrenr		name = "anon0";
288145554Sdarrenr
289145554Sdarrenr	addr = strchr(name, '=');
290145554Sdarrenr	if (addr != NULL)
291145554Sdarrenr		*addr++ = '\0';
292145554Sdarrenr
293145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
294255332Scy		COPYIFNAME(family, ifp, ifname);
295145554Sdarrenr		if (!strcmp(name, ifname)) {
296145554Sdarrenr			if (addr != NULL)
297255332Scy				ipf_setifpaddr(ifp, addr);
298145554Sdarrenr			return ifp;
299145554Sdarrenr		}
300145554Sdarrenr	}
301145554Sdarrenr#endif
302145554Sdarrenr
303145554Sdarrenr	if (!ifneta) {
304145554Sdarrenr		ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
305145554Sdarrenr		if (!ifneta)
306145554Sdarrenr			return NULL;
307145554Sdarrenr		ifneta[1] = NULL;
308145554Sdarrenr		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
309145554Sdarrenr		if (!ifneta[0]) {
310145554Sdarrenr			free(ifneta);
311145554Sdarrenr			return NULL;
312145554Sdarrenr		}
313145554Sdarrenr		nifs = 1;
314145554Sdarrenr	} else {
315145554Sdarrenr		old_ifneta = ifneta;
316145554Sdarrenr		nifs++;
317145554Sdarrenr		ifneta = (struct ifnet **)realloc(ifneta,
318145554Sdarrenr						  (nifs + 1) * sizeof(ifp));
319145554Sdarrenr		if (!ifneta) {
320145554Sdarrenr			free(old_ifneta);
321145554Sdarrenr			nifs = 0;
322145554Sdarrenr			return NULL;
323145554Sdarrenr		}
324145554Sdarrenr		ifneta[nifs] = NULL;
325145554Sdarrenr		ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
326145554Sdarrenr		if (!ifneta[nifs - 1]) {
327145554Sdarrenr			nifs--;
328145554Sdarrenr			return NULL;
329145554Sdarrenr		}
330145554Sdarrenr	}
331145554Sdarrenr	ifp = ifneta[nifs - 1];
332145554Sdarrenr
333172776Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
334172776Sdarrenr	TAILQ_INIT(&ifp->if_addrlist);
335172776Sdarrenr#endif
336145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
337145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
338145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
339145554Sdarrenr	(void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
340145554Sdarrenr#else
341255332Scy	s = name + strlen(name) - 1;
342255332Scy	for (; s > name; s--) {
343255332Scy		if (!ISDIGIT(*s)) {
344255332Scy			s++;
345255332Scy			break;
346255332Scy		}
347255332Scy	}
348255332Scy
349255332Scy	if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
350145554Sdarrenr		ifp->if_unit = atoi(s);
351145554Sdarrenr		ifp->if_name = (char *)malloc(s - name + 1);
352145554Sdarrenr		(void) strncpy(ifp->if_name, name, s - name);
353145554Sdarrenr		ifp->if_name[s - name] = '\0';
354145554Sdarrenr	} else {
355145554Sdarrenr		ifp->if_name = strdup(name);
356145554Sdarrenr		ifp->if_unit = -1;
357145554Sdarrenr	}
358145554Sdarrenr#endif
359170268Sdarrenr	ifp->if_output = (void *)no_output;
360145554Sdarrenr
361145554Sdarrenr	if (addr != NULL) {
362255332Scy		ipf_setifpaddr(ifp, addr);
363145554Sdarrenr	}
364145554Sdarrenr
365145554Sdarrenr	return ifp;
366145554Sdarrenr}
367145554Sdarrenr
368145554Sdarrenr
369255332Scychar *
370255332Scyget_ifname(ifp)
371255332Scy	struct ifnet *ifp;
372145554Sdarrenr{
373145554Sdarrenr	static char ifname[LIFNAMSIZ];
374145554Sdarrenr
375145554Sdarrenr#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
376145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
377145554Sdarrenr	sprintf(ifname, "%s", ifp->if_xname);
378145554Sdarrenr#else
379255332Scy	if (ifp->if_unit != -1)
380255332Scy		sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
381255332Scy	else
382255332Scy		strcpy(ifname, ifp->if_name);
383145554Sdarrenr#endif
384145554Sdarrenr	return ifname;
385145554Sdarrenr}
386145554Sdarrenr
387145554Sdarrenr
388145554Sdarrenr
389255332Scyvoid
390255332Scyinit_ifp()
391145554Sdarrenr{
392145554Sdarrenr	struct ifnet *ifp, **ifpp;
393145554Sdarrenr	char fname[32];
394145554Sdarrenr	int fd;
395145554Sdarrenr
396145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
397145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
398145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
399145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
400170268Sdarrenr		ifp->if_output = (void *)write_output;
401145554Sdarrenr		sprintf(fname, "/tmp/%s", ifp->if_xname);
402145554Sdarrenr		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
403145554Sdarrenr		if (fd == -1)
404145554Sdarrenr			perror("open");
405145554Sdarrenr		else
406145554Sdarrenr			close(fd);
407145554Sdarrenr	}
408145554Sdarrenr#else
409145554Sdarrenr
410145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
411255332Scy		ifp->if_output = (void *)write_output;
412145554Sdarrenr		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
413145554Sdarrenr		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
414145554Sdarrenr		if (fd == -1)
415145554Sdarrenr			perror("open");
416145554Sdarrenr		else
417145554Sdarrenr			close(fd);
418145554Sdarrenr	}
419145554Sdarrenr#endif
420145554Sdarrenr}
421145554Sdarrenr
422145554Sdarrenr
423255332Scyint
424255332Scyipf_fastroute(m, mpp, fin, fdp)
425255332Scy	mb_t *m, **mpp;
426255332Scy	fr_info_t *fin;
427255332Scy	frdest_t *fdp;
428145554Sdarrenr{
429255332Scy	struct ifnet *ifp;
430145554Sdarrenr	ip_t *ip = fin->fin_ip;
431255332Scy	frdest_t node;
432161357Sguido	int error = 0;
433161357Sguido	frentry_t *fr;
434161357Sguido	void *sifp;
435255332Scy	int sout;
436145554Sdarrenr
437255332Scy	sifp = fin->fin_ifp;
438255332Scy	sout = fin->fin_out;
439161357Sguido	fr = fin->fin_fr;
440145554Sdarrenr	ip->ip_sum = 0;
441161357Sguido
442255332Scy	if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
443255332Scy	    (fdp->fd_type == FRD_DSTLIST)) {
444255332Scy		bzero(&node, sizeof(node));
445255332Scy		ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
446255332Scy		fdp = &node;
447255332Scy	}
448255332Scy	ifp = fdp->fd_ptr;
449255332Scy
450255332Scy	if (ifp == NULL)
451255332Scy		return 0;	/* no routing table out here */
452255332Scy
453161357Sguido	if (fin->fin_out == 0) {
454161357Sguido		fin->fin_ifp = ifp;
455161357Sguido		fin->fin_out = 1;
456255332Scy		(void) ipf_acctpkt(fin, NULL);
457161357Sguido		fin->fin_fr = NULL;
458161357Sguido		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
459161357Sguido			u_32_t pass;
460161357Sguido
461255332Scy			(void) ipf_state_check(fin, &pass);
462161357Sguido		}
463161357Sguido
464255332Scy		switch (ipf_nat_checkout(fin, NULL))
465161357Sguido		{
466161357Sguido		case 0 :
467161357Sguido			break;
468161357Sguido		case 1 :
469161357Sguido			ip->ip_sum = 0;
470161357Sguido			break;
471161357Sguido		case -1 :
472161357Sguido			error = -1;
473161357Sguido			goto done;
474161357Sguido			break;
475161357Sguido		}
476161357Sguido
477161357Sguido	}
478161357Sguido
479255332Scy	m->mb_ifp = ifp;
480255332Scy	printpacket(fin->fin_out, m);
481255332Scy
482145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
483145554Sdarrenr	(*ifp->if_output)(ifp, (void *)ip, NULL);
484145554Sdarrenr# if TRU64 >= 1885
485145554Sdarrenr	(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
486145554Sdarrenr# else
487145554Sdarrenr	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
488145554Sdarrenr# endif
489145554Sdarrenr#endif
490161357Sguidodone:
491255332Scy	fin->fin_ifp = sifp;
492255332Scy	fin->fin_out = sout;
493161357Sguido	return error;
494145554Sdarrenr}
495145554Sdarrenr
496145554Sdarrenr
497255332Scyint
498255332Scyipf_send_reset(fin)
499255332Scy	fr_info_t *fin;
500145554Sdarrenr{
501255332Scy	ipfkverbose("- TCP RST sent\n");
502145554Sdarrenr	return 0;
503145554Sdarrenr}
504145554Sdarrenr
505145554Sdarrenr
506255332Scyint
507255332Scyipf_send_icmp_err(type, fin, dst)
508255332Scy	int type;
509255332Scy	fr_info_t *fin;
510255332Scy	int dst;
511145554Sdarrenr{
512255332Scy	ipfkverbose("- ICMP unreachable sent\n");
513145554Sdarrenr	return 0;
514145554Sdarrenr}
515145554Sdarrenr
516145554Sdarrenr
517255332Scyvoid
518255332Scym_freem(m)
519255332Scy	mb_t *m;
520145554Sdarrenr{
521145554Sdarrenr	return;
522145554Sdarrenr}
523145554Sdarrenr
524145554Sdarrenr
525255332Scyvoid
526255332Scym_copydata(m, off, len, cp)
527255332Scy	mb_t *m;
528255332Scy	int off, len;
529255332Scy	caddr_t cp;
530145554Sdarrenr{
531145554Sdarrenr	bcopy((char *)m + off, cp, len);
532145554Sdarrenr}
533145554Sdarrenr
534145554Sdarrenr
535255332Scyint
536255332Scyipfuiomove(buf, len, rwflag, uio)
537255332Scy	caddr_t buf;
538255332Scy	int len, rwflag;
539255332Scy	struct uio *uio;
540145554Sdarrenr{
541145554Sdarrenr	int left, ioc, num, offset;
542145554Sdarrenr	struct iovec *io;
543145554Sdarrenr	char *start;
544145554Sdarrenr
545145554Sdarrenr	if (rwflag == UIO_READ) {
546145554Sdarrenr		left = len;
547145554Sdarrenr		ioc = 0;
548145554Sdarrenr
549145554Sdarrenr		offset = uio->uio_offset;
550145554Sdarrenr
551145554Sdarrenr		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
552145554Sdarrenr			io = uio->uio_iov + ioc;
553145554Sdarrenr			num = io->iov_len;
554145554Sdarrenr			if (num > left)
555145554Sdarrenr				num = left;
556145554Sdarrenr			start = (char *)io->iov_base + offset;
557145554Sdarrenr			if (start > (char *)io->iov_base + io->iov_len) {
558145554Sdarrenr				offset -= io->iov_len;
559145554Sdarrenr				ioc++;
560145554Sdarrenr				continue;
561145554Sdarrenr			}
562145554Sdarrenr			bcopy(buf, start, num);
563145554Sdarrenr			uio->uio_resid -= num;
564145554Sdarrenr			uio->uio_offset += num;
565145554Sdarrenr			left -= num;
566145554Sdarrenr			if (left > 0)
567145554Sdarrenr				ioc++;
568145554Sdarrenr		}
569145554Sdarrenr		if (left > 0)
570145554Sdarrenr			return EFAULT;
571145554Sdarrenr	}
572145554Sdarrenr	return 0;
573145554Sdarrenr}
574145554Sdarrenr
575145554Sdarrenr
576255332Scyu_32_t
577255332Scyipf_newisn(fin)
578255332Scy	fr_info_t *fin;
579145554Sdarrenr{
580145554Sdarrenr	static int iss_seq_off = 0;
581145554Sdarrenr	u_char hash[16];
582145554Sdarrenr	u_32_t newiss;
583145554Sdarrenr	MD5_CTX ctx;
584145554Sdarrenr
585145554Sdarrenr	/*
586145554Sdarrenr	 * Compute the base value of the ISS.  It is a hash
587145554Sdarrenr	 * of (saddr, sport, daddr, dport, secret).
588145554Sdarrenr	 */
589145554Sdarrenr	MD5Init(&ctx);
590145554Sdarrenr
591145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
592145554Sdarrenr		  sizeof(fin->fin_fi.fi_src));
593145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
594145554Sdarrenr		  sizeof(fin->fin_fi.fi_dst));
595145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
596145554Sdarrenr
597145554Sdarrenr	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
598145554Sdarrenr
599145554Sdarrenr	MD5Final(hash, &ctx);
600145554Sdarrenr
601145554Sdarrenr	memcpy(&newiss, hash, sizeof(newiss));
602145554Sdarrenr
603145554Sdarrenr	/*
604145554Sdarrenr	 * Now increment our "timer", and add it in to
605145554Sdarrenr	 * the computed value.
606145554Sdarrenr	 *
607145554Sdarrenr	 * XXX Use `addin'?
608145554Sdarrenr	 * XXX TCP_ISSINCR too large to use?
609145554Sdarrenr	 */
610145554Sdarrenr	iss_seq_off += 0x00010000;
611145554Sdarrenr	newiss += iss_seq_off;
612145554Sdarrenr	return newiss;
613145554Sdarrenr}
614145554Sdarrenr
615145554Sdarrenr
616145554Sdarrenr/* ------------------------------------------------------------------------ */
617255332Scy/* Function:    ipf_nextipid                                                */
618145554Sdarrenr/* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
619145554Sdarrenr/* Parameters:  fin(I) - pointer to packet information                      */
620145554Sdarrenr/*                                                                          */
621145554Sdarrenr/* Returns the next IPv4 ID to use for this packet.                         */
622145554Sdarrenr/* ------------------------------------------------------------------------ */
623255332ScyINLINE u_short
624255332Scyipf_nextipid(fin)
625255332Scy	fr_info_t *fin;
626145554Sdarrenr{
627145554Sdarrenr	static u_short ipid = 0;
628255332Scy	ipf_main_softc_t *softc = fin->fin_main_soft;
629145554Sdarrenr	u_short id;
630145554Sdarrenr
631255332Scy	MUTEX_ENTER(&softc->ipf_rw);
632255332Scy	if (fin->fin_pktnum != 0) {
633255332Scy		/*
634255332Scy		 * The -1 is for aligned test results.
635255332Scy		 */
636255332Scy		id = (fin->fin_pktnum - 1) & 0xffff;
637255332Scy	} else {
638255332Scy	}
639255332Scy		id = ipid++;
640255332Scy	MUTEX_EXIT(&softc->ipf_rw);
641145554Sdarrenr
642145554Sdarrenr	return id;
643145554Sdarrenr}
644145554Sdarrenr
645145554Sdarrenr
646255332ScyINLINE int
647255332Scyipf_checkv4sum(fin)
648255332Scy	fr_info_t *fin;
649145554Sdarrenr{
650255332Scy
651255332Scy	if (fin->fin_flx & FI_SHORT)
652255332Scy		return 1;
653255332Scy
654255332Scy	if (ipf_checkl4sum(fin) == -1) {
655145554Sdarrenr		fin->fin_flx |= FI_BAD;
656255332Scy		return -1;
657255332Scy	}
658255332Scy	return 0;
659145554Sdarrenr}
660145554Sdarrenr
661145554Sdarrenr
662145554Sdarrenr#ifdef	USE_INET6
663255332ScyINLINE int
664255332Scyipf_checkv6sum(fin)
665255332Scy	fr_info_t *fin;
666145554Sdarrenr{
667255332Scy	if (fin->fin_flx & FI_SHORT)
668255332Scy		return 1;
669255332Scy
670255332Scy	if (ipf_checkl4sum(fin) == -1) {
671145554Sdarrenr		fin->fin_flx |= FI_BAD;
672255332Scy		return -1;
673255332Scy	}
674255332Scy	return 0;
675145554Sdarrenr}
676145554Sdarrenr#endif
677145554Sdarrenr
678145554Sdarrenr
679255332Scy#if 0
680145554Sdarrenr/*
681145554Sdarrenr * See above for description, except that all addressing is in user space.
682145554Sdarrenr */
683255332Scyint
684255332Scycopyoutptr(softc, src, dst, size)
685255332Scy	void *src, *dst;
686255332Scy	size_t size;
687145554Sdarrenr{
688145554Sdarrenr	caddr_t ca;
689145554Sdarrenr
690145554Sdarrenr	bcopy(dst, (char *)&ca, sizeof(ca));
691145554Sdarrenr	bcopy(src, ca, size);
692145554Sdarrenr	return 0;
693145554Sdarrenr}
694145554Sdarrenr
695145554Sdarrenr
696145554Sdarrenr/*
697145554Sdarrenr * See above for description, except that all addressing is in user space.
698145554Sdarrenr */
699255332Scyint
700255332Scycopyinptr(src, dst, size)
701255332Scy	void *src, *dst;
702255332Scy	size_t size;
703145554Sdarrenr{
704145554Sdarrenr	caddr_t ca;
705145554Sdarrenr
706145554Sdarrenr	bcopy(src, (char *)&ca, sizeof(ca));
707145554Sdarrenr	bcopy(ca, dst, size);
708145554Sdarrenr	return 0;
709145554Sdarrenr}
710255332Scy#endif
711145554Sdarrenr
712145554Sdarrenr
713145554Sdarrenr/*
714145554Sdarrenr * return the first IP Address associated with an interface
715145554Sdarrenr */
716255332Scyint
717255332Scyipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
718255332Scy	ipf_main_softc_t *softc;
719255332Scy	int v, atype;
720255332Scy	void *ifptr;
721255332Scy	i6addr_t *inp, *inpmask;
722145554Sdarrenr{
723145554Sdarrenr	struct ifnet *ifp = ifptr;
724145554Sdarrenr#ifdef __sgi
725145554Sdarrenr	struct in_ifaddr *ifa;
726145554Sdarrenr#else
727145554Sdarrenr	struct ifaddr *ifa;
728145554Sdarrenr#endif
729145554Sdarrenr
730145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
731145554Sdarrenr	ifa = ifp->if_addrlist.tqh_first;
732145554Sdarrenr#else
733145554Sdarrenr# ifdef __sgi
734145554Sdarrenr	ifa = (struct in_ifaddr *)ifp->in_ifaddr;
735145554Sdarrenr# else
736145554Sdarrenr	ifa = ifp->if_addrlist;
737145554Sdarrenr# endif
738145554Sdarrenr#endif
739145554Sdarrenr	if (ifa != NULL) {
740255332Scy		if (v == 4) {
741255332Scy			struct sockaddr_in *sin, mask;
742145554Sdarrenr
743255332Scy			mask.sin_addr.s_addr = 0xffffffff;
744145554Sdarrenr
745145554Sdarrenr#ifdef __sgi
746255332Scy			sin = (struct sockaddr_in *)&ifa->ia_addr;
747145554Sdarrenr#else
748255332Scy			sin = (struct sockaddr_in *)&ifa->ifa_addr;
749145554Sdarrenr#endif
750145554Sdarrenr
751255332Scy			return ipf_ifpfillv4addr(atype, sin, &mask,
752255332Scy						 &inp->in4, &inpmask->in4);
753255332Scy		}
754255332Scy#ifdef USE_INET6
755255332Scy		if (v == 6) {
756255332Scy			struct sockaddr_in6 *sin6, mask;
757255332Scy
758255332Scy			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
759255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
760255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
761255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
762255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
763255332Scy			return ipf_ifpfillv6addr(atype, sin6, &mask,
764255332Scy						 inp, inpmask);
765255332Scy		}
766255332Scy#endif
767145554Sdarrenr	}
768145554Sdarrenr	return 0;
769145554Sdarrenr}
770170268Sdarrenr
771170268Sdarrenr
772255332Scy/*
773255332Scy * This function is not meant to be random, rather just produce a
774255332Scy * sequence of numbers that isn't linear to show "randomness".
775255332Scy */
776255332Scyu_32_t
777255332Scyipf_random()
778170268Sdarrenr{
779255332Scy	static unsigned int last = 0xa5a5a5a5;
780255332Scy	static int calls = 0;
781255332Scy	int number;
782255332Scy
783255332Scy	calls++;
784255332Scy
785255332Scy	/*
786255332Scy	 * These are deliberately chosen to ensure that there is some
787255332Scy	 * attempt to test whether the output covers the range in test n18.
788255332Scy	 */
789255332Scy	switch (calls)
790255332Scy	{
791255332Scy	case 1 :
792255332Scy		number = 0;
793255332Scy		break;
794255332Scy	case 2 :
795255332Scy		number = 4;
796255332Scy		break;
797255332Scy	case 3 :
798255332Scy		number = 3999;
799255332Scy		break;
800255332Scy	case 4 :
801255332Scy		number = 4000;
802255332Scy		break;
803255332Scy	case 5 :
804255332Scy		number = 48999;
805255332Scy		break;
806255332Scy	case 6 :
807255332Scy		number = 49000;
808255332Scy		break;
809255332Scy	default :
810255332Scy		number = last;
811255332Scy		last *= calls;
812255332Scy		last++;
813255332Scy		number ^= last;
814255332Scy		break;
815255332Scy	}
816255332Scy	return number;
817255332Scy}
818255332Scy
819255332Scy
820255332Scyint
821255332Scyipf_verifysrc(fin)
822255332Scy	fr_info_t *fin;
823255332Scy{
824255332Scy	return 1;
825255332Scy}
826255332Scy
827255332Scy
828255332Scyint
829255332Scyipf_inject(fin, m)
830255332Scy	fr_info_t *fin;
831255332Scy	mb_t *m;
832255332Scy{
833255332Scy	FREE_MB_T(m);
834255332Scy
835170268Sdarrenr	return 0;
836170268Sdarrenr}
837180778Sdarrenr
838180778Sdarrenr
839255332Scyu_int
840255332Scyipf_pcksum(fin, hlen, sum)
841255332Scy	fr_info_t *fin;
842255332Scy	int hlen;
843255332Scy	u_int sum;
844180778Sdarrenr{
845255332Scy	u_short *sp;
846255332Scy	u_int sum2;
847255332Scy	int slen;
848180778Sdarrenr
849255332Scy	slen = fin->fin_plen - hlen;
850255332Scy	sp = (u_short *)((u_char *)fin->fin_ip + hlen);
851255332Scy
852255332Scy	for (; slen > 1; slen -= 2)
853255332Scy		sum += *sp++;
854255332Scy	if (slen)
855255332Scy		sum += ntohs(*(u_char *)sp << 8);
856255332Scy	while (sum > 0xffff)
857255332Scy		sum = (sum & 0xffff) + (sum >> 16);
858255332Scy	sum2 = (u_short)(~sum & 0xffff);
859255332Scy
860255332Scy	return sum2;
861255332Scy}
862255332Scy
863255332Scy
864255332Scyvoid *
865255332Scyipf_pullup(m, fin, plen)
866255332Scy	mb_t *m;
867255332Scy	fr_info_t *fin;
868255332Scy	int plen;
869255332Scy{
870255332Scy	if (M_LEN(m) >= plen)
871255332Scy		return fin->fin_ip;
872255332Scy
873180778Sdarrenr	/*
874255332Scy	 * Fake ipf_pullup failing
875180778Sdarrenr	 */
876255332Scy	fin->fin_reason = FRB_PULLUP;
877255332Scy	*fin->fin_mp = NULL;
878255332Scy	fin->fin_m = NULL;
879255332Scy	fin->fin_ip = NULL;
880255332Scy	return NULL;
881180778Sdarrenr}
882