if_loop.c revision 113255
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 3385051Sru * @(#)if_loop.c 8.2 (Berkeley) 1/9/95 3450477Speter * $FreeBSD: head/sys/net/if_loop.c 113255 2003-04-08 14:25:47Z des $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * Loopback interface driver for protocol testing and timing. 391541Srgrimes */ 401541Srgrimes 4132356Seivind#include "opt_atalk.h" 4232350Seivind#include "opt_inet.h" 4354263Sshin#include "opt_inet6.h" 4431742Seivind#include "opt_ipx.h" 45108041Srwatson#include "opt_mac.h" 4631742Seivind 471541Srgrimes#include <sys/param.h> 481541Srgrimes#include <sys/systm.h> 491541Srgrimes#include <sys/kernel.h> 50108041Srwatson#include <sys/mac.h> 5171791Speter#include <sys/malloc.h> 521541Srgrimes#include <sys/mbuf.h> 5371862Speter#include <sys/module.h> 5491648Sbrooks#include <machine/bus.h> 5591648Sbrooks#include <sys/rman.h> 561541Srgrimes#include <sys/socket.h> 5724204Sbde#include <sys/sockio.h> 5871791Speter#include <sys/sysctl.h> 591541Srgrimes 601541Srgrimes#include <net/if.h> 611541Srgrimes#include <net/if_types.h> 621541Srgrimes#include <net/netisr.h> 631541Srgrimes#include <net/route.h> 641541Srgrimes#include <net/bpf.h> 6578064Sume#include <net/bpfdesc.h> 661541Srgrimes 671541Srgrimes#ifdef INET 681541Srgrimes#include <netinet/in.h> 691541Srgrimes#include <netinet/in_var.h> 701541Srgrimes#endif 711541Srgrimes 7211819Sjulian#ifdef IPX 7311819Sjulian#include <netipx/ipx.h> 7411819Sjulian#include <netipx/ipx_if.h> 7511819Sjulian#endif 7611819Sjulian 7753541Sshin#ifdef INET6 7853541Sshin#ifndef INET 7953541Sshin#include <netinet/in.h> 8053541Sshin#endif 8153541Sshin#include <netinet6/in6_var.h> 8262587Sitojun#include <netinet/ip6.h> 8353541Sshin#endif 8453541Sshin 8515885Sjulian#ifdef NETATALK 8615885Sjulian#include <netatalk/at.h> 8715885Sjulian#include <netatalk/at_var.h> 8883268Speter#endif 8915885Sjulian 901622Sdg#ifdef TINY_LOMTU 911541Srgrimes#define LOMTU (1024+512) 9253541Sshin#elif defined(LARGE_LOMTU) 9353541Sshin#define LOMTU 131072 941622Sdg#else 956876Sdg#define LOMTU 16384 961622Sdg#endif 971541Srgrimes 9891648Sbrooks#define LONAME "lo" 991541Srgrimes 10071791Speterstruct lo_softc { 10171791Speter struct ifnet sc_if; /* network-visible interface */ 10287914Sjlemon LIST_ENTRY(lo_softc) sc_next; 10371791Speter}; 10491648Sbrooks 10591648Sbrooksint loioctl(struct ifnet *, u_long, caddr_t); 10691648Sbrooksstatic void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 10791648Sbrooksint looutput(struct ifnet *ifp, struct mbuf *m, 10891648Sbrooks struct sockaddr *dst, struct rtentry *rt); 10992081Smuxint lo_clone_create(struct if_clone *, int); 11097289Sbrooksvoid lo_clone_destroy(struct ifnet *); 11191648Sbrooks 11291648Sbrooksstruct ifnet *loif = NULL; /* Used externally */ 11391648Sbrooks 11491648Sbrooksstatic MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface"); 11591648Sbrooks 11671791Speterstatic LIST_HEAD(lo_list, lo_softc) lo_list; 11771791Speter 11897289Sbrooksstruct if_clone lo_cloner = IF_CLONE_INITIALIZER(LONAME, 11997289Sbrooks lo_clone_create, lo_clone_destroy, 1, IF_MAXUNIT); 12091648Sbrooks 12197289Sbrooksvoid 12291648Sbrookslo_clone_destroy(ifp) 12391648Sbrooks struct ifnet *ifp; 12491648Sbrooks{ 12591648Sbrooks struct lo_softc *sc; 12691648Sbrooks 12791648Sbrooks sc = ifp->if_softc; 12891648Sbrooks 12997289Sbrooks /* XXX: destroying lo0 will lead to panics. */ 13097289Sbrooks KASSERT(loif != ifp, ("%s: destroying lo0", __func__)); 13191648Sbrooks 13291648Sbrooks bpfdetach(ifp); 13391648Sbrooks if_detach(ifp); 13491648Sbrooks LIST_REMOVE(sc, sc_next); 13593752Sluigi free(sc, M_LO); 13691648Sbrooks} 13791648Sbrooks 13892081Smuxint 13992081Smuxlo_clone_create(ifc, unit) 14092081Smux struct if_clone *ifc; 14192081Smux int unit; 14271791Speter{ 14371791Speter struct lo_softc *sc; 14471791Speter 145111119Simp MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO); 14671791Speter 14791648Sbrooks sc->sc_if.if_name = LONAME; 14871791Speter sc->sc_if.if_unit = unit; 14971791Speter sc->sc_if.if_mtu = LOMTU; 15071791Speter sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST; 15171791Speter sc->sc_if.if_ioctl = loioctl; 15271791Speter sc->sc_if.if_output = looutput; 15371791Speter sc->sc_if.if_type = IFT_LOOP; 15471791Speter sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; 15591648Sbrooks sc->sc_if.if_softc = sc; 15671791Speter if_attach(&sc->sc_if); 15771791Speter bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); 15871791Speter LIST_INSERT_HEAD(&lo_list, sc, sc_next); 15971791Speter if (loif == NULL) 16071791Speter loif = &sc->sc_if; 16192081Smux 16292081Smux return (0); 16371791Speter} 16471791Speter 16571791Speterstatic int 16671862Speterloop_modevent(module_t mod, int type, void *data) 16771862Speter{ 16871862Speter switch (type) { 16971862Speter case MOD_LOAD: 17091648Sbrooks LIST_INIT(&lo_list); 17191648Sbrooks if_clone_attach(&lo_cloner); 17271862Speter break; 17371862Speter case MOD_UNLOAD: 17471862Speter printf("loop module unload - not possible for this module type\n"); 17571862Speter return EINVAL; 17671862Speter } 17771862Speter return 0; 17871862Speter} 1791541Srgrimes 18071862Speterstatic moduledata_t loop_mod = { 18171862Speter "loop", 18271862Speter loop_modevent, 18371862Speter 0 18471862Speter}; 18571862Speter 18671862SpeterDECLARE_MODULE(loop, loop_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 18771862Speter 18854263Sshinint 1891541Srgrimeslooutput(ifp, m, dst, rt) 1901541Srgrimes struct ifnet *ifp; 1911541Srgrimes register struct mbuf *m; 1921541Srgrimes struct sockaddr *dst; 1931541Srgrimes register struct rtentry *rt; 1941541Srgrimes{ 19536908Sjulian 196113255Sdes M_ASSERTPKTHDR(m); /* check if we have the packet header */ 197113255Sdes 19836908Sjulian if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 19936908Sjulian m_freem(m); 20036908Sjulian return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 20136908Sjulian rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 20236908Sjulian } 20353541Sshin /* 20453541Sshin * KAME requires that the packet to be contiguous on the 20553541Sshin * mbuf. We need to make that sure. 20653541Sshin * this kind of code should be avoided. 20753541Sshin * XXX: fails to join if interface MTU > MCLBYTES. jumbogram? 20853541Sshin */ 20953541Sshin if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) { 21053541Sshin struct mbuf *n; 21153541Sshin 212108466Ssam /* XXX MT_HEADER should be m->m_type */ 213111119Simp MGETHDR(n, M_DONTWAIT, MT_HEADER); 21453541Sshin if (!n) 21553541Sshin goto contiguousfail; 216108466Ssam M_MOVE_PKTHDR(n, m); 217108466Ssam#ifdef MAC 218108466Ssam /* 219108466Ssam * XXXMAC: Once we put labels in tags and proper 220108466Ssam * primitives are used for relocating mbuf header 221108466Ssam * data, this will no longer be required. 222108466Ssam */ 223108466Ssam m->m_pkthdr.label.l_flags &= ~MAC_FLAG_INITIALIZED; 224108466Ssam#endif 225111119Simp MCLGET(n, M_DONTWAIT); 22653541Sshin if (! (n->m_flags & M_EXT)) { 22753541Sshin m_freem(n); 22853541Sshin goto contiguousfail; 22953541Sshin } 23053541Sshin 231108825Ssam m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t)); 232108825Ssam n->m_len = n->m_pkthdr.len; 23353541Sshin m_freem(m); 23453541Sshin m = n; 23553541Sshin } 23653541Sshin if (0) { 23753541Sshincontiguousfail: 23853541Sshin printf("looutput: mbuf allocation failed\n"); 23953541Sshin } 24053541Sshin 24136908Sjulian ifp->if_opackets++; 24236908Sjulian ifp->if_obytes += m->m_pkthdr.len; 24336992Sjulian#if 1 /* XXX */ 24436992Sjulian switch (dst->sa_family) { 24536992Sjulian case AF_INET: 24653541Sshin case AF_INET6: 24736992Sjulian case AF_IPX: 24836992Sjulian case AF_APPLETALK: 24936994Sjulian break; 25036992Sjulian default: 25165454Srwatson printf("looutput: af=%d unexpected\n", dst->sa_family); 25236992Sjulian m_freem(m); 25336992Sjulian return (EAFNOSUPPORT); 25436992Sjulian } 25536992Sjulian#endif 25660889Sarchie return(if_simloop(ifp, m, dst->sa_family, 0)); 25736908Sjulian} 25836908Sjulian 25936908Sjulian/* 26036908Sjulian * if_simloop() 26136908Sjulian * 26236908Sjulian * This function is to support software emulation of hardware loopback, 26336908Sjulian * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 26436908Sjulian * hear their own broadcasts, we create a copy of the packet that we 26536908Sjulian * would normally receive via a hardware loopback. 26636908Sjulian * 26736908Sjulian * This function expects the packet to include the media header of length hlen. 26836908Sjulian */ 26936908Sjulian 27036908Sjulianint 27160889Sarchieif_simloop(ifp, m, af, hlen) 27236908Sjulian struct ifnet *ifp; 27378064Sume struct mbuf *m; 27460889Sarchie int af; 27536908Sjulian int hlen; 27636908Sjulian{ 27769152Sjlemon int isr; 2781541Srgrimes 279113255Sdes M_ASSERTPKTHDR(m); 28036908Sjulian m->m_pkthdr.rcvif = ifp; 28160889Sarchie 28210957Swollman /* BPF write needs to be handled specially */ 28360889Sarchie if (af == AF_UNSPEC) { 28460889Sarchie KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len")); 28560889Sarchie af = *(mtod(m, int *)); 28610957Swollman m->m_len -= sizeof(int); 28710957Swollman m->m_pkthdr.len -= sizeof(int); 28810957Swollman m->m_data += sizeof(int); 28910957Swollman } 29010957Swollman 29160889Sarchie /* Let BPF see incoming packet */ 2928090Spst if (ifp->if_bpf) { 29336908Sjulian struct mbuf m0, *n = m; 2941541Srgrimes 29578064Sume if (ifp->if_bpf->bif_dlt == DLT_NULL) { 29678064Sume /* 29778064Sume * We need to prepend the address family as 29878064Sume * a four byte field. Cons up a dummy header 29978064Sume * to pacify bpf. This is safe because bpf 30078064Sume * will only read from the mbuf (i.e., it won't 30178064Sume * try to free it or keep a pointer a to it). 30278064Sume */ 30378064Sume m0.m_next = m; 30478064Sume m0.m_len = 4; 30578064Sume m0.m_data = (char *)⁡ 30678064Sume n = &m0; 30778064Sume } 308106939Ssam BPF_MTAP(ifp, n); 3091541Srgrimes } 3101541Srgrimes 31136908Sjulian /* Strip away media header */ 31237600Sdfr if (hlen > 0) { 31360952Sgallatin m_adj(m, hlen); 31488660Sjake#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) 31537600Sdfr /* The alpha doesn't like unaligned data. 31637600Sdfr * We move data down in the first mbuf */ 31760952Sgallatin if (mtod(m, vm_offset_t) & 3) { 31861181Smjacob KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 31960952Sgallatin bcopy(m->m_data, 32060952Sgallatin (char *)(mtod(m, vm_offset_t) 32160952Sgallatin - (mtod(m, vm_offset_t) & 3)), 32260952Sgallatin m->m_len); 32360952Sgallatin mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3); 32460952Sgallatin } 32537600Sdfr#endif 32637600Sdfr } 32736908Sjulian 32860889Sarchie /* Deliver to upper layer protocol */ 32960889Sarchie switch (af) { 3301541Srgrimes#ifdef INET 3311541Srgrimes case AF_INET: 3321541Srgrimes isr = NETISR_IP; 3331541Srgrimes break; 3341541Srgrimes#endif 33553541Sshin#ifdef INET6 33653541Sshin case AF_INET6: 33753541Sshin m->m_flags |= M_LOOP; 33853541Sshin isr = NETISR_IPV6; 33953541Sshin break; 34053541Sshin#endif 34111819Sjulian#ifdef IPX 34211819Sjulian case AF_IPX: 34311819Sjulian isr = NETISR_IPX; 34411819Sjulian break; 34511819Sjulian#endif 34615885Sjulian#ifdef NETATALK 34715885Sjulian case AF_APPLETALK: 348111888Sjlemon isr = NETISR_ATALK2; 34915885Sjulian break; 35083268Speter#endif 3511541Srgrimes default: 35260889Sarchie printf("if_simloop: can't handle af=%d\n", af); 3531541Srgrimes m_freem(m); 3541541Srgrimes return (EAFNOSUPPORT); 3551541Srgrimes } 3561541Srgrimes ifp->if_ipackets++; 3571541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 358111888Sjlemon netisr_dispatch(isr, m); 3591541Srgrimes return (0); 3601541Srgrimes} 3611541Srgrimes 3621541Srgrimes/* ARGSUSED */ 36312706Sphkstatic void 36485074Srulortrequest(cmd, rt, info) 3651541Srgrimes int cmd; 3661541Srgrimes struct rtentry *rt; 36785074Sru struct rt_addrinfo *info; 3681541Srgrimes{ 36913928Swollman if (rt) { 37013928Swollman rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 37113928Swollman /* 37213928Swollman * For optimal performance, the send and receive buffers 37313928Swollman * should be at least twice the MTU plus a little more for 37413928Swollman * overhead. 37513928Swollman */ 37653541Sshin rt->rt_rmx.rmx_recvpipe = 37713928Swollman rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 37813928Swollman } 3791541Srgrimes} 3801541Srgrimes 3811541Srgrimes/* 3821541Srgrimes * Process an ioctl request. 3831541Srgrimes */ 3841541Srgrimes/* ARGSUSED */ 38554263Sshinint 3861541Srgrimesloioctl(ifp, cmd, data) 3871541Srgrimes register struct ifnet *ifp; 38836735Sdfr u_long cmd; 3891541Srgrimes caddr_t data; 3901541Srgrimes{ 3911541Srgrimes register struct ifaddr *ifa; 3921944Sdg register struct ifreq *ifr = (struct ifreq *)data; 3931541Srgrimes register int error = 0; 3941541Srgrimes 3951541Srgrimes switch (cmd) { 3961541Srgrimes 3971541Srgrimes case SIOCSIFADDR: 39816512Swollman ifp->if_flags |= IFF_UP | IFF_RUNNING; 3991541Srgrimes ifa = (struct ifaddr *)data; 40013928Swollman ifa->ifa_rtrequest = lortrequest; 4011541Srgrimes /* 4021541Srgrimes * Everything else is done at a higher level. 4031541Srgrimes */ 4041541Srgrimes break; 4051541Srgrimes 4061541Srgrimes case SIOCADDMULTI: 4071541Srgrimes case SIOCDELMULTI: 4081541Srgrimes if (ifr == 0) { 4091541Srgrimes error = EAFNOSUPPORT; /* XXX */ 4101541Srgrimes break; 4111541Srgrimes } 4121541Srgrimes switch (ifr->ifr_addr.sa_family) { 4131541Srgrimes 4141541Srgrimes#ifdef INET 4151541Srgrimes case AF_INET: 4161541Srgrimes break; 4171541Srgrimes#endif 41853541Sshin#ifdef INET6 41953541Sshin case AF_INET6: 42053541Sshin break; 42153541Sshin#endif 4221541Srgrimes 4231541Srgrimes default: 4241541Srgrimes error = EAFNOSUPPORT; 4251541Srgrimes break; 4261541Srgrimes } 4271541Srgrimes break; 4281541Srgrimes 4291944Sdg case SIOCSIFMTU: 43049468Sbrian ifp->if_mtu = ifr->ifr_mtu; 4311944Sdg break; 4321944Sdg 43335563Sphk case SIOCSIFFLAGS: 43435563Sphk break; 43535563Sphk 4361541Srgrimes default: 4371541Srgrimes error = EINVAL; 4381541Srgrimes } 4391541Srgrimes return (error); 4401541Srgrimes} 441