if_loop.c revision 31742
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 3431742Seivind * $Id: if_loop.c,v 1.27 1997/08/02 14:32:37 bde Exp $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * Loopback interface driver for protocol testing and timing. 391541Srgrimes */ 408090Spst#include "loop.h" 418090Spst#if NLOOP > 0 421541Srgrimes 4331742Seivind#include "opt_ipx.h" 4431742Seivind 451541Srgrimes#include <sys/param.h> 461541Srgrimes#include <sys/systm.h> 471541Srgrimes#include <sys/kernel.h> 481541Srgrimes#include <sys/mbuf.h> 491541Srgrimes#include <sys/socket.h> 5024204Sbde#include <sys/sockio.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_var.h> 611541Srgrimes#endif 621541Srgrimes 6311819Sjulian#ifdef IPX 6411819Sjulian#include <netipx/ipx.h> 6511819Sjulian#include <netipx/ipx_if.h> 6611819Sjulian#endif 6711819Sjulian 681541Srgrimes#ifdef NS 691541Srgrimes#include <netns/ns.h> 701541Srgrimes#include <netns/ns_if.h> 711541Srgrimes#endif 721541Srgrimes 731541Srgrimes#ifdef ISO 741541Srgrimes#include <netiso/iso.h> 751541Srgrimes#include <netiso/iso_var.h> 761541Srgrimes#endif 771541Srgrimes 7815885Sjulian#ifdef NETATALK 7915885Sjulian#include <netatalk/at.h> 8015885Sjulian#include <netatalk/at_var.h> 8115885Sjulian#endif NETATALK 8215885Sjulian 831541Srgrimes#include "bpfilter.h" 841541Srgrimes 8512706Sphkstatic int loioctl __P((struct ifnet *, int, caddr_t)); 8612706Sphkstatic void lortrequest __P((int, struct rtentry *, struct sockaddr *)); 8712706Sphk 8810653Sdgstatic void loopattach __P((void *)); 8910429SbdePSEUDO_SET(loopattach, if_loop); 9010429Sbde 911622Sdg#ifdef TINY_LOMTU 921541Srgrimes#define LOMTU (1024+512) 931622Sdg#else 946876Sdg#define LOMTU 16384 951622Sdg#endif 961541Srgrimes 978090Spststruct ifnet loif[NLOOP]; 981541Srgrimes 991541Srgrimes/* ARGSUSED */ 10010429Sbdestatic void 10112569Sbdeloopattach(dummy) 10212569Sbde void *dummy; 1031541Srgrimes{ 1048090Spst register struct ifnet *ifp; 1058090Spst register int i = 0; 1061541Srgrimes 1078090Spst for (ifp = loif; i < NLOOP; ifp++) { 1088090Spst ifp->if_name = "lo"; 1098090Spst ifp->if_unit = i++; 1108090Spst ifp->if_mtu = LOMTU; 1118090Spst ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 1128090Spst ifp->if_ioctl = loioctl; 1138090Spst ifp->if_output = looutput; 1148090Spst ifp->if_type = IFT_LOOP; 1158090Spst if_attach(ifp); 1161541Srgrimes#if NBPFILTER > 0 11713937Swollman bpfattach(ifp, DLT_NULL, sizeof(u_int)); 1181541Srgrimes#endif 1198090Spst } 1201541Srgrimes} 1211541Srgrimes 1221541Srgrimesint 1231541Srgrimeslooutput(ifp, m, dst, rt) 1241541Srgrimes struct ifnet *ifp; 1251541Srgrimes register struct mbuf *m; 1261541Srgrimes struct sockaddr *dst; 1271541Srgrimes register struct rtentry *rt; 1281541Srgrimes{ 1291541Srgrimes int s, isr; 1301541Srgrimes register struct ifqueue *ifq = 0; 1311541Srgrimes 1321541Srgrimes if ((m->m_flags & M_PKTHDR) == 0) 1331541Srgrimes panic("looutput no HDR"); 1341541Srgrimes#if NBPFILTER > 0 13510957Swollman /* BPF write needs to be handled specially */ 13610957Swollman if (dst->sa_family == AF_UNSPEC) { 13710957Swollman dst->sa_family = *(mtod(m, int *)); 13810957Swollman m->m_len -= sizeof(int); 13910957Swollman m->m_pkthdr.len -= sizeof(int); 14010957Swollman m->m_data += sizeof(int); 14110957Swollman } 14210957Swollman 1438090Spst if (ifp->if_bpf) { 1441541Srgrimes /* 1451541Srgrimes * We need to prepend the address family as 1461541Srgrimes * a four byte field. Cons up a dummy header 1471541Srgrimes * to pacify bpf. This is safe because bpf 1481541Srgrimes * will only read from the mbuf (i.e., it won't 1491541Srgrimes * try to free it or keep a pointer a to it). 1501541Srgrimes */ 1511541Srgrimes struct mbuf m0; 1521541Srgrimes u_int af = dst->sa_family; 1531541Srgrimes 1541541Srgrimes m0.m_next = m; 1551541Srgrimes m0.m_len = 4; 1561541Srgrimes m0.m_data = (char *)⁡ 1578876Srgrimes 15813937Swollman bpf_mtap(ifp, &m0); 1591541Srgrimes } 1601541Srgrimes#endif 1611541Srgrimes m->m_pkthdr.rcvif = ifp; 1621541Srgrimes 1631541Srgrimes if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1641541Srgrimes m_freem(m); 1651541Srgrimes return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 1661541Srgrimes rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1671541Srgrimes } 1681541Srgrimes ifp->if_opackets++; 1691541Srgrimes ifp->if_obytes += m->m_pkthdr.len; 1701541Srgrimes switch (dst->sa_family) { 1711541Srgrimes 1721541Srgrimes#ifdef INET 1731541Srgrimes case AF_INET: 1741541Srgrimes ifq = &ipintrq; 1751541Srgrimes isr = NETISR_IP; 1761541Srgrimes break; 1771541Srgrimes#endif 17811819Sjulian#ifdef IPX 17911819Sjulian case AF_IPX: 18011819Sjulian ifq = &ipxintrq; 18111819Sjulian isr = NETISR_IPX; 18211819Sjulian break; 18311819Sjulian#endif 1841541Srgrimes#ifdef NS 1851541Srgrimes case AF_NS: 1861541Srgrimes ifq = &nsintrq; 1871541Srgrimes isr = NETISR_NS; 1881541Srgrimes break; 1891541Srgrimes#endif 1901541Srgrimes#ifdef ISO 1911541Srgrimes case AF_ISO: 1921541Srgrimes ifq = &clnlintrq; 1931541Srgrimes isr = NETISR_ISO; 1941541Srgrimes break; 1951541Srgrimes#endif 19615885Sjulian#ifdef NETATALK 19715885Sjulian case AF_APPLETALK: 19815885Sjulian ifq = &atintrq2; 19915885Sjulian isr = NETISR_ATALK; 20015885Sjulian break; 20115885Sjulian#endif NETATALK 2021541Srgrimes default: 2031541Srgrimes printf("lo%d: can't handle af%d\n", ifp->if_unit, 2041541Srgrimes dst->sa_family); 2051541Srgrimes m_freem(m); 2061541Srgrimes return (EAFNOSUPPORT); 2071541Srgrimes } 2081541Srgrimes s = splimp(); 2091541Srgrimes if (IF_QFULL(ifq)) { 2101541Srgrimes IF_DROP(ifq); 2111541Srgrimes m_freem(m); 2121541Srgrimes splx(s); 2131541Srgrimes return (ENOBUFS); 2141541Srgrimes } 2151541Srgrimes IF_ENQUEUE(ifq, m); 2161541Srgrimes schednetisr(isr); 2171541Srgrimes ifp->if_ipackets++; 2181541Srgrimes ifp->if_ibytes += m->m_pkthdr.len; 2191541Srgrimes splx(s); 2201541Srgrimes return (0); 2211541Srgrimes} 2221541Srgrimes 2231541Srgrimes/* ARGSUSED */ 22412706Sphkstatic void 2251541Srgrimeslortrequest(cmd, rt, sa) 2261541Srgrimes int cmd; 2271541Srgrimes struct rtentry *rt; 2281541Srgrimes struct sockaddr *sa; 2291541Srgrimes{ 23013928Swollman if (rt) { 23113928Swollman rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 23213928Swollman /* 23313928Swollman * For optimal performance, the send and receive buffers 23413928Swollman * should be at least twice the MTU plus a little more for 23513928Swollman * overhead. 23613928Swollman */ 23713928Swollman rt->rt_rmx.rmx_recvpipe = 23813928Swollman rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 23913928Swollman } 2401541Srgrimes} 2411541Srgrimes 2421541Srgrimes/* 2431541Srgrimes * Process an ioctl request. 2441541Srgrimes */ 2451541Srgrimes/* ARGSUSED */ 24612706Sphkstatic int 2471541Srgrimesloioctl(ifp, cmd, data) 2481541Srgrimes register struct ifnet *ifp; 2491541Srgrimes int cmd; 2501541Srgrimes caddr_t data; 2511541Srgrimes{ 2521541Srgrimes register struct ifaddr *ifa; 2531944Sdg register struct ifreq *ifr = (struct ifreq *)data; 2541541Srgrimes register int error = 0; 2551541Srgrimes 2561541Srgrimes switch (cmd) { 2571541Srgrimes 2581541Srgrimes case SIOCSIFADDR: 25916512Swollman ifp->if_flags |= IFF_UP | IFF_RUNNING; 2601541Srgrimes ifa = (struct ifaddr *)data; 26113928Swollman ifa->ifa_rtrequest = lortrequest; 2621541Srgrimes /* 2631541Srgrimes * Everything else is done at a higher level. 2641541Srgrimes */ 2651541Srgrimes break; 2661541Srgrimes 2671541Srgrimes case SIOCADDMULTI: 2681541Srgrimes case SIOCDELMULTI: 2691541Srgrimes if (ifr == 0) { 2701541Srgrimes error = EAFNOSUPPORT; /* XXX */ 2711541Srgrimes break; 2721541Srgrimes } 2731541Srgrimes switch (ifr->ifr_addr.sa_family) { 2741541Srgrimes 2751541Srgrimes#ifdef INET 2761541Srgrimes case AF_INET: 2771541Srgrimes break; 2781541Srgrimes#endif 2791541Srgrimes 2801541Srgrimes default: 2811541Srgrimes error = EAFNOSUPPORT; 2821541Srgrimes break; 2831541Srgrimes } 2841541Srgrimes break; 2851541Srgrimes 2861944Sdg case SIOCSIFMTU: 2871944Sdg ifp->if_mtu = ifr->ifr_mtu; 2881944Sdg break; 2891944Sdg 2901541Srgrimes default: 2911541Srgrimes error = EINVAL; 2921541Srgrimes } 2931541Srgrimes return (error); 2941541Srgrimes} 2958090Spst#endif /* NLOOP > 0 */ 296