1145554Sdarrenr/*	$FreeBSD$	*/
2145554Sdarrenr
3145554Sdarrenr/*
4145554Sdarrenr * Copyright (C) 1993-2001 by Darren Reed.
5145554Sdarrenr *
6145554Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145554Sdarrenr */
8145554Sdarrenr#if !defined(lint)
9145554Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
10172776Sdarrenrstatic const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.18 2007/09/09 11:32:05 darrenr Exp $";
11145554Sdarrenr#endif
12145554Sdarrenr
13145554Sdarrenr#ifndef	SOLARIS
14145554Sdarrenr#define	SOLARIS	(defined(sun) && (defined(__svr4__) || defined(__SVR4)))
15145554Sdarrenr#endif
16145554Sdarrenr
17145554Sdarrenr#include <sys/param.h>
18145554Sdarrenr#if defined(__FreeBSD__) && !defined(__FreeBSD_version)
19145554Sdarrenr# if defined(IPFILTER_LKM)
20145554Sdarrenr#  ifndef __FreeBSD_cc_version
21145554Sdarrenr#   include <osreldate.h>
22145554Sdarrenr#  else
23145554Sdarrenr#   if __FreeBSD_cc_version < 430000
24145554Sdarrenr#    include <osreldate.h>
25145554Sdarrenr#   endif
26145554Sdarrenr#  endif
27145554Sdarrenr# endif
28145554Sdarrenr#endif
29145554Sdarrenr#include <sys/errno.h>
30145554Sdarrenr#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
31145554Sdarrenr# include <sys/kern_svcs.h>
32145554Sdarrenr#endif
33145554Sdarrenr#include <sys/types.h>
34145554Sdarrenr#define _KERNEL
35145554Sdarrenr#define KERNEL
36145554Sdarrenr#ifdef __OpenBSD__
37145554Sdarrenrstruct file;
38145554Sdarrenr#endif
39145554Sdarrenr#include <sys/uio.h>
40145554Sdarrenr#undef _KERNEL
41145554Sdarrenr#undef KERNEL
42145554Sdarrenr#include <sys/file.h>
43145554Sdarrenr#include <sys/ioctl.h>
44145554Sdarrenr#ifdef __sgi
45145554Sdarrenr# include <sys/ptimers.h>
46145554Sdarrenr#endif
47145554Sdarrenr#include <sys/time.h>
48145554Sdarrenr#if !SOLARIS
49145554Sdarrenr# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
50145554Sdarrenr#  include <sys/dirent.h>
51145554Sdarrenr# else
52145554Sdarrenr#  include <sys/dir.h>
53145554Sdarrenr# endif
54145554Sdarrenr#else
55145554Sdarrenr# include <sys/filio.h>
56145554Sdarrenr#endif
57145554Sdarrenr#ifndef linux
58145554Sdarrenr# include <sys/protosw.h>
59145554Sdarrenr#endif
60145554Sdarrenr#include <sys/socket.h>
61145554Sdarrenr
62145554Sdarrenr#include <stdio.h>
63145554Sdarrenr#include <string.h>
64145554Sdarrenr#include <stdlib.h>
65145554Sdarrenr#include <ctype.h>
66145554Sdarrenr#include <fcntl.h>
67145554Sdarrenr
68145554Sdarrenr#ifdef __hpux
69145554Sdarrenr# define _NET_ROUTE_INCLUDED
70145554Sdarrenr#endif
71145554Sdarrenr#include <net/if.h>
72145554Sdarrenr#ifdef sun
73145554Sdarrenr# include <net/af.h>
74145554Sdarrenr#endif
75145554Sdarrenr#if __FreeBSD_version >= 300000
76145554Sdarrenr# include <net/if_var.h>
77145554Sdarrenr#endif
78145554Sdarrenr#ifdef __sgi
79145554Sdarrenr#include <sys/debug.h>
80145554Sdarrenr# ifdef IFF_DRVRLOCK /* IRIX6 */
81145554Sdarrenr#include <sys/hashing.h>
82145554Sdarrenr# endif
83145554Sdarrenr#endif
84172776Sdarrenr#if defined(__FreeBSD__) || defined(SOLARIS2)
85145554Sdarrenr# include "radix_ipf.h"
86145554Sdarrenr#endif
87170268Sdarrenr#ifndef __osf__
88170268Sdarrenr# include <net/route.h>
89170268Sdarrenr#endif
90145554Sdarrenr#include <netinet/in.h>
91145554Sdarrenr#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
92145554Sdarrenr    !defined(__hpux) && !defined(linux)
93145554Sdarrenr# include <netinet/in_var.h>
94145554Sdarrenr#endif
95145554Sdarrenr#include <netinet/in_systm.h>
96145554Sdarrenr#include <netinet/ip.h>
97145554Sdarrenr#if !defined(linux)
98145554Sdarrenr# include <netinet/ip_var.h>
99145554Sdarrenr#endif
100145554Sdarrenr#include <netinet/tcp.h>
101145554Sdarrenr#if defined(__osf__)
102145554Sdarrenr# include <netinet/tcp_timer.h>
103145554Sdarrenr#endif
104145554Sdarrenr#if defined(__osf__) || defined(__hpux) || defined(__sgi)
105145554Sdarrenr# include "radix_ipf_local.h"
106145554Sdarrenr# define _RADIX_H_
107145554Sdarrenr#endif
108145554Sdarrenr#include <netinet/udp.h>
109145554Sdarrenr#include <netinet/tcpip.h>
110145554Sdarrenr#include <netinet/ip_icmp.h>
111145554Sdarrenr#include <unistd.h>
112145554Sdarrenr#include <syslog.h>
113170268Sdarrenr#include <arpa/inet.h>
114145554Sdarrenr#ifdef __hpux
115145554Sdarrenr# undef _NET_ROUTE_INCLUDED
116145554Sdarrenr#endif
117145554Sdarrenr#include "netinet/ip_compat.h"
118145554Sdarrenr#include "netinet/ip_fil.h"
119145554Sdarrenr#include "netinet/ip_nat.h"
120145554Sdarrenr#include "netinet/ip_frag.h"
121145554Sdarrenr#include "netinet/ip_state.h"
122145554Sdarrenr#include "netinet/ip_proxy.h"
123145554Sdarrenr#include "netinet/ip_auth.h"
124145554Sdarrenr#ifdef	IPFILTER_SYNC
125145554Sdarrenr#include "netinet/ip_sync.h"
126145554Sdarrenr#endif
127145554Sdarrenr#ifdef	IPFILTER_SCAN
128145554Sdarrenr#include "netinet/ip_scan.h"
129145554Sdarrenr#endif
130145554Sdarrenr#include "netinet/ip_pool.h"
131145554Sdarrenr#ifdef IPFILTER_COMPILED
132145554Sdarrenr# include "netinet/ip_rules.h"
133145554Sdarrenr#endif
134145554Sdarrenr#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
135145554Sdarrenr# include <sys/malloc.h>
136145554Sdarrenr#endif
137145554Sdarrenr#ifdef __hpux
138145554Sdarrenrstruct rtentry;
139145554Sdarrenr#endif
140145554Sdarrenr#include "md5.h"
141145554Sdarrenr
142145554Sdarrenr
143161357Sguido#if !defined(__osf__) && !defined(__linux__)
144145554Sdarrenrextern	struct	protosw	inetsw[];
145145554Sdarrenr#endif
146145554Sdarrenr
147145554Sdarrenr#include "ipt.h"
148145554Sdarrenrstatic	struct	ifnet **ifneta = NULL;
149145554Sdarrenrstatic	int	nifs = 0;
150145554Sdarrenr
151145554Sdarrenrstatic	void	fr_setifpaddr __P((struct ifnet *, char *));
152145554Sdarrenrvoid	init_ifp __P((void));
153145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
154145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
155145554Sdarrenr			       struct sockaddr *));
156145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
157145554Sdarrenr				  struct sockaddr *));
158145554Sdarrenr#else
159145554Sdarrenr# if TRU64 >= 1885
160145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
161145554Sdarrenr			       struct sockaddr *, struct rtentry *, char *));
162145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
163145554Sdarrenr				  struct sockaddr *, struct rtentry *, char *));
164145554Sdarrenr# else
165145554Sdarrenrstatic int 	no_output __P((struct ifnet *, struct mbuf *,
166145554Sdarrenr			       struct sockaddr *, struct rtentry *));
167145554Sdarrenrstatic int	write_output __P((struct ifnet *, struct mbuf *,
168145554Sdarrenr				  struct sockaddr *, struct rtentry *));
169145554Sdarrenr# endif
170145554Sdarrenr#endif
171145554Sdarrenr
172145554Sdarrenr
173170268Sdarrenrint ipfattach()
174145554Sdarrenr{
175145554Sdarrenr	fr_running = 1;
176145554Sdarrenr	return 0;
177145554Sdarrenr}
178145554Sdarrenr
179145554Sdarrenr
180170268Sdarrenrint ipfdetach()
181145554Sdarrenr{
182145554Sdarrenr	fr_running = -1;
183145554Sdarrenr	return 0;
184145554Sdarrenr}
185145554Sdarrenr
186145554Sdarrenr
187145554Sdarrenr/*
188145554Sdarrenr * Filter ioctl interface.
189145554Sdarrenr */
190145554Sdarrenrint iplioctl(dev, cmd, data, mode)
191145554Sdarrenrint dev;
192145554Sdarrenrioctlcmd_t cmd;
193145554Sdarrenrcaddr_t data;
194145554Sdarrenrint mode;
195145554Sdarrenr{
196170268Sdarrenr	int error = 0, unit = 0, uid;
197170268Sdarrenr	SPL_INT(s);
198145554Sdarrenr
199170268Sdarrenr	uid = getuid();
200145554Sdarrenr	unit = dev;
201145554Sdarrenr
202145554Sdarrenr	SPL_NET(s);
203145554Sdarrenr
204170268Sdarrenr	error = fr_ioctlswitch(unit, data, cmd, mode, uid, NULL);
205170268Sdarrenr	if (error != -1) {
206145554Sdarrenr		SPL_X(s);
207145554Sdarrenr		return error;
208145554Sdarrenr	}
209145554Sdarrenr
210145554Sdarrenr	SPL_X(s);
211145554Sdarrenr	return error;
212145554Sdarrenr}
213145554Sdarrenr
214145554Sdarrenr
215145554Sdarrenrvoid fr_forgetifp(ifp)
216145554Sdarrenrvoid *ifp;
217145554Sdarrenr{
218145554Sdarrenr	register frentry_t *f;
219145554Sdarrenr
220145554Sdarrenr	WRITE_ENTER(&ipf_mutex);
221145554Sdarrenr	for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
222145554Sdarrenr		if (f->fr_ifa == ifp)
223145554Sdarrenr			f->fr_ifa = (void *)-1;
224145554Sdarrenr	for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
225145554Sdarrenr		if (f->fr_ifa == ifp)
226145554Sdarrenr			f->fr_ifa = (void *)-1;
227145554Sdarrenr	for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
228145554Sdarrenr		if (f->fr_ifa == ifp)
229145554Sdarrenr			f->fr_ifa = (void *)-1;
230145554Sdarrenr	for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
231145554Sdarrenr		if (f->fr_ifa == ifp)
232145554Sdarrenr			f->fr_ifa = (void *)-1;
233145554Sdarrenr#ifdef	USE_INET6
234145554Sdarrenr	for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
235145554Sdarrenr		if (f->fr_ifa == ifp)
236145554Sdarrenr			f->fr_ifa = (void *)-1;
237145554Sdarrenr	for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
238145554Sdarrenr		if (f->fr_ifa == ifp)
239145554Sdarrenr			f->fr_ifa = (void *)-1;
240145554Sdarrenr	for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
241145554Sdarrenr		if (f->fr_ifa == ifp)
242145554Sdarrenr			f->fr_ifa = (void *)-1;
243145554Sdarrenr	for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
244145554Sdarrenr		if (f->fr_ifa == ifp)
245145554Sdarrenr			f->fr_ifa = (void *)-1;
246145554Sdarrenr#endif
247145554Sdarrenr	RWLOCK_EXIT(&ipf_mutex);
248145554Sdarrenr	fr_natsync(ifp);
249145554Sdarrenr}
250145554Sdarrenr
251145554Sdarrenr
252145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
253145554Sdarrenrstatic int no_output(ifp, m, s)
254145554Sdarrenr#else
255145554Sdarrenr# if TRU64 >= 1885
256145554Sdarrenrstatic int no_output (ifp, m, s, rt, cp)
257145554Sdarrenrchar *cp;
258145554Sdarrenr# else
259145554Sdarrenrstatic int no_output(ifp, m, s, rt)
260145554Sdarrenr# endif
261145554Sdarrenrstruct rtentry *rt;
262145554Sdarrenr#endif
263145554Sdarrenrstruct ifnet *ifp;
264145554Sdarrenrstruct mbuf *m;
265145554Sdarrenrstruct sockaddr *s;
266145554Sdarrenr{
267145554Sdarrenr	return 0;
268145554Sdarrenr}
269145554Sdarrenr
270145554Sdarrenr
271145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
272145554Sdarrenrstatic int write_output(ifp, m, s)
273145554Sdarrenr#else
274145554Sdarrenr# if TRU64 >= 1885
275145554Sdarrenrstatic int write_output (ifp, m, s, rt, cp)
276145554Sdarrenrchar *cp;
277145554Sdarrenr# else
278145554Sdarrenrstatic int write_output(ifp, m, s, rt)
279145554Sdarrenr# endif
280145554Sdarrenrstruct rtentry *rt;
281145554Sdarrenr#endif
282145554Sdarrenrstruct ifnet *ifp;
283145554Sdarrenrstruct mbuf *m;
284145554Sdarrenrstruct sockaddr *s;
285145554Sdarrenr{
286145554Sdarrenr	char fname[32];
287145554Sdarrenr	mb_t *mb;
288145554Sdarrenr	ip_t *ip;
289145554Sdarrenr	int fd;
290145554Sdarrenr
291145554Sdarrenr	mb = (mb_t *)m;
292145554Sdarrenr	ip = MTOD(mb, ip_t *);
293145554Sdarrenr
294145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
295145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
296145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
297145554Sdarrenr	sprintf(fname, "/tmp/%s", ifp->if_xname);
298145554Sdarrenr#else
299145554Sdarrenr	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
300145554Sdarrenr#endif
301145554Sdarrenr	fd = open(fname, O_WRONLY|O_APPEND);
302145554Sdarrenr	if (fd == -1) {
303145554Sdarrenr		perror("open");
304145554Sdarrenr		return -1;
305145554Sdarrenr	}
306145554Sdarrenr	write(fd, (char *)ip, ntohs(ip->ip_len));
307145554Sdarrenr	close(fd);
308145554Sdarrenr	return 0;
309145554Sdarrenr}
310145554Sdarrenr
311145554Sdarrenr
312145554Sdarrenrstatic void fr_setifpaddr(ifp, addr)
313145554Sdarrenrstruct ifnet *ifp;
314145554Sdarrenrchar *addr;
315145554Sdarrenr{
316145554Sdarrenr#ifdef __sgi
317145554Sdarrenr	struct in_ifaddr *ifa;
318145554Sdarrenr#else
319145554Sdarrenr	struct ifaddr *ifa;
320145554Sdarrenr#endif
321145554Sdarrenr
322145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
323145554Sdarrenr	if (ifp->if_addrlist.tqh_first != NULL)
324145554Sdarrenr#else
325145554Sdarrenr# ifdef __sgi
326145554Sdarrenr	if (ifp->in_ifaddr != NULL)
327145554Sdarrenr# else
328145554Sdarrenr	if (ifp->if_addrlist != NULL)
329145554Sdarrenr# endif
330145554Sdarrenr#endif
331145554Sdarrenr		return;
332145554Sdarrenr
333145554Sdarrenr	ifa = (struct ifaddr *)malloc(sizeof(*ifa));
334145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
335145554Sdarrenr	ifp->if_addrlist.tqh_first = ifa;
336145554Sdarrenr#else
337145554Sdarrenr# ifdef __sgi
338145554Sdarrenr	ifp->in_ifaddr = ifa;
339145554Sdarrenr# else
340145554Sdarrenr	ifp->if_addrlist = ifa;
341145554Sdarrenr# endif
342145554Sdarrenr#endif
343145554Sdarrenr
344145554Sdarrenr	if (ifa != NULL) {
345145554Sdarrenr		struct sockaddr_in *sin;
346145554Sdarrenr
347145554Sdarrenr#ifdef __sgi
348145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ia_addr;
349145554Sdarrenr#else
350145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ifa_addr;
351145554Sdarrenr#endif
352145554Sdarrenr		sin->sin_addr.s_addr = inet_addr(addr);
353145554Sdarrenr		if (sin->sin_addr.s_addr == 0)
354145554Sdarrenr			abort();
355145554Sdarrenr	}
356145554Sdarrenr}
357145554Sdarrenr
358145554Sdarrenrstruct ifnet *get_unit(name, v)
359145554Sdarrenrchar *name;
360145554Sdarrenrint v;
361145554Sdarrenr{
362145554Sdarrenr	struct ifnet *ifp, **ifpp, **old_ifneta;
363145554Sdarrenr	char *addr;
364145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
365145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
366145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
367145554Sdarrenr
368145554Sdarrenr	if (name == NULL)
369145554Sdarrenr		name = "anon0";
370145554Sdarrenr
371145554Sdarrenr	addr = strchr(name, '=');
372145554Sdarrenr	if (addr != NULL)
373145554Sdarrenr		*addr++ = '\0';
374145554Sdarrenr
375145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
376145554Sdarrenr		if (!strcmp(name, ifp->if_xname)) {
377145554Sdarrenr			if (addr != NULL)
378145554Sdarrenr				fr_setifpaddr(ifp, addr);
379145554Sdarrenr			return ifp;
380145554Sdarrenr		}
381145554Sdarrenr	}
382145554Sdarrenr#else
383145554Sdarrenr	char *s, ifname[LIFNAMSIZ+1];
384145554Sdarrenr
385145554Sdarrenr	if (name == NULL)
386145554Sdarrenr		name = "anon0";
387145554Sdarrenr
388145554Sdarrenr	addr = strchr(name, '=');
389145554Sdarrenr	if (addr != NULL)
390145554Sdarrenr		*addr++ = '\0';
391145554Sdarrenr
392145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
393172776Sdarrenr		COPYIFNAME(v, ifp, ifname);
394145554Sdarrenr		if (!strcmp(name, ifname)) {
395145554Sdarrenr			if (addr != NULL)
396145554Sdarrenr				fr_setifpaddr(ifp, addr);
397145554Sdarrenr			return ifp;
398145554Sdarrenr		}
399145554Sdarrenr	}
400145554Sdarrenr#endif
401145554Sdarrenr
402145554Sdarrenr	if (!ifneta) {
403145554Sdarrenr		ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
404145554Sdarrenr		if (!ifneta)
405145554Sdarrenr			return NULL;
406145554Sdarrenr		ifneta[1] = NULL;
407145554Sdarrenr		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
408145554Sdarrenr		if (!ifneta[0]) {
409145554Sdarrenr			free(ifneta);
410145554Sdarrenr			return NULL;
411145554Sdarrenr		}
412145554Sdarrenr		nifs = 1;
413145554Sdarrenr	} else {
414145554Sdarrenr		old_ifneta = ifneta;
415145554Sdarrenr		nifs++;
416145554Sdarrenr		ifneta = (struct ifnet **)realloc(ifneta,
417145554Sdarrenr						  (nifs + 1) * sizeof(ifp));
418145554Sdarrenr		if (!ifneta) {
419145554Sdarrenr			free(old_ifneta);
420145554Sdarrenr			nifs = 0;
421145554Sdarrenr			return NULL;
422145554Sdarrenr		}
423145554Sdarrenr		ifneta[nifs] = NULL;
424145554Sdarrenr		ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
425145554Sdarrenr		if (!ifneta[nifs - 1]) {
426145554Sdarrenr			nifs--;
427145554Sdarrenr			return NULL;
428145554Sdarrenr		}
429145554Sdarrenr	}
430145554Sdarrenr	ifp = ifneta[nifs - 1];
431145554Sdarrenr
432172776Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
433172776Sdarrenr	TAILQ_INIT(&ifp->if_addrlist);
434172776Sdarrenr#endif
435145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
436145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
437145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
438145554Sdarrenr	(void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
439145554Sdarrenr#else
440145554Sdarrenr	for (s = name; *s && !ISDIGIT(*s); s++)
441145554Sdarrenr		;
442145554Sdarrenr	if (*s && ISDIGIT(*s)) {
443145554Sdarrenr		ifp->if_unit = atoi(s);
444145554Sdarrenr		ifp->if_name = (char *)malloc(s - name + 1);
445145554Sdarrenr		(void) strncpy(ifp->if_name, name, s - name);
446145554Sdarrenr		ifp->if_name[s - name] = '\0';
447145554Sdarrenr	} else {
448145554Sdarrenr		ifp->if_name = strdup(name);
449145554Sdarrenr		ifp->if_unit = -1;
450145554Sdarrenr	}
451145554Sdarrenr#endif
452170268Sdarrenr	ifp->if_output = (void *)no_output;
453145554Sdarrenr
454145554Sdarrenr	if (addr != NULL) {
455145554Sdarrenr		fr_setifpaddr(ifp, addr);
456145554Sdarrenr	}
457145554Sdarrenr
458145554Sdarrenr	return ifp;
459145554Sdarrenr}
460145554Sdarrenr
461145554Sdarrenr
462145554Sdarrenrchar *get_ifname(ifp)
463145554Sdarrenrstruct ifnet *ifp;
464145554Sdarrenr{
465145554Sdarrenr	static char ifname[LIFNAMSIZ];
466145554Sdarrenr
467145554Sdarrenr#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
468145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
469145554Sdarrenr	sprintf(ifname, "%s", ifp->if_xname);
470145554Sdarrenr#else
471145554Sdarrenr	sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
472145554Sdarrenr#endif
473145554Sdarrenr	return ifname;
474145554Sdarrenr}
475145554Sdarrenr
476145554Sdarrenr
477145554Sdarrenr
478145554Sdarrenrvoid init_ifp()
479145554Sdarrenr{
480145554Sdarrenr	struct ifnet *ifp, **ifpp;
481145554Sdarrenr	char fname[32];
482145554Sdarrenr	int fd;
483145554Sdarrenr
484145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
485145554Sdarrenr    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
486145554Sdarrenr    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
487145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
488170268Sdarrenr		ifp->if_output = (void *)write_output;
489145554Sdarrenr		sprintf(fname, "/tmp/%s", ifp->if_xname);
490145554Sdarrenr		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
491145554Sdarrenr		if (fd == -1)
492145554Sdarrenr			perror("open");
493145554Sdarrenr		else
494145554Sdarrenr			close(fd);
495145554Sdarrenr	}
496145554Sdarrenr#else
497145554Sdarrenr
498145554Sdarrenr	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
499145554Sdarrenr		ifp->if_output = write_output;
500145554Sdarrenr		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
501145554Sdarrenr		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
502145554Sdarrenr		if (fd == -1)
503145554Sdarrenr			perror("open");
504145554Sdarrenr		else
505145554Sdarrenr			close(fd);
506145554Sdarrenr	}
507145554Sdarrenr#endif
508145554Sdarrenr}
509145554Sdarrenr
510145554Sdarrenr
511145554Sdarrenrint fr_fastroute(m, mpp, fin, fdp)
512145554Sdarrenrmb_t *m, **mpp;
513145554Sdarrenrfr_info_t *fin;
514145554Sdarrenrfrdest_t *fdp;
515145554Sdarrenr{
516145554Sdarrenr	struct ifnet *ifp = fdp->fd_ifp;
517145554Sdarrenr	ip_t *ip = fin->fin_ip;
518161357Sguido	int error = 0;
519161357Sguido	frentry_t *fr;
520161357Sguido	void *sifp;
521145554Sdarrenr
522145554Sdarrenr	if (!ifp)
523145554Sdarrenr		return 0;	/* no routing table out here */
524145554Sdarrenr
525161357Sguido	fr = fin->fin_fr;
526145554Sdarrenr	ip->ip_sum = 0;
527161357Sguido
528161357Sguido	if (fin->fin_out == 0) {
529161357Sguido		sifp = fin->fin_ifp;
530161357Sguido		fin->fin_ifp = ifp;
531161357Sguido		fin->fin_out = 1;
532161357Sguido		(void) fr_acctpkt(fin, NULL);
533161357Sguido		fin->fin_fr = NULL;
534161357Sguido		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
535161357Sguido			u_32_t pass;
536161357Sguido
537161357Sguido			(void) fr_checkstate(fin, &pass);
538161357Sguido		}
539161357Sguido
540161357Sguido		switch (fr_checknatout(fin, NULL))
541161357Sguido		{
542161357Sguido		case 0 :
543161357Sguido			break;
544161357Sguido		case 1 :
545161357Sguido			ip->ip_sum = 0;
546161357Sguido			break;
547161357Sguido		case -1 :
548161357Sguido			error = -1;
549161357Sguido			goto done;
550161357Sguido			break;
551161357Sguido		}
552161357Sguido
553161357Sguido		fin->fin_ifp = sifp;
554161357Sguido		fin->fin_out = 0;
555161357Sguido	}
556161357Sguido
557145554Sdarrenr#if defined(__sgi) && (IRIX < 60500)
558145554Sdarrenr	(*ifp->if_output)(ifp, (void *)ip, NULL);
559145554Sdarrenr# if TRU64 >= 1885
560145554Sdarrenr	(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
561145554Sdarrenr# else
562145554Sdarrenr	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
563145554Sdarrenr# endif
564145554Sdarrenr#endif
565161357Sguidodone:
566161357Sguido	return error;
567145554Sdarrenr}
568145554Sdarrenr
569145554Sdarrenr
570145554Sdarrenrint fr_send_reset(fin)
571145554Sdarrenrfr_info_t *fin;
572145554Sdarrenr{
573145554Sdarrenr	verbose("- TCP RST sent\n");
574145554Sdarrenr	return 0;
575145554Sdarrenr}
576145554Sdarrenr
577145554Sdarrenr
578145554Sdarrenrint fr_send_icmp_err(type, fin, dst)
579145554Sdarrenrint type;
580145554Sdarrenrfr_info_t *fin;
581145554Sdarrenrint dst;
582145554Sdarrenr{
583145554Sdarrenr	verbose("- ICMP unreachable sent\n");
584145554Sdarrenr	return 0;
585145554Sdarrenr}
586145554Sdarrenr
587145554Sdarrenr
588145554Sdarrenrvoid frsync(ifp)
589145554Sdarrenrvoid *ifp;
590145554Sdarrenr{
591145554Sdarrenr	return;
592145554Sdarrenr}
593145554Sdarrenr
594145554Sdarrenr
595145554Sdarrenrvoid m_freem(m)
596145554Sdarrenrmb_t *m;
597145554Sdarrenr{
598145554Sdarrenr	return;
599145554Sdarrenr}
600145554Sdarrenr
601145554Sdarrenr
602145554Sdarrenrvoid m_copydata(m, off, len, cp)
603145554Sdarrenrmb_t *m;
604145554Sdarrenrint off, len;
605145554Sdarrenrcaddr_t cp;
606145554Sdarrenr{
607145554Sdarrenr	bcopy((char *)m + off, cp, len);
608145554Sdarrenr}
609145554Sdarrenr
610145554Sdarrenr
611145554Sdarrenrint ipfuiomove(buf, len, rwflag, uio)
612145554Sdarrenrcaddr_t buf;
613145554Sdarrenrint len, rwflag;
614145554Sdarrenrstruct uio *uio;
615145554Sdarrenr{
616145554Sdarrenr	int left, ioc, num, offset;
617145554Sdarrenr	struct iovec *io;
618145554Sdarrenr	char *start;
619145554Sdarrenr
620145554Sdarrenr	if (rwflag == UIO_READ) {
621145554Sdarrenr		left = len;
622145554Sdarrenr		ioc = 0;
623145554Sdarrenr
624145554Sdarrenr		offset = uio->uio_offset;
625145554Sdarrenr
626145554Sdarrenr		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
627145554Sdarrenr			io = uio->uio_iov + ioc;
628145554Sdarrenr			num = io->iov_len;
629145554Sdarrenr			if (num > left)
630145554Sdarrenr				num = left;
631145554Sdarrenr			start = (char *)io->iov_base + offset;
632145554Sdarrenr			if (start > (char *)io->iov_base + io->iov_len) {
633145554Sdarrenr				offset -= io->iov_len;
634145554Sdarrenr				ioc++;
635145554Sdarrenr				continue;
636145554Sdarrenr			}
637145554Sdarrenr			bcopy(buf, start, num);
638145554Sdarrenr			uio->uio_resid -= num;
639145554Sdarrenr			uio->uio_offset += num;
640145554Sdarrenr			left -= num;
641145554Sdarrenr			if (left > 0)
642145554Sdarrenr				ioc++;
643145554Sdarrenr		}
644145554Sdarrenr		if (left > 0)
645145554Sdarrenr			return EFAULT;
646145554Sdarrenr	}
647145554Sdarrenr	return 0;
648145554Sdarrenr}
649145554Sdarrenr
650145554Sdarrenr
651145554Sdarrenru_32_t fr_newisn(fin)
652145554Sdarrenrfr_info_t *fin;
653145554Sdarrenr{
654145554Sdarrenr	static int iss_seq_off = 0;
655145554Sdarrenr	u_char hash[16];
656145554Sdarrenr	u_32_t newiss;
657145554Sdarrenr	MD5_CTX ctx;
658145554Sdarrenr
659145554Sdarrenr	/*
660145554Sdarrenr	 * Compute the base value of the ISS.  It is a hash
661145554Sdarrenr	 * of (saddr, sport, daddr, dport, secret).
662145554Sdarrenr	 */
663145554Sdarrenr	MD5Init(&ctx);
664145554Sdarrenr
665145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
666145554Sdarrenr		  sizeof(fin->fin_fi.fi_src));
667145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
668145554Sdarrenr		  sizeof(fin->fin_fi.fi_dst));
669145554Sdarrenr	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
670145554Sdarrenr
671145554Sdarrenr	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
672145554Sdarrenr
673145554Sdarrenr	MD5Final(hash, &ctx);
674145554Sdarrenr
675145554Sdarrenr	memcpy(&newiss, hash, sizeof(newiss));
676145554Sdarrenr
677145554Sdarrenr	/*
678145554Sdarrenr	 * Now increment our "timer", and add it in to
679145554Sdarrenr	 * the computed value.
680145554Sdarrenr	 *
681145554Sdarrenr	 * XXX Use `addin'?
682145554Sdarrenr	 * XXX TCP_ISSINCR too large to use?
683145554Sdarrenr	 */
684145554Sdarrenr	iss_seq_off += 0x00010000;
685145554Sdarrenr	newiss += iss_seq_off;
686145554Sdarrenr	return newiss;
687145554Sdarrenr}
688145554Sdarrenr
689145554Sdarrenr
690145554Sdarrenr/* ------------------------------------------------------------------------ */
691145554Sdarrenr/* Function:    fr_nextipid                                                 */
692145554Sdarrenr/* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
693145554Sdarrenr/* Parameters:  fin(I) - pointer to packet information                      */
694145554Sdarrenr/*                                                                          */
695145554Sdarrenr/* Returns the next IPv4 ID to use for this packet.                         */
696145554Sdarrenr/* ------------------------------------------------------------------------ */
697145554SdarrenrINLINE u_short fr_nextipid(fin)
698145554Sdarrenrfr_info_t *fin;
699145554Sdarrenr{
700145554Sdarrenr	static u_short ipid = 0;
701145554Sdarrenr	u_short id;
702145554Sdarrenr
703145554Sdarrenr	MUTEX_ENTER(&ipf_rw);
704145554Sdarrenr	id = ipid++;
705145554Sdarrenr	MUTEX_EXIT(&ipf_rw);
706145554Sdarrenr
707145554Sdarrenr	return id;
708145554Sdarrenr}
709145554Sdarrenr
710145554Sdarrenr
711145554SdarrenrINLINE void fr_checkv4sum(fin)
712145554Sdarrenrfr_info_t *fin;
713145554Sdarrenr{
714145554Sdarrenr	if (fr_checkl4sum(fin) == -1)
715145554Sdarrenr		fin->fin_flx |= FI_BAD;
716145554Sdarrenr}
717145554Sdarrenr
718145554Sdarrenr
719145554Sdarrenr#ifdef	USE_INET6
720145554SdarrenrINLINE void fr_checkv6sum(fin)
721145554Sdarrenrfr_info_t *fin;
722145554Sdarrenr{
723145554Sdarrenr	if (fr_checkl4sum(fin) == -1)
724145554Sdarrenr		fin->fin_flx |= FI_BAD;
725145554Sdarrenr}
726145554Sdarrenr#endif
727145554Sdarrenr
728145554Sdarrenr
729145554Sdarrenr/*
730145554Sdarrenr * See above for description, except that all addressing is in user space.
731145554Sdarrenr */
732145554Sdarrenrint copyoutptr(src, dst, size)
733145554Sdarrenrvoid *src, *dst;
734145554Sdarrenrsize_t size;
735145554Sdarrenr{
736145554Sdarrenr	caddr_t ca;
737145554Sdarrenr
738145554Sdarrenr	bcopy(dst, (char *)&ca, sizeof(ca));
739145554Sdarrenr	bcopy(src, ca, size);
740145554Sdarrenr	return 0;
741145554Sdarrenr}
742145554Sdarrenr
743145554Sdarrenr
744145554Sdarrenr/*
745145554Sdarrenr * See above for description, except that all addressing is in user space.
746145554Sdarrenr */
747145554Sdarrenrint copyinptr(src, dst, size)
748145554Sdarrenrvoid *src, *dst;
749145554Sdarrenrsize_t size;
750145554Sdarrenr{
751145554Sdarrenr	caddr_t ca;
752145554Sdarrenr
753145554Sdarrenr	bcopy(src, (char *)&ca, sizeof(ca));
754145554Sdarrenr	bcopy(ca, dst, size);
755145554Sdarrenr	return 0;
756145554Sdarrenr}
757145554Sdarrenr
758145554Sdarrenr
759145554Sdarrenr/*
760145554Sdarrenr * return the first IP Address associated with an interface
761145554Sdarrenr */
762145554Sdarrenrint fr_ifpaddr(v, atype, ifptr, inp, inpmask)
763145554Sdarrenrint v, atype;
764145554Sdarrenrvoid *ifptr;
765145554Sdarrenrstruct in_addr *inp, *inpmask;
766145554Sdarrenr{
767145554Sdarrenr	struct ifnet *ifp = ifptr;
768145554Sdarrenr#ifdef __sgi
769145554Sdarrenr	struct in_ifaddr *ifa;
770145554Sdarrenr#else
771145554Sdarrenr	struct ifaddr *ifa;
772145554Sdarrenr#endif
773145554Sdarrenr
774145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
775145554Sdarrenr	ifa = ifp->if_addrlist.tqh_first;
776145554Sdarrenr#else
777145554Sdarrenr# ifdef __sgi
778145554Sdarrenr	ifa = (struct in_ifaddr *)ifp->in_ifaddr;
779145554Sdarrenr# else
780145554Sdarrenr	ifa = ifp->if_addrlist;
781145554Sdarrenr# endif
782145554Sdarrenr#endif
783145554Sdarrenr	if (ifa != NULL) {
784145554Sdarrenr		struct sockaddr_in *sin, mask;
785145554Sdarrenr
786145554Sdarrenr		mask.sin_addr.s_addr = 0xffffffff;
787145554Sdarrenr
788145554Sdarrenr#ifdef __sgi
789145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ia_addr;
790145554Sdarrenr#else
791145554Sdarrenr		sin = (struct sockaddr_in *)&ifa->ifa_addr;
792145554Sdarrenr#endif
793145554Sdarrenr
794145554Sdarrenr		return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
795145554Sdarrenr	}
796145554Sdarrenr	return 0;
797145554Sdarrenr}
798170268Sdarrenr
799170268Sdarrenr
800170268Sdarrenrint ipfsync()
801170268Sdarrenr{
802170268Sdarrenr	return 0;
803170268Sdarrenr}
804180778Sdarrenr
805180778Sdarrenr
806181313Smlaier#ifndef ipf_random
807180778Sdarrenru_32_t ipf_random()
808180778Sdarrenr{
809180778Sdarrenr	static int seeded = 0;
810180778Sdarrenr
811180778Sdarrenr	/*
812180778Sdarrenr	 * Choose a non-random seed so that "randomness" can be "tested."
813180778Sdarrenr	 */
814180778Sdarrenr	if (seeded == 0) {
815180778Sdarrenr		srand(0);
816180778Sdarrenr		seeded = 1;
817180778Sdarrenr	}
818180778Sdarrenr	return rand();
819180778Sdarrenr}
820181313Smlaier#endif
821