if_loop.c revision 24204
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 3424204Sbde * $Id: if_loop.c,v 1.25 1997/02/22 09:41:02 peter Exp $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * Loopback interface driver for protocol testing and timing. 391541Srgrimes */ 408090Spst#include "loop.h" 418090Spst#if NLOOP > 0 421541Srgrimes 431541Srgrimes#include <sys/param.h> 441541Srgrimes#include <sys/systm.h> 451541Srgrimes#include <sys/kernel.h> 461541Srgrimes#include <sys/mbuf.h> 471541Srgrimes#include <sys/socket.h> 481541Srgrimes#include <sys/errno.h> 4924204Sbde#include <sys/sockio.h> 501541Srgrimes#include <sys/time.h> 511541Srgrimes 521541Srgrimes#include <net/if.h> 531541Srgrimes#include <net/if_types.h> 541541Srgrimes#include <net/netisr.h> 551541Srgrimes#include <net/route.h> 561541Srgrimes#include <net/bpf.h> 571541Srgrimes 581541Srgrimes#ifdef INET 591541Srgrimes#include <netinet/in.h> 601541Srgrimes#include <netinet/in_systm.h> 611541Srgrimes#include <netinet/in_var.h> 621541Srgrimes#include <netinet/ip.h> 631541Srgrimes#endif 641541Srgrimes 6511819Sjulian#ifdef IPX 6611819Sjulian#include <netipx/ipx.h> 6711819Sjulian#include <netipx/ipx_if.h> 6811819Sjulian#endif 6911819Sjulian 701541Srgrimes#ifdef NS 711541Srgrimes#include <netns/ns.h> 721541Srgrimes#include <netns/ns_if.h> 731541Srgrimes#endif 741541Srgrimes 751541Srgrimes#ifdef ISO 761541Srgrimes#include <netiso/iso.h> 771541Srgrimes#include <netiso/iso_var.h> 781541Srgrimes#endif 791541Srgrimes 8015885Sjulian#ifdef NETATALK 8115885Sjulian#include <netinet/if_ether.h> 8215885Sjulian#include <netatalk/at.h> 8315885Sjulian#include <netatalk/at_var.h> 8415885Sjulian#endif NETATALK 8515885Sjulian 861541Srgrimes#include "bpfilter.h" 871541Srgrimes 8812706Sphkstatic int loioctl __P((struct ifnet *, int, caddr_t)); 8912706Sphkstatic void lortrequest __P((int, struct rtentry *, struct sockaddr *)); 9012706Sphk 9110653Sdgstatic void loopattach __P((void *)); 9210429SbdePSEUDO_SET(loopattach, if_loop); 9310429Sbde 941622Sdg#ifdef TINY_LOMTU 951541Srgrimes#define LOMTU (1024+512) 961622Sdg#else 976876Sdg#define LOMTU 16384 981622Sdg#endif 991541Srgrimes 1008090Spststruct ifnet loif[NLOOP]; 1011541Srgrimes 1021541Srgrimes/* ARGSUSED */ 10310429Sbdestatic void 10412569Sbdeloopattach(dummy) 10512569Sbde void *dummy; 1061541Srgrimes{ 1078090Spst register struct ifnet *ifp; 1088090Spst register int i = 0; 1091541Srgrimes 1108090Spst for (ifp = loif; i < NLOOP; ifp++) { 1118090Spst ifp->if_name = "lo"; 1128090Spst ifp->if_unit = i++; 1138090Spst ifp->if_mtu = LOMTU; 1148090Spst ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 1158090Spst ifp->if_ioctl = loioctl; 1168090Spst ifp->if_output = looutput; 1178090Spst ifp->if_type = IFT_LOOP; 1188090Spst if_attach(ifp); 1191541Srgrimes#if NBPFILTER > 0 12013937Swollman bpfattach(ifp, DLT_NULL, sizeof(u_int)); 1211541Srgrimes#endif 1228090Spst } 1231541Srgrimes} 1241541Srgrimes 1251541Srgrimesint 1261541Srgrimeslooutput(ifp, m, dst, rt) 1271541Srgrimes struct ifnet *ifp; 1281541Srgrimes register struct mbuf *m; 1291541Srgrimes struct sockaddr *dst; 1301541Srgrimes register struct rtentry *rt; 1311541Srgrimes{ 1321541Srgrimes int s, isr; 1331541Srgrimes register struct ifqueue *ifq = 0; 1341541Srgrimes 1351541Srgrimes if ((m->m_flags & M_PKTHDR) == 0) 1361541Srgrimes panic("looutput no HDR"); 1371541Srgrimes#if NBPFILTER > 0 13810957Swollman /* BPF write needs to be handled specially */ 13910957Swollman if (dst->sa_family == AF_UNSPEC) { 14010957Swollman dst->sa_family = *(mtod(m, int *)); 14110957Swollman m->m_len -= sizeof(int); 14210957Swollman m->m_pkthdr.len -= sizeof(int); 14310957Swollman m->m_data += sizeof(int); 14410957Swollman } 14510957Swollman 1468090Spst if (ifp->if_bpf) { 1471541Srgrimes /* 1481541Srgrimes * We need to prepend the address family as 1491541Srgrimes * a four byte field. Cons up a dummy header 1501541Srgrimes * to pacify bpf. This is safe because bpf 1511541Srgrimes * will only read from the mbuf (i.e., it won't 1521541Srgrimes * try to free it or keep a pointer a to it). 1531541Srgrimes */ 1541541Srgrimes struct mbuf m0; 1551541Srgrimes u_int af = dst->sa_family; 1561541Srgrimes 1571541Srgrimes m0.m_next = m; 1581541Srgrimes m0.m_len = 4; 1591541Srgrimes m0.m_data = (char *)⁡ 1608876Srgrimes 16113937Swollman bpf_mtap(ifp, &m0); 1621541Srgrimes } 1631541Srgrimes#endif 1641541Srgrimes m->m_pkthdr.rcvif = ifp; 1651541Srgrimes 1661541Srgrimes if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1671541Srgrimes m_freem(m); 1681541Srgrimes return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 1691541Srgrimes rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1701541Srgrimes } 1711541Srgrimes ifp->if_opackets++; 1721541Srgrimes ifp->if_obytes += m->m_pkthdr.len; 1731541Srgrimes switch (dst->sa_family) { 1741541Srgrimes 1751541Srgrimes#ifdef INET 1761541Srgrimes case AF_INET: 1771541Srgrimes ifq = &ipintrq; 1781541Srgrimes isr = NETISR_IP; 1791541Srgrimes break; 1801541Srgrimes#endif 18111819Sjulian#ifdef IPX 18211819Sjulian case AF_IPX: 18311819Sjulian ifq = &ipxintrq; 18411819Sjulian isr = NETISR_IPX; 18511819Sjulian break; 18611819Sjulian#endif 1871541Srgrimes#ifdef NS 1881541Srgrimes case AF_NS: 1891541Srgrimes ifq = &nsintrq; 1901541Srgrimes isr = NETISR_NS; 1911541Srgrimes break; 1921541Srgrimes#endif 1931541Srgrimes#ifdef ISO 1941541Srgrimes case AF_ISO: 1951541Srgrimes ifq = &clnlintrq; 1961541Srgrimes isr = NETISR_ISO; 1971541Srgrimes break; 1981541Srgrimes#endif 19915885Sjulian#ifdef NETATALK 20015885Sjulian case AF_APPLETALK: 20115885Sjulian ifq = &atintrq2; 20215885Sjulian isr = NETISR_ATALK; 20315885Sjulian break; 20415885Sjulian#endif NETATALK 2051541Srgrimes default: 2061541Srgrimes printf("lo%d: can't handle af%d\n", ifp->if_unit, 2071541Srgrimes dst->sa_family); 2081541Srgrimes m_freem(m); 2091541Srgrimes return (EAFNOSUPPORT); 2101541Srgrimes } 2111541Srgrimes s = splimp(); 2121541Srgrimes if (IF_QFULL(ifq)) { 2131541Srgrimes IF_DROP(ifq); 2141541Srgrimes m_freem(m); 2151541Srgrimes splx(s); 2161541Srgrimes return (ENOBUFS); 2171541Srgrimes } 2181541Srgrimes IF_ENQUEUE(ifq, m); 2191541Srgrimes schednetisr(isr); 2201541Srgrimes ifp->if_ipackets++; 2211541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 2221541Srgrimes splx(s); 2231541Srgrimes return (0); 2241541Srgrimes} 2251541Srgrimes 2261541Srgrimes/* ARGSUSED */ 22712706Sphkstatic void 2281541Srgrimeslortrequest(cmd, rt, sa) 2291541Srgrimes int cmd; 2301541Srgrimes struct rtentry *rt; 2311541Srgrimes struct sockaddr *sa; 2321541Srgrimes{ 23313928Swollman if (rt) { 23413928Swollman rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 23513928Swollman /* 23613928Swollman * For optimal performance, the send and receive buffers 23713928Swollman * should be at least twice the MTU plus a little more for 23813928Swollman * overhead. 23913928Swollman */ 24013928Swollman rt->rt_rmx.rmx_recvpipe = 24113928Swollman rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 24213928Swollman } 2431541Srgrimes} 2441541Srgrimes 2451541Srgrimes/* 2461541Srgrimes * Process an ioctl request. 2471541Srgrimes */ 2481541Srgrimes/* ARGSUSED */ 24912706Sphkstatic int 2501541Srgrimesloioctl(ifp, cmd, data) 2511541Srgrimes register struct ifnet *ifp; 2521541Srgrimes int cmd; 2531541Srgrimes caddr_t data; 2541541Srgrimes{ 2551541Srgrimes register struct ifaddr *ifa; 2561944Sdg register struct ifreq *ifr = (struct ifreq *)data; 2571541Srgrimes register int error = 0; 2581541Srgrimes 2591541Srgrimes switch (cmd) { 2601541Srgrimes 2611541Srgrimes case SIOCSIFADDR: 26216512Swollman ifp->if_flags |= IFF_UP | IFF_RUNNING; 2631541Srgrimes ifa = (struct ifaddr *)data; 26413928Swollman ifa->ifa_rtrequest = lortrequest; 2651541Srgrimes /* 2661541Srgrimes * Everything else is done at a higher level. 2671541Srgrimes */ 2681541Srgrimes break; 2691541Srgrimes 2701541Srgrimes case SIOCADDMULTI: 2711541Srgrimes case SIOCDELMULTI: 2721541Srgrimes if (ifr == 0) { 2731541Srgrimes error = EAFNOSUPPORT; /* XXX */ 2741541Srgrimes break; 2751541Srgrimes } 2761541Srgrimes switch (ifr->ifr_addr.sa_family) { 2771541Srgrimes 2781541Srgrimes#ifdef INET 2791541Srgrimes case AF_INET: 2801541Srgrimes break; 2811541Srgrimes#endif 2821541Srgrimes 2831541Srgrimes default: 2841541Srgrimes error = EAFNOSUPPORT; 2851541Srgrimes break; 2861541Srgrimes } 2871541Srgrimes break; 2881541Srgrimes 2891944Sdg case SIOCSIFMTU: 2901944Sdg ifp->if_mtu = ifr->ifr_mtu; 2911944Sdg break; 2921944Sdg 2931541Srgrimes default: 2941541Srgrimes error = EINVAL; 2951541Srgrimes } 2961541Srgrimes return (error); 2971541Srgrimes} 2988090Spst#endif /* NLOOP > 0 */ 299