From 9494d5968ff60672ca84b345e32dde28113cbf36 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 25 Sep 2001 18:40:52 +0000 Subject: [PATCH] Make faith loadable, unloadable, and clonable. --- share/man/man4/faith.4 | 2 +- sys/conf/files | 2 +- sys/modules/Makefile | 1 + sys/modules/if_faith/Makefile | 15 +++ sys/net/if_faith.c | 185 ++++++++++++++++++++++++++-------- sys/net/if_faith.h | 43 -------- sys/netinet/in_pcb.c | 4 - sys/netinet/ip_icmp.c | 8 +- sys/netinet/ip_input.c | 10 +- sys/netinet/ip_output.c | 10 -- sys/netinet6/icmp6.c | 9 +- sys/netinet6/in6.c | 2 + sys/netinet6/in6.h | 2 + sys/netinet6/in6_pcb.c | 14 +-- sys/netinet6/ip6_input.c | 4 - sys/netinet6/raw_ip6.c | 9 +- sys/netinet6/udp6_output.c | 2 - sys/netinet6/udp6_usrreq.c | 9 +- 18 files changed, 174 insertions(+), 157 deletions(-) create mode 100644 sys/modules/if_faith/Makefile delete mode 100644 sys/net/if_faith.h diff --git a/share/man/man4/faith.4 b/share/man/man4/faith.4 index c87563c7906f..576496fddd7e 100644 --- a/share/man/man4/faith.4 +++ b/share/man/man4/faith.4 @@ -36,7 +36,7 @@ .Nm faith .Nd IPv6-to-IPv4 TCP relay capturing interface .Sh SYNOPSIS -.Cd "device faith" Op Ar count +.Cd "device faith" .Sh DESCRIPTION The .Nm diff --git a/sys/conf/files b/sys/conf/files index d97bb7890416..d43edbd3e8f9 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -903,7 +903,7 @@ net/if_atmsubr.c optional atm net/if_disc.c optional disc net/if_ef.c optional ef net/if_ethersubr.c optional ether -net/if_faith.c count faith +net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_gif.c optional gif net/if_iso88025subr.c optional token diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 445127fafd59..f7ef8f94b4e7 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -28,6 +28,7 @@ SUBDIR= 3dfx \ if_disc \ if_ef \ if_gif \ + if_faith \ if_ppp \ if_sl \ if_stf \ diff --git a/sys/modules/if_faith/Makefile b/sys/modules/if_faith/Makefile new file mode 100644 index 000000000000..1f6e4a9cb9c3 --- /dev/null +++ b/sys/modules/if_faith/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../net + +KMOD= if_faith +SRCS= if_faith.c opt_inet.h opt_inet6.h +NOMAN= + +opt_inet.h: + echo "#define INET 1" > ${.TARGET} + +opt_inet6.h: + echo "#define INET6 1" > ${.TARGET} + +.include diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c index 631049f4d5e8..1dac1b686dde 100644 --- a/sys/net/if_faith.c +++ b/sys/net/if_faith.c @@ -46,9 +46,6 @@ #include "opt_inet.h" #include "opt_inet6.h" -#include "faith.h" -#if NFAITH > 0 - #include #include #include @@ -58,13 +55,16 @@ #include #include #include +#include +#include +#include /* XXX: Shouldn't really be required! */ +#include #include #include #include #include #include -#include #ifdef INET #include @@ -82,54 +82,157 @@ #include #endif -#include "bpf.h" -#define NBPFILTER NBPF - #include +#define FAITHNAME "faith" +#define FAITH_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ + +struct faith_softc { + struct ifnet sc_if; /* must be first */ + struct resource *r_unit; + LIST_ENTRY(faith_softc) sc_list; +}; + static int faithioctl __P((struct ifnet *, u_long, caddr_t)); int faithoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); static void faithrtrequest __P((int, struct rtentry *, struct sockaddr *)); +static int faithprefix __P((struct in6_addr *)); -void faithattach __P((void *)); -PSEUDO_SET(faithattach, if_faith); +static int faithmodevent __P((module_t, int, void *)); -static struct ifnet faithif[NFAITH]; +static MALLOC_DEFINE(M_FAITH, FAITHNAME, "Firewall Assisted Tunnel Interface"); +static struct rman faithunits[1]; +LIST_HEAD(, faith_softc) faith_softc_list; + +int faith_clone_create __P((struct if_clone *, int *)); +void faith_clone_destroy __P((struct ifnet *)); + +struct if_clone faith_cloner = + IF_CLONE_INITIALIZER(FAITHNAME, faith_clone_create, faith_clone_destroy); #define FAITHMTU 1500 -/* ARGSUSED */ -void -faithattach(faith) - void *faith; +static int +faithmodevent(mod, type, data) + module_t mod; + int type; + void *data; { - struct ifnet *ifp; - int i; + int err; - for (i = 0; i < NFAITH; i++) { - ifp = &faithif[i]; - bzero(ifp, sizeof(faithif[i])); - ifp->if_name = "faith"; - ifp->if_unit = i; - ifp->if_mtu = FAITHMTU; - /* LOOPBACK commented out to announce IPv6 routes to faith */ - ifp->if_flags = /* IFF_LOOPBACK | */ IFF_MULTICAST; - ifp->if_ioctl = faithioctl; - ifp->if_output = faithoutput; - ifp->if_type = IFT_FAITH; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_hdrlen = 0; - ifp->if_addrlen = 0; - if_attach(ifp); -#if NBPFILTER > 0 -#ifdef HAVE_OLD_BPF - bpfattach(ifp, DLT_NULL, sizeof(u_int)); -#else - bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int)); + switch (type) { + case MOD_LOAD: + faithunits->rm_type = RMAN_ARRAY; + faithunits->rm_descr = "configurable if_faith units"; + err = rman_init(faithunits); + if (err != 0) + return (err); + err = rman_manage_region(faithunits, 0, FAITH_MAXUNIT); + if (err != 0) { + printf("%s: faithunits: rman_manage_region: " + "Failed %d\n", FAITHNAME, err); + rman_fini(faithunits); + return (err); + } + LIST_INIT(&faith_softc_list); + if_clone_attach(&faith_cloner); + +#ifdef INET6 + faithprefix_p = faithprefix; #endif + + break; + case MOD_UNLOAD: +#ifdef INET6 + faithprefix_p = NULL; #endif + + if_clone_detach(&faith_cloner); + + while (!LIST_EMPTY(&faith_softc_list)) + faith_clone_destroy( + &LIST_FIRST(&faith_softc_list)->sc_if); + + err = rman_fini(faithunits); + if (err != 0) + return (err); + + break; } + return 0; +} + +static moduledata_t faith_mod = { + "if_faith", + faithmodevent, + 0 +}; + +DECLARE_MODULE(if_faith, faith_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +MODULE_VERSION(if_faith, 1); + +int +faith_clone_create(ifc, unit) + struct if_clone *ifc; + int *unit; +{ + struct resource *r; + struct faith_softc *sc; + + if (*unit > FAITH_MAXUNIT) + return (ENXIO); + + if (*unit < 0) { + r = rman_reserve_resource(faithunits, 0, FAITH_MAXUNIT, 1, + RF_ALLOCATED | RF_ACTIVE, NULL); + if (r == NULL) + return (ENOSPC); + *unit = rman_get_start(r); + } else { + r = rman_reserve_resource(faithunits, *unit, *unit, 1, + RF_ALLOCATED | RF_ACTIVE, NULL); + if (r == NULL) + return (ENOSPC); + } + + sc = malloc(sizeof(struct faith_softc), M_FAITH, M_WAITOK); + bzero(sc, sizeof(struct faith_softc)); + + sc->sc_if.if_softc = sc; + sc->sc_if.if_name = FAITHNAME; + sc->sc_if.if_unit = *unit; + sc->r_unit = r; + + sc->sc_if.if_mtu = FAITHMTU; + /* Change to BROADCAST experimentaly to announce its prefix. */ + sc->sc_if.if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST; + sc->sc_if.if_ioctl = faithioctl; + sc->sc_if.if_output = faithoutput; + sc->sc_if.if_type = IFT_FAITH; + sc->sc_if.if_hdrlen = 0; + sc->sc_if.if_addrlen = 0; + if_attach(&sc->sc_if); + bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); + LIST_INSERT_HEAD(&faith_softc_list, sc, sc_list); + return (0); +} + +void +faith_clone_destroy(ifp) + struct ifnet *ifp; +{ + int err; + struct faith_softc *sc = (void *) ifp; + + LIST_REMOVE(sc, sc_list); + bpfdetach(ifp); + if_detach(ifp); + + err = rman_release_resource(sc->r_unit); + KASSERT(err == 0, ("Unexpected error freeing resource")); + + free(sc, M_FAITH); } int @@ -144,7 +247,7 @@ faithoutput(ifp, m, dst, rt) if ((m->m_flags & M_PKTHDR) == 0) panic("faithoutput no HDR"); -#if NBPFILTER > 0 + /* BPF write needs to be handled specially */ if (dst->sa_family == AF_UNSPEC) { dst->sa_family = *(mtod(m, int *)); @@ -168,13 +271,8 @@ faithoutput(ifp, m, dst, rt) m0.m_len = 4; m0.m_data = (char *)⁡ -#ifdef HAVE_OLD_BPF bpf_mtap(ifp, &m0); -#else - bpf_mtap(ifp->if_bpf, &m0); -#endif } -#endif if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); @@ -297,7 +395,7 @@ faithioctl(ifp, cmd, data) * XXX could be slow * XXX could be layer violation to call sys/net from sys/netinet6 */ -int +static int faithprefix(in6) struct in6_addr *in6; { @@ -323,4 +421,3 @@ faithprefix(in6) return ret; } #endif -#endif /* NFAITH > 0 */ diff --git a/sys/net/if_faith.h b/sys/net/if_faith.h deleted file mode 100644 index 7fa9b5a04c70..000000000000 --- a/sys/net/if_faith.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $FreeBSD$ */ -/* $KAME: if_faith.h,v 1.1 2000/07/26 05:49:21 itojun Exp $ */ - -/* - * Copyright (C) 2000 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _NET_IF_FAITH_H_ -#define _NET_IF_FAITH_H_ - -#ifdef _KERNEL -#ifdef INET6 -struct in6_addr; -int faithprefix __P((struct in6_addr *)); -#endif -#endif - -#endif /* _NET_IF_FAITH_H_ */ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 0b5402450fce..1db834c965d8 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -67,8 +67,6 @@ #include #endif /* INET6 */ -#include "faith.h" - #ifdef IPSEC #include #include @@ -919,11 +917,9 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, #endif if (inp->inp_faddr.s_addr == INADDR_ANY && inp->inp_lport == lport) { -#if defined(NFAITH) && NFAITH > 0 if (ifp && ifp->if_type == IFT_FAITH && (inp->inp_flags & INP_FAITH) == 0) continue; -#endif if (inp->inp_laddr.s_addr == laddr.s_addr) return (inp); else if (inp->inp_laddr.s_addr == INADDR_ANY) { diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index ac38d9debdf9..566451695234 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -46,6 +46,7 @@ #include #include +#include #include #define _IP_VHL @@ -62,11 +63,6 @@ #include #endif -#include "faith.h" -#if defined(NFAITH) && NFAITH > 0 -#include -#endif - #include /* @@ -275,7 +271,6 @@ icmp_input(m, off) m->m_len += hlen; m->m_data -= hlen; -#if defined(NFAITH) && 0 < NFAITH if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { /* * Deliver very specific ICMP type only. @@ -288,7 +283,6 @@ icmp_input(m, off) goto freeit; } } -#endif #ifdef ICMPPRINTFS if (icmpprintfs) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 69eb78d8e06b..d80c7d4f72cb 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -60,6 +60,7 @@ #include #include +#include #include #include #include @@ -84,11 +85,6 @@ #include #endif -#include "faith.h" -#if defined(NFAITH) && NFAITH > 0 -#include -#endif - #ifdef DUMMYNET #include #endif @@ -557,6 +553,7 @@ ip_input(struct mbuf *m) * the packets are received. */ checkif = ip_checkinterface && (ipforwarding == 0) && + m->m_pkthdr.rcvif != NULL && ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) && (ip_fw_fwd_addr == NULL); @@ -634,7 +631,6 @@ ip_input(struct mbuf *m) if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; -#if defined(NFAITH) && 0 < NFAITH /* * FAITH(Firewall Aided Internet Translator) */ @@ -646,7 +642,7 @@ ip_input(struct mbuf *m) m_freem(m); return; } -#endif + /* * Not for us; forward if possible and desirable. */ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 86b321e2f1c8..bd09521b1846 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -63,8 +63,6 @@ #include #include -#include "faith.h" - #include static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); @@ -1166,9 +1164,7 @@ ip_ctloutput(so, sopt) case IP_RECVRETOPTS: case IP_RECVDSTADDR: case IP_RECVIF: -#if defined(NFAITH) && NFAITH > 0 case IP_FAITH: -#endif error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) @@ -1204,11 +1200,9 @@ ip_ctloutput(so, sopt) OPTSET(INP_RECVIF); break; -#if defined(NFAITH) && NFAITH > 0 case IP_FAITH: OPTSET(INP_FAITH); break; -#endif } break; #undef OPTSET @@ -1300,9 +1294,7 @@ ip_ctloutput(so, sopt) case IP_RECVDSTADDR: case IP_RECVIF: case IP_PORTRANGE: -#if defined(NFAITH) && NFAITH > 0 case IP_FAITH: -#endif switch (sopt->sopt_name) { case IP_TOS: @@ -1340,11 +1332,9 @@ ip_ctloutput(so, sopt) optval = 0; break; -#if defined(NFAITH) && NFAITH > 0 case IP_FAITH: optval = OPTBIT(INP_FAITH); break; -#endif } error = sooptcopyout(sopt, &optval, sizeof optval); break; diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index fad1e05d7fa0..2ae56e9132c6 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -103,11 +103,6 @@ #include #endif -#include "faith.h" -#if defined(NFAITH) && 0 < NFAITH -#include -#endif - #include #ifdef HAVE_NRL_INPCB @@ -439,8 +434,7 @@ icmp6_input(mp, offp, proto) goto freeit; } -#if defined(NFAITH) && 0 < NFAITH - if (faithprefix(&ip6->ip6_dst)) { + if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { /* * Deliver very specific ICMP6 type only. * This is important to deilver TOOBIG. Otherwise PMTUD @@ -455,7 +449,6 @@ icmp6_input(mp, offp, proto) goto freeit; } } -#endif icmp6stat.icp6s_inhist[icmp6->icmp6_type]++; icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index c17bf55872cd..8c837e14d79e 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -138,6 +138,8 @@ static void in6_unlink_ifa __P((struct in6_ifaddr *, struct ifnet *)); struct in6_multihead in6_multihead; /* XXX BSS initialization */ +int (*faithprefix_p)(struct in6_addr *); + /* * Subroutine for in6_ifaddloop() and in6_ifremloop(). * This routine does actual work. diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 6ef9cc4c5617..b16af5f6cc73 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -600,6 +600,8 @@ void in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam)); #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) #define sin6tosa(sin6) ((struct sockaddr *)(sin6)) #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) + +extern int (*faithprefix_p)(struct in6_addr *); #endif /* _KERNEL */ __BEGIN_DECLS diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index fa6704316faa..430d5e5877e5 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -100,11 +100,6 @@ #include #include -#include "faith.h" -#if defined(NFAITH) && NFAITH > 0 -#include -#endif - #ifdef IPSEC #include #ifdef INET6 @@ -1039,11 +1034,10 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp) u_short fport = fport_arg, lport = lport_arg; int faith; -#if defined(NFAITH) && NFAITH > 0 - faith = faithprefix(laddr); -#else - faith = 0; -#endif + if (faithprefix_p != NULL) + faith = (*faithprefix_p)(laddr); + else + faith = 0; /* * First look for an exact match. diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index c426e1376419..77557f3e3458 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -121,8 +121,6 @@ #include -#include "faith.h" - #include extern struct domain inet6domain; @@ -633,7 +631,6 @@ ip6_input(m) /* * FAITH(Firewall Aided Internet Translator) */ -#if defined(NFAITH) && 0 < NFAITH if (ip6_keepfaith) { if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) { @@ -643,7 +640,6 @@ ip6_input(m) goto hbhcheck; } } -#endif /* * Now there is no reason to process the packet if it's not our own diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 5f896688507a..10a73cb2399c 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -104,11 +104,6 @@ #include -#include "faith.h" -#if defined(NFAITH) && 0 < NFAITH -#include -#endif - #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) @@ -142,13 +137,11 @@ rip6_input(mp, offp, proto) rip6stat.rip6s_ipackets++; -#if defined(NFAITH) && 0 < NFAITH - if (faithprefix(&ip6->ip6_dst)) { + if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { /* XXX send icmp6 host/port unreach? */ m_freem(m); return IPPROTO_DONE; } -#endif init_sin6(&rip6src, m); /* general init */ diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index 37a820dd8a5c..d1d6a19bb3fc 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -107,8 +107,6 @@ #endif #endif /*IPSEC*/ -#include "faith.h" - #include /* diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 6440dbebc236..448945dae0bd 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -106,11 +106,6 @@ #include #endif /*IPSEC*/ -#include "faith.h" -#if defined(NFAITH) && NFAITH > 0 -#include -#endif - /* * UDP protocol inplementation. * Per RFC 768, August, 1980. @@ -161,13 +156,11 @@ udp6_input(mp, offp, proto) ip6 = mtod(m, struct ip6_hdr *); -#if defined(NFAITH) && 0 < NFAITH - if (faithprefix(&ip6->ip6_dst)) { + if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { /* XXX send icmp6 host/port unreach? */ m_freem(m); return IPPROTO_DONE; } -#endif udpstat.udps_ipackets++;