if_loop.c revision 190787
1139823Simp/*- 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 * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 2985051Sru * @(#)if_loop.c 8.2 (Berkeley) 1/9/95 3050477Speter * $FreeBSD: head/sys/net/if_loop.c 190787 2009-04-06 22:29:41Z zec $ 311541Srgrimes */ 321541Srgrimes 331541Srgrimes/* 341541Srgrimes * Loopback interface driver for protocol testing and timing. 351541Srgrimes */ 361541Srgrimes 3732356Seivind#include "opt_atalk.h" 3832350Seivind#include "opt_inet.h" 3954263Sshin#include "opt_inet6.h" 4031742Seivind#include "opt_ipx.h" 41189106Sbz#include "opt_route.h" 42187039Srwatson#include "opt_mac.h" 4331742Seivind 441541Srgrimes#include <sys/param.h> 451541Srgrimes#include <sys/systm.h> 461541Srgrimes#include <sys/kernel.h> 471541Srgrimes#include <sys/mbuf.h> 4871862Speter#include <sys/module.h> 4991648Sbrooks#include <machine/bus.h> 5091648Sbrooks#include <sys/rman.h> 511541Srgrimes#include <sys/socket.h> 5224204Sbde#include <sys/sockio.h> 5371791Speter#include <sys/sysctl.h> 54181803Sbz#include <sys/vimage.h> 551541Srgrimes 561541Srgrimes#include <net/if.h> 57130933Sbrooks#include <net/if_clone.h> 581541Srgrimes#include <net/if_types.h> 591541Srgrimes#include <net/netisr.h> 601541Srgrimes#include <net/route.h> 611541Srgrimes#include <net/bpf.h> 62185571Sbz#include <net/vnet.h> 631541Srgrimes 641541Srgrimes#ifdef INET 651541Srgrimes#include <netinet/in.h> 661541Srgrimes#include <netinet/in_var.h> 671541Srgrimes#endif 681541Srgrimes 6911819Sjulian#ifdef IPX 7011819Sjulian#include <netipx/ipx.h> 7111819Sjulian#include <netipx/ipx_if.h> 7211819Sjulian#endif 7311819Sjulian 7453541Sshin#ifdef INET6 7553541Sshin#ifndef INET 7653541Sshin#include <netinet/in.h> 7753541Sshin#endif 7853541Sshin#include <netinet6/in6_var.h> 7962587Sitojun#include <netinet/ip6.h> 8053541Sshin#endif 8153541Sshin 8215885Sjulian#ifdef NETATALK 8315885Sjulian#include <netatalk/at.h> 8415885Sjulian#include <netatalk/at_var.h> 8583268Speter#endif 8615885Sjulian 87187039Srwatson#include <security/mac/mac_framework.h> 88187039Srwatson 891622Sdg#ifdef TINY_LOMTU 901541Srgrimes#define LOMTU (1024+512) 9153541Sshin#elif defined(LARGE_LOMTU) 9253541Sshin#define LOMTU 131072 931622Sdg#else 946876Sdg#define LOMTU 16384 951622Sdg#endif 961541Srgrimes 97189873Srwatson#define LO_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP) 98189873Srwatson#define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_PSEUDO_HDR | \ 99189873Srwatson CSUM_IP_CHECKED | CSUM_IP_VALID | \ 100189873Srwatson CSUM_SCTP_VALID) 101189873Srwatson 10291648Sbrooksint loioctl(struct ifnet *, u_long, caddr_t); 10391648Sbrooksstatic void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 10491648Sbrooksint looutput(struct ifnet *ifp, struct mbuf *m, 10591648Sbrooks struct sockaddr *dst, struct rtentry *rt); 106160195Ssamstatic int lo_clone_create(struct if_clone *, int, caddr_t); 107128209Sbrooksstatic void lo_clone_destroy(struct ifnet *); 108190787Szecstatic int vnet_loif_iattach(const void *); 10991648Sbrooks 110185088Szec#ifdef VIMAGE_GLOBALS 111185088Szecstruct ifnet *loif; /* Used externally */ 112185088Szec#endif 11391648Sbrooks 114130933SbrooksIFC_SIMPLE_DECLARE(lo, 1); 11591648Sbrooks 116128209Sbrooksstatic void 117177965Srwatsonlo_clone_destroy(struct ifnet *ifp) 11891648Sbrooks{ 119185348Szec#ifdef INVARIANTS 120185348Szec INIT_VNET_NET(ifp->if_vnet); 121185348Szec#endif 12291648Sbrooks 12397289Sbrooks /* XXX: destroying lo0 will lead to panics. */ 124181803Sbz KASSERT(V_loif != ifp, ("%s: destroying lo0", __func__)); 12591648Sbrooks 12691648Sbrooks bpfdetach(ifp); 12791648Sbrooks if_detach(ifp); 128147256Sbrooks if_free(ifp); 12991648Sbrooks} 13091648Sbrooks 131128209Sbrooksstatic int 132177965Srwatsonlo_clone_create(struct if_clone *ifc, int unit, caddr_t params) 13371791Speter{ 134183550Szec INIT_VNET_NET(curvnet); 135147256Sbrooks struct ifnet *ifp; 13671791Speter 137180094Sed ifp = if_alloc(IFT_LOOP); 138180094Sed if (ifp == NULL) 139147256Sbrooks return (ENOSPC); 14071791Speter 141147256Sbrooks if_initname(ifp, ifc->ifc_name, unit); 142147256Sbrooks ifp->if_mtu = LOMTU; 143147256Sbrooks ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 144147256Sbrooks ifp->if_ioctl = loioctl; 145147256Sbrooks ifp->if_output = looutput; 146147256Sbrooks ifp->if_snd.ifq_maxlen = ifqmaxlen; 147189871Srwatson ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM; 148189873Srwatson ifp->if_hwassist = LO_CSUM_FEATURES; 149147256Sbrooks if_attach(ifp); 150147611Sdwmalone bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 151181803Sbz if (V_loif == NULL) 152181803Sbz V_loif = ifp; 15392081Smux 15492081Smux return (0); 15571791Speter} 15671791Speter 157190787Szecstatic int vnet_loif_iattach(const void *unused __unused) 158190787Szec{ 159190787Szec INIT_VNET_NET(curvnet); 160190787Szec 161190787Szec V_loif = NULL; 162190787Szec if_clone_attach(&lo_cloner); 163190787Szec return (0); 164190787Szec} 165190787Szec 16671791Speterstatic int 167178883Srwatsonloop_modevent(module_t mod, int type, void *data) 168178883Srwatson{ 169185348Szec INIT_VNET_NET(curvnet); 170177965Srwatson 171178883Srwatson switch (type) { 172178883Srwatson case MOD_LOAD: 173190787Szec vnet_loif_iattach(NULL); 174178883Srwatson break; 175177965Srwatson 176178883Srwatson case MOD_UNLOAD: 177178883Srwatson printf("loop module unload - not possible for this module type\n"); 178177965Srwatson return (EINVAL); 179177965Srwatson 180132199Sphk default: 181177965Srwatson return (EOPNOTSUPP); 182178883Srwatson } 183177965Srwatson return (0); 184178883Srwatson} 1851541Srgrimes 186178883Srwatsonstatic moduledata_t loop_mod = { 187178883Srwatson "loop", 188178883Srwatson loop_modevent, 18971862Speter 0 190178883Srwatson}; 19171862Speter 192121596SkanDECLARE_MODULE(loop, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 19371862Speter 19454263Sshinint 195177965Srwatsonlooutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 196177965Srwatson struct rtentry *rt) 1971541Srgrimes{ 198147611Sdwmalone u_int32_t af; 199187039Srwatson#ifdef MAC 200187039Srwatson int error; 201187039Srwatson#endif 202147611Sdwmalone 203113255Sdes M_ASSERTPKTHDR(m); /* check if we have the packet header */ 204113255Sdes 205187039Srwatson#ifdef MAC 206187039Srwatson error = mac_ifnet_check_transmit(ifp, m); 207187039Srwatson if (error) { 208187039Srwatson m_freem(m); 209187039Srwatson return (error); 210187039Srwatson } 211187039Srwatson#endif 212187039Srwatson 21336908Sjulian if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 21436908Sjulian m_freem(m); 21536908Sjulian return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 21636908Sjulian rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 21736908Sjulian } 21853541Sshin 21936908Sjulian ifp->if_opackets++; 22036908Sjulian ifp->if_obytes += m->m_pkthdr.len; 221147611Sdwmalone 222147611Sdwmalone /* BPF writes need to be handled specially. */ 223147611Sdwmalone if (dst->sa_family == AF_UNSPEC) { 224147611Sdwmalone bcopy(dst->sa_data, &af, sizeof(af)); 225147611Sdwmalone dst->sa_family = af; 226147611Sdwmalone } 227147611Sdwmalone 22836992Sjulian#if 1 /* XXX */ 22936992Sjulian switch (dst->sa_family) { 23036992Sjulian case AF_INET: 231189863Srwatson if (ifp->if_capenable & IFCAP_RXCSUM) { 232189863Srwatson m->m_pkthdr.csum_data = 0xffff; 233189873Srwatson m->m_pkthdr.csum_flags = LO_CSUM_SET; 234189863Srwatson } 235189873Srwatson m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES; 23653541Sshin case AF_INET6: 23736992Sjulian case AF_IPX: 23836992Sjulian case AF_APPLETALK: 23936994Sjulian break; 24036992Sjulian default: 24165454Srwatson printf("looutput: af=%d unexpected\n", dst->sa_family); 24236992Sjulian m_freem(m); 24336992Sjulian return (EAFNOSUPPORT); 24436992Sjulian } 24536992Sjulian#endif 246177965Srwatson return (if_simloop(ifp, m, dst->sa_family, 0)); 24736908Sjulian} 24836908Sjulian 24936908Sjulian/* 25036908Sjulian * if_simloop() 25136908Sjulian * 25236908Sjulian * This function is to support software emulation of hardware loopback, 25336908Sjulian * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 25436908Sjulian * hear their own broadcasts, we create a copy of the packet that we 25536908Sjulian * would normally receive via a hardware loopback. 25636908Sjulian * 25736908Sjulian * This function expects the packet to include the media header of length hlen. 25836908Sjulian */ 25936908Sjulianint 260177965Srwatsonif_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) 26136908Sjulian{ 262183550Szec INIT_VNET_NET(ifp->if_vnet); 26369152Sjlemon int isr; 2641541Srgrimes 265113255Sdes M_ASSERTPKTHDR(m); 266121645Ssam m_tag_delete_nonpersistent(m); 26736908Sjulian m->m_pkthdr.rcvif = ifp; 26860889Sarchie 269187039Srwatson#ifdef MAC 270187039Srwatson mac_ifnet_create_mbuf(ifp, m); 271187039Srwatson#endif 272187039Srwatson 273162539Ssuz /* 274162539Ssuz * Let BPF see incoming packet in the following manner: 275178883Srwatson * - Emulated packet loopback for a simplex interface 276162539Ssuz * (net/if_ethersubr.c) 277162539Ssuz * -> passes it to ifp's BPF 278162539Ssuz * - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c) 279162539Ssuz * -> not passes it to any BPF 280162539Ssuz * - Normal packet loopback from myself to myself (net/if_loop.c) 281162539Ssuz * -> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0) 282162539Ssuz */ 283162539Ssuz if (hlen > 0) { 284162539Ssuz if (bpf_peers_present(ifp->if_bpf)) { 285123922Ssam bpf_mtap(ifp->if_bpf, m); 286162539Ssuz } 287162539Ssuz } else { 288181803Sbz if (bpf_peers_present(V_loif->if_bpf)) { 289181803Sbz if ((m->m_flags & M_MCAST) == 0 || V_loif == ifp) { 290162539Ssuz /* XXX beware sizeof(af) != 4 */ 291181118Srwatson u_int32_t af1 = af; 292162539Ssuz 293162539Ssuz /* 294162539Ssuz * We need to prepend the address family. 295162539Ssuz */ 296181803Sbz bpf_mtap2(V_loif->if_bpf, &af1, sizeof(af1), m); 297162539Ssuz } 298162539Ssuz } 2991541Srgrimes } 3001541Srgrimes 30136908Sjulian /* Strip away media header */ 30237600Sdfr if (hlen > 0) { 30360952Sgallatin m_adj(m, hlen); 304166577Scognet#ifndef __NO_STRICT_ALIGNMENT 305158471Sjhb /* 306158471Sjhb * Some archs do not like unaligned data, so 307158471Sjhb * we move data down in the first mbuf. 308158471Sjhb */ 30960952Sgallatin if (mtod(m, vm_offset_t) & 3) { 31061181Smjacob KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 311178883Srwatson bcopy(m->m_data, 312178883Srwatson (char *)(mtod(m, vm_offset_t) 31360952Sgallatin - (mtod(m, vm_offset_t) & 3)), 31460952Sgallatin m->m_len); 315132780Skan m->m_data -= (mtod(m,vm_offset_t) & 3); 31660952Sgallatin } 31737600Sdfr#endif 31837600Sdfr } 31936908Sjulian 32060889Sarchie /* Deliver to upper layer protocol */ 32160889Sarchie switch (af) { 3221541Srgrimes#ifdef INET 3231541Srgrimes case AF_INET: 3241541Srgrimes isr = NETISR_IP; 3251541Srgrimes break; 3261541Srgrimes#endif 32753541Sshin#ifdef INET6 32853541Sshin case AF_INET6: 32953541Sshin m->m_flags |= M_LOOP; 33053541Sshin isr = NETISR_IPV6; 33153541Sshin break; 33253541Sshin#endif 33311819Sjulian#ifdef IPX 33411819Sjulian case AF_IPX: 33511819Sjulian isr = NETISR_IPX; 33611819Sjulian break; 33711819Sjulian#endif 33815885Sjulian#ifdef NETATALK 33915885Sjulian case AF_APPLETALK: 340111888Sjlemon isr = NETISR_ATALK2; 34115885Sjulian break; 34283268Speter#endif 3431541Srgrimes default: 34460889Sarchie printf("if_simloop: can't handle af=%d\n", af); 3451541Srgrimes m_freem(m); 3461541Srgrimes return (EAFNOSUPPORT); 3471541Srgrimes } 3481541Srgrimes ifp->if_ipackets++; 3491541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 350134391Sandre netisr_queue(isr, m); /* mbuf is free'd on failure. */ 3511541Srgrimes return (0); 3521541Srgrimes} 3531541Srgrimes 3541541Srgrimes/* ARGSUSED */ 35512706Sphkstatic void 356177965Srwatsonlortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) 3571541Srgrimes{ 358177965Srwatson 359120727Ssam RT_LOCK_ASSERT(rt); 360142352Ssam rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; 3611541Srgrimes} 3621541Srgrimes 3631541Srgrimes/* 3641541Srgrimes * Process an ioctl request. 3651541Srgrimes */ 3661541Srgrimes/* ARGSUSED */ 36754263Sshinint 368177965Srwatsonloioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 3691541Srgrimes{ 370177965Srwatson struct ifaddr *ifa; 371177965Srwatson struct ifreq *ifr = (struct ifreq *)data; 372189863Srwatson int error = 0, mask; 3731541Srgrimes 3741541Srgrimes switch (cmd) { 3751541Srgrimes case SIOCSIFADDR: 376148887Srwatson ifp->if_flags |= IFF_UP; 377148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 3781541Srgrimes ifa = (struct ifaddr *)data; 37913928Swollman ifa->ifa_rtrequest = lortrequest; 3801541Srgrimes /* 3811541Srgrimes * Everything else is done at a higher level. 3821541Srgrimes */ 3831541Srgrimes break; 3841541Srgrimes 3851541Srgrimes case SIOCADDMULTI: 3861541Srgrimes case SIOCDELMULTI: 3871541Srgrimes if (ifr == 0) { 3881541Srgrimes error = EAFNOSUPPORT; /* XXX */ 3891541Srgrimes break; 3901541Srgrimes } 3911541Srgrimes switch (ifr->ifr_addr.sa_family) { 3921541Srgrimes 3931541Srgrimes#ifdef INET 3941541Srgrimes case AF_INET: 3951541Srgrimes break; 3961541Srgrimes#endif 39753541Sshin#ifdef INET6 39853541Sshin case AF_INET6: 39953541Sshin break; 40053541Sshin#endif 4011541Srgrimes 4021541Srgrimes default: 4031541Srgrimes error = EAFNOSUPPORT; 4041541Srgrimes break; 4051541Srgrimes } 4061541Srgrimes break; 4071541Srgrimes 4081944Sdg case SIOCSIFMTU: 40949468Sbrian ifp->if_mtu = ifr->ifr_mtu; 4101944Sdg break; 4111944Sdg 41235563Sphk case SIOCSIFFLAGS: 41335563Sphk break; 41435563Sphk 415189863Srwatson case SIOCSIFCAP: 416189863Srwatson mask = ifp->if_capenable ^ ifr->ifr_reqcap; 417189863Srwatson if ((mask & IFCAP_RXCSUM) != 0) 418189863Srwatson ifp->if_capenable ^= IFCAP_RXCSUM; 419189863Srwatson if ((mask & IFCAP_TXCSUM) != 0) 420189863Srwatson ifp->if_capenable ^= IFCAP_TXCSUM; 421189863Srwatson if (ifp->if_capenable & IFCAP_TXCSUM) 422189873Srwatson ifp->if_hwassist = LO_CSUM_FEATURES; 423189863Srwatson else 424189863Srwatson ifp->if_hwassist = 0; 425189863Srwatson break; 426189863Srwatson 4271541Srgrimes default: 4281541Srgrimes error = EINVAL; 4291541Srgrimes } 4301541Srgrimes return (error); 4311541Srgrimes} 432