if_loop.c revision 60952
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 * 331541Srgrimes * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 3450477Speter * $FreeBSD: head/sys/net/if_loop.c 60952 2000-05-26 13:47:02Z gallatin $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * Loopback interface driver for protocol testing and timing. 391541Srgrimes */ 408090Spst#include "loop.h" 411541Srgrimes 4232356Seivind#include "opt_atalk.h" 4332350Seivind#include "opt_inet.h" 4454263Sshin#include "opt_inet6.h" 4531742Seivind#include "opt_ipx.h" 4631742Seivind 471541Srgrimes#include <sys/param.h> 481541Srgrimes#include <sys/systm.h> 491541Srgrimes#include <sys/kernel.h> 501541Srgrimes#include <sys/mbuf.h> 511541Srgrimes#include <sys/socket.h> 5224204Sbde#include <sys/sockio.h> 531541Srgrimes 541541Srgrimes#include <net/if.h> 551541Srgrimes#include <net/if_types.h> 561541Srgrimes#include <net/netisr.h> 571541Srgrimes#include <net/route.h> 581541Srgrimes#include <net/bpf.h> 591541Srgrimes 601541Srgrimes#ifdef INET 611541Srgrimes#include <netinet/in.h> 621541Srgrimes#include <netinet/in_var.h> 631541Srgrimes#endif 641541Srgrimes 6511819Sjulian#ifdef IPX 6611819Sjulian#include <netipx/ipx.h> 6711819Sjulian#include <netipx/ipx_if.h> 6811819Sjulian#endif 6911819Sjulian 7053541Sshin#ifdef INET6 7153541Sshin#ifndef INET 7253541Sshin#include <netinet/in.h> 7353541Sshin#endif 7453541Sshin#include <netinet6/in6_var.h> 7553541Sshin#include <netinet6/ip6.h> 7653541Sshin#endif 7753541Sshin 781541Srgrimes#ifdef NS 791541Srgrimes#include <netns/ns.h> 801541Srgrimes#include <netns/ns_if.h> 811541Srgrimes#endif 821541Srgrimes 8315885Sjulian#ifdef NETATALK 8415885Sjulian#include <netatalk/at.h> 8515885Sjulian#include <netatalk/at_var.h> 8615885Sjulian#endif NETATALK 8715885Sjulian 8854263Sshinint loioctl __P((struct ifnet *, u_long, caddr_t)); 8912706Sphkstatic void lortrequest __P((int, struct rtentry *, struct sockaddr *)); 9012706Sphk 9110653Sdgstatic void loopattach __P((void *)); 9210429SbdePSEUDO_SET(loopattach, if_loop); 9310429Sbde 9454263Sshinint looutput __P((struct ifnet *ifp, 9536908Sjulian struct mbuf *m, struct sockaddr *dst, struct rtentry *rt)); 9636908Sjulian 971622Sdg#ifdef TINY_LOMTU 981541Srgrimes#define LOMTU (1024+512) 9953541Sshin#elif defined(LARGE_LOMTU) 10053541Sshin#define LOMTU 131072 1011622Sdg#else 1026876Sdg#define LOMTU 16384 1031622Sdg#endif 1041541Srgrimes 1058090Spststruct ifnet loif[NLOOP]; 1061541Srgrimes 1071541Srgrimes/* ARGSUSED */ 10810429Sbdestatic void 10912569Sbdeloopattach(dummy) 11012569Sbde void *dummy; 1111541Srgrimes{ 1128090Spst register struct ifnet *ifp; 1138090Spst register int i = 0; 1141541Srgrimes 1158090Spst for (ifp = loif; i < NLOOP; ifp++) { 1168090Spst ifp->if_name = "lo"; 1178090Spst ifp->if_unit = i++; 1188090Spst ifp->if_mtu = LOMTU; 1198090Spst ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 1208090Spst ifp->if_ioctl = loioctl; 1218090Spst ifp->if_output = looutput; 1228090Spst ifp->if_type = IFT_LOOP; 12344169Sdt ifp->if_snd.ifq_maxlen = ifqmaxlen; 1248090Spst if_attach(ifp); 12513937Swollman bpfattach(ifp, DLT_NULL, sizeof(u_int)); 1268090Spst } 1271541Srgrimes} 1281541Srgrimes 12954263Sshinint 1301541Srgrimeslooutput(ifp, m, dst, rt) 1311541Srgrimes struct ifnet *ifp; 1321541Srgrimes register struct mbuf *m; 1331541Srgrimes struct sockaddr *dst; 1341541Srgrimes register struct rtentry *rt; 1351541Srgrimes{ 13636908Sjulian if ((m->m_flags & M_PKTHDR) == 0) 13736908Sjulian panic("looutput no HDR"); 13836908Sjulian 13936908Sjulian if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 14036908Sjulian m_freem(m); 14136908Sjulian return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 14236908Sjulian rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 14336908Sjulian } 14453541Sshin /* 14553541Sshin * KAME requires that the packet to be contiguous on the 14653541Sshin * mbuf. We need to make that sure. 14753541Sshin * this kind of code should be avoided. 14853541Sshin * XXX: fails to join if interface MTU > MCLBYTES. jumbogram? 14953541Sshin */ 15053541Sshin if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) { 15153541Sshin struct mbuf *n; 15253541Sshin 15353541Sshin MGETHDR(n, M_DONTWAIT, MT_HEADER); 15453541Sshin if (!n) 15553541Sshin goto contiguousfail; 15653541Sshin MCLGET(n, M_DONTWAIT); 15753541Sshin if (! (n->m_flags & M_EXT)) { 15853541Sshin m_freem(n); 15953541Sshin goto contiguousfail; 16053541Sshin } 16153541Sshin 16253541Sshin m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); 16353541Sshin n->m_pkthdr = m->m_pkthdr; 16453541Sshin n->m_len = m->m_pkthdr.len; 16553541Sshin m_freem(m); 16653541Sshin m = n; 16753541Sshin } 16853541Sshin if (0) { 16953541Sshincontiguousfail: 17053541Sshin printf("looutput: mbuf allocation failed\n"); 17153541Sshin } 17253541Sshin 17336908Sjulian ifp->if_opackets++; 17436908Sjulian ifp->if_obytes += m->m_pkthdr.len; 17536992Sjulian#if 1 /* XXX */ 17636992Sjulian switch (dst->sa_family) { 17736992Sjulian case AF_INET: 17853541Sshin case AF_INET6: 17936992Sjulian case AF_IPX: 18036992Sjulian case AF_NS: 18136992Sjulian case AF_APPLETALK: 18236994Sjulian break; 18336992Sjulian default: 18436992Sjulian printf("looutput: af=%d unexpected", dst->sa_family); 18536992Sjulian m_freem(m); 18636992Sjulian return (EAFNOSUPPORT); 18736992Sjulian } 18836992Sjulian#endif 18960889Sarchie return(if_simloop(ifp, m, dst->sa_family, 0)); 19036908Sjulian} 19136908Sjulian 19236908Sjulian/* 19336908Sjulian * if_simloop() 19436908Sjulian * 19536908Sjulian * This function is to support software emulation of hardware loopback, 19636908Sjulian * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 19736908Sjulian * hear their own broadcasts, we create a copy of the packet that we 19836908Sjulian * would normally receive via a hardware loopback. 19936908Sjulian * 20036908Sjulian * This function expects the packet to include the media header of length hlen. 20136908Sjulian */ 20236908Sjulian 20336908Sjulianint 20460889Sarchieif_simloop(ifp, m, af, hlen) 20536908Sjulian struct ifnet *ifp; 20636908Sjulian register struct mbuf *m; 20760889Sarchie int af; 20836908Sjulian int hlen; 20936908Sjulian{ 2101541Srgrimes int s, isr; 2111541Srgrimes register struct ifqueue *ifq = 0; 2121541Srgrimes 21360889Sarchie KASSERT((m->m_flags & M_PKTHDR) != 0, ("if_simloop: no HDR")); 21436908Sjulian m->m_pkthdr.rcvif = ifp; 21560889Sarchie 21610957Swollman /* BPF write needs to be handled specially */ 21760889Sarchie if (af == AF_UNSPEC) { 21860889Sarchie KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len")); 21960889Sarchie af = *(mtod(m, int *)); 22010957Swollman m->m_len -= sizeof(int); 22110957Swollman m->m_pkthdr.len -= sizeof(int); 22210957Swollman m->m_data += sizeof(int); 22310957Swollman } 22410957Swollman 22560889Sarchie /* Let BPF see incoming packet */ 2268090Spst if (ifp->if_bpf) { 22736908Sjulian struct mbuf m0, *n = m; 2281541Srgrimes 22951646Sphk /* 23051646Sphk * We need to prepend the address family as 23151646Sphk * a four byte field. Cons up a dummy header 23251646Sphk * to pacify bpf. This is safe because bpf 23351646Sphk * will only read from the mbuf (i.e., it won't 23451646Sphk * try to free it or keep a pointer a to it). 23551646Sphk */ 23651646Sphk m0.m_next = m; 23751646Sphk m0.m_len = 4; 23851646Sphk m0.m_data = (char *)⁡ 23951646Sphk n = &m0; 24036908Sjulian bpf_mtap(ifp, n); 2411541Srgrimes } 2421541Srgrimes 24336908Sjulian /* Strip away media header */ 24437600Sdfr if (hlen > 0) { 24560952Sgallatin m_adj(m, hlen); 24637600Sdfr#ifdef __alpha__ 24737600Sdfr /* The alpha doesn't like unaligned data. 24837600Sdfr * We move data down in the first mbuf */ 24960952Sgallatin if (mtod(m, vm_offset_t) & 3) { 25060952Sgallatin KASSERT(hlen >= 3, "if_simloop: hlen too small"); 25160952Sgallatin bcopy(m->m_data, 25260952Sgallatin (char *)(mtod(m, vm_offset_t) 25360952Sgallatin - (mtod(m, vm_offset_t) & 3)), 25460952Sgallatin m->m_len); 25560952Sgallatin mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3); 25660952Sgallatin } 25737600Sdfr#endif 25837600Sdfr } 25936908Sjulian 26060889Sarchie /* Deliver to upper layer protocol */ 26160889Sarchie switch (af) { 2621541Srgrimes#ifdef INET 2631541Srgrimes case AF_INET: 2641541Srgrimes ifq = &ipintrq; 2651541Srgrimes isr = NETISR_IP; 2661541Srgrimes break; 2671541Srgrimes#endif 26853541Sshin#ifdef INET6 26953541Sshin case AF_INET6: 27053541Sshin m->m_flags |= M_LOOP; 27153541Sshin ifq = &ip6intrq; 27253541Sshin isr = NETISR_IPV6; 27353541Sshin break; 27453541Sshin#endif 27511819Sjulian#ifdef IPX 27611819Sjulian case AF_IPX: 27711819Sjulian ifq = &ipxintrq; 27811819Sjulian isr = NETISR_IPX; 27911819Sjulian break; 28011819Sjulian#endif 2811541Srgrimes#ifdef NS 2821541Srgrimes case AF_NS: 2831541Srgrimes ifq = &nsintrq; 2841541Srgrimes isr = NETISR_NS; 2851541Srgrimes break; 2861541Srgrimes#endif 28715885Sjulian#ifdef NETATALK 28815885Sjulian case AF_APPLETALK: 28915885Sjulian ifq = &atintrq2; 29015885Sjulian isr = NETISR_ATALK; 29115885Sjulian break; 29215885Sjulian#endif NETATALK 2931541Srgrimes default: 29460889Sarchie printf("if_simloop: can't handle af=%d\n", af); 2951541Srgrimes m_freem(m); 2961541Srgrimes return (EAFNOSUPPORT); 2971541Srgrimes } 2981541Srgrimes s = splimp(); 2991541Srgrimes if (IF_QFULL(ifq)) { 3001541Srgrimes IF_DROP(ifq); 3011541Srgrimes m_freem(m); 3021541Srgrimes splx(s); 3031541Srgrimes return (ENOBUFS); 3041541Srgrimes } 3051541Srgrimes IF_ENQUEUE(ifq, m); 3061541Srgrimes schednetisr(isr); 3071541Srgrimes ifp->if_ipackets++; 3081541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 3091541Srgrimes splx(s); 3101541Srgrimes return (0); 3111541Srgrimes} 3121541Srgrimes 3131541Srgrimes/* ARGSUSED */ 31412706Sphkstatic void 3151541Srgrimeslortrequest(cmd, rt, sa) 3161541Srgrimes int cmd; 3171541Srgrimes struct rtentry *rt; 3181541Srgrimes struct sockaddr *sa; 3191541Srgrimes{ 32013928Swollman if (rt) { 32113928Swollman rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 32213928Swollman /* 32313928Swollman * For optimal performance, the send and receive buffers 32413928Swollman * should be at least twice the MTU plus a little more for 32513928Swollman * overhead. 32613928Swollman */ 32753541Sshin rt->rt_rmx.rmx_recvpipe = 32813928Swollman rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 32913928Swollman } 3301541Srgrimes} 3311541Srgrimes 3321541Srgrimes/* 3331541Srgrimes * Process an ioctl request. 3341541Srgrimes */ 3351541Srgrimes/* ARGSUSED */ 33654263Sshinint 3371541Srgrimesloioctl(ifp, cmd, data) 3381541Srgrimes register struct ifnet *ifp; 33936735Sdfr u_long cmd; 3401541Srgrimes caddr_t data; 3411541Srgrimes{ 3421541Srgrimes register struct ifaddr *ifa; 3431944Sdg register struct ifreq *ifr = (struct ifreq *)data; 3441541Srgrimes register int error = 0; 3451541Srgrimes 3461541Srgrimes switch (cmd) { 3471541Srgrimes 3481541Srgrimes case SIOCSIFADDR: 34916512Swollman ifp->if_flags |= IFF_UP | IFF_RUNNING; 3501541Srgrimes ifa = (struct ifaddr *)data; 35113928Swollman ifa->ifa_rtrequest = lortrequest; 3521541Srgrimes /* 3531541Srgrimes * Everything else is done at a higher level. 3541541Srgrimes */ 3551541Srgrimes break; 3561541Srgrimes 3571541Srgrimes case SIOCADDMULTI: 3581541Srgrimes case SIOCDELMULTI: 3591541Srgrimes if (ifr == 0) { 3601541Srgrimes error = EAFNOSUPPORT; /* XXX */ 3611541Srgrimes break; 3621541Srgrimes } 3631541Srgrimes switch (ifr->ifr_addr.sa_family) { 3641541Srgrimes 3651541Srgrimes#ifdef INET 3661541Srgrimes case AF_INET: 3671541Srgrimes break; 3681541Srgrimes#endif 36953541Sshin#ifdef INET6 37053541Sshin case AF_INET6: 37153541Sshin break; 37253541Sshin#endif 3731541Srgrimes 3741541Srgrimes default: 3751541Srgrimes error = EAFNOSUPPORT; 3761541Srgrimes break; 3771541Srgrimes } 3781541Srgrimes break; 3791541Srgrimes 3801944Sdg case SIOCSIFMTU: 38149468Sbrian ifp->if_mtu = ifr->ifr_mtu; 3821944Sdg break; 3831944Sdg 38435563Sphk case SIOCSIFFLAGS: 38535563Sphk break; 38635563Sphk 3871541Srgrimes default: 3881541Srgrimes error = EINVAL; 3891541Srgrimes } 3901541Srgrimes return (error); 3911541Srgrimes} 392