diff options
Diffstat (limited to 'sys/netinet/ip_fil.c')
-rw-r--r-- | sys/netinet/ip_fil.c | 1069 |
1 files changed, 699 insertions, 370 deletions
diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c index 6e90df072bb..f28ce0f7cac 100644 --- a/sys/netinet/ip_fil.c +++ b/sys/netinet/ip_fil.c @@ -1,34 +1,82 @@ -/* $OpenBSD: ip_fil.c,v 1.15 1997/12/03 01:25:32 kstailey Exp $ */ +/* $OpenBSD: ip_fil.c,v 1.16 1998/01/26 04:10:39 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed"; -static char rcsid[] = "$DRId: ip_fil.c,v 2.0.1.8 1997/03/20 15:51:56 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.16 1998/01/26 04:10:39 dgregor Exp $"; #endif -#include <sys/param.h> +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#if defined(KERNEL) && !defined(_KERNEL) +# define _KERNEL +#endif +#ifdef __FreeBSD__ +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include <sys/osreldate.h> +# else +# include <osreldate.h> +# endif +#endif +#ifndef _KERNEL +# include <stdio.h> +# include <string.h> +# include <stdlib.h> +# include <ctype.h> +#endif #include <sys/errno.h> +#include <sys/types.h> +#include <sys/param.h> #include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/mbuf.h> +#if __FreeBSD_version >= 220000 && defined(_KERNEL) +# include <sys/fcntl.h> +# include <sys/filio.h> +#else +# include <sys/ioctl.h> +#endif +#include <sys/time.h> +#ifdef _KERNEL +# include <sys/systm.h> +#endif +#include <sys/uio.h> +#if !SOLARIS +# if (NetBSD > 199609) || (OpenBSD > 199603) +# include <sys/dirent.h> +# else +# include <sys/dir.h> +# endif +# include <sys/mbuf.h> +#else +# include <sys/filio.h> +#endif #include <sys/protosw.h> #include <sys/socket.h> -#include <sys/syslog.h> -#include <sys/systm.h> -#include <sys/uio.h> #include <net/if.h> #ifdef sun -#include <net/af.h> +# include <net/af.h> +#endif +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#ifdef __sgi +#include <sys/debug.h> +# ifdef IFF_DRVRLOCK /* IRIX6 */ +#include <sys/hashing.h> +# endif #endif #include <net/route.h> #include <netinet/in.h> +#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ #include <netinet/in_var.h> +#endif #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_var.h> @@ -36,60 +84,79 @@ static char rcsid[] = "$DRId: ip_fil.c,v 2.0.1.8 1997/03/20 15:51:56 darrenr #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> - +#ifndef _KERNEL +# include <syslog.h> +#endif #include "ip_fil_compat.h" #include "ip_fil.h" -#include "ip_frag.h" +#include "ip_proxy.h" #include "ip_nat.h" +#include "ip_frag.h" #include "ip_state.h" +#include "ip_auth.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif +#if !SOLARIS && defined(_KERNEL) +extern int ip_optcopy __P((struct ip *, struct ip *)); +#endif + -extern fr_flags, fr_active; extern struct protosw inetsw[]; -extern int (*fr_checkp) __P((ip_t *, int, struct ifnet *, int, - struct mbuf **)); -#if BSD < 199306 -extern int ipfr_slowtimer __P((void)); -static int (*fr_saveslowtimo) __P((void)); -extern int tcp_ttl; + +#ifndef _KERNEL +# include "ipt.h" +static struct ifnet **ifneta = NULL; +static int nifs = 0; #else -extern void ipfr_slowtimer __P((void)); +# if (BSD < 199306) && !defined(__sgi) +static int (*fr_saveslowtimo) __P((void)); +# else static void (*fr_saveslowtimo) __P((void)); +# endif +# if (BSD < 199306) || defined(__sgi) +extern int tcp_ttl; +# endif #endif -static void frzerostats __P((caddr_t)); - int ipl_inited = 0; +#ifdef __OpenBSD__ int ipl_unreach = ICMP_UNREACH_FILTER_PROHIB; -int send_reset __P((struct tcpiphdr *)); +#else +int ipl_unreach = ICMP_UNREACH_FILTER; +#endif +u_long ipl_frouteok[2] = {0, 0}; -#ifdef IPFILTER_LOG -# define LOGSIZE 8192 -int ipllog __P((u_int, ip_t *, register fr_info_t *, struct mbuf *)); -char iplbuf[LOGSIZE]; -caddr_t iplh = iplbuf, iplt = iplbuf; -static int iplused = 0; -#endif /* IPFILTER_LOG */ -static int (*fr_savep) __P((ip_t *, int, struct ifnet *, int, - struct mbuf **)); -static void frflush __P((caddr_t)); -static int frrequest __P((u_long, caddr_t, int)); +static void fixskip __P((frentry_t **, frentry_t *, int)); +static void frzerostats __P((caddr_t)); +static void frsync __P((void)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +static int frrequest __P((int, u_long, caddr_t, int)); +#else +static int frrequest __P((int, int, caddr_t, int)); +#endif +#ifdef _KERNEL +static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); +#else +int ipllog __P((void)); +void init_ifp __P((void)); +# ifdef __sgi +static int no_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *)); +static int write_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *)); +# else +static int no_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *)); +static int write_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *)); +# endif +#endif -#if _BSDI_VERSION >= 199501 +#if (_BSDI_VERSION >= 199510) && defined(_KERNEL) # include <sys/device.h> # include <sys/conf.h> -int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); -int iplopen __P((dev_t, int, int, struct proc *)); -int iplclose __P((dev_t, int, int, struct proc *)); -# ifdef IPFILTER_LOG -int iplread __P((dev_t, struct uio *, int)); -# else -# define iplread noread -# endif - struct cfdriver iplcd = { NULL, "ipl", NULL, NULL, DV_DULL, 0 }; @@ -100,44 +167,48 @@ struct devsw iplsw = { nostrat, nodump, nopsize, 0, nostop }; -#else /* _BSDI_VERSION >= 199501 */ +#endif /* _BSDI_VERSION >= 199510 && _KERNEL */ +#ifdef __OpenBSD__ /* called by main() at boot time */ -void iplattach __P((int)); - -# ifdef IPFILTER_LOG -# if BSD >= 199306 -int iplread __P((dev_t, struct uio *, int)); -# else -int iplread __P((dev_t, struct uio *)); -# endif -# else -# define iplread noread -# endif -int iplioctl __P((dev_t, int, caddr_t, int)); -int iplopen __P((dev_t, int)); -int iplclose __P((dev_t, int)); -#endif /* _BSDI_VERSION >= 199501 */ - -int ipl_enable __P((void)); -int ipl_disable __P((void)); - -#ifdef IPFILTER_LKM -int iplidentify __P((char *)); +void iplattach __P((int)); +#endif -int -iplidentify(s) - char *s; +#if defined(__NetBSD__) || defined(__OpenBSD__) +# include <sys/conf.h> +# if defined(NETBSD_PF) +# include <net/pfil.h> +/* + * We provide the fr_checkp name just to minimize changes later. + */ +int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); +# endif /* NETBSD_PF */ +#endif /* __NetBSD__ */ + +#ifdef _KERNEL +# if defined(IPFILTER_LKM) && !defined(__sgi) +int iplidentify(s) +char *s; { if (strcmp(s, "ipl") == 0) return 1; return 0; } -#else -void iplinit __P((void)); -#endif /* IPFILTER_LKM */ +# endif /* IPFILTER_LKM */ + + +/* + * Try to detect the case when compiling for NetBSD with pseudo-device + */ +# if defined(__NetBSD__) && defined(PFIL_HOOKS) +void +ipfilterattach(count) +int count; +{ + iplattach(); +} +# endif -void ipfr_fastroute __P((struct mbuf *, fr_info_t *, frdest_t *)); /* * None of the machinery should be initialized until the caller explicitly @@ -152,55 +223,105 @@ int dummy; int ipl_enable() { + char *defpass; int s; +# ifdef __sgi + int error; +# endif - SPLNET(s); + SPL_NET(s); if (ipl_inited || (fr_checkp == fr_check)) { printf("IP Filter: already initialized\n"); - SPLX(s); + SPL_X(s); return EBUSY; } + +# ifdef NETBSD_PF + pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); +# endif + +# ifdef __sgi + error = ipfilter_sgi_attach(); + if (error) { + SPL_X(s); + return error; + } +# endif + ipl_inited = 1; - bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2); + bzero((char *)frcache, sizeof(frcache)); + bzero((char *)nat_table, sizeof(nat_table)); fr_savep = fr_checkp; fr_checkp = fr_check; fr_saveslowtimo = inetsw[0].pr_slowtimo; inetsw[0].pr_slowtimo = ipfr_slowtimer; - SPLX(s); + +# ifdef IPFILTER_LOG + ipflog_init(); +# endif + SPL_X(s); + if (fr_pass & FR_PASS) + defpass = "pass"; + else if (fr_pass & FR_BLOCK) + defpass = "block"; + else + defpass = "no-match -> block"; + +#ifdef __OpenBSD__ /* don't print this message */ + printf("IP Filter: initialized. Default = %s all, Logging = %s\n", + defpass, +# ifdef IPFILTER_LOG + "enabled"); +# else + "disabled"); +# endif +#endif /* __OpenBSD__ */ return 0; } -int -ipl_disable() +/* + * Disable the filter by removing the hooks from the IP input/output + * stream. + */ +int ipl_disable() { int s, i = FR_INQUE|FR_OUTQUE; - SPLNET(s); + SPL_NET(s); if (!ipl_inited) { printf("IP Filter: not initialized\n"); - SPLX(s); - return EBUSY; + SPL_X(s); + return 0; } fr_checkp = fr_savep; inetsw[0].pr_slowtimo = fr_saveslowtimo; - frflush((caddr_t)&i); + frflush(IPL_LOGIPF, &i); ipl_inited = 0; +# ifdef NETBSD_PF + pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); +# endif + +# ifdef __sgi + ipfilter_sgi_detach(); +# endif + ipfr_unload(); ip_natunload(); fr_stateunload(); + fr_authunload(); - SPLX(s); + SPL_X(s); return 0; } +#endif /* _KERNEL */ -static void -frzerostats(data) - caddr_t data; +static void frzerostats(data) +caddr_t data; { struct friostat fio; @@ -215,77 +336,59 @@ frzerostats(data) fio.f_acctout[0] = ipacct[1][0]; fio.f_acctout[1] = ipacct[1][1]; fio.f_active = fr_active; + fio.f_froute[0] = ipl_frouteok[0]; + fio.f_froute[1] = ipl_frouteok[1]; IWCOPY((caddr_t)&fio, data, sizeof(fio)); bzero((char *)frstats, sizeof(*frstats) * 2); } -static void -frflush(data) - caddr_t data; -{ - struct frentry *f, **fp; - int flags = *(int *)data, flushed = 0, set = fr_active; - - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - if (flags & FR_INACTIVE) - set = 1 - set; - if (flags & FR_OUTQUE) { - for (fp = &ipfilter[1][set]; (f = *fp); ) { - *fp = f->fr_next; - KFREE(f); - flushed++; - } - for (fp = &ipacct[1][set]; (f = *fp); ) { - *fp = f->fr_next; - KFREE(f); - flushed++; - } - } - if (flags & FR_INQUE) { - for (fp = &ipfilter[0][set]; (f = *fp); ) { - *fp = f->fr_next; - KFREE(f); - flushed++; - } - for (fp = &ipacct[0][set]; (f = *fp); ) { - *fp = f->fr_next; - KFREE(f); - flushed++; - } - } - *(int *)data = flushed; -} - - /* * Filter ioctl interface. */ -int -iplioctl(dev, cmd, data, mode -#if _BSDI_VERSION >= 199501 - , p) - struct proc *p; +#ifdef __sgi +int IPL_EXTERN(ioctl)(dev_t dev, int cmd, caddr_t data, int mode +# ifdef _KERNEL + , cred_t *cp, int *rp +# endif +) +#else +int IPL_EXTERN(ioctl)(dev, cmd, data, mode +#if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ + (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) +, p) +struct proc *p; +#else +) +#endif +dev_t dev; +#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) +u_long cmd; #else - ) +int cmd; #endif - dev_t dev; - int cmd; - caddr_t data; - int mode; +caddr_t data; +int mode; +#endif /* __sgi */ { - int error = 0, s, unit; +#if defined(_KERNEL) && !SOLARIS + int s; +#endif + int error = 0, unit = 0, tmp; - unit = minor(dev); - if (unit != 0) +#ifdef _KERNEL + unit = GET_MINOR(dev); + if ((IPL_LOGMAX < unit) || (unit < 0)) return ENXIO; +#endif + +#if defined(__OpenBSD__) && defined(_KERNEL) if (securelevel > 1) { switch (cmd) { -#ifndef IPFILTER_LKM +# ifndef IPFILTER_LKM case SIOCFRENB: -#endif +# endif case SIOCSETFF: case SIOCADAFR: case SIOCADIFR: @@ -297,9 +400,9 @@ iplioctl(dev, cmd, data, mode case SIOCSWAPA: case SIOCFRZST: case SIOCIPFFL: -#ifdef IPFILTER_LOG +# ifdef IPFILTER_LOG case SIOCIPFFB: -#endif +# endif case SIOCADNAT: case SIOCRMNAT: case SIOCFLNAT: @@ -307,15 +410,28 @@ iplioctl(dev, cmd, data, mode return EPERM; } } +#endif - SPLNET(s); + SPL_NET(s); + + if (unit == IPL_LOGNAT) { + error = nat_ioctl(data, cmd, mode); + SPL_X(s); + return error; + } + if (unit == IPL_LOGSTATE) { + error = fr_state_ioctl(data, cmd, mode); + SPL_X(s); + return error; + } switch (cmd) { case FIONREAD : #ifdef IPFILTER_LOG - *(int *)data = iplused; + IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data, + sizeof(iplused[IPL_LOGIPF])); #endif break; -#ifndef IPFILTER_LKM +#if !defined(IPFILTER_LKM) && defined(_KERNEL) case SIOCFRENB : { u_int enable; @@ -348,7 +464,7 @@ iplioctl(dev, cmd, data, mode if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(cmd, data, fr_active); + error = frrequest(unit, cmd, data, fr_active); break; case SIOCINIFR : case SIOCRMIFR : @@ -356,7 +472,7 @@ iplioctl(dev, cmd, data, mode if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(cmd, data, 1 - fr_active); + error = frrequest(unit, cmd, data, 1 - fr_active); break; case SIOCSWAPA : if (!(mode & FWRITE)) @@ -381,7 +497,10 @@ iplioctl(dev, cmd, data, mode fio.f_acctin[1] = ipacct[0][1]; fio.f_acctout[0] = ipacct[1][0]; fio.f_acctout[1] = ipacct[1][1]; + fio.f_auth = ipauth; fio.f_active = fr_active; + fio.f_froute[0] = ipl_frouteok[0]; + fio.f_froute[1] = ipl_frouteok[1]; IWCOPY((caddr_t)&fio, data, sizeof(fio)); break; } @@ -394,72 +513,139 @@ iplioctl(dev, cmd, data, mode case SIOCIPFFL : if (!(mode & FWRITE)) error = EPERM; - else - frflush(data); + else { + IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); + frflush(unit, &tmp); + IWCOPY((caddr_t)&tmp, data, sizeof(tmp)); + } break; #ifdef IPFILTER_LOG case SIOCIPFFB : if (!(mode & FWRITE)) error = EPERM; - else { - *(int *)data = iplused; - iplh = iplt = iplbuf; - iplused = 0; - } + else + *(int *)data = ipflog_clear(unit); break; #endif /* IPFILTER_LOG */ - case SIOCADNAT : - case SIOCRMNAT : - case SIOCGNATS : - case SIOCGNATL : - case SIOCFLNAT : - case SIOCCNATL : - error = nat_ioctl(data, cmd, mode); - break; case SIOCGFRST : IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t)); break; - case SIOCGIPST : - IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t)); + case SIOCAUTHW : + case SIOCAUTHR : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + case SIOCATHST : + error = fr_auth_ioctl(data, cmd, NULL, NULL); + break; + case SIOCFRSYN : + if (!(mode & FWRITE)) + error = EPERM; + else { +#if defined(_KERNEL) && defined(__sgi) + ipfsync(); +#endif + frsync(); + } break; default : error = EINVAL; break; } - SPLX(s); + SPL_X(s); return error; } -static int -frrequest(req, data, set) - u_long req; - caddr_t data; - int set; +static void frsync() +{ +#ifdef _KERNEL + struct ifnet *ifp; + +# if defined(__OpenBSD__) || (NetBSD >= 199511) + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) +# else + for (ifp = ifnet; ifp; ifp = ifp->if_next) +# endif + ip_natsync(ifp); +#endif +} + + +static void fixskip(listp, rp, addremove) +frentry_t **listp, *rp; +int addremove; +{ + frentry_t *fp; + int rules = 0, rn = 0; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) + ; + + if (!fp) + return; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) + if (fp->fr_skip && (rn + fp->fr_skip >= rules)) + fp->fr_skip += addremove; +} + + +static int frrequest(unit, req, data, set) +int unit; +#if defined(__NetBSD__) || defined(__OpenBSD__) +u_long req; +#else +int req; +#endif +int set; +caddr_t data; { register frentry_t *fp, *f, **fprev; register frentry_t **ftail; frentry_t frd; frdest_t *fdp; - int error = 0, in; + frgroup_t *fg = NULL; + int error = 0, in, group; fp = &frd; IRCOPY(data, (caddr_t)fp, sizeof(*fp)); + /* + * Check that the group number does exist and that if a head group + * has been specified, doesn't exist. + */ + if (fp->fr_grhead && + fr_findgroup(fp->fr_grhead, fp->fr_flags, unit, set, NULL)) + return EEXIST; + if (fp->fr_group && + !fr_findgroup(fp->fr_group, fp->fr_flags, unit, set, NULL)) + return ESRCH; + in = (fp->fr_flags & FR_INQUE) ? 0 : 1; - if (fp->fr_flags & FR_ACCOUNT) { + + if (unit == IPL_LOGAUTH) + ftail = fprev = &ipauth; + else if (fp->fr_flags & FR_ACCOUNT) ftail = fprev = &ipacct[in][set]; - } else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE)) + else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE)) ftail = fprev = &ipfilter[in][set]; else return ESRCH; + if ((group = fp->fr_group)) { + if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL))) + return ESRCH; + ftail = fprev = fg->fg_start; + } + bzero((char *)frcache, sizeof(frcache[0]) * 2); if (*fp->fr_ifname) { fp->fr_ifa = GETUNIT(fp->fr_ifname); if (!fp->fr_ifa) - fp->fr_ifa = (struct ifnet *)-1; + fp->fr_ifa = (void *)-1; } fdp = &fp->fr_dif; @@ -515,18 +701,39 @@ frrequest(req, data, set) if (!f) error = ESRCH; else { + if (f->fr_ref > 1) + return EBUSY; + if (fg && fg->fg_head) + fg->fg_head->fr_ref--; + if (unit == IPL_LOGAUTH) + return fr_auth_ioctl(data, req, f, ftail); + if (f->fr_grhead) + fr_delgroup(f->fr_grhead, fp->fr_flags, unit, + set); + fixskip(fprev, f, -1); *ftail = f->fr_next; - (void) KFREE(f); + KFREE(f); } } else { if (f) error = EEXIST; else { - if ((f = (struct frentry *)KMALLOC(sizeof(*f)))) { + if (unit == IPL_LOGAUTH) + return fr_auth_ioctl(data, req, f, ftail); + KMALLOC(f, frentry_t *, sizeof(*f)); + if (f != NULL) { + if (fg && fg->fg_head) + fg->fg_head->fr_ref++; bcopy((char *)fp, (char *)f, sizeof(*f)); + f->fr_ref = 1; f->fr_hits = 0; f->fr_next = *ftail; *ftail = f; + if (req == SIOCINIFR || req == SIOCINAFR) + fixskip(fprev, f, 1); + f->fr_grp = NULL; + if ((group = f->fr_grhead)) + fg = fr_addgroup(group, f, unit, set); } else error = ENOMEM; } @@ -535,216 +742,130 @@ frrequest(req, data, set) } -#if !defined(linux) +#ifdef _KERNEL /* * routines below for saving IP headers to buffer */ -int -iplopen(dev, flags -#if _BSDI_VERSION >= 199501 - , devtype, p) - int devtype; - struct proc *p; +#ifdef __sgi +# ifdef _KERNEL +int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp) +# else +int IPL_EXTERN(open)(dev_t dev, int flags) +# endif #else - ) -#endif - dev_t dev; - int flags; +int IPL_EXTERN(open)(dev, flags +# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ + (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) +, devtype, p) +int devtype; +struct proc *p; +# else +) +# endif +dev_t dev; +int flags; +#endif /* __sgi */ { - u_int min = minor(dev); +#if defined(__sgi) && defined(_KERNEL) + u_int min = geteminor(*pdev); +#else + u_int min = GET_MINOR(dev); +#endif - if (min) + if (2 < min) min = ENXIO; + else + min = 0; return min; } -int -iplclose(dev, flags -#if _BSDI_VERSION >= 199501 - , devtype, p) - int devtype; - struct proc *p; +#ifdef __sgi +int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp) #else - ) -#endif - dev_t dev; - int flags; +int IPL_EXTERN(close)(dev, flags +# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ + (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) +, devtype, p) +int devtype; +struct proc *p; +# else +) +# endif +dev_t dev; +int flags; +#endif /* __sgi */ { - u_int min = minor(dev); + u_int min = GET_MINOR(dev); - if (min) + if (2 < min) min = ENXIO; + else + min = 0; return min; } -# ifdef IPFILTER_LOG /* * iplread/ipllog * both of these must operate with at least splnet() lest they be * called during packet processing and cause an inconsistancy to appear in * the filter lists. */ +#ifdef __sgi +int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp) +#else # if BSD >= 199306 -int -iplread(dev, uio, ioflag) - int ioflag; +int IPL_EXTERN(read)(dev, uio, ioflag) +int ioflag; # else -int -iplread(dev, uio) +int IPL_EXTERN(read)(dev, uio) # endif - dev_t dev; - register struct uio *uio; +dev_t dev; +register struct uio *uio; +#endif /* __sgi */ { - register int ret, s; - register size_t sz, sx; - int error; - - if (!uio->uio_resid) - return 0; - while (!iplused) { - error = SLEEP(iplbuf, "ipl_sleep"); - if (error) - return error; - } - SPLNET(s); - - sx = sz = MIN(uio->uio_resid, iplused); - if (iplh < iplt) - sz = MIN(sz, LOGSIZE - (iplt - iplbuf)); - sx -= sz; - -# if BSD >= 199306 || defined(__FreeBSD__) - uio->uio_rw = UIO_READ; +# ifdef IPFILTER_LOG + return ipflog_read(GET_MINOR(dev), uio); +# else + return ENXIO; # endif - if (!(ret = UIOMOVE(iplt, sz, UIO_READ, uio))) { - iplt += sz; - iplused -= sz; - if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE)) - iplt = iplbuf; - - if (sx && !(ret = UIOMOVE(iplt, sx, UIO_READ, uio))) { - iplt += sx; - iplused -= sx; - if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE)) - iplt = iplbuf; - } - if (!iplused) /* minimise wrapping around the end */ - iplh = iplt = iplbuf; - } - SPLX(s); - return ret; } -# endif /* IPFILTER_LOG */ -#endif /* linux */ - - -#ifdef IPFILTER_LOG -int -ipllog(flags, ip, fin, m) - u_int flags; - ip_t *ip; - register fr_info_t *fin; - struct mbuf *m; -{ - struct ipl_ci iplci; - register int len, mlen, hlen; - struct ifnet *ifp = fin->fin_ifp; - - hlen = fin->fin_hlen; - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) - hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); - else if (ip->ip_p == IPPROTO_ICMP) { - struct icmp *icmp = (struct icmp *)((char *)ip + hlen); - - switch (icmp->icmp_type) { - case ICMP_UNREACH : - case ICMP_SOURCEQUENCH : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_PARAMPROB : - hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen); - break; - default : - hlen += MIN(sizeof(struct icmp), fin->fin_dlen); - break; - } - } - mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0; - len = hlen + sizeof(iplci) + mlen; - if (iplused + len > LOGSIZE) - return 0; - iplused += len; - -# ifdef sun - uniqtime(&iplci); -# endif -# if BSD >= 199306 || defined(__FreeBSD__) - microtime((struct timeval *)&iplci); -# endif - iplci.flags = flags; - iplci.hlen = (u_char)hlen; - iplci.plen = (u_char)mlen; - iplci.rule = fin->fin_rule; -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(iplci.ifname, ifp->if_xname, IFNAMSIZ); -# else - iplci.unit = (u_char)ifp->if_unit; - if ((iplci.ifname[0] = ifp->if_name[0])) - if ((iplci.ifname[1] = ifp->if_name[1])) - if ((iplci.ifname[2] = ifp->if_name[2])) - iplci.ifname[3] = ifp->if_name[3]; -# endif - /* - * Guaranteed to succeed from above - */ - (void) fr_copytolog((char *)&iplci, sizeof(iplci)); - - for (len -= sizeof(iplci); m && len > 0; m = m->m_next, len -= hlen) { - hlen = MIN(len, m->m_len); - if (fr_copytolog(mtod(m, char *), hlen)) - break; - } - - wakeup(iplbuf); - return 1; -} -#endif /* IPFILTER_LOG */ /* * send_reset - this could conceivably be a call to tcp_respond(), but that * requires a large amount of setting up and isn't any more efficient. */ -int -send_reset(ti) - struct tcpiphdr *ti; +int send_reset(ti) +struct tcpiphdr *ti; { struct tcpiphdr *tp; - struct ip *ip; struct tcphdr *tcp; struct mbuf *m; - int tlen = 0; + int tlen = 0, err; + ip_t *ip; +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) + struct route ro; +# endif if (ti->ti_flags & TH_RST) return -1; /* feedback loop */ -#if BSD < 199306 +# if (BSD < 199306) || defined(__sgi) m = m_get(M_DONTWAIT, MT_HEADER); -#else +# else m = m_gethdr(M_DONTWAIT, MT_HEADER); m->m_data += max_linkhdr; -#endif +# endif if (m == NULL) return -1; if (ti->ti_flags & TH_SYN) tlen = 1; m->m_len = sizeof (struct tcpiphdr); -#if BSD >= 199306 +# if BSD >= 199306 m->m_pkthdr.len = sizeof (struct tcpiphdr); m->m_pkthdr.rcvif = (struct ifnet *)0; -#endif +# endif bzero(mtod(m, char *), sizeof(struct tcpiphdr)); ip = mtod(m, struct ip *); tp = mtod(m, struct tcpiphdr *); @@ -764,39 +885,60 @@ send_reset(ti) ip->ip_tos = ((struct ip *)ti)->ip_tos; ip->ip_p = ((struct ip *)ti)->ip_p; ip->ip_len = sizeof (struct tcpiphdr); -#if BSD < 199306 +# if (BSD < 199306) || defined(__sgi) ip->ip_ttl = tcp_ttl; -#else +# else ip->ip_ttl = ip_defttl; -#endif +# endif +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) + bzero((char *)&ro, sizeof(ro)); + err = ip_output(m, (struct mbuf *)0, &ro, 0, 0); + if (ro.ro_rt) + RTFREE(ro.ro_rt); +# else /* * extra 0 in case of multicast */ - (void) ip_output(m, (struct mbuf *)0, 0, 0, 0); - return 0; + err = ip_output(m, (struct mbuf *)0, 0, 0, 0); +# endif + return err; } -#ifndef IPFILTER_LKM -# if BSD < 199306 +# if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi) +# if (BSD < 199306) +int iplinit __P((void)); + int -# else +# else +void iplinit __P((void)); + void -# endif +# endif iplinit() { /* (void) ipl_enable(); must explicitly enable with ipf -E */ ip_init(); } -#endif +# endif /* ! __NetBSD__ */ -void -ipfr_fastroute(m0, fin, fdp) - struct mbuf *m0; - fr_info_t *fin; - frdest_t *fdp; +size_t mbufchainlen(m0) +register struct mbuf *m0; +{ + register size_t len = 0; + + for (; m0; m0 = m0->m_next) + len += m0->m_len; + return len; +} + + +void ipfr_fastroute(m0, fin, fdp) +struct mbuf *m0; +fr_info_t *fin; +frdest_t *fdp; { register struct ip *ip, *mhip; register struct mbuf *m = m0; @@ -816,16 +958,19 @@ ipfr_fastroute(m0, fin, fdp) dst = (struct sockaddr_in *)&ro->ro_dst; dst->sin_family = AF_INET; dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst; -#if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) \ - && !defined(__OpenBSD__) +# ifdef __bsdi__ + dst->sin_len = sizeof(*dst); +# endif +# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ + !defined(__OpenBSD__) # ifdef RTF_CLONING rtalloc_ign(ro, RTF_CLONING); -# else +# else rtalloc_ign(ro, RTF_PRCLONING); -# endif -#else +# endif +# else rtalloc(ro); -#endif +# endif if (!ifp) { if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) { error = -2; @@ -855,20 +1000,19 @@ ipfr_fastroute(m0, fin, fdp) * If small enough for interface, can just send directly. */ if (ip->ip_len <= ifp->if_mtu) { -#ifndef sparc +# ifndef sparc ip->ip_id = htons(ip->ip_id); ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); -#endif +# endif if (!ip->ip_sum) ip->ip_sum = in_cksum(m, hlen); -#if BSD >= 199306 +# if BSD >= 199306 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); - -#else +# else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -#endif +# endif goto done; } /* @@ -901,11 +1045,11 @@ ipfr_fastroute(m0, fin, fdp) error = ENOBUFS; goto bad; } -#if BSD >= 199306 +# if BSD >= 199306 m->m_data += max_linkhdr; -#else +# else m->m_off = MMAXOFF - hlen; -#endif +# endif mhip = mtod(m, struct ip *); bcopy((char *)ip, (char *)mhip, sizeof(*ip)); if (hlen > sizeof (struct ip)) { @@ -926,9 +1070,9 @@ ipfr_fastroute(m0, fin, fdp) error = ENOBUFS; /* ??? */ goto sendorfree; } -#ifndef sparc +# ifndef sparc mhip->ip_off = htons((u_short)mhip->ip_off); -#endif +# endif mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); *mnext = m; @@ -948,18 +1092,23 @@ sendorfree: m0 = m->m_act; m->m_act = 0; if (error == 0) -#if BSD >= 199306 +# if BSD >= 199306 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); -#else +# else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -#endif +# endif else m_freem(m); } } done: + if (!error) + ipl_frouteok[0]++; + else + ipl_frouteok[1]++; + if (ro->ro_rt) { RTFREE(ro->ro_rt); } @@ -968,3 +1117,183 @@ bad: m_freem(m); goto done; } +#else /* #ifdef _KERNEL */ + + +#ifdef __sgi +static int no_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s)) +#else +static int no_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s, struct rtentry *rt)) +#endif +{ + return 0; +} + + +# ifdef __STDC__ +#ifdef __sgi +static int write_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s)) +#else +static int write_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s, struct rtentry *rt)) +#endif +{ +# if !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + ip_t *ip = (ip_t *)m; +# endif +# else +static int write_output(ifp, ip) +struct ifnet *ifp; +ip_t *ip; +{ +# endif + FILE *fp; + char fname[32]; + +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + sprintf(fname, "/tmp/%s", ifp->if_xname); + if ((fp = fopen(fname, "a"))) { + fclose(fp); + } +# else + sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); + if ((fp = fopen(fname, "a"))) { + fwrite((char *)ip, ntohs(ip->ip_len), 1, fp); + fclose(fp); + } +# endif + return 0; +} + + +struct ifnet *get_unit(name) +char *name; +{ + struct ifnet *ifp, **ifa; +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + if (!strcmp(name, ifp->if_xname)) + return ifp; + } +# else + char ifname[32], *s; + + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); + if (!strcmp(name, ifname)) + return ifp; + } +# endif + + if (!ifneta) { + ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); + ifneta[1] = NULL; + ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); + nifs = 1; + } else { + nifs++; + ifneta = (struct ifnet **)realloc(ifneta, + (nifs + 1) * sizeof(*ifa)); + ifneta[nifs] = NULL; + ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); + } + ifp = ifneta[nifs - 1]; + +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); +# else + for (s = name; *s && !isdigit(*s); s++) + ; + if (*s && isdigit(*s)) { + ifp->if_unit = atoi(s); + ifp->if_name = (char *)malloc(s - name + 1); + strncpy(ifp->if_name, name, s - name); + ifp->if_name[s - name] = '\0'; + } else { + ifp->if_name = strdup(name); + ifp->if_unit = -1; + } +# endif + ifp->if_output = no_output; + return ifp; +} + + + +void init_ifp() +{ + FILE *fp; + struct ifnet *ifp, **ifa; + char fname[32]; +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + ifp->if_output = write_output; + sprintf(fname, "/tmp/%s", ifp->if_xname); + if ((fp = fopen(fname, "w"))) + fclose(fp); + } +# else + + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + ifp->if_output = write_output; + sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); + if ((fp = fopen(fname, "w"))) + fclose(fp); + } +# endif +} + + +void ipfr_fastroute(ip, fin, fdp) +ip_t *ip; +fr_info_t *fin; +frdest_t *fdp; +{ + struct ifnet *ifp = fdp->fd_ifp; + + if (!ifp) + return; /* no routing table out here */ + + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); + ip->ip_sum = 0; +#ifdef __sgi + (*ifp->if_output)(ifp, (void *)ip, NULL); +#else + (*ifp->if_output)(ifp, (void *)ip, NULL, 0); +#endif +} + + +int ipllog __P((void)) +{ + verbose("l"); + return 0; +} + + +int send_reset(ip, ifp) +ip_t *ip; +struct ifnet *ifp; +{ + verbose("- TCP RST sent\n"); + return 0; +} + + +int icmp_error(ip, ifp) +ip_t *ip; +struct ifnet *ifp; +{ + verbose("- TCP RST sent\n"); + return 0; +} +#endif /* _KERNEL */ |