123174Smckusick /* 223174Smckusick * Copyright (c) 1982 Regents of the University of California. 323174Smckusick * All rights reserved. The Berkeley software License Agreement 423174Smckusick * specifies the terms and conditions for redistribution. 523174Smckusick * 6*24771Skarels * @(#)if_loop.c 6.7 (Berkeley) 09/16/85 723174Smckusick */ 85122Swnj 95122Swnj /* 105122Swnj * Loopback interface driver for protocol testing and timing. 115122Swnj */ 125122Swnj 1317058Sbloom #include "param.h" 1417058Sbloom #include "systm.h" 1517058Sbloom #include "mbuf.h" 1617058Sbloom #include "socket.h" 1717058Sbloom #include "errno.h" 1817058Sbloom #include "ioctl.h" 1910907Ssam 20*24771Skarels #ifdef BBNNET 21*24771Skarels #define INET 22*24771Skarels #endif 2310907Ssam #include "../net/if.h" 2410907Ssam #include "../net/netisr.h" 2510907Ssam #include "../net/route.h" 2610907Ssam 27*24771Skarels #ifdef INET 28*24771Skarels #include "../netinet/in.h" 29*24771Skarels #include "../netinet/in_systm.h" 30*24771Skarels #include "../netinet/ip.h" 31*24771Skarels #include "../netinet/ip_var.h" 32*24771Skarels #endif 335122Swnj 3412460Ssam #ifdef vax 3512460Ssam #include "../vax/mtpr.h" 3612460Ssam #endif 3710907Ssam 3818815Ssklower #ifdef NS 3918815Ssklower #include "../netns/ns.h" 4018815Ssklower #include "../netns/ns_if.h" 4118815Ssklower #endif 4218815Ssklower 435207Swnj #define LOMTU (1024+512) 445122Swnj 455122Swnj struct ifnet loif; 4613066Ssam int looutput(), loioctl(); 475122Swnj 485122Swnj loattach() 495122Swnj { 505122Swnj register struct ifnet *ifp = &loif; 515122Swnj 525172Swnj ifp->if_name = "lo"; 535122Swnj ifp->if_mtu = LOMTU; 5413066Ssam ifp->if_ioctl = loioctl; 555122Swnj ifp->if_output = looutput; 565161Swnj if_attach(ifp); 575122Swnj } 585122Swnj 596337Ssam looutput(ifp, m0, dst) 605122Swnj struct ifnet *ifp; 61*24771Skarels register struct mbuf *m0; 626337Ssam struct sockaddr *dst; 635122Swnj { 64*24771Skarels int s; 656209Swnj register struct ifqueue *ifq; 66*24771Skarels struct mbuf *m; 675122Swnj 68*24771Skarels /* 69*24771Skarels * Place interface pointer before the data 70*24771Skarels * for the receiving protocol. 71*24771Skarels */ 72*24771Skarels if (m0->m_off <= MMAXOFF && 73*24771Skarels m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { 74*24771Skarels m0->m_off -= sizeof(struct ifnet *); 75*24771Skarels m0->m_len += sizeof(struct ifnet *); 76*24771Skarels } else { 77*24771Skarels MGET(m, M_DONTWAIT, MT_HEADER); 78*24771Skarels if (m == (struct mbuf *)0) 79*24771Skarels return (ENOBUFS); 80*24771Skarels m->m_off = MMINOFF; 81*24771Skarels m->m_len = sizeof(struct ifnet *); 82*24771Skarels m->m_next = m0; 83*24771Skarels m0 = m; 84*24771Skarels } 85*24771Skarels *(mtod(m0, struct ifnet **)) = ifp; 86*24771Skarels s = splimp(); 875172Swnj ifp->if_opackets++; 886337Ssam switch (dst->sa_family) { 895122Swnj 905122Swnj #ifdef INET 916337Ssam case AF_INET: 926209Swnj ifq = &ipintrq; 936209Swnj if (IF_QFULL(ifq)) { 946209Swnj IF_DROP(ifq); 956337Ssam m_freem(m0); 966209Swnj splx(s); 976544Sfeldman return (ENOBUFS); 986209Swnj } 996209Swnj IF_ENQUEUE(ifq, m0); 1006262Swnj schednetisr(NETISR_IP); 1015122Swnj break; 1025122Swnj #endif 10318815Ssklower #ifdef NS 10418815Ssklower case AF_NS: 10518815Ssklower ifq = &nsintrq; 10618815Ssklower if (IF_QFULL(ifq)) { 10718815Ssklower IF_DROP(ifq); 10818815Ssklower m_freem(m0); 10918815Ssklower splx(s); 11018815Ssklower return (ENOBUFS); 11118815Ssklower } 11218815Ssklower IF_ENQUEUE(ifq, m0); 11318815Ssklower schednetisr(NETISR_NS); 11418815Ssklower break; 11518815Ssklower #endif 1165122Swnj default: 1175122Swnj splx(s); 1186337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1196337Ssam dst->sa_family); 1206337Ssam m_freem(m0); 1216544Sfeldman return (EAFNOSUPPORT); 1225122Swnj } 1235172Swnj ifp->if_ipackets++; 1245122Swnj splx(s); 1256544Sfeldman return (0); 1265122Swnj } 12713066Ssam 12813066Ssam /* 12913066Ssam * Process an ioctl request. 13013066Ssam */ 13118370Skarels /* ARGSUSED */ 13213066Ssam loioctl(ifp, cmd, data) 13313066Ssam register struct ifnet *ifp; 13413066Ssam int cmd; 13513066Ssam caddr_t data; 13613066Ssam { 13718370Skarels int error = 0; 13813066Ssam 13913066Ssam switch (cmd) { 14013066Ssam 14113066Ssam case SIOCSIFADDR: 14218370Skarels ifp->if_flags |= IFF_UP; 14318370Skarels /* 14418370Skarels * Everything else is done at a higher level. 14518370Skarels */ 14613066Ssam break; 14713066Ssam 14813066Ssam default: 14913066Ssam error = EINVAL; 15013066Ssam } 15113066Ssam return (error); 15213066Ssam } 153