123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 544464Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*52947Storek * @(#)if_loop.c 7.16 (Berkeley) 03/15/92 823174Smckusick */ 95122Swnj 105122Swnj /* 115122Swnj * Loopback interface driver for protocol testing and timing. 125122Swnj */ 135122Swnj 1417058Sbloom #include "param.h" 1517058Sbloom #include "systm.h" 1617058Sbloom #include "mbuf.h" 1717058Sbloom #include "socket.h" 1817058Sbloom #include "errno.h" 1917058Sbloom #include "ioctl.h" 2052270Storek #include "machine/cpu.h" 2110907Ssam 2252270Storek #include "if.h" 2352270Storek #include "if_types.h" 2452270Storek #include "netisr.h" 2552270Storek #include "route.h" 2610907Ssam 2724771Skarels #ifdef INET 2852271Ssklower #include "netinet/in.h" 2952271Ssklower #include "netinet/in_systm.h" 3052271Ssklower #include "netinet/in_var.h" 3152271Ssklower #include "netinet/ip.h" 3224771Skarels #endif 335122Swnj 3418815Ssklower #ifdef NS 3552271Ssklower #include "netns/ns.h" 3652271Ssklower #include "netns/ns_if.h" 3718815Ssklower #endif 3818815Ssklower 3937472Ssklower #ifdef ISO 4052271Ssklower #include "netiso/iso.h" 4152271Ssklower #include "netiso/iso_var.h" 4237472Ssklower #endif 4337472Ssklower 445207Swnj #define LOMTU (1024+512) 455122Swnj 465122Swnj struct ifnet loif; 4713066Ssam int looutput(), loioctl(); 485122Swnj 495122Swnj loattach() 505122Swnj { 515122Swnj register struct ifnet *ifp = &loif; 525122Swnj 535172Swnj ifp->if_name = "lo"; 545122Swnj ifp->if_mtu = LOMTU; 5526091Skarels ifp->if_flags = IFF_LOOPBACK; 5613066Ssam ifp->if_ioctl = loioctl; 575122Swnj ifp->if_output = looutput; 5837472Ssklower ifp->if_type = IFT_LOOP; 5937472Ssklower ifp->if_hdrlen = 0; 6037472Ssklower ifp->if_addrlen = 0; 615161Swnj if_attach(ifp); 625122Swnj } 635122Swnj 6445198Ssklower looutput(ifp, m, dst, rt) 655122Swnj struct ifnet *ifp; 6635795Skarels register struct mbuf *m; 676337Ssam struct sockaddr *dst; 6845198Ssklower register struct rtentry *rt; 695122Swnj { 7045523Ssklower int s, isr; 7145523Ssklower register struct ifqueue *ifq = 0; 725122Swnj 7335795Skarels if ((m->m_flags & M_PKTHDR) == 0) 7435795Skarels panic("looutput no HDR"); 7535795Skarels m->m_pkthdr.rcvif = ifp; 7635795Skarels 7745198Ssklower if (rt && rt->rt_flags & RTF_REJECT) { 7845198Ssklower m_freem(m); 7945198Ssklower return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 8045198Ssklower } 815172Swnj ifp->if_opackets++; 8239187Ssklower ifp->if_obytes += m->m_pkthdr.len; 836337Ssam switch (dst->sa_family) { 845122Swnj 855122Swnj #ifdef INET 866337Ssam case AF_INET: 876209Swnj ifq = &ipintrq; 8845523Ssklower isr = NETISR_IP; 895122Swnj break; 905122Swnj #endif 9118815Ssklower #ifdef NS 9218815Ssklower case AF_NS: 9318815Ssklower ifq = &nsintrq; 9445523Ssklower isr = NETISR_NS; 9518815Ssklower break; 9618815Ssklower #endif 9737472Ssklower #ifdef ISO 9837472Ssklower case AF_ISO: 9937472Ssklower ifq = &clnlintrq; 10045523Ssklower isr = NETISR_ISO; 10137472Ssklower break; 10237472Ssklower #endif 1035122Swnj default: 1046337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1056337Ssam dst->sa_family); 10635795Skarels m_freem(m); 1076544Sfeldman return (EAFNOSUPPORT); 1085122Swnj } 10948727Ssklower s = splimp(); 11045523Ssklower if (IF_QFULL(ifq)) { 11145523Ssklower IF_DROP(ifq); 11245523Ssklower m_freem(m); 11345523Ssklower splx(s); 11445523Ssklower return (ENOBUFS); 11545523Ssklower } 11645523Ssklower IF_ENQUEUE(ifq, m); 11745523Ssklower schednetisr(isr); 1185172Swnj ifp->if_ipackets++; 11939187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1205122Swnj splx(s); 1216544Sfeldman return (0); 1225122Swnj } 12313066Ssam 12448727Ssklower /* ARGSUSED */ 12548727Ssklower lortrequest(cmd, rt, sa) 126*52947Storek int cmd; 127*52947Storek struct rtentry *rt; 128*52947Storek struct sockaddr *sa; 12948727Ssklower { 130*52947Storek 13148727Ssklower if (rt) 13248727Ssklower rt->rt_rmx.rmx_mtu = LOMTU; 13348727Ssklower } 13448727Ssklower 13513066Ssam /* 13613066Ssam * Process an ioctl request. 13713066Ssam */ 13818370Skarels /* ARGSUSED */ 13913066Ssam loioctl(ifp, cmd, data) 14013066Ssam register struct ifnet *ifp; 14113066Ssam int cmd; 14213066Ssam caddr_t data; 14313066Ssam { 14448727Ssklower register struct ifaddr *ifa; 14518370Skarels int error = 0; 14613066Ssam 14713066Ssam switch (cmd) { 14813066Ssam 14913066Ssam case SIOCSIFADDR: 15018370Skarels ifp->if_flags |= IFF_UP; 15148727Ssklower ifa = (struct ifaddr *)data; 15248727Ssklower if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 15348727Ssklower ifa->ifa_rtrequest = lortrequest; 15418370Skarels /* 15518370Skarels * Everything else is done at a higher level. 15618370Skarels */ 15713066Ssam break; 15813066Ssam 15913066Ssam default: 16013066Ssam error = EINVAL; 16113066Ssam } 16213066Ssam return (error); 16313066Ssam } 164