123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 5*44464Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*44464Sbostic * @(#)if_loop.c 7.10 (Berkeley) 06/28/90 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" 2010907Ssam 2110907Ssam #include "../net/if.h" 2238988Skarels #include "../net/if_types.h" 2310907Ssam #include "../net/netisr.h" 2410907Ssam #include "../net/route.h" 2510907Ssam 2637500Smckusick #include "machine/mtpr.h" 2729922Skarels 2824771Skarels #ifdef INET 2924771Skarels #include "../netinet/in.h" 3024771Skarels #include "../netinet/in_systm.h" 3129071Skarels #include "../netinet/in_var.h" 3224771Skarels #include "../netinet/ip.h" 3324771Skarels #endif 345122Swnj 3518815Ssklower #ifdef NS 3618815Ssklower #include "../netns/ns.h" 3718815Ssklower #include "../netns/ns_if.h" 3818815Ssklower #endif 3918815Ssklower 4037472Ssklower #ifdef ISO 4137472Ssklower #include "../netiso/iso.h" 4237472Ssklower #include "../netiso/iso_var.h" 4337472Ssklower #endif 4437472Ssklower 455207Swnj #define LOMTU (1024+512) 465122Swnj 475122Swnj struct ifnet loif; 4813066Ssam int looutput(), loioctl(); 495122Swnj 505122Swnj loattach() 515122Swnj { 525122Swnj register struct ifnet *ifp = &loif; 535122Swnj 545172Swnj ifp->if_name = "lo"; 555122Swnj ifp->if_mtu = LOMTU; 5626091Skarels ifp->if_flags = IFF_LOOPBACK; 5713066Ssam ifp->if_ioctl = loioctl; 585122Swnj ifp->if_output = looutput; 5937472Ssklower ifp->if_type = IFT_LOOP; 6037472Ssklower ifp->if_hdrlen = 0; 6137472Ssklower ifp->if_addrlen = 0; 625161Swnj if_attach(ifp); 635122Swnj } 645122Swnj 6535795Skarels struct mbuf *Loop_Sanity; 6635795Skarels 6735795Skarels looutput(ifp, m, dst) 685122Swnj struct ifnet *ifp; 6935795Skarels register struct mbuf *m; 706337Ssam struct sockaddr *dst; 715122Swnj { 7224771Skarels int s; 736209Swnj register struct ifqueue *ifq; 745122Swnj 7535795Skarels if ((m->m_flags & M_PKTHDR) == 0) 7635795Skarels panic("looutput no HDR"); 7735795Skarels m->m_pkthdr.rcvif = ifp; 7835795Skarels 7935795Skarels {struct mbuf *mm; int mlen = 0; 8037472Ssklower for (mm = m; m; m = m->m_next) /* XXX debugging code -- sklower */ 8135795Skarels mlen += m->m_len; 8235795Skarels m = mm; 8335795Skarels if (mlen != m->m_pkthdr.len) { 8435795Skarels if (Loop_Sanity) 8535795Skarels m_freem(Loop_Sanity); 8637472Ssklower Loop_Sanity = m_copy(m, 0, (int)M_COPYALL); 8735795Skarels } 8835795Skarels } 8935795Skarels 9024771Skarels s = splimp(); 915172Swnj ifp->if_opackets++; 9239187Ssklower ifp->if_obytes += m->m_pkthdr.len; 936337Ssam switch (dst->sa_family) { 945122Swnj 955122Swnj #ifdef INET 966337Ssam case AF_INET: 976209Swnj ifq = &ipintrq; 986209Swnj if (IF_QFULL(ifq)) { 996209Swnj IF_DROP(ifq); 10035795Skarels m_freem(m); 1016209Swnj splx(s); 1026544Sfeldman return (ENOBUFS); 1036209Swnj } 10435795Skarels IF_ENQUEUE(ifq, m); 1056262Swnj schednetisr(NETISR_IP); 1065122Swnj break; 1075122Swnj #endif 10818815Ssklower #ifdef NS 10918815Ssklower case AF_NS: 11018815Ssklower ifq = &nsintrq; 11118815Ssklower if (IF_QFULL(ifq)) { 11218815Ssklower IF_DROP(ifq); 11335795Skarels m_freem(m); 11418815Ssklower splx(s); 11518815Ssklower return (ENOBUFS); 11618815Ssklower } 11735795Skarels IF_ENQUEUE(ifq, m); 11818815Ssklower schednetisr(NETISR_NS); 11918815Ssklower break; 12018815Ssklower #endif 12137472Ssklower #ifdef ISO 12237472Ssklower case AF_ISO: 12337472Ssklower ifq = &clnlintrq; 12437472Ssklower if (IF_QFULL(ifq)) { 12537472Ssklower IF_DROP(ifq); 12637472Ssklower m_freem(m); 12737472Ssklower splx(s); 12837472Ssklower return (ENOBUFS); 12937472Ssklower } 13037472Ssklower IF_ENQUEUE(ifq, m); 13137472Ssklower schednetisr(NETISR_ISO); 13237472Ssklower break; 13337472Ssklower #endif 1345122Swnj default: 1355122Swnj splx(s); 1366337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1376337Ssam dst->sa_family); 13835795Skarels m_freem(m); 1396544Sfeldman return (EAFNOSUPPORT); 1405122Swnj } 1415172Swnj ifp->if_ipackets++; 14239187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1435122Swnj splx(s); 1446544Sfeldman return (0); 1455122Swnj } 14613066Ssam 14713066Ssam /* 14813066Ssam * Process an ioctl request. 14913066Ssam */ 15018370Skarels /* ARGSUSED */ 15113066Ssam loioctl(ifp, cmd, data) 15213066Ssam register struct ifnet *ifp; 15313066Ssam int cmd; 15413066Ssam caddr_t data; 15513066Ssam { 15618370Skarels int error = 0; 15713066Ssam 15813066Ssam switch (cmd) { 15913066Ssam 16013066Ssam case SIOCSIFADDR: 16118370Skarels ifp->if_flags |= IFF_UP; 16218370Skarels /* 16318370Skarels * Everything else is done at a higher level. 16418370Skarels */ 16513066Ssam break; 16613066Ssam 16713066Ssam default: 16813066Ssam error = EINVAL; 16913066Ssam } 17013066Ssam return (error); 17113066Ssam } 172