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$ 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" 4131742Seivind 421541Srgrimes#include <sys/param.h> 431541Srgrimes#include <sys/systm.h> 441541Srgrimes#include <sys/kernel.h> 451541Srgrimes#include <sys/mbuf.h> 4671862Speter#include <sys/module.h> 4791648Sbrooks#include <machine/bus.h> 4891648Sbrooks#include <sys/rman.h> 491541Srgrimes#include <sys/socket.h> 5024204Sbde#include <sys/sockio.h> 5171791Speter#include <sys/sysctl.h> 521541Srgrimes 531541Srgrimes#include <net/if.h> 54130933Sbrooks#include <net/if_clone.h> 551541Srgrimes#include <net/if_types.h> 561541Srgrimes#include <net/netisr.h> 571541Srgrimes#include <net/route.h> 581541Srgrimes#include <net/bpf.h> 59185571Sbz#include <net/vnet.h> 601541Srgrimes 611541Srgrimes#ifdef INET 621541Srgrimes#include <netinet/in.h> 631541Srgrimes#include <netinet/in_var.h> 641541Srgrimes#endif 651541Srgrimes 6611819Sjulian#ifdef IPX 6711819Sjulian#include <netipx/ipx.h> 6811819Sjulian#include <netipx/ipx_if.h> 6911819Sjulian#endif 7011819Sjulian 7153541Sshin#ifdef INET6 7253541Sshin#ifndef INET 7353541Sshin#include <netinet/in.h> 7453541Sshin#endif 7553541Sshin#include <netinet6/in6_var.h> 7662587Sitojun#include <netinet/ip6.h> 7753541Sshin#endif 7853541Sshin 7915885Sjulian#ifdef NETATALK 8015885Sjulian#include <netatalk/at.h> 8115885Sjulian#include <netatalk/at_var.h> 8283268Speter#endif 8315885Sjulian 84187039Srwatson#include <security/mac/mac_framework.h> 85187039Srwatson 861622Sdg#ifdef TINY_LOMTU 871541Srgrimes#define LOMTU (1024+512) 8853541Sshin#elif defined(LARGE_LOMTU) 8953541Sshin#define LOMTU 131072 901622Sdg#else 916876Sdg#define LOMTU 16384 921622Sdg#endif 931541Srgrimes 94189873Srwatson#define LO_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP) 95236332Stuexen#define LO_CSUM_FEATURES6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_SCTP_IPV6) 96236170Sbz#define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_DATA_VALID_IPV6 | \ 97236170Sbz CSUM_PSEUDO_HDR | \ 98189873Srwatson CSUM_IP_CHECKED | CSUM_IP_VALID | \ 99189873Srwatson CSUM_SCTP_VALID) 100189873Srwatson 10191648Sbrooksint loioctl(struct ifnet *, u_long, caddr_t); 10291648Sbrooksstatic void lortrequest(int, struct rtentry *, struct rt_addrinfo *); 10391648Sbrooksint looutput(struct ifnet *ifp, struct mbuf *m, 104249925Sglebius const struct sockaddr *dst, struct route *ro); 105160195Ssamstatic int lo_clone_create(struct if_clone *, int, caddr_t); 106128209Sbrooksstatic void lo_clone_destroy(struct ifnet *); 10791648Sbrooks 108195699SrwatsonVNET_DEFINE(struct ifnet *, loif); /* Used externally */ 10991648Sbrooks 110192669Szec#ifdef VIMAGE 111241610Sglebiusstatic VNET_DEFINE(struct if_clone *, lo_cloner); 112195727Srwatson#define V_lo_cloner VNET(lo_cloner) 113192669Szec#endif 114192669Szec 115241610Sglebiusstatic struct if_clone *lo_cloner; 116241610Sglebiusstatic const char loname[] = "lo"; 11791648Sbrooks 118128209Sbrooksstatic void 119177965Srwatsonlo_clone_destroy(struct ifnet *ifp) 12091648Sbrooks{ 12191648Sbrooks 122193731Szec#ifndef VIMAGE 12397289Sbrooks /* XXX: destroying lo0 will lead to panics. */ 124181803Sbz KASSERT(V_loif != ifp, ("%s: destroying lo0", __func__)); 125193731Szec#endif 12691648Sbrooks 12791648Sbrooks bpfdetach(ifp); 12891648Sbrooks if_detach(ifp); 129147256Sbrooks if_free(ifp); 13091648Sbrooks} 13191648Sbrooks 132128209Sbrooksstatic int 133177965Srwatsonlo_clone_create(struct if_clone *ifc, int unit, caddr_t params) 13471791Speter{ 135147256Sbrooks struct ifnet *ifp; 13671791Speter 137180094Sed ifp = if_alloc(IFT_LOOP); 138180094Sed if (ifp == NULL) 139147256Sbrooks return (ENOSPC); 14071791Speter 141241610Sglebius if_initname(ifp, loname, 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; 147236170Sbz ifp->if_capabilities = ifp->if_capenable = 148236170Sbz IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; 149236170Sbz ifp->if_hwassist = LO_CSUM_FEATURES | LO_CSUM_FEATURES6; 150147256Sbrooks if_attach(ifp); 151147611Sdwmalone bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 152181803Sbz if (V_loif == NULL) 153181803Sbz V_loif = ifp; 15492081Smux 15592081Smux return (0); 15671791Speter} 15771791Speter 158195837Srwatsonstatic void 159195837Srwatsonvnet_loif_init(const void *unused __unused) 160190787Szec{ 161190787Szec 162192669Szec#ifdef VIMAGE 163241610Sglebius lo_cloner = if_clone_simple(loname, lo_clone_create, lo_clone_destroy, 164241610Sglebius 1); 165195837Srwatson V_lo_cloner = lo_cloner; 166192669Szec#else 167241610Sglebius lo_cloner = if_clone_simple(loname, lo_clone_create, lo_clone_destroy, 168241610Sglebius 1); 169192669Szec#endif 170190787Szec} 171195837SrwatsonVNET_SYSINIT(vnet_loif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, 172195837Srwatson vnet_loif_init, NULL); 173190787Szec 174193731Szec#ifdef VIMAGE 175195837Srwatsonstatic void 176195837Srwatsonvnet_loif_uninit(const void *unused __unused) 177193731Szec{ 178193731Szec 179241610Sglebius if_clone_detach(V_lo_cloner); 180193731Szec V_loif = NULL; 181193731Szec} 182195837SrwatsonVNET_SYSUNINIT(vnet_loif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, 183195837Srwatson vnet_loif_uninit, NULL); 184193731Szec#endif 185193731Szec 186193731Szecstatic int 187178883Srwatsonloop_modevent(module_t mod, int type, void *data) 188178883Srwatson{ 189177965Srwatson 190178883Srwatson switch (type) { 191178883Srwatson case MOD_LOAD: 192178883Srwatson break; 193177965Srwatson 194178883Srwatson case MOD_UNLOAD: 195178883Srwatson printf("loop module unload - not possible for this module type\n"); 196177965Srwatson return (EINVAL); 197177965Srwatson 198132199Sphk default: 199177965Srwatson return (EOPNOTSUPP); 200178883Srwatson } 201177965Srwatson return (0); 202178883Srwatson} 2031541Srgrimes 204178883Srwatsonstatic moduledata_t loop_mod = { 205204173Srwatson "if_lo", 206178883Srwatson loop_modevent, 207241394Skevlo 0 208178883Srwatson}; 20971862Speter 210204173SrwatsonDECLARE_MODULE(if_lo, loop_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 21171862Speter 21254263Sshinint 213249925Sglebiuslooutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 214191148Skmacy struct route *ro) 2151541Srgrimes{ 216147611Sdwmalone u_int32_t af; 217191148Skmacy struct rtentry *rt = NULL; 218187039Srwatson#ifdef MAC 219187039Srwatson int error; 220187039Srwatson#endif 221147611Sdwmalone 222113255Sdes M_ASSERTPKTHDR(m); /* check if we have the packet header */ 223113255Sdes 224191148Skmacy if (ro != NULL) 225191148Skmacy rt = ro->ro_rt; 226187039Srwatson#ifdef MAC 227187039Srwatson error = mac_ifnet_check_transmit(ifp, m); 228187039Srwatson if (error) { 229187039Srwatson m_freem(m); 230187039Srwatson return (error); 231187039Srwatson } 232187039Srwatson#endif 233187039Srwatson 23436908Sjulian if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 23536908Sjulian m_freem(m); 23636908Sjulian return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 23736908Sjulian rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 23836908Sjulian } 23953541Sshin 24036908Sjulian ifp->if_opackets++; 24136908Sjulian ifp->if_obytes += m->m_pkthdr.len; 242147611Sdwmalone 243147611Sdwmalone /* BPF writes need to be handled specially. */ 244249925Sglebius if (dst->sa_family == AF_UNSPEC) 245147611Sdwmalone bcopy(dst->sa_data, &af, sizeof(af)); 246249925Sglebius else 247249925Sglebius af = dst->sa_family; 248147611Sdwmalone 24936992Sjulian#if 1 /* XXX */ 250249925Sglebius switch (af) { 25136992Sjulian case AF_INET: 252189863Srwatson if (ifp->if_capenable & IFCAP_RXCSUM) { 253189863Srwatson m->m_pkthdr.csum_data = 0xffff; 254189873Srwatson m->m_pkthdr.csum_flags = LO_CSUM_SET; 255189863Srwatson } 256189873Srwatson m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES; 257236170Sbz break; 258236170Sbz case AF_INET6: 259238871Sbz#if 0 260238871Sbz /* 261238871Sbz * XXX-BZ for now always claim the checksum is good despite 262238871Sbz * any interface flags. This is a workaround for 9.1-R and 263238871Sbz * a proper solution ought to be sought later. 264238871Sbz */ 265236170Sbz if (ifp->if_capenable & IFCAP_RXCSUM_IPV6) { 266236170Sbz m->m_pkthdr.csum_data = 0xffff; 267236170Sbz m->m_pkthdr.csum_flags = LO_CSUM_SET; 268236170Sbz } 269238871Sbz#else 270238871Sbz m->m_pkthdr.csum_data = 0xffff; 271238871Sbz m->m_pkthdr.csum_flags = LO_CSUM_SET; 272238871Sbz#endif 273236170Sbz m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES6; 274236170Sbz break; 27536992Sjulian case AF_IPX: 27636992Sjulian case AF_APPLETALK: 27736994Sjulian break; 27836992Sjulian default: 279249925Sglebius printf("looutput: af=%d unexpected\n", af); 28036992Sjulian m_freem(m); 28136992Sjulian return (EAFNOSUPPORT); 28236992Sjulian } 28336992Sjulian#endif 284249925Sglebius return (if_simloop(ifp, m, af, 0)); 28536908Sjulian} 28636908Sjulian 28736908Sjulian/* 28836908Sjulian * if_simloop() 28936908Sjulian * 29036908Sjulian * This function is to support software emulation of hardware loopback, 29136908Sjulian * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 29236908Sjulian * hear their own broadcasts, we create a copy of the packet that we 29336908Sjulian * would normally receive via a hardware loopback. 29436908Sjulian * 29536908Sjulian * This function expects the packet to include the media header of length hlen. 29636908Sjulian */ 29736908Sjulianint 298177965Srwatsonif_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) 29936908Sjulian{ 30069152Sjlemon int isr; 3011541Srgrimes 302113255Sdes M_ASSERTPKTHDR(m); 303121645Ssam m_tag_delete_nonpersistent(m); 30436908Sjulian m->m_pkthdr.rcvif = ifp; 30560889Sarchie 306187039Srwatson#ifdef MAC 307187039Srwatson mac_ifnet_create_mbuf(ifp, m); 308187039Srwatson#endif 309187039Srwatson 310162539Ssuz /* 311162539Ssuz * Let BPF see incoming packet in the following manner: 312178883Srwatson * - Emulated packet loopback for a simplex interface 313162539Ssuz * (net/if_ethersubr.c) 314162539Ssuz * -> passes it to ifp's BPF 315162539Ssuz * - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c) 316162539Ssuz * -> not passes it to any BPF 317162539Ssuz * - Normal packet loopback from myself to myself (net/if_loop.c) 318162539Ssuz * -> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0) 319162539Ssuz */ 320162539Ssuz if (hlen > 0) { 321162539Ssuz if (bpf_peers_present(ifp->if_bpf)) { 322123922Ssam bpf_mtap(ifp->if_bpf, m); 323162539Ssuz } 324162539Ssuz } else { 325181803Sbz if (bpf_peers_present(V_loif->if_bpf)) { 326181803Sbz if ((m->m_flags & M_MCAST) == 0 || V_loif == ifp) { 327162539Ssuz /* XXX beware sizeof(af) != 4 */ 328181118Srwatson u_int32_t af1 = af; 329162539Ssuz 330162539Ssuz /* 331162539Ssuz * We need to prepend the address family. 332162539Ssuz */ 333181803Sbz bpf_mtap2(V_loif->if_bpf, &af1, sizeof(af1), m); 334162539Ssuz } 335162539Ssuz } 3361541Srgrimes } 3371541Srgrimes 33836908Sjulian /* Strip away media header */ 33937600Sdfr if (hlen > 0) { 34060952Sgallatin m_adj(m, hlen); 341166577Scognet#ifndef __NO_STRICT_ALIGNMENT 342158471Sjhb /* 343158471Sjhb * Some archs do not like unaligned data, so 344158471Sjhb * we move data down in the first mbuf. 345158471Sjhb */ 34660952Sgallatin if (mtod(m, vm_offset_t) & 3) { 34761181Smjacob KASSERT(hlen >= 3, ("if_simloop: hlen too small")); 348178883Srwatson bcopy(m->m_data, 349178883Srwatson (char *)(mtod(m, vm_offset_t) 35060952Sgallatin - (mtod(m, vm_offset_t) & 3)), 35160952Sgallatin m->m_len); 352132780Skan m->m_data -= (mtod(m,vm_offset_t) & 3); 35360952Sgallatin } 35437600Sdfr#endif 35537600Sdfr } 35636908Sjulian 35760889Sarchie /* Deliver to upper layer protocol */ 35860889Sarchie switch (af) { 3591541Srgrimes#ifdef INET 3601541Srgrimes case AF_INET: 3611541Srgrimes isr = NETISR_IP; 3621541Srgrimes break; 3631541Srgrimes#endif 36453541Sshin#ifdef INET6 36553541Sshin case AF_INET6: 36653541Sshin m->m_flags |= M_LOOP; 36753541Sshin isr = NETISR_IPV6; 36853541Sshin break; 36953541Sshin#endif 37011819Sjulian#ifdef IPX 37111819Sjulian case AF_IPX: 37211819Sjulian isr = NETISR_IPX; 37311819Sjulian break; 37411819Sjulian#endif 37515885Sjulian#ifdef NETATALK 37615885Sjulian case AF_APPLETALK: 377111888Sjlemon isr = NETISR_ATALK2; 37815885Sjulian break; 37983268Speter#endif 3801541Srgrimes default: 38160889Sarchie printf("if_simloop: can't handle af=%d\n", af); 3821541Srgrimes m_freem(m); 3831541Srgrimes return (EAFNOSUPPORT); 3841541Srgrimes } 3851541Srgrimes ifp->if_ipackets++; 3861541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 387134391Sandre netisr_queue(isr, m); /* mbuf is free'd on failure. */ 3881541Srgrimes return (0); 3891541Srgrimes} 3901541Srgrimes 3911541Srgrimes/* ARGSUSED */ 39212706Sphkstatic void 393177965Srwatsonlortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) 3941541Srgrimes{ 395177965Srwatson 396120727Ssam RT_LOCK_ASSERT(rt); 397263478Sglebius rt->rt_mtu = rt->rt_ifp->if_mtu; 3981541Srgrimes} 3991541Srgrimes 4001541Srgrimes/* 4011541Srgrimes * Process an ioctl request. 4021541Srgrimes */ 4031541Srgrimes/* ARGSUSED */ 40454263Sshinint 405177965Srwatsonloioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 4061541Srgrimes{ 407177965Srwatson struct ifaddr *ifa; 408177965Srwatson struct ifreq *ifr = (struct ifreq *)data; 409189863Srwatson int error = 0, mask; 4101541Srgrimes 4111541Srgrimes switch (cmd) { 4121541Srgrimes case SIOCSIFADDR: 413148887Srwatson ifp->if_flags |= IFF_UP; 414148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 4151541Srgrimes ifa = (struct ifaddr *)data; 41613928Swollman ifa->ifa_rtrequest = lortrequest; 4171541Srgrimes /* 4181541Srgrimes * Everything else is done at a higher level. 4191541Srgrimes */ 4201541Srgrimes break; 4211541Srgrimes 4221541Srgrimes case SIOCADDMULTI: 4231541Srgrimes case SIOCDELMULTI: 4241541Srgrimes if (ifr == 0) { 4251541Srgrimes error = EAFNOSUPPORT; /* XXX */ 4261541Srgrimes break; 4271541Srgrimes } 4281541Srgrimes switch (ifr->ifr_addr.sa_family) { 4291541Srgrimes 4301541Srgrimes#ifdef INET 4311541Srgrimes case AF_INET: 4321541Srgrimes break; 4331541Srgrimes#endif 43453541Sshin#ifdef INET6 43553541Sshin case AF_INET6: 43653541Sshin break; 43753541Sshin#endif 4381541Srgrimes 4391541Srgrimes default: 4401541Srgrimes error = EAFNOSUPPORT; 4411541Srgrimes break; 4421541Srgrimes } 4431541Srgrimes break; 4441541Srgrimes 4451944Sdg case SIOCSIFMTU: 44649468Sbrian ifp->if_mtu = ifr->ifr_mtu; 4471944Sdg break; 4481944Sdg 44935563Sphk case SIOCSIFFLAGS: 45035563Sphk break; 45135563Sphk 452189863Srwatson case SIOCSIFCAP: 453189863Srwatson mask = ifp->if_capenable ^ ifr->ifr_reqcap; 454189863Srwatson if ((mask & IFCAP_RXCSUM) != 0) 455189863Srwatson ifp->if_capenable ^= IFCAP_RXCSUM; 456189863Srwatson if ((mask & IFCAP_TXCSUM) != 0) 457189863Srwatson ifp->if_capenable ^= IFCAP_TXCSUM; 458238871Sbz if ((mask & IFCAP_RXCSUM_IPV6) != 0) { 459238871Sbz#if 0 460236170Sbz ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; 461238871Sbz#else 462238871Sbz error = EOPNOTSUPP; 463238871Sbz break; 464238871Sbz#endif 465238871Sbz } 466238871Sbz if ((mask & IFCAP_TXCSUM_IPV6) != 0) { 467238871Sbz#if 0 468236170Sbz ifp->if_capenable ^= IFCAP_TXCSUM_IPV6; 469238871Sbz#else 470238871Sbz error = EOPNOTSUPP; 471238871Sbz break; 472238871Sbz#endif 473238871Sbz } 474236170Sbz ifp->if_hwassist = 0; 475189863Srwatson if (ifp->if_capenable & IFCAP_TXCSUM) 476189873Srwatson ifp->if_hwassist = LO_CSUM_FEATURES; 477238871Sbz#if 0 478236170Sbz if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) 479236170Sbz ifp->if_hwassist |= LO_CSUM_FEATURES6; 480238871Sbz#endif 481189863Srwatson break; 482189863Srwatson 4831541Srgrimes default: 4841541Srgrimes error = EINVAL; 4851541Srgrimes } 4861541Srgrimes return (error); 4871541Srgrimes} 488