1145554Sdarrenr/*	$FreeBSD: stable/10/contrib/ipfilter/ip_fil.c 341804 2018-12-11 01:49:06Z cy $	*/
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	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
483161357Sguidodone:
484255332Scy	fin->fin_ifp = sifp;
485255332Scy	fin->fin_out = sout;
486161357Sguido	return error;
487145554Sdarrenr}
488145554Sdarrenr
489145554Sdarrenr
490255332Scyint
491255332Scyipf_send_reset(fin)
492255332Scy	fr_info_t *fin;
493145554Sdarrenr{
494255332Scy	ipfkverbose("- TCP RST sent\n");
495145554Sdarrenr	return 0;
496145554Sdarrenr}
497145554Sdarrenr
498145554Sdarrenr
499255332Scyint
500255332Scyipf_send_icmp_err(type, fin, dst)
501255332Scy	int type;
502255332Scy	fr_info_t *fin;
503255332Scy	int dst;
504145554Sdarrenr{
505255332Scy	ipfkverbose("- ICMP unreachable sent\n");
506145554Sdarrenr	return 0;
507145554Sdarrenr}
508145554Sdarrenr
509145554Sdarrenr
510255332Scyvoid
511255332Scym_freem(m)
512255332Scy	mb_t *m;
513145554Sdarrenr{
514145554Sdarrenr	return;
515145554Sdarrenr}
516145554Sdarrenr
517145554Sdarrenr
518255332Scyvoid
519255332Scym_copydata(m, off, len, cp)
520255332Scy	mb_t *m;
521255332Scy	int off, len;
522255332Scy	caddr_t cp;
523145554Sdarrenr{
524145554Sdarrenr	bcopy((char *)m + off, cp, len);
525145554Sdarrenr}
526145554Sdarrenr
527145554Sdarrenr
528255332Scyint
529255332Scyipfuiomove(buf, len, rwflag, uio)
530255332Scy	caddr_t buf;
531255332Scy	int len, rwflag;
532255332Scy	struct uio *uio;
533145554Sdarrenr{
534145554Sdarrenr	int left, ioc, num, offset;
535145554Sdarrenr	struct iovec *io;
536145554Sdarrenr	char *start;
537145554Sdarrenr
538145554Sdarrenr	if (rwflag == UIO_READ) {
539145554Sdarrenr		left = len;
540145554Sdarrenr		ioc = 0;
541145554Sdarrenr
542145554Sdarrenr		offset = uio->uio_offset;
543145554Sdarrenr
544145554Sdarrenr		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
545145554Sdarrenr			io = uio->uio_iov + ioc;
546145554Sdarrenr			num = io->iov_len;
547145554Sdarrenr			if (num > left)
548145554Sdarrenr				num = left;
549145554Sdarrenr			start = (char *)io->iov_base + offset;
550145554Sdarrenr			if (start > (char *)io->iov_base + io->iov_len) {
551145554Sdarrenr				offset -= io->iov_len;
552145554Sdarrenr				ioc++;
553145554Sdarrenr				continue;
554145554Sdarrenr			}
555145554Sdarrenr			bcopy(buf, start, num);
556145554Sdarrenr			uio->uio_resid -= num;
557145554Sdarrenr			uio->uio_offset += num;
558145554Sdarrenr			left -= num;
559145554Sdarrenr			if (left > 0)
560145554Sdarrenr				ioc++;
561145554Sdarrenr		}
562145554Sdarrenr		if (left > 0)
563145554Sdarrenr			return EFAULT;
564145554Sdarrenr	}
565145554Sdarrenr	return 0;
566145554Sdarrenr}
567145554Sdarrenr
568145554Sdarrenr
569255332Scyu_32_t
570255332Scyipf_newisn(fin)
571255332Scy	fr_info_t *fin;
572145554Sdarrenr{
573145554Sdarrenr	static int iss_seq_off = 0;
574145554Sdarrenr	u_char hash[16];
575145554Sdarrenr	u_32_t newiss;
576145554Sdarrenr	MD5_CTX ctx;
577145554Sdarrenr
578145554Sdarrenr	/*
579145554Sdarrenr	 * Compute the base value of the ISS.  It is a hash
580145554Sdarrenr	 * of (saddr, sport, daddr, dport, secret).
581145554Sdarrenr	 */
582145554Sdarrenr	MD5Init(&ctx);
583145554Sdarrenr
584145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
585145554Sdarrenr		  sizeof(fin->fin_fi.fi_src));
586145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
587145554Sdarrenr		  sizeof(fin->fin_fi.fi_dst));
588145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
589145554Sdarrenr
590145554Sdarrenr	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
591145554Sdarrenr
592145554Sdarrenr	MD5Final(hash, &ctx);
593145554Sdarrenr
594145554Sdarrenr	memcpy(&newiss, hash, sizeof(newiss));
595145554Sdarrenr
596145554Sdarrenr	/*
597145554Sdarrenr	 * Now increment our "timer", and add it in to
598145554Sdarrenr	 * the computed value.
599145554Sdarrenr	 *
600145554Sdarrenr	 * XXX Use `addin'?
601145554Sdarrenr	 * XXX TCP_ISSINCR too large to use?
602145554Sdarrenr	 */
603145554Sdarrenr	iss_seq_off += 0x00010000;
604145554Sdarrenr	newiss += iss_seq_off;
605145554Sdarrenr	return newiss;
606145554Sdarrenr}
607145554Sdarrenr
608145554Sdarrenr
609145554Sdarrenr/* ------------------------------------------------------------------------ */
610255332Scy/* Function:    ipf_nextipid                                                */
611145554Sdarrenr/* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
612145554Sdarrenr/* Parameters:  fin(I) - pointer to packet information                      */
613145554Sdarrenr/*                                                                          */
614145554Sdarrenr/* Returns the next IPv4 ID to use for this packet.                         */
615145554Sdarrenr/* ------------------------------------------------------------------------ */
616255332ScyINLINE u_short
617255332Scyipf_nextipid(fin)
618255332Scy	fr_info_t *fin;
619145554Sdarrenr{
620145554Sdarrenr	static u_short ipid = 0;
621255332Scy	ipf_main_softc_t *softc = fin->fin_main_soft;
622145554Sdarrenr	u_short id;
623145554Sdarrenr
624255332Scy	MUTEX_ENTER(&softc->ipf_rw);
625255332Scy	if (fin->fin_pktnum != 0) {
626255332Scy		/*
627255332Scy		 * The -1 is for aligned test results.
628255332Scy		 */
629255332Scy		id = (fin->fin_pktnum - 1) & 0xffff;
630255332Scy	} else {
631255332Scy	}
632255332Scy		id = ipid++;
633255332Scy	MUTEX_EXIT(&softc->ipf_rw);
634145554Sdarrenr
635145554Sdarrenr	return id;
636145554Sdarrenr}
637145554Sdarrenr
638145554Sdarrenr
639255332ScyINLINE int
640255332Scyipf_checkv4sum(fin)
641255332Scy	fr_info_t *fin;
642145554Sdarrenr{
643255332Scy
644255332Scy	if (fin->fin_flx & FI_SHORT)
645255332Scy		return 1;
646255332Scy
647255332Scy	if (ipf_checkl4sum(fin) == -1) {
648145554Sdarrenr		fin->fin_flx |= FI_BAD;
649255332Scy		return -1;
650255332Scy	}
651255332Scy	return 0;
652145554Sdarrenr}
653145554Sdarrenr
654145554Sdarrenr
655145554Sdarrenr#ifdef	USE_INET6
656255332ScyINLINE int
657255332Scyipf_checkv6sum(fin)
658255332Scy	fr_info_t *fin;
659145554Sdarrenr{
660255332Scy	if (fin->fin_flx & FI_SHORT)
661255332Scy		return 1;
662255332Scy
663255332Scy	if (ipf_checkl4sum(fin) == -1) {
664145554Sdarrenr		fin->fin_flx |= FI_BAD;
665255332Scy		return -1;
666255332Scy	}
667255332Scy	return 0;
668145554Sdarrenr}
669145554Sdarrenr#endif
670145554Sdarrenr
671145554Sdarrenr
672255332Scy#if 0
673145554Sdarrenr/*
674145554Sdarrenr * See above for description, except that all addressing is in user space.
675145554Sdarrenr */
676255332Scyint
677255332Scycopyoutptr(softc, src, dst, size)
678255332Scy	void *src, *dst;
679255332Scy	size_t size;
680145554Sdarrenr{
681145554Sdarrenr	caddr_t ca;
682145554Sdarrenr
683145554Sdarrenr	bcopy(dst, (char *)&ca, sizeof(ca));
684145554Sdarrenr	bcopy(src, ca, size);
685145554Sdarrenr	return 0;
686145554Sdarrenr}
687145554Sdarrenr
688145554Sdarrenr
689145554Sdarrenr/*
690145554Sdarrenr * See above for description, except that all addressing is in user space.
691145554Sdarrenr */
692255332Scyint
693255332Scycopyinptr(src, dst, size)
694255332Scy	void *src, *dst;
695255332Scy	size_t size;
696145554Sdarrenr{
697145554Sdarrenr	caddr_t ca;
698145554Sdarrenr
699145554Sdarrenr	bcopy(src, (char *)&ca, sizeof(ca));
700145554Sdarrenr	bcopy(ca, dst, size);
701145554Sdarrenr	return 0;
702145554Sdarrenr}
703255332Scy#endif
704145554Sdarrenr
705145554Sdarrenr
706145554Sdarrenr/*
707145554Sdarrenr * return the first IP Address associated with an interface
708145554Sdarrenr */
709255332Scyint
710255332Scyipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
711255332Scy	ipf_main_softc_t *softc;
712255332Scy	int v, atype;
713255332Scy	void *ifptr;
714255332Scy	i6addr_t *inp, *inpmask;
715145554Sdarrenr{
716145554Sdarrenr	struct ifnet *ifp = ifptr;
717145554Sdarrenr#ifdef __sgi
718145554Sdarrenr	struct in_ifaddr *ifa;
719145554Sdarrenr#else
720145554Sdarrenr	struct ifaddr *ifa;
721145554Sdarrenr#endif
722145554Sdarrenr
723145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
724145554Sdarrenr	ifa = ifp->if_addrlist.tqh_first;
725145554Sdarrenr#else
726145554Sdarrenr# ifdef __sgi
727145554Sdarrenr	ifa = (struct in_ifaddr *)ifp->in_ifaddr;
728145554Sdarrenr# else
729145554Sdarrenr	ifa = ifp->if_addrlist;
730145554Sdarrenr# endif
731145554Sdarrenr#endif
732145554Sdarrenr	if (ifa != NULL) {
733255332Scy		if (v == 4) {
734255332Scy			struct sockaddr_in *sin, mask;
735145554Sdarrenr
736255332Scy			mask.sin_addr.s_addr = 0xffffffff;
737145554Sdarrenr
738145554Sdarrenr#ifdef __sgi
739255332Scy			sin = (struct sockaddr_in *)&ifa->ia_addr;
740145554Sdarrenr#else
741255332Scy			sin = (struct sockaddr_in *)&ifa->ifa_addr;
742145554Sdarrenr#endif
743145554Sdarrenr
744255332Scy			return ipf_ifpfillv4addr(atype, sin, &mask,
745255332Scy						 &inp->in4, &inpmask->in4);
746255332Scy		}
747255332Scy#ifdef USE_INET6
748255332Scy		if (v == 6) {
749255332Scy			struct sockaddr_in6 *sin6, mask;
750255332Scy
751255332Scy			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
752255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
753255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
754255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
755255332Scy			((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
756255332Scy			return ipf_ifpfillv6addr(atype, sin6, &mask,
757255332Scy						 inp, inpmask);
758255332Scy		}
759255332Scy#endif
760145554Sdarrenr	}
761145554Sdarrenr	return 0;
762145554Sdarrenr}
763170268Sdarrenr
764170268Sdarrenr
765255332Scy/*
766255332Scy * This function is not meant to be random, rather just produce a
767255332Scy * sequence of numbers that isn't linear to show "randomness".
768255332Scy */
769255332Scyu_32_t
770255332Scyipf_random()
771170268Sdarrenr{
772255332Scy	static unsigned int last = 0xa5a5a5a5;
773255332Scy	static int calls = 0;
774255332Scy	int number;
775255332Scy
776255332Scy	calls++;
777255332Scy
778255332Scy	/*
779255332Scy	 * These are deliberately chosen to ensure that there is some
780255332Scy	 * attempt to test whether the output covers the range in test n18.
781255332Scy	 */
782255332Scy	switch (calls)
783255332Scy	{
784255332Scy	case 1 :
785255332Scy		number = 0;
786255332Scy		break;
787255332Scy	case 2 :
788255332Scy		number = 4;
789255332Scy		break;
790255332Scy	case 3 :
791255332Scy		number = 3999;
792255332Scy		break;
793255332Scy	case 4 :
794255332Scy		number = 4000;
795255332Scy		break;
796255332Scy	case 5 :
797255332Scy		number = 48999;
798255332Scy		break;
799255332Scy	case 6 :
800255332Scy		number = 49000;
801255332Scy		break;
802255332Scy	default :
803255332Scy		number = last;
804255332Scy		last *= calls;
805255332Scy		last++;
806255332Scy		number ^= last;
807255332Scy		break;
808255332Scy	}
809255332Scy	return number;
810255332Scy}
811255332Scy
812255332Scy
813255332Scyint
814255332Scyipf_verifysrc(fin)
815255332Scy	fr_info_t *fin;
816255332Scy{
817255332Scy	return 1;
818255332Scy}
819255332Scy
820255332Scy
821255332Scyint
822255332Scyipf_inject(fin, m)
823255332Scy	fr_info_t *fin;
824255332Scy	mb_t *m;
825255332Scy{
826255332Scy	FREE_MB_T(m);
827255332Scy
828170268Sdarrenr	return 0;
829170268Sdarrenr}
830180778Sdarrenr
831180778Sdarrenr
832255332Scyu_int
833255332Scyipf_pcksum(fin, hlen, sum)
834255332Scy	fr_info_t *fin;
835255332Scy	int hlen;
836255332Scy	u_int sum;
837180778Sdarrenr{
838255332Scy	u_short *sp;
839255332Scy	u_int sum2;
840255332Scy	int slen;
841180778Sdarrenr
842255332Scy	slen = fin->fin_plen - hlen;
843255332Scy	sp = (u_short *)((u_char *)fin->fin_ip + hlen);
844255332Scy
845255332Scy	for (; slen > 1; slen -= 2)
846255332Scy		sum += *sp++;
847255332Scy	if (slen)
848255332Scy		sum += ntohs(*(u_char *)sp << 8);
849255332Scy	while (sum > 0xffff)
850255332Scy		sum = (sum & 0xffff) + (sum >> 16);
851255332Scy	sum2 = (u_short)(~sum & 0xffff);
852255332Scy
853255332Scy	return sum2;
854255332Scy}
855255332Scy
856255332Scy
857255332Scyvoid *
858255332Scyipf_pullup(m, fin, plen)
859255332Scy	mb_t *m;
860255332Scy	fr_info_t *fin;
861255332Scy	int plen;
862255332Scy{
863255332Scy	if (M_LEN(m) >= plen)
864255332Scy		return fin->fin_ip;
865255332Scy
866180778Sdarrenr	/*
867255332Scy	 * Fake ipf_pullup failing
868180778Sdarrenr	 */
869255332Scy	fin->fin_reason = FRB_PULLUP;
870255332Scy	*fin->fin_mp = NULL;
871255332Scy	fin->fin_m = NULL;
872255332Scy	fin->fin_ip = NULL;
873255332Scy	return NULL;
874180778Sdarrenr}
875