diff options
Diffstat (limited to 'contrib/ipfilter/ip_fil.c')
-rw-r--r-- | contrib/ipfilter/ip_fil.c | 2308 |
1 files changed, 491 insertions, 1817 deletions
diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c index 00e8565..a790c02 100644 --- a/contrib/ipfilter/ip_fil.c +++ b/contrib/ipfilter/ip_fil.c @@ -1,75 +1,80 @@ +/* $NetBSD$ */ + /* * Copyright (C) 1993-2001 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ +#if !defined(lint) +static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp"; +#endif + #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif -#if defined(_KERNEL) && defined(__FreeBSD_version) && \ - (__FreeBSD_version >= 400000) && !defined(KLD_MODULE) -#include "opt_inet6.h" -#endif #include <sys/param.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) && !defined(_LKM) -# include "opt_ipfilter_log.h" -#endif #if defined(__FreeBSD__) && !defined(__FreeBSD_version) -# if !defined(_KERNEL) || defined(IPFILTER_LKM) -# include <osreldate.h> +# if defined(IPFILTER_LKM) +# ifndef __FreeBSD_cc_version +# include <osreldate.h> +# else +# if __FreeBSD_cc_version < 430000 +# include <osreldate.h> +# endif +# endif # endif #endif -#if defined(__sgi) && (IRIX > 602) -# define _KMEMUSER -# include <sys/ptimers.h> -#endif -#ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -# include <fcntl.h> -#endif #include <sys/errno.h> +#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) +# include <sys/kern_svcs.h> +#endif #include <sys/types.h> +#define _KERNEL +#define KERNEL +#ifdef __OpenBSD__ +struct file; +#endif +#include <sys/uio.h> +#undef _KERNEL +#undef KERNEL #include <sys/file.h> -#if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> -#else -# include <sys/ioctl.h> +#include <sys/ioctl.h> +#ifdef __sgi +# include <sys/ptimers.h> #endif #include <sys/time.h> -#ifdef _KERNEL -# include <sys/systm.h> -#endif #if !SOLARIS # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include <sys/dirent.h> # else # include <sys/dir.h> # endif -# include <sys/mbuf.h> #else # include <sys/filio.h> #endif -#include <sys/protosw.h> +#ifndef linux +# include <sys/protosw.h> +#endif #include <sys/socket.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <fcntl.h> +#include <arpa/inet.h> + +#ifdef __hpux +# define _NET_ROUTE_INCLUDED +#endif #include <net/if.h> #ifdef sun # include <net/af.h> #endif #if __FreeBSD_version >= 300000 # include <net/if_var.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif #endif #ifdef __sgi #include <sys/debug.h> @@ -77,101 +82,84 @@ #include <sys/hashing.h> # endif #endif +#if defined(__FreeBSD__) +# include "radix_ipf.h" +#endif #include <net/route.h> #include <netinet/in.h> -#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ +#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ + !defined(__hpux) && !defined(linux) # include <netinet/in_var.h> #endif #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> +#if defined(__osf__) +# include <netinet/tcp_timer.h> +#endif +#if defined(__osf__) || defined(__hpux) || defined(__sgi) +# include "radix_ipf_local.h" +# define _RADIX_H_ +#endif #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> -#ifndef _KERNEL -# include <unistd.h> -# include <syslog.h> +#include <unistd.h> +#include <syslog.h> +#ifdef __hpux +# undef _NET_ROUTE_INCLUDED #endif #include "netinet/ip_compat.h" -#ifdef USE_INET6 -# include <netinet/icmp6.h> -# if !SOLARIS -# include <netinet6/ip6protosw.h> -# include <netinet6/nd6.h> -# endif -#endif #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "netinet/ip_auth.h" -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> +#ifdef IPFILTER_SYNC +#include "netinet/ip_sync.h" #endif -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" #endif -#if !SOLARIS && defined(_KERNEL) && !defined(__sgi) -# include <sys/kernel.h> -extern int ip_optcopy __P((struct ip *, struct ip *)); +#include "netinet/ip_pool.h" +#ifdef IPFILTER_COMPILED +# include "netinet/ip_rules.h" #endif -#if defined(OpenBSD) && (OpenBSD >= 200211) && defined(_KERNEL) -extern int ip6_getpmtu(struct route_in6 *, struct route_in6 *, - struct ifnet *, struct in6_addr *, u_long *); +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include <sys/malloc.h> #endif - -#if !defined(lint) -static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.76 2004/05/12 23:21:03 darrenr Exp $"; +#ifdef __hpux +struct rtentry; #endif +#include "md5.h" +#if !defined(__osf__) extern struct protosw inetsw[]; +#endif -#ifndef _KERNEL -# include "ipt.h" +#include "ipt.h" static struct ifnet **ifneta = NULL; static int nifs = 0; -#else -# if (BSD < 199306) || defined(__sgi) -extern int tcp_ttl; -# endif -#endif - -#ifdef ICMP_UNREACH_FILTER_PROHIB -int ipl_unreach = ICMP_UNREACH_FILTER_PROHIB; -#else -int ipl_unreach = ICMP_UNREACH_FILTER; -#endif -u_long ipl_frouteok[2] = {0, 0}; static int frzerostats __P((caddr_t)); -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -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 **)); -static int send_ip __P((ip_t *, fr_info_t *, struct mbuf **)); -# ifdef USE_INET6 -static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **, - fr_info_t *, frdest_t *)); -# endif -# ifdef __sgi -extern int tcp_mtudisc; -extern kmutex_t ipf_rw; -extern KRWLOCK_T ipf_mutex; -# endif -#else +static void fr_setifpaddr __P((struct ifnet *, char *)); void init_ifp __P((void)); -# if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) static int no_output __P((struct ifnet *, struct mbuf *, struct sockaddr *)); static int write_output __P((struct ifnet *, struct mbuf *, struct sockaddr *)); +#else +# if TRU64 >= 1885 +static int no_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *, char *)); +static int write_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *, char *)); # else static int no_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); @@ -179,423 +167,20 @@ static int write_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); # endif #endif -int fr_running = 0; - -#if (__FreeBSD_version >= 300000) && defined(_KERNEL) -struct callout_handle ipfr_slowtimer_ch; -#endif -#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) -# include <sys/callout.h> -struct callout ipfr_slowtimer_ch; -#endif -#if defined(__OpenBSD__) -# include <sys/timeout.h> -struct timeout ipfr_slowtimer_ch; -#endif -#if defined(__sgi) && defined(_KERNEL) -toid_t ipfr_slowtimer_ch; -#endif - -#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000) && \ - defined(_KERNEL) -# include <sys/conf.h> -const struct cdevsw ipl_cdevsw = { - iplopen, iplclose, iplread, nowrite, iplioctl, - nostop, notty, nopoll, nommap, -}; -#endif - -#if (_BSDI_VERSION >= 199510) && defined(_KERNEL) -# include <sys/device.h> -# include <sys/conf.h> - -struct cfdriver iplcd = { - NULL, "ipl", NULL, NULL, DV_DULL, 0 -}; - -struct devsw iplsw = { - &iplcd, - iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap, - nostrat, nodump, nopsize, 0, - nostop -}; -#endif /* _BSDI_VERSION >= 199510 && _KERNEL */ - -#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) -# 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__ */ - - -#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \ - defined(_KERNEL) -# include <net/pfil.h> - -static int fr_check_wrapper(void *, struct mbuf **, struct ifnet *, int ); - -static int fr_check_wrapper(arg, mp, ifp, dir) -void *arg; -struct mbuf **mp; -struct ifnet *ifp; -int dir; -{ - struct ip *ip = mtod(*mp, struct ip *); - int rv, hlen = ip->ip_hl << 2; - -#if defined(M_CSUM_TCPv4) - /* - * If the packet is out-bound, we can't delay checksums - * here. For in-bound, the checksum has already been - * validated. - */ - if (dir == PFIL_OUT) { - if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { - in_delayed_cksum(*mp); - (*mp)->m_pkthdr.csum_flags &= - ~(M_CSUM_TCPv4|M_CSUM_UDPv4); - } - } -#endif /* M_CSUM_TCPv4 */ - - /* - * We get the packet with all fields in network byte - * order. We expect ip_len and ip_off to be in host - * order. We frob them, call the filter, then frob - * them back. - * - * Note, we don't need to update the checksum, because - * it has already been verified. - */ - NTOHS(ip->ip_len); - NTOHS(ip->ip_off); - - rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp); - - if (rv == 0 && *mp != NULL) { - ip = mtod(*mp, struct ip *); - HTONS(ip->ip_len); - HTONS(ip->ip_off); - } - - return (rv); -} - -# ifdef USE_INET6 -# include <netinet/ip6.h> - -static int fr_check_wrapper6(void *, struct mbuf **, struct ifnet *, int ); - -static int fr_check_wrapper6(arg, mp, ifp, dir) -void *arg; -struct mbuf **mp; -struct ifnet *ifp; -int dir; -{ - - return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), - ifp, (dir == PFIL_OUT), mp)); -} -# endif -#endif /* __NetBSD_Version >= 105110000 && _KERNEL */ -#ifdef _KERNEL -# if defined(IPFILTER_LKM) && !defined(__sgi) -int iplidentify(s) -char *s; -{ - if (strcmp(s, "ipl") == 0) - return 1; - return 0; -} -# 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; -{ - - /* - * Do nothing here, really. The filter will be enabled - * by the SIOCFRENB ioctl. - */ -} -# endif -# if defined(__NetBSD__) || defined(__OpenBSD__) -int ipl_enable() -# else int iplattach() -# endif { - char *defpass; - int s; -# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)) - int error = 0; -# endif -#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -#endif - - SPL_NET(s); - if (fr_running || (fr_checkp == fr_check)) { - printf("IP Filter: already initialized\n"); - SPL_X(s); - return EBUSY; - } - -# ifdef IPFILTER_LOG - ipflog_init(); -# endif - if (nat_init() == -1) { - SPL_X(s); - return EIO; - } - if (fr_stateinit() == -1) { - SPL_X(s); - return EIO; - } - if (appr_init() == -1) { - SPL_X(s); - return EIO; - } - -# ifdef NETBSD_PF -# if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) -# if __NetBSD_Version__ >= 105110000 - ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); -# ifdef USE_INET6 - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); -# endif - if (ph_inet == NULL -# ifdef USE_INET6 - && ph_inet6 == NULL -# endif - ) - return ENODEV; - - if (ph_inet != NULL) - error = pfil_add_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { -# ifdef USE_INET6 - goto pfil_error; -# else - SPL_X(s); - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; -# endif - } -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if __NetBSD_Version__ >= 105110000 - if (ph_inet6 != NULL) - error = pfil_add_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; - if (error) { - pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); - if (error) { - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -pfil_error: - SPL_X(s); - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; - } -# endif -# endif - -# ifdef __sgi - error = ipfilter_sgi_attach(); - if (error) { - SPL_X(s); - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; - } -# endif - - bzero((char *)frcache, sizeof(frcache)); - fr_savep = fr_checkp; - fr_checkp = fr_check; fr_running = 1; - - SPL_X(s); - if (fr_pass & FR_PASS) - defpass = "pass"; - else if (fr_pass & FR_BLOCK) - defpass = "block"; - else - defpass = "no-match -> block"; - - printf("%s initialized. Default = %s all, Logging = %s\n", - ipfilter_version, defpass, -# ifdef IPFILTER_LOG - "enabled"); -# else - "disabled"); -# endif -#ifdef _KERNEL -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) - callout_init(&ipfr_slowtimer_ch); - callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL); -# else -# if defined(__OpenBSD__) - timeout_set(&ipfr_slowtimer_ch, ipfr_slowtimer, NULL); - timeout_add(&ipfr_slowtimer_ch, hz/2); -# else -# if (__FreeBSD_version >= 300000) || defined(__sgi) - ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); -# else - timeout(ipfr_slowtimer, NULL, hz/2); -# endif -# endif -# endif -#endif return 0; } -/* - * Disable the filter by removing the hooks from the IP input/output - * stream. - */ -# if defined(__NetBSD__) -int ipl_disable() -# else int ipldetach() -# endif { - int s, i; -#if defined(NETBSD_PF) && \ - ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) - int error = 0; -# if __NetBSD_Version__ >= 105150000 - struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); -# ifdef USE_INET6 - struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); -# endif -# endif -#endif - -#ifdef _KERNEL -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) - callout_stop(&ipfr_slowtimer_ch); -# else -# if (__FreeBSD_version >= 300000) - untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch); -# else -# ifdef __sgi - untimeout(ipfr_slowtimer_ch); -# else -# if defined(__OpenBSD__) - timeout_del(&ipfr_slowtimer_ch); -# else - untimeout(ipfr_slowtimer, NULL); -# endif /* OpenBSD */ -# endif /* __sgi */ -# endif /* FreeBSD */ -# endif /* NetBSD */ -#endif - SPL_NET(s); - if (!fr_running) - { - printf("IP Filter: not initialized\n"); - SPL_X(s); - return 0; - } - - printf("%s unloaded\n", ipfilter_version); - - fr_checkp = fr_savep; - i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); - fr_running = 0; - -# ifdef NETBSD_PF -# if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) -# if __NetBSD_Version__ >= 105110000 - if (ph_inet != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if __NetBSD_Version__ >= 105110000 - if (ph_inet6 != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# endif -# endif - -# ifdef __sgi - ipfilter_sgi_detach(); -# endif - - appr_unload(); - ipfr_unload(); - ip_natunload(); - fr_stateunload(); - fr_authunload(); - - SPL_X(s); + fr_running = -1; return 0; } -#endif /* _KERNEL */ static int frzerostats(data) @@ -605,7 +190,7 @@ caddr_t data; int error; fr_getstat(&fio); - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); + error = copyoutptr(&fio, data, sizeof(fio)); if (error) return EFAULT; @@ -618,65 +203,29 @@ caddr_t data; /* * Filter ioctl interface. */ -#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 (defined(_KERNEL) && ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || \ - (NetBSD >= 199511) || (__FreeBSD_version >= 220000) || \ - defined(__OpenBSD__))) -, p) -struct proc *p; -# else -) -# endif -dev_t dev; -# if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -u_long cmd; -# else -int cmd; -# endif +int iplioctl(dev, cmd, data, mode) +int dev; +ioctlcmd_t cmd; caddr_t data; int mode; -#endif /* __sgi */ { -#if defined(_KERNEL) && !SOLARIS - int s; -#endif int error = 0, unit = 0, tmp; + friostat_t fio; -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 3) && (mode & FWRITE)) - return EPERM; -#endif -#ifdef _KERNEL - unit = GET_MINOR(dev); - if ((IPL_LOGMAX < unit) || (unit < 0)) - return ENXIO; -#else unit = dev; -#endif - - if (fr_running == 0 && (cmd != SIOCFRENB || unit != IPL_LOGIPF)) - return ENODEV; SPL_NET(s); if (unit == IPL_LOGNAT) { - if (fr_running) - error = nat_ioctl(data, cmd, mode); + if (fr_running > 0) + error = fr_nat_ioctl(data, cmd, mode); else error = EIO; SPL_X(s); return error; } if (unit == IPL_LOGSTATE) { - if (fr_running) + if (fr_running > 0) error = fr_state_ioctl(data, cmd, mode); else error = EIO; @@ -684,66 +233,93 @@ int mode; return error; } if (unit == IPL_LOGAUTH) { - if (!fr_running) - error = EIO; - else - if ((cmd == SIOCADAFR) || (cmd == SIOCRMAFR)) { - if (!(mode & FWRITE)) { + if (fr_running > 0) { + if ((cmd == (ioctlcmd_t)SIOCADAFR) || + (cmd == (ioctlcmd_t)SIOCRMAFR)) { + if (!(mode & FWRITE)) { error = EPERM; } else { error = frrequest(unit, cmd, data, - fr_active); + fr_active, 1); } } else { error = fr_auth_ioctl(data, mode, cmd); } + } else + error = EIO; + SPL_X(s); + return error; + } + if (unit == IPL_LOGSYNC) { +#ifdef IPFILTER_SYNC + if (fr_running > 0) + error = fr_sync_ioctl(data, cmd, mode); + else +#endif + error = EIO; + SPL_X(s); + return error; + } + if (unit == IPL_LOGSCAN) { +#ifdef IPFILTER_SCAN + if (fr_running > 0) + error = fr_scan_ioctl(data, cmd, mode); + else +#endif + error = EIO; + SPL_X(s); + return error; + } + if (unit == IPL_LOGLOOKUP) { + if (fr_running > 0) + error = ip_lookup_ioctl(data, cmd, mode); + else + error = EIO; SPL_X(s); return error; } - switch (cmd) { + switch (cmd) + { case FIONREAD : #ifdef IPFILTER_LOG - error = IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data, + error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data, sizeof(iplused[IPL_LOGIPF])); #endif break; -#if (!defined(IPFILTER_LKM) || defined(__NetBSD__)) && defined(_KERNEL) case SIOCFRENB : - { - u_int enable; - if (!(mode & FWRITE)) error = EPERM; else { - error = IRCOPY(data, (caddr_t)&enable, sizeof(enable)); + error = COPYIN(data, &tmp, sizeof(tmp)); if (error) break; - if (enable) -# if defined(__NetBSD__) || defined(__OpenBSD__) - error = ipl_enable(); -# else + if (tmp) error = iplattach(); -# endif else -# if defined(__NetBSD__) - error = ipl_disable(); -# else error = ipldetach(); -# endif } break; - } -#endif + case SIOCIPFSET : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + case SIOCIPFGETNEXT : + case SIOCIPFGET : + error = fr_ipftune(cmd, (void *)data); + break; case SIOCSETFF : if (!(mode & FWRITE)) error = EPERM; else - error = IRCOPY(data, (caddr_t)&fr_flags, - sizeof(fr_flags)); + error = COPYIN(data, &fr_flags, sizeof(fr_flags)); break; case SIOCGETFF : - error = IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags)); + error = COPYOUT(&fr_flags, data, sizeof(fr_flags)); + break; + case SIOCFUNCL : + error = fr_resolvefunc(data); break; case SIOCINAFR : case SIOCRMAFR : @@ -752,7 +328,7 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(unit, cmd, data, fr_active); + error = frrequest(unit, cmd, data, fr_active, 1); break; case SIOCINIFR : case SIOCRMIFR : @@ -760,7 +336,7 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else - error = frrequest(unit, cmd, data, 1 - fr_active); + error = frrequest(unit, cmd, data, 1 - fr_active, 1); break; case SIOCSWAPA : if (!(mode & FWRITE)) @@ -772,15 +348,9 @@ int mode; } break; case SIOCGETFS : - { - friostat_t fio; - fr_getstat(&fio); - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - if (error) - error = EFAULT; + error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); break; - } case SIOCFRZST : if (!(mode & FWRITE)) error = EPERM; @@ -791,11 +361,10 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); + error = COPYIN(data, &tmp, sizeof(tmp)); if (!error) { tmp = frflush(unit, 4, tmp); - error = IWCOPY((caddr_t)&tmp, data, - sizeof(tmp)); + error = COPYOUT(&tmp, data, sizeof(tmp)); } } break; @@ -804,18 +373,17 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); + error = COPYIN(data, &tmp, sizeof(tmp)); if (!error) { tmp = frflush(unit, 6, tmp); - error = IWCOPY((caddr_t)&tmp, data, - sizeof(tmp)); + error = COPYOUT(&tmp, data, sizeof(tmp)); } } break; #endif case SIOCSTLCK : - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); - if (!error) { + error = COPYIN(data, &tmp, sizeof(tmp)); + if (error == 0) { fr_state_lock = tmp; fr_nat_lock = tmp; fr_frag_lock = tmp; @@ -832,19 +400,13 @@ int mode; break; #endif /* IPFILTER_LOG */ case SIOCGFRST : - error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data, - sizeof(ipfrstat_t)); - if (error) - error = EFAULT; + error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT); break; case SIOCFRSYN : if (!(mode & FWRITE)) error = EPERM; else { -#if defined(_KERNEL) && defined(__sgi) - ipfsync(); -#endif - frsync(); + frsync(NULL); } break; default : @@ -889,1251 +451,159 @@ void *ifp; f->fr_ifa = (void *)-1; #endif RWLOCK_EXIT(&ipf_mutex); - ip_natsync(ifp); + fr_natsync(ifp); } -static int frrequest(unit, req, data, set) -int unit; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long req; +#if defined(__sgi) && (IRIX < 60500) +static int no_output(ifp, m, s) #else -int req; -#endif -int set; -caddr_t data; -{ - register frentry_t *fp, *f, **fprev; - register frentry_t **ftail; - frgroup_t *fg = NULL; - int error = 0, in, i; - u_int *p, *pp; - frentry_t frd; - frdest_t *fdp; - u_int group; - - fp = &frd; - error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp)); - if (error) - return EFAULT; - fp->fr_ref = 0; -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel > 0) && (fp->fr_func != NULL)) - return EPERM; -#endif - - /* - * Check that the group number does exist and that if a head group - * has been specified, doesn't exist. - */ - if ((req != SIOCZRLST) && ((req == SIOCINAFR) || (req == SIOCINIFR) || - (req == SIOCADAFR) || (req == SIOCADIFR)) && fp->fr_grhead && - fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL)) - return EEXIST; - if ((req != SIOCZRLST) && fp->fr_group && - !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL)) - return ESRCH; - - in = (fp->fr_flags & FR_INQUE) ? 0 : 1; - - if (unit == IPL_LOGAUTH) - ftail = fprev = &ipauth; - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 4)) - ftail = fprev = &ipacct[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 4)) - ftail = fprev = &ipfilter[in][set]; -#ifdef USE_INET6 - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 6)) - ftail = fprev = &ipacct6[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 6)) - ftail = fprev = &ipfilter6[in][set]; -#endif - 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); - - for (i = 0; i < 4; i++) { - if ((fp->fr_ifnames[i][1] == '\0') && - ((fp->fr_ifnames[i][0] == '-') || - (fp->fr_ifnames[i][0] == '*'))) { - fp->fr_ifas[i] = NULL; - } else if (*fp->fr_ifnames[i]) { - fp->fr_ifas[i] = GETUNIT(fp->fr_ifnames[i], fp->fr_v); - if (!fp->fr_ifas[i]) - fp->fr_ifas[i] = (void *)-1; - } - } - - fdp = &fp->fr_dif; - fp->fr_flags &= ~FR_DUP; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - else - fp->fr_flags |= FR_DUP; - } - - fdp = &fp->fr_tif; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - } - - /* - * Look for a matching filter rule, but don't include the next or - * interface pointer in the comparison (fr_next, fr_ifa). - */ - for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_ip, pp = &fp->fr_cksum; - p < pp; p++) - fp->fr_cksum += *p; - - for (; (f = *ftail); ftail = &f->fr_next) - if ((fp->fr_cksum == f->fr_cksum) && - !bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, FR_CMPSIZ)) - break; - - /* - * If zero'ing statistics, copy current to caller and zero. - */ - if (req == SIOCZRLST) { - if (!f) - return ESRCH; - error = IWCOPYPTR((caddr_t)f, data, sizeof(*f)); - if (error) - return EFAULT; - f->fr_hits = 0; - f->fr_bytes = 0; - return 0; - } - - if (!f) { - if (req != SIOCINAFR && req != SIOCINIFR) - while ((f = *ftail)) - ftail = &f->fr_next; - else { - ftail = fprev; - if (fp->fr_hits) { - while (--fp->fr_hits && (f = *ftail)) - ftail = &f->fr_next; - } - f = NULL; - } - } - - if (req == SIOCRMAFR || req == SIOCRMIFR) { - if (!f) - error = ESRCH; - else { - /* - * Only return EBUSY if there is a group list, else - * it's probably just state information referencing - * the rule. - */ - if ((f->fr_ref > 1) && f->fr_grp) - return EBUSY; - if (fg && fg->fg_head) - fg->fg_head->fr_ref--; - if (unit == IPL_LOGAUTH) { - return fr_preauthcmd(req, f, ftail); - } - if (f->fr_grhead) - fr_delgroup((u_int)f->fr_grhead, fp->fr_flags, - unit, set); - fixskip(fprev, f, -1); - *ftail = f->fr_next; - f->fr_next = NULL; - f->fr_ref--; - if (f->fr_ref == 0) - KFREE(f); - } - } else { - if (f) - error = EEXIST; - else { - if (unit == IPL_LOGAUTH) { - return fr_preauthcmd(req, fp, ftail); - } - KMALLOC(f, frentry_t *); - 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; - } - } - return (error); -} - - -#ifdef _KERNEL -/* - * routines below for saving IP headers to buffer - */ -# 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 -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 */ -{ -# if defined(__sgi) && defined(_KERNEL) - u_int min = geteminor(*pdev); +# if TRU64 >= 1885 +static int no_output (ifp, m, s, rt, cp) +char *cp; # else - u_int min = GET_MINOR(dev); +static int no_output(ifp, m, s, rt) # endif - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - - -# ifdef __sgi -int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp) -#else -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 = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - -/* - * 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 IPL_EXTERN(read)(dev, uio, ioflag) -int ioflag; -# else -int IPL_EXTERN(read)(dev, uio) -# endif -dev_t dev; -register struct uio *uio; -# endif /* __sgi */ +struct rtentry *rt; +#endif +struct ifnet *ifp; +struct mbuf *m; +struct sockaddr *s; { -# ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(dev), uio); -# else - return ENXIO; -# endif + return 0; } -/* - * 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(oip, fin) -struct ip *oip; -fr_info_t *fin; -{ - struct tcphdr *tcp, *tcp2; - int tlen = 0, hlen; - struct mbuf *m; -#ifdef USE_INET6 - ip6_t *ip6, *oip6 = (ip6_t *)oip; -#endif - ip_t *ip; - - tcp = (struct tcphdr *)fin->fin_dp; - if (tcp->th_flags & TH_RST) - return -1; /* feedback loop */ -# if (BSD < 199306) || defined(__sgi) - m = m_get(M_DONTWAIT, MT_HEADER); -# else - m = m_gethdr(M_DONTWAIT, MT_HEADER); -# endif - if (m == NULL) - return ENOBUFS; - if (m == NULL) - return -1; - - tlen = fin->fin_dlen - (tcp->th_off << 2) + - ((tcp->th_flags & TH_SYN) ? 1 : 0) + - ((tcp->th_flags & TH_FIN) ? 1 : 0); - -#ifdef USE_INET6 - hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); +#if defined(__sgi) && (IRIX < 60500) +static int write_output(ifp, m, s) #else - hlen = sizeof(ip_t); -#endif - m->m_len = sizeof(*tcp2) + hlen; -# if BSD >= 199306 - m->m_data += max_linkhdr; - m->m_pkthdr.len = m->m_len; - m->m_pkthdr.rcvif = (struct ifnet *)0; -# endif - ip = mtod(m, struct ip *); -# ifdef USE_INET6 - ip6 = (ip6_t *)ip; -# endif - bzero((char *)ip, sizeof(*tcp2) + hlen); - tcp2 = (struct tcphdr *)((char *)ip + hlen); - - tcp2->th_sport = tcp->th_dport; - tcp2->th_dport = tcp->th_sport; - if (tcp->th_flags & TH_ACK) { - tcp2->th_seq = tcp->th_ack; - tcp2->th_flags = TH_RST; - } else { - tcp2->th_ack = ntohl(tcp->th_seq); - tcp2->th_ack += tlen; - tcp2->th_ack = htonl(tcp2->th_ack); - tcp2->th_flags = TH_RST|TH_ACK; - } - tcp2->th_off = sizeof(*tcp2) >> 2; -# ifdef USE_INET6 - if (fin->fin_v == 6) { - ip6->ip6_plen = htons(sizeof(struct tcphdr)); - ip6->ip6_nxt = IPPROTO_TCP; - ip6->ip6_src = oip6->ip6_dst; - ip6->ip6_dst = oip6->ip6_src; - tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, - sizeof(*ip6), sizeof(*tcp2)); - return send_ip(oip, fin, &m); - } -# endif - ip->ip_p = IPPROTO_TCP; - ip->ip_len = htons(sizeof(struct tcphdr)); - ip->ip_src.s_addr = oip->ip_dst.s_addr; - ip->ip_dst.s_addr = oip->ip_src.s_addr; - tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); - ip->ip_len = hlen + sizeof(*tcp2); - return send_ip(oip, fin, &m); -} - - -/* - * Send an IP(v4/v6) datagram out into the network - */ -static int send_ip(oip, fin, mp) -ip_t *oip; -fr_info_t *fin; -struct mbuf **mp; -{ - struct mbuf *m = *mp; - int error, hlen; - fr_info_t frn; - ip_t *ip; - - bzero((char *)&frn, sizeof(frn)); - frn.fin_ifp = fin->fin_ifp; - frn.fin_v = fin->fin_v; - frn.fin_out = fin->fin_out; - frn.fin_mp = mp; - - ip = mtod(m, ip_t *); - hlen = sizeof(*ip); - - ip->ip_v = fin->fin_v; - if (ip->ip_v == 4) { - ip->ip_hl = (sizeof(*oip) >> 2); - ip->ip_v = IPVERSION; - ip->ip_tos = oip->ip_tos; - ip->ip_id = oip->ip_id; - -# if defined(__NetBSD__) || \ - (defined(__OpenBSD__) && (OpenBSD >= 200012)) - if (ip_mtudisc != 0) - ip->ip_off = IP_DF; -# else -# if defined(__sgi) - if (ip->ip_p == IPPROTO_TCP && tcp_mtudisc != 0) - ip->ip_off = IP_DF; -# endif -# endif - -# if (BSD < 199306) || defined(__sgi) - ip->ip_ttl = tcp_ttl; +# if TRU64 >= 1885 +static int write_output (ifp, m, s, rt, cp) +char *cp; # else - ip->ip_ttl = ip_defttl; +static int write_output(ifp, m, s, rt) # endif - ip->ip_sum = 0; - frn.fin_dp = (char *)(ip + 1); - } -# ifdef USE_INET6 - else if (ip->ip_v == 6) { - ip6_t *ip6 = (ip6_t *)ip; - - hlen = sizeof(*ip6); - ip6->ip6_hlim = 127; - frn.fin_dp = (char *)(ip6 + 1); - } -# endif -# ifdef IPSEC - m->m_pkthdr.rcvif = NULL; -# endif - - if (fr_makefrip(hlen, ip, &frn) == 0) - error = ipfr_fastroute(m, mp, &frn, NULL); - else - error = EINVAL; - return error; -} - - -int send_icmp_err(oip, type, fin, dst) -ip_t *oip; -int type; -fr_info_t *fin; -int dst; -{ - int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code; - u_short shlen, slen = 0, soff = 0; - struct in_addr dst4; - struct icmp *icmp; - struct mbuf *m; - void *ifp; -#ifdef USE_INET6 - ip6_t *ip6, *oip6 = (ip6_t *)oip; - struct in6_addr dst6; +struct rtentry *rt; #endif +struct ifnet *ifp; +struct mbuf *m; +struct sockaddr *s; +{ + char fname[32]; + mb_t *mb; ip_t *ip; + int fd; - if ((type < 0) || (type > ICMP_MAXTYPE)) - return -1; - - code = fin->fin_icode; -#ifdef USE_INET6 - if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) - return -1; -#endif - - avail = 0; - m = NULL; - ifp = fin->fin_ifp; - if (fin->fin_v == 4) { - if ((oip->ip_p == IPPROTO_ICMP) && - !(fin->fin_fi.fi_fl & FI_SHORT)) - switch (ntohs(fin->fin_data[0]) >> 8) - { - case ICMP_ECHO : - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - break; - default : - return 0; - } - -# if (BSD < 199306) || defined(__sgi) - avail = MLEN; - m = m_get(M_DONTWAIT, MT_HEADER); -# else - avail = MHLEN; - m = m_gethdr(M_DONTWAIT, MT_HEADER); -# endif - if (m == NULL) - return ENOBUFS; - - if (dst == 0) { - if (fr_ifpaddr(4, ifp, &dst4) == -1) - return -1; - } else - dst4.s_addr = oip->ip_dst.s_addr; - - hlen = sizeof(ip_t); - ohlen = oip->ip_hl << 2; - xtra = 8; - } - -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - hlen = sizeof(ip6_t); - ohlen = sizeof(ip6_t); - type = icmptoicmp6types[type]; - if (type == ICMP6_DST_UNREACH) - code = icmptoicmp6unreach[code]; - - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (!m) - return ENOBUFS; - - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - return ENOBUFS; - } -# ifdef M_TRAILINGSPACE - m->m_len = 0; - avail = M_TRAILINGSPACE(m); -# else - avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; -# endif - xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t), - avail - hlen - sizeof(*icmp) - max_linkhdr); - if (dst == 0) { - if (fr_ifpaddr(6, ifp, (struct in_addr *)&dst6) == -1) - return -1; - } else - dst6 = oip6->ip6_dst; - } -#endif + mb = (mb_t *)m; + ip = MTOD(mb, ip_t *); - iclen = hlen + sizeof(*icmp); -# if BSD >= 199306 - avail -= (max_linkhdr + iclen); - m->m_data += max_linkhdr; - m->m_pkthdr.rcvif = (struct ifnet *)0; - if (xtra > avail) - xtra = avail; - iclen += xtra; - m->m_pkthdr.len = iclen; +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + sprintf(fname, "/tmp/%s", ifp->if_xname); #else - avail -= (m->m_off + iclen); - if (xtra > avail) - xtra = avail; - iclen += xtra; + sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); #endif - m->m_len = iclen; - ip = mtod(m, ip_t *); - icmp = (struct icmp *)((char *)ip + hlen); - bzero((char *)ip, iclen); - - icmp->icmp_type = type; - icmp->icmp_code = fin->fin_icode; - icmp->icmp_cksum = 0; -#ifdef icmp_nextmtu - if (type == ICMP_UNREACH && - fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) - icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu); -#endif - - if (avail) { - slen = oip->ip_len; - oip->ip_len = htons(oip->ip_len); - soff = oip->ip_off; - oip->ip_off = htons(oip->ip_off); - bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail)); - oip->ip_len = slen; - oip->ip_off = soff; - avail -= MIN(ohlen, avail); - } - -#ifdef USE_INET6 - ip6 = (ip6_t *)ip; - if (fin->fin_v == 6) { - ip6->ip6_flow = 0; - ip6->ip6_plen = htons(iclen - hlen); - ip6->ip6_nxt = IPPROTO_ICMPV6; - ip6->ip6_hlim = 0; - ip6->ip6_src = dst6; - ip6->ip6_dst = oip6->ip6_src; - if (avail) - bcopy((char *)oip + ohlen, - (char *)&icmp->icmp_ip + ohlen, avail); - icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, - sizeof(*ip6), iclen - hlen); - } else -#endif - { - - ip->ip_src.s_addr = dst4.s_addr; - ip->ip_dst.s_addr = oip->ip_src.s_addr; - - if (avail > 8) - avail = 8; - if (avail) - bcopy((char *)oip + ohlen, - (char *)&icmp->icmp_ip + ohlen, avail); - icmp->icmp_cksum = ipf_cksum((u_short *)icmp, - sizeof(*icmp) + 8); - ip->ip_len = iclen; - ip->ip_p = IPPROTO_ICMP; - } - - shlen = fin->fin_hlen; - fin->fin_hlen = hlen; - err = send_ip(oip, fin, &m); - fin->fin_hlen = shlen; - - return err; -} - - -# if !defined(IPFILTER_LKM) && !defined(__sgi) && \ - (!defined(__FreeBSD_version) || (__FreeBSD_version < 300000)) -# if (BSD < 199306) -int iplinit __P((void)); - -int -# else -void iplinit __P((void)); - -void -# endif -iplinit() -{ - -# if defined(__NetBSD__) || defined(__OpenBSD__) - if (ipl_enable() != 0) -# else - if (iplattach() != 0) -# endif - { - printf("IP Filter failed to attach\n"); + fd = open(fname, O_WRONLY|O_APPEND); + if (fd == -1) { + perror("open"); + return -1; } - ip_init(); + write(fd, (char *)ip, ntohs(ip->ip_len)); + close(fd); + return 0; } -# endif /* ! __NetBSD__ */ -/* - * Return the length of the entire mbuf. - */ -size_t mbufchainlen(m0) -register struct mbuf *m0; +static void fr_setifpaddr(ifp, addr) +struct ifnet *ifp; +char *addr; { -#if BSD >= 199306 - return m0->m_pkthdr.len; +#ifdef __sgi + struct in_ifaddr *ifa; #else - register size_t len = 0; - - for (; m0; m0 = m0->m_next) - len += m0->m_len; - return len; + struct ifaddr *ifa; #endif -} - - -int ipfr_fastroute(m0, mpp, fin, fdp) -struct mbuf *m0, **mpp; -fr_info_t *fin; -frdest_t *fdp; -{ - register struct ip *ip, *mhip; - register struct mbuf *m = m0; - register struct route *ro; - int len, off, error = 0, hlen, code, sout; - struct ifnet *ifp, *sifp; - struct sockaddr_in *dst; - struct route iproute; - frentry_t *fr; - - ip = NULL; - ro = NULL; - ifp = NULL; - ro = &iproute; - ro->ro_rt = NULL; -#ifdef USE_INET6 - if (fin->fin_v == 6) { - error = ipfr_fastroute6(m0, mpp, fin, fdp); - if (error != 0) - goto bad; - goto done; - } +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + if (ifp->if_addrlist.tqh_first != NULL) #else - if (fin->fin_v == 6) - goto bad; -#endif - -#ifdef M_WRITABLE - /* - * HOT FIX/KLUDGE: - * - * If the mbuf we're about to send is not writable (because of - * a cluster reference, for example) we'll need to make a copy - * of it since this routine modifies the contents. - * - * If you have non-crappy network hardware that can transmit data - * from the mbuf, rather than making a copy, this is gonna be a - * problem. - */ - if (M_WRITABLE(m) == 0) { - if ((m0 = m_dup(m, M_DONTWAIT)) != NULL) { - m_freem(*mpp); - *mpp = m0; - m = m0; - } else { - error = ENOBUFS; - m_freem(*mpp); - goto done; - } - } -#endif - - hlen = fin->fin_hlen; - ip = mtod(m0, struct ip *); - -#if defined(__NetBSD__) && defined(M_CSUM_IPv4) - /* - * Clear any in-bound checksum flags for this packet. - */ -# if (__NetBSD_Version__ > 105009999) - m0->m_pkthdr.csum_flags = 0; +# ifdef __sgi + if (ifp->in_ifaddr != NULL) # else - m0->m_pkthdr.csuminfo = 0; + if (ifp->if_addrlist != NULL) # endif -#endif /* __NetBSD__ && M_CSUM_IPv4 */ - - /* - * Route packet. - */ -#if (defined(IRIX) && (IRIX >= 605)) - ROUTE_RDLOCK(); #endif - bzero((caddr_t)ro, sizeof (*ro)); - dst = (struct sockaddr_in *)&ro->ro_dst; - dst->sin_family = AF_INET; - dst->sin_addr = ip->ip_dst; - - fr = fin->fin_fr; - if (fdp != NULL) - ifp = fdp->fd_ifp; - else - ifp = fin->fin_ifp; + return; - /* - * In case we're here due to "to <if>" being used with "keep state", - * check that we're going in the correct direction. - */ - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) { -# if (defined(IRIX) && (IRIX >= 605)) - ROUTE_UNLOCK(); -# endif - return 0; - } - } else if (fdp != NULL) { - if (fdp->fd_ip.s_addr != 0) - dst->sin_addr = fdp->fd_ip; - } - -# if BSD >= 199306 - dst->sin_len = sizeof(*dst); -# endif -# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ - !defined(__OpenBSD__) -# ifdef RTF_CLONING - rtalloc_ign(ro, RTF_CLONING); -# else - rtalloc_ign(ro, RTF_PRCLONING); -# endif -# else - rtalloc(ro); -# endif - - if (!ifp) { - if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { - error = -2; -# if (defined(IRIX) && (IRIX >= 605)) - ROUTE_UNLOCK(); -# endif - goto bad; - } - } - - if ((ifp == NULL) && (ro->ro_rt != NULL)) - ifp = ro->ro_rt->rt_ifp; - - if ((ro->ro_rt == NULL) || (ifp == NULL)) { - if (in_localaddr(ip->ip_dst)) - error = EHOSTUNREACH; - else - error = ENETUNREACH; -# if (defined(IRIX) && (IRIX >= 605)) - ROUTE_UNLOCK(); -# endif - goto bad; - } - - if (ro->ro_rt->rt_flags & RTF_GATEWAY) { -#if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) - dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; + ifa = (struct ifaddr *)malloc(sizeof(*ifa)); +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + ifp->if_addrlist.tqh_first = ifa; #else - dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; -#endif - } - ro->ro_rt->rt_use++; - -#if (defined(IRIX) && (IRIX > 602)) - ROUTE_UNLOCK(); -#endif - - /* - * For input packets which are being "fastrouted", they won't - * go back through output filtering and miss their chance to get - * NAT'd and counted. - */ - if (fin->fin_out == 0) { - sifp = fin->fin_ifp; - sout = fin->fin_out; - fin->fin_ifp = ifp; - fin->fin_out = 1; - if ((fin->fin_fr = ipacct[1][fr_active]) && - (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { - ATOMIC_INCL(frstats[1].fr_acct); - } - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) - (void) fr_checkstate(ip, fin); - - switch (ip_natout(ip, fin)) - { - case 0 : - break; - case 1 : - ip->ip_sum = 0; - break; - case -1 : - error = EINVAL; - goto done; - break; - } - - fin->fin_ifp = sifp; - fin->fin_out = sout; - } else - ip->ip_sum = 0; - - /* - * If small enough for interface, can just send directly. - */ - if (ip->ip_len <= ifp->if_mtu) { -# ifndef sparc -# if (!defined(__FreeBSD__) && !(_BSDI_VERSION >= 199510)) && \ - !(__NetBSD_Version__ >= 105110000) - ip->ip_id = htons(ip->ip_id); -# endif - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); -# endif -# if defined(__NetBSD__) && defined(M_CSUM_IPv4) -# if (__NetBSD_Version__ > 105009999) - if (ifp->if_csum_flags_tx & IFCAP_CSUM_IPv4) - m->m_pkthdr.csum_flags |= M_CSUM_IPv4; - else if (ip->ip_sum == 0) - ip->ip_sum = in_cksum(m, hlen); -# else - if (ifp->if_capabilities & IFCAP_CSUM_IPv4) - m->m_pkthdr.csuminfo |= M_CSUM_IPv4; - else if (ip->ip_sum == 0) - ip->ip_sum = in_cksum(m, hlen); -# endif -# else - if (!ip->ip_sum) - ip->ip_sum = in_cksum(m, hlen); -# endif /* __NetBSD__ && M_CSUM_IPv4 */ -# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) -# ifdef IRIX - IFNET_UPPERLOCK(ifp); -# endif - error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, - ro->ro_rt); -# ifdef IRIX - IFNET_UPPERUNLOCK(ifp); -# endif -# else - error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -# endif - goto done; - } - - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = EMSGSIZE; - goto bad; - } - len = (ifp->if_mtu - hlen) &~ 7; - if (len < 8) { - error = EMSGSIZE; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_act; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { -# ifdef MGETHDR - MGETHDR(m, M_DONTWAIT, MT_HEADER); -# else - MGET(m, M_DONTWAIT, MT_HEADER); -# endif - if (m == 0) { - error = ENOBUFS; - goto bad; - } -# if BSD >= 199306 - m->m_data += max_linkhdr; -# else - m->m_off = MMAXOFF - hlen; -# endif - mhip = mtod(m, struct ip *); - bcopy((char *)ip, (char *)mhip, sizeof(*ip)); - if (hlen > sizeof (struct ip)) { - mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - mhip->ip_hl = mhlen >> 2; - } - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_short)(len + mhlen)); - m->m_next = m_copy(m0, off, len); - if (m->m_next == 0) { - error = ENOBUFS; /* ??? */ - goto sendorfree; - } -# if BSD >= 199306 - m->m_pkthdr.len = mhlen + len; - m->m_pkthdr.rcvif = NULL; -# endif - mhip->ip_off = htons((u_short)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; - mnext = &m->m_act; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m_adj(m0, hlen + firstlen - ip->ip_len); - ip->ip_len = htons((u_short)(hlen + firstlen)); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m0, hlen); -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_act; - m->m_act = 0; - if (error == 0) -# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); -# else - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst); -# endif - else - m_freem(m); - } - } -done: - if (!error) - ipl_frouteok[0]++; - else - ipl_frouteok[1]++; - - if (ro->ro_rt != NULL) { - RTFREE(ro->ro_rt); - } - *mpp = NULL; - return error; -bad: - if ((error == EMSGSIZE) && (fin->fin_v == 4)) { - sifp = fin->fin_ifp; - code = fin->fin_icode; - fin->fin_icode = ICMP_UNREACH_NEEDFRAG; - fin->fin_ifp = ifp; - (void) send_icmp_err(ip, ICMP_UNREACH, fin, 1); - fin->fin_ifp = sifp; - fin->fin_icode = code; - } - m_freem(m); - goto done; -} - - -/* - * Return true or false depending on whether the route to the - * given IP address uses the same interface as the one passed. - */ -int fr_verifysrc(ipa, ifp) -struct in_addr ipa; -void *ifp; -{ - struct sockaddr_in *dst; - struct route iproute; - - bzero((char *)&iproute, sizeof(iproute)); - dst = (struct sockaddr_in *)&iproute.ro_dst; -# if (BSD >= 199306) - dst->sin_len = sizeof(*dst); -# endif - dst->sin_family = AF_INET; - dst->sin_addr = ipa; -# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ - !defined(__OpenBSD__) -# ifdef RTF_CLONING - rtalloc_ign(&iproute, RTF_CLONING); -# else - rtalloc_ign(&iproute, RTF_PRCLONING); -# endif +# ifdef __sgi + ifp->in_ifaddr = ifa; # else - rtalloc(&iproute); + ifp->if_addrlist = ifa; # endif - if (iproute.ro_rt == NULL) - return 0; - return (ifp == iproute.ro_rt->rt_ifp); -} - - -# ifdef USE_GETIFNAME -char * -get_ifname(ifp) -struct ifnet *ifp; -{ - static char workbuf[64]; - - sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); - return workbuf; -} -# endif - - -# if defined(USE_INET6) -/* - * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's - * or ensure that it is an IPv6 packet that is being forwarded, those are - * expected to be done by the called (ipfr_fastroute). - */ -static int ipfr_fastroute6(m0, mpp, fin, fdp) -struct mbuf *m0, **mpp; -fr_info_t *fin; -frdest_t *fdp; -{ - struct route_in6 ip6route; - struct sockaddr_in6 *dst6; - struct route_in6 *ro; - struct ifnet *ifp; - frentry_t *fr; -#if defined(OpenBSD) && (OpenBSD >= 200211) - struct route_in6 *ro_pmtu = NULL; - struct in6_addr finaldst; - ip6_t *ip6; -#endif - u_long mtu; - int error; - - ro = &ip6route; - fr = fin->fin_fr; - bzero((caddr_t)ro, sizeof(*ro)); - dst6 = (struct sockaddr_in6 *)&ro->ro_dst; - dst6->sin6_family = AF_INET6; - dst6->sin6_len = sizeof(struct sockaddr_in6); - dst6->sin6_addr = fin->fin_fi.fi_dst.in6; - - if (fdp != NULL) - ifp = fdp->fd_ifp; - else - ifp = fin->fin_ifp; - - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return 0; - } else if (fdp != NULL) { - if (IP6_NOTZERO(&fdp->fd_ip6)) - dst6->sin6_addr = fdp->fd_ip6.in6; - } - if (ifp == NULL) - return -2; - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - /* KAME */ - if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) - dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); #endif - rtalloc((struct route *)ro); - if ((ifp == NULL) && (ro->ro_rt != NULL)) - ifp = ro->ro_rt->rt_ifp; + if (ifa != NULL) { + struct sockaddr_in *sin; - if ((ro->ro_rt == NULL) || (ifp == NULL) || - (ifp != ro->ro_rt->rt_ifp)) { - error = EHOSTUNREACH; - } else { - if (ro->ro_rt->rt_flags & RTF_GATEWAY) - dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; - ro->ro_rt->rt_use++; - -#if defined(OpenBSD) && (OpenBSD >= 200211) - ip6 = mtod(m0, ip6_t *); - ro_pmtu = ro; - finaldst = ip6->ip6_dst; - error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu); - if (error == 0) { +#ifdef __sgi + sin = (struct sockaddr_in *)&ifa->ia_addr; #else -# ifdef IN6_LINKMTU - mtu = IN6_LINKMTU(ifp); -# else -# ifdef ND_IFINFO - mtu = ND_IFINFO(ifp)->linkmtu; -# else - mtu = nd_ifinfo[ifp->if_index].linkmtu; -# endif -# endif -#endif - if (m0->m_pkthdr.len <= mtu) - error = nd6_output(ifp, fin->fin_ifp, m0, - dst6, ro->ro_rt); - else - error = EMSGSIZE; -#if defined(OpenBSD) && (OpenBSD >= 200211) - } + sin = (struct sockaddr_in *)&ifa->ifa_addr; #endif + sin->sin_addr.s_addr = inet_addr(addr); + if (sin->sin_addr.s_addr == 0) + abort(); } - - if (ro->ro_rt != NULL) { - RTFREE(ro->ro_rt); - } - return error; } -# endif -#else /* #ifdef _KERNEL */ - -# if defined(__sgi) && (IRIX < 605) -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 +struct ifnet *get_unit(name, v) +char *name; +int v; { - return 0; -} + struct ifnet *ifp, **ifpp, **old_ifneta; + char *addr; +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + if (name == NULL) + name = "anon0"; -# ifdef __STDC__ -# if defined(__sgi) && (IRIX < 605) -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 -{ - ip_t *ip = (ip_t *)m; -# else -static int write_output(ifp, ip) -struct ifnet *ifp; -ip_t *ip; -{ -# endif - char fname[32]; - int fd; + addr = strchr(name, '='); + if (addr != NULL) + *addr++ = '\0'; -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - sprintf(fname, "%s", ifp->if_xname); -# else - sprintf(fname, "%s%d", ifp->if_name, ifp->if_unit); -# endif - fd = open(fname, O_WRONLY|O_APPEND); - if (fd == -1) { - perror("open"); - return -1; + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { + if (!strcmp(name, ifp->if_xname)) { + if (addr != NULL) + fr_setifpaddr(ifp, addr); + return ifp; + } } - write(fd, (char *)ip, ntohs(ip->ip_len)); - close(fd); - return 0; -} - - -char *get_ifname(ifp) -struct ifnet *ifp; -{ -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - return ifp->if_xname; -# else - static char fullifname[LIFNAMSIZ]; - - sprintf(fullifname, "%s%d", ifp->if_name, ifp->if_unit); - return fullifname; -# endif -} - +#else + char *s, ifname[LIFNAMSIZ+1]; -struct ifnet *get_unit(ifname, v) -char *ifname; -int v; -{ - struct ifnet *ifp, **ifa, **old_ifneta; + if (name == NULL) + name = "anon0"; - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - if (!strncmp(ifname, ifp->if_xname, sizeof(ifp->if_xname))) -# else - char fullname[LIFNAMSIZ]; + addr = strchr(name, '='); + if (addr != NULL) + *addr++ = '\0'; - sprintf(fullname, "%s%d", ifp->if_name, ifp->if_unit); - if (!strcmp(ifname, fullname)) -# endif + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { + COPYIFNAME(ifp, ifname); + if (!strcmp(name, ifname)) { + if (addr != NULL) + fr_setifpaddr(ifp, addr); return ifp; + } } +#endif if (!ifneta) { ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); @@ -2150,7 +620,7 @@ int v; old_ifneta = ifneta; nifs++; ifneta = (struct ifnet **)realloc(ifneta, - (nifs + 1) * sizeof(*ifa)); + (nifs + 1) * sizeof(ifp)); if (!ifneta) { free(old_ifneta); nifs = 0; @@ -2165,36 +635,59 @@ int v; } ifp = ifneta[nifs - 1]; -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ifp->if_xname, ifname, sizeof(ifp->if_xname)); -# else - ifp->if_name = strdup(ifname); - - ifname = ifp->if_name; - while (*ifname && !isdigit(*ifname)) - ifname++; - if (*ifname && isdigit(*ifname)) { - ifp->if_unit = atoi(ifname); - *ifname = '\0'; - } else +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + (void) 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); + (void) strncpy(ifp->if_name, name, s - name); + ifp->if_name[s - name] = '\0'; + } else { + ifp->if_name = strdup(name); ifp->if_unit = -1; -# endif + } +#endif ifp->if_output = no_output; + + if (addr != NULL) { + fr_setifpaddr(ifp, addr); + } + return ifp; } +char *get_ifname(ifp) +struct ifnet *ifp; +{ + static char ifname[LIFNAMSIZ]; + +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + sprintf(ifname, "%s", ifp->if_xname); +#else + sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); +#endif + return ifname; +} + + void init_ifp() { - struct ifnet *ifp, **ifa; + struct ifnet *ifp, **ifpp; char fname[32]; int fd; -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = write_output; sprintf(fname, "/tmp/%s", ifp->if_xname); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); @@ -2203,9 +696,9 @@ void init_ifp() else close(fd); } -# else +#else - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = write_output; sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); @@ -2214,12 +707,37 @@ void init_ifp() else close(fd); } +#endif +} + + +int fr_fastroute(m, mpp, fin, fdp) +mb_t *m, **mpp; +fr_info_t *fin; +frdest_t *fdp; +{ + struct ifnet *ifp = fdp->fd_ifp; + ip_t *ip = fin->fin_ip; + + if (!ifp) + return 0; /* 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; +#if defined(__sgi) && (IRIX < 60500) + (*ifp->if_output)(ifp, (void *)ip, NULL); +# if TRU64 >= 1885 + (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); +# else + (*ifp->if_output)(ifp, (void *)m, NULL, 0); # endif +#endif + return 0; } -int send_reset(ip, fin) -ip_t *ip; +int fr_send_reset(fin) fr_info_t *fin; { verbose("- TCP RST sent\n"); @@ -2227,22 +745,30 @@ fr_info_t *fin; } -int send_icmp_err(ip, code, fin, dst) -ip_t *ip; -int code; +int fr_send_icmp_err(type, fin, dst) +int type; fr_info_t *fin; int dst; { - verbose("- ICMP UNREACHABLE sent\n"); + verbose("- ICMP unreachable sent\n"); return 0; } -void frsync() +void frsync(ifp) +void *ifp; { return; } + +void m_freem(m) +mb_t *m; +{ + return; +} + + void m_copydata(m, off, len, cp) mb_t *m; int off, len; @@ -2290,4 +816,152 @@ struct uio *uio; } return 0; } -#endif /* _KERNEL */ + + +u_32_t fr_newisn(fin) +fr_info_t *fin; +{ + static int iss_seq_off = 0; + u_char hash[16]; + u_32_t newiss; + MD5_CTX ctx; + + /* + * Compute the base value of the ISS. It is a hash + * of (saddr, sport, daddr, dport, secret). + */ + MD5Init(&ctx); + + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, + sizeof(fin->fin_fi.fi_src)); + MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, + sizeof(fin->fin_fi.fi_dst)); + MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); + + /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ + + MD5Final(hash, &ctx); + + memcpy(&newiss, hash, sizeof(newiss)); + + /* + * Now increment our "timer", and add it in to + * the computed value. + * + * XXX Use `addin'? + * XXX TCP_ISSINCR too large to use? + */ + iss_seq_off += 0x00010000; + newiss += iss_seq_off; + return newiss; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_nextipid */ +/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Returns the next IPv4 ID to use for this packet. */ +/* ------------------------------------------------------------------------ */ +INLINE u_short fr_nextipid(fin) +fr_info_t *fin; +{ + static u_short ipid = 0; + u_short id; + + MUTEX_ENTER(&ipf_rw); + id = ipid++; + MUTEX_EXIT(&ipf_rw); + + return id; +} + + +INLINE void fr_checkv4sum(fin) +fr_info_t *fin; +{ + if (fr_checkl4sum(fin) == -1) + fin->fin_flx |= FI_BAD; +} + + +#ifdef USE_INET6 +INLINE void fr_checkv6sum(fin) +fr_info_t *fin; +{ + if (fr_checkl4sum(fin) == -1) + fin->fin_flx |= FI_BAD; +} +#endif + + +/* + * See above for description, except that all addressing is in user space. + */ +int copyoutptr(src, dst, size) +void *src, *dst; +size_t size; +{ + caddr_t ca; + + bcopy(dst, (char *)&ca, sizeof(ca)); + bcopy(src, ca, size); + return 0; +} + + +/* + * See above for description, except that all addressing is in user space. + */ +int copyinptr(src, dst, size) +void *src, *dst; +size_t size; +{ + caddr_t ca; + + bcopy(src, (char *)&ca, sizeof(ca)); + bcopy(ca, dst, size); + return 0; +} + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(v, atype, ifptr, inp, inpmask) +int v, atype; +void *ifptr; +struct in_addr *inp, *inpmask; +{ + struct ifnet *ifp = ifptr; +#ifdef __sgi + struct in_ifaddr *ifa; +#else + struct ifaddr *ifa; +#endif + +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + ifa = ifp->if_addrlist.tqh_first; +#else +# ifdef __sgi + ifa = (struct in_ifaddr *)ifp->in_ifaddr; +# else + ifa = ifp->if_addrlist; +# endif +#endif + if (ifa != NULL) { + struct sockaddr_in *sin, mask; + + mask.sin_addr.s_addr = 0xffffffff; + +#ifdef __sgi + sin = (struct sockaddr_in *)&ifa->ia_addr; +#else + sin = (struct sockaddr_in *)&ifa->ifa_addr; +#endif + + return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); + } + return 0; +} |