if_faith.c revision 231852
1179737Sjfv/* $KAME: if_faith.c,v 1.23 2001/12/17 13:55:29 sumikawa Exp $ */ 2179737Sjfv 3179737Sjfv/*- 4179737Sjfv * Copyright (c) 1982, 1986, 1993 5179737Sjfv * The Regents of the University of California. All rights reserved. 6179737Sjfv * 7179737Sjfv * Redistribution and use in source and binary forms, with or without 8179737Sjfv * modification, are permitted provided that the following conditions 9179737Sjfv * are met: 10179737Sjfv * 1. Redistributions of source code must retain the above copyright 11179737Sjfv * notice, this list of conditions and the following disclaimer. 12179737Sjfv * 2. Redistributions in binary form must reproduce the above copyright 13179737Sjfv * notice, this list of conditions and the following disclaimer in the 14179737Sjfv * documentation and/or other materials provided with the distribution. 15179737Sjfv * 4. Neither the name of the University nor the names of its contributors 16179737Sjfv * may be used to endorse or promote products derived from this software 17179737Sjfv * without specific prior written permission. 18179737Sjfv * 19179737Sjfv * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20179737Sjfv * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21179737Sjfv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22179737Sjfv * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23179737Sjfv * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24179737Sjfv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25179737Sjfv * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26179737Sjfv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27179737Sjfv * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28179737Sjfv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29179737Sjfv * SUCH DAMAGE. 30179737Sjfv * 31179737Sjfv * $FreeBSD: head/sys/net/if_faith.c 231852 2012-02-17 02:39:58Z bz $ 32179737Sjfv */ 33179737Sjfv/* 34179737Sjfv * derived from 35179737Sjfv * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 36179737Sjfv * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp 37179737Sjfv */ 38179737Sjfv 39179737Sjfv/* 40179737Sjfv * Loopback interface driver for protocol testing and timing. 41179737Sjfv */ 42179737Sjfv#include "opt_inet.h" 43179737Sjfv#include "opt_inet6.h" 44179737Sjfv 45179737Sjfv#include <sys/param.h> 46179737Sjfv#include <sys/systm.h> 47179737Sjfv#include <sys/kernel.h> 48179737Sjfv#include <sys/mbuf.h> 49179737Sjfv#include <sys/module.h> 50179737Sjfv#include <sys/socket.h> 51179737Sjfv#include <sys/errno.h> 52179737Sjfv#include <sys/sockio.h> 53179737Sjfv#include <sys/time.h> 54179737Sjfv#include <sys/queue.h> 55179737Sjfv#include <sys/types.h> 56179737Sjfv#include <sys/malloc.h> 57179737Sjfv 58179737Sjfv#include <net/if.h> 59179737Sjfv#include <net/if_clone.h> 60179737Sjfv#include <net/if_types.h> 61179737Sjfv#include <net/netisr.h> 62179737Sjfv#include <net/route.h> 63179737Sjfv#include <net/bpf.h> 64179737Sjfv#include <net/vnet.h> 65179737Sjfv 66179737Sjfv#ifdef INET 67179737Sjfv#include <netinet/in.h> 68179737Sjfv#include <netinet/in_systm.h> 69179737Sjfv#include <netinet/in_var.h> 70179737Sjfv#include <netinet/ip.h> 71179737Sjfv#endif 72179737Sjfv 73179737Sjfv#ifdef INET6 74179737Sjfv#ifndef INET 75179737Sjfv#include <netinet/in.h> 76179737Sjfv#endif 77179737Sjfv#include <netinet6/in6_var.h> 78179737Sjfv#include <netinet/ip6.h> 79179737Sjfv#include <netinet6/ip6_var.h> 80179737Sjfv#endif 81179737Sjfv 82179737Sjfv#define FAITHNAME "faith" 83179737Sjfv 84179737Sjfvstruct faith_softc { 85179737Sjfv struct ifnet *sc_ifp; 86179737Sjfv}; 87179737Sjfv 88179737Sjfvstatic int faithioctl(struct ifnet *, u_long, caddr_t); 89179737Sjfvint faithoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 90179737Sjfv struct route *); 91179737Sjfvstatic void faithrtrequest(int, struct rtentry *, struct rt_addrinfo *); 92179737Sjfv#ifdef INET6 93179737Sjfvstatic int faithprefix(struct in6_addr *); 94179737Sjfv#endif 95179737Sjfv 96179737Sjfvstatic int faithmodevent(module_t, int, void *); 97179737Sjfv 98179737Sjfvstatic MALLOC_DEFINE(M_FAITH, FAITHNAME, "Firewall Assisted Tunnel Interface"); 99179737Sjfv 100179737Sjfvstatic int faith_clone_create(struct if_clone *, int, caddr_t); 101179737Sjfvstatic void faith_clone_destroy(struct ifnet *); 102179737Sjfv 103179737SjfvIFC_SIMPLE_DECLARE(faith, 0); 104179737Sjfv 105179737Sjfv#define FAITHMTU 1500 106179737Sjfv 107179737Sjfvstatic int 108179737Sjfvfaithmodevent(mod, type, data) 109179737Sjfv module_t mod; 110179737Sjfv int type; 111217126Sjhb void *data; 112179737Sjfv{ 113179737Sjfv 114179737Sjfv switch (type) { 115179737Sjfv case MOD_LOAD: 116179737Sjfv if_clone_attach(&faith_cloner); 117179737Sjfv 118179737Sjfv#ifdef INET6 119179737Sjfv faithprefix_p = faithprefix; 120179737Sjfv#endif 121179737Sjfv 122179737Sjfv break; 123179737Sjfv case MOD_UNLOAD: 124179737Sjfv#ifdef INET6 125179737Sjfv faithprefix_p = NULL; 126179737Sjfv#endif 127179737Sjfv 128179737Sjfv if_clone_detach(&faith_cloner); 129179737Sjfv break; 130179737Sjfv default: 131179737Sjfv return EOPNOTSUPP; 132179737Sjfv } 133179737Sjfv return 0; 134179737Sjfv} 135179737Sjfv 136179737Sjfvstatic moduledata_t faith_mod = { 137179737Sjfv "if_faith", 138179737Sjfv faithmodevent, 139179737Sjfv 0 140179737Sjfv}; 141179737Sjfv 142179737SjfvDECLARE_MODULE(if_faith, faith_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 143179737SjfvMODULE_VERSION(if_faith, 1); 144179737Sjfv 145179737Sjfvstatic int 146179737Sjfvfaith_clone_create(ifc, unit, params) 147179737Sjfv struct if_clone *ifc; 148179737Sjfv int unit; 149179737Sjfv caddr_t params; 150179737Sjfv{ 151179737Sjfv struct ifnet *ifp; 152179737Sjfv struct faith_softc *sc; 153179737Sjfv 154179737Sjfv sc = malloc(sizeof(struct faith_softc), M_FAITH, M_WAITOK | M_ZERO); 155179737Sjfv ifp = sc->sc_ifp = if_alloc(IFT_FAITH); 156179737Sjfv if (ifp == NULL) { 157179737Sjfv free(sc, M_FAITH); 158179737Sjfv return (ENOSPC); 159179737Sjfv } 160179737Sjfv 161179737Sjfv ifp->if_softc = sc; 162179737Sjfv if_initname(sc->sc_ifp, ifc->ifc_name, unit); 163179737Sjfv 164179737Sjfv ifp->if_mtu = FAITHMTU; 165179737Sjfv /* Change to BROADCAST experimentaly to announce its prefix. */ 166179737Sjfv ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST; 167179737Sjfv ifp->if_ioctl = faithioctl; 168179737Sjfv ifp->if_output = faithoutput; 169179737Sjfv ifp->if_hdrlen = 0; 170179737Sjfv ifp->if_addrlen = 0; 171179737Sjfv ifp->if_snd.ifq_maxlen = ifqmaxlen; 172179737Sjfv if_attach(ifp); 173179737Sjfv bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 174179737Sjfv return (0); 175179737Sjfv} 176179737Sjfv 177179737Sjfvstatic void 178179737Sjfvfaith_clone_destroy(ifp) 179179737Sjfv struct ifnet *ifp; 180179737Sjfv{ 181179737Sjfv struct faith_softc *sc = ifp->if_softc; 182179737Sjfv 183179737Sjfv bpfdetach(ifp); 184179737Sjfv if_detach(ifp); 185179737Sjfv if_free(ifp); 186179737Sjfv free(sc, M_FAITH); 187182089Skmacy} 188179737Sjfv 189179737Sjfvint 190179737Sjfvfaithoutput(ifp, m, dst, ro) 191179737Sjfv struct ifnet *ifp; 192179737Sjfv struct mbuf *m; 193179737Sjfv struct sockaddr *dst; 194179737Sjfv struct route *ro; 195179737Sjfv{ 196179737Sjfv int isr; 197179737Sjfv u_int32_t af; 198179737Sjfv struct rtentry *rt = NULL; 199179737Sjfv 200179737Sjfv M_ASSERTPKTHDR(m); 201179737Sjfv 202179737Sjfv if (ro != NULL) 203179737Sjfv rt = ro->ro_rt; 204179737Sjfv /* BPF writes need to be handled specially. */ 205179737Sjfv if (dst->sa_family == AF_UNSPEC) { 206179737Sjfv bcopy(dst->sa_data, &af, sizeof(af)); 207182089Skmacy dst->sa_family = af; 208182089Skmacy } 209182089Skmacy 210182089Skmacy if (bpf_peers_present(ifp->if_bpf)) { 211182089Skmacy af = dst->sa_family; 212182089Skmacy bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); 213182089Skmacy } 214182089Skmacy 215182089Skmacy if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 216182089Skmacy m_freem(m); 217182089Skmacy return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 218182089Skmacy rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 219179737Sjfv } 220182089Skmacy ifp->if_opackets++; 221179737Sjfv ifp->if_obytes += m->m_pkthdr.len; 222179737Sjfv switch (dst->sa_family) { 223179737Sjfv#ifdef INET 224179737Sjfv case AF_INET: 225179737Sjfv isr = NETISR_IP; 226179737Sjfv break; 227179737Sjfv#endif 228179737Sjfv#ifdef INET6 229179737Sjfv case AF_INET6: 230179737Sjfv isr = NETISR_IPV6; 231179737Sjfv break; 232179737Sjfv#endif 233179737Sjfv default: 234179737Sjfv m_freem(m); 235179737Sjfv return EAFNOSUPPORT; 236179737Sjfv } 237179737Sjfv 238179737Sjfv /* XXX do we need more sanity checks? */ 239179737Sjfv 240179737Sjfv m->m_pkthdr.rcvif = ifp; 241179737Sjfv ifp->if_ipackets++; 242179737Sjfv ifp->if_ibytes += m->m_pkthdr.len; 243179737Sjfv netisr_dispatch(isr, m); 244179737Sjfv return (0); 245179737Sjfv} 246179737Sjfv 247179737Sjfv/* ARGSUSED */ 248179737Sjfvstatic void 249179737Sjfvfaithrtrequest(cmd, rt, info) 250179737Sjfv int cmd; 251179737Sjfv struct rtentry *rt; 252179737Sjfv struct rt_addrinfo *info; 253179737Sjfv{ 254179737Sjfv RT_LOCK_ASSERT(rt); 255179737Sjfv rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; 256179737Sjfv} 257179737Sjfv 258179737Sjfv/* 259179737Sjfv * Process an ioctl request. 260179737Sjfv */ 261179737Sjfv/* ARGSUSED */ 262179737Sjfvstatic int 263179737Sjfvfaithioctl(ifp, cmd, data) 264179737Sjfv struct ifnet *ifp; 265179737Sjfv u_long cmd; 266179737Sjfv caddr_t data; 267179737Sjfv{ 268179737Sjfv struct ifaddr *ifa; 269179737Sjfv struct ifreq *ifr = (struct ifreq *)data; 270179737Sjfv int error = 0; 271179737Sjfv 272179737Sjfv switch (cmd) { 273179737Sjfv 274179737Sjfv case SIOCSIFADDR: 275179737Sjfv ifp->if_flags |= IFF_UP; 276179737Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 277179737Sjfv ifa = (struct ifaddr *)data; 278179737Sjfv ifa->ifa_rtrequest = faithrtrequest; 279179737Sjfv /* 280223797Scperciva * Everything else is done at a higher level. 281223797Scperciva */ 282223797Scperciva break; 283223797Scperciva 284223797Scperciva case SIOCADDMULTI: 285223797Scperciva case SIOCDELMULTI: 286223797Scperciva if (ifr == 0) { 287223797Scperciva error = EAFNOSUPPORT; /* XXX */ 288179737Sjfv break; 289179737Sjfv } 290220428Sjfv switch (ifr->ifr_addr.sa_family) { 291220428Sjfv#ifdef INET 292220428Sjfv case AF_INET: 293220428Sjfv break; 294179737Sjfv#endif 295179737Sjfv#ifdef INET6 296179737Sjfv case AF_INET6: 297179737Sjfv break; 298179737Sjfv#endif 299179737Sjfv 300179737Sjfv default: 301179737Sjfv error = EAFNOSUPPORT; 302179737Sjfv break; 303179737Sjfv } 304179737Sjfv break; 305179737Sjfv 306179737Sjfv#ifdef SIOCSIFMTU 307179737Sjfv case SIOCSIFMTU: 308179737Sjfv ifp->if_mtu = ifr->ifr_mtu; 309179737Sjfv break; 310179737Sjfv#endif 311179737Sjfv 312179737Sjfv case SIOCSIFFLAGS: 313179737Sjfv break; 314179737Sjfv 315179737Sjfv default: 316179737Sjfv error = EINVAL; 317179737Sjfv } 318179737Sjfv return (error); 319179737Sjfv} 320179737Sjfv 321179737Sjfv#ifdef INET6 322179737Sjfv/* 323179737Sjfv * XXX could be slow 324179737Sjfv * XXX could be layer violation to call sys/net from sys/netinet6 325179737Sjfv */ 326179737Sjfvstatic int 327179737Sjfvfaithprefix(in6) 328179737Sjfv struct in6_addr *in6; 329179737Sjfv{ 330179737Sjfv struct rtentry *rt; 331179737Sjfv struct sockaddr_in6 sin6; 332179737Sjfv int ret; 333179737Sjfv 334179737Sjfv if (V_ip6_keepfaith == 0) 335179737Sjfv return 0; 336179737Sjfv 337179737Sjfv bzero(&sin6, sizeof(sin6)); 338179737Sjfv sin6.sin6_family = AF_INET6; 339179737Sjfv sin6.sin6_len = sizeof(struct sockaddr_in6); 340179737Sjfv sin6.sin6_addr = *in6; 341179737Sjfv rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB); 342179737Sjfv if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH && 343179737Sjfv (rt->rt_ifp->if_flags & IFF_UP) != 0) 344179737Sjfv ret = 1; 345179737Sjfv else 346179737Sjfv ret = 0; 347179737Sjfv if (rt) 348179737Sjfv RTFREE_LOCKED(rt); 349179737Sjfv return ret; 350179737Sjfv} 351179737Sjfv#endif 352179737Sjfv