1*18815Ssklower /* if_loop.c 6.4 85/04/27 */ 25122Swnj 35122Swnj /* 45122Swnj * Loopback interface driver for protocol testing and timing. 55122Swnj */ 65122Swnj 717058Sbloom #include "param.h" 817058Sbloom #include "systm.h" 917058Sbloom #include "mbuf.h" 1017058Sbloom #include "socket.h" 1117058Sbloom #include "errno.h" 1217058Sbloom #include "ioctl.h" 1310907Ssam 1410907Ssam #include "../net/if.h" 1510907Ssam #include "../net/netisr.h" 1610907Ssam #include "../net/route.h" 1710907Ssam 1817058Sbloom #include "in.h" 1917058Sbloom #include "in_systm.h" 2017058Sbloom #include "ip.h" 2117058Sbloom #include "ip_var.h" 225122Swnj 2312460Ssam #ifdef vax 2412460Ssam #include "../vax/mtpr.h" 2512460Ssam #endif 2610907Ssam 27*18815Ssklower #ifdef NS 28*18815Ssklower #include "../netns/ns.h" 29*18815Ssklower #include "../netns/ns_if.h" 30*18815Ssklower #endif 31*18815Ssklower 325296Sroot #define LONET 127 3312761Ssam #define LOHOST 1 /* can't be 0, that's broadcast */ 345207Swnj #define LOMTU (1024+512) 355122Swnj 365122Swnj struct ifnet loif; 3713066Ssam int looutput(), loioctl(); 385122Swnj 395122Swnj loattach() 405122Swnj { 415122Swnj register struct ifnet *ifp = &loif; 426337Ssam register struct sockaddr_in *sin; 435122Swnj 445172Swnj ifp->if_name = "lo"; 455122Swnj ifp->if_mtu = LOMTU; 4613066Ssam ifp->if_ioctl = loioctl; 475122Swnj ifp->if_output = looutput; 485161Swnj if_attach(ifp); 495122Swnj } 505122Swnj 516337Ssam looutput(ifp, m0, dst) 525122Swnj struct ifnet *ifp; 535122Swnj struct mbuf *m0; 546337Ssam struct sockaddr *dst; 555122Swnj { 565122Swnj int s = splimp(); 576209Swnj register struct ifqueue *ifq; 585122Swnj 595172Swnj ifp->if_opackets++; 606337Ssam switch (dst->sa_family) { 615122Swnj 625122Swnj #ifdef INET 636337Ssam case AF_INET: 646209Swnj ifq = &ipintrq; 656209Swnj if (IF_QFULL(ifq)) { 666209Swnj IF_DROP(ifq); 676337Ssam m_freem(m0); 686209Swnj splx(s); 696544Sfeldman return (ENOBUFS); 706209Swnj } 716209Swnj IF_ENQUEUE(ifq, m0); 726262Swnj schednetisr(NETISR_IP); 735122Swnj break; 745122Swnj #endif 75*18815Ssklower #ifdef NS 76*18815Ssklower case AF_NS: 77*18815Ssklower ifq = &nsintrq; 78*18815Ssklower if (IF_QFULL(ifq)) { 79*18815Ssklower IF_DROP(ifq); 80*18815Ssklower m_freem(m0); 81*18815Ssklower splx(s); 82*18815Ssklower return (ENOBUFS); 83*18815Ssklower } 84*18815Ssklower IF_ENQUEUE(ifq, m0); 85*18815Ssklower schednetisr(NETISR_NS); 86*18815Ssklower break; 87*18815Ssklower #endif 885122Swnj default: 895122Swnj splx(s); 906337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 916337Ssam dst->sa_family); 926337Ssam m_freem(m0); 936544Sfeldman return (EAFNOSUPPORT); 945122Swnj } 955172Swnj ifp->if_ipackets++; 965122Swnj splx(s); 976544Sfeldman return (0); 985122Swnj } 9913066Ssam 10013066Ssam /* 10113066Ssam * Process an ioctl request. 10213066Ssam */ 10318370Skarels /* ARGSUSED */ 10413066Ssam loioctl(ifp, cmd, data) 10513066Ssam register struct ifnet *ifp; 10613066Ssam int cmd; 10713066Ssam caddr_t data; 10813066Ssam { 10918370Skarels int error = 0; 11013066Ssam 11113066Ssam switch (cmd) { 11213066Ssam 11313066Ssam case SIOCSIFADDR: 11418370Skarels ifp->if_flags |= IFF_UP; 11518370Skarels /* 11618370Skarels * Everything else is done at a higher level. 11718370Skarels */ 11813066Ssam break; 11913066Ssam 12013066Ssam default: 12113066Ssam error = EINVAL; 12213066Ssam } 12313066Ssam return (error); 12413066Ssam } 125