123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 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*29922Skarels * @(#)if_loop.c 7.2 (Berkeley) 10/28/86 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 2010907Ssam #include "../net/if.h" 2110907Ssam #include "../net/netisr.h" 2210907Ssam #include "../net/route.h" 2310907Ssam 24*29922Skarels #include "../machine/mtpr.h" 25*29922Skarels 2624771Skarels #ifdef INET 2724771Skarels #include "../netinet/in.h" 2824771Skarels #include "../netinet/in_systm.h" 2929071Skarels #include "../netinet/in_var.h" 3024771Skarels #include "../netinet/ip.h" 3124771Skarels #endif 325122Swnj 3318815Ssklower #ifdef NS 3418815Ssklower #include "../netns/ns.h" 3518815Ssklower #include "../netns/ns_if.h" 3618815Ssklower #endif 3718815Ssklower 385207Swnj #define LOMTU (1024+512) 395122Swnj 405122Swnj struct ifnet loif; 4113066Ssam int looutput(), loioctl(); 425122Swnj 435122Swnj loattach() 445122Swnj { 455122Swnj register struct ifnet *ifp = &loif; 465122Swnj 475172Swnj ifp->if_name = "lo"; 485122Swnj ifp->if_mtu = LOMTU; 4926091Skarels ifp->if_flags = IFF_LOOPBACK; 5013066Ssam ifp->if_ioctl = loioctl; 515122Swnj ifp->if_output = looutput; 525161Swnj if_attach(ifp); 535122Swnj } 545122Swnj 556337Ssam looutput(ifp, m0, dst) 565122Swnj struct ifnet *ifp; 5724771Skarels register struct mbuf *m0; 586337Ssam struct sockaddr *dst; 595122Swnj { 6024771Skarels int s; 616209Swnj register struct ifqueue *ifq; 6224771Skarels struct mbuf *m; 635122Swnj 6424771Skarels /* 6524771Skarels * Place interface pointer before the data 6624771Skarels * for the receiving protocol. 6724771Skarels */ 6824771Skarels if (m0->m_off <= MMAXOFF && 6924771Skarels m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { 7024771Skarels m0->m_off -= sizeof(struct ifnet *); 7124771Skarels m0->m_len += sizeof(struct ifnet *); 7224771Skarels } else { 7324771Skarels MGET(m, M_DONTWAIT, MT_HEADER); 7424771Skarels if (m == (struct mbuf *)0) 7524771Skarels return (ENOBUFS); 7624771Skarels m->m_off = MMINOFF; 7724771Skarels m->m_len = sizeof(struct ifnet *); 7824771Skarels m->m_next = m0; 7924771Skarels m0 = m; 8024771Skarels } 8124771Skarels *(mtod(m0, struct ifnet **)) = ifp; 8224771Skarels s = splimp(); 835172Swnj ifp->if_opackets++; 846337Ssam switch (dst->sa_family) { 855122Swnj 865122Swnj #ifdef INET 876337Ssam case AF_INET: 886209Swnj ifq = &ipintrq; 896209Swnj if (IF_QFULL(ifq)) { 906209Swnj IF_DROP(ifq); 916337Ssam m_freem(m0); 926209Swnj splx(s); 936544Sfeldman return (ENOBUFS); 946209Swnj } 956209Swnj IF_ENQUEUE(ifq, m0); 966262Swnj schednetisr(NETISR_IP); 975122Swnj break; 985122Swnj #endif 9918815Ssklower #ifdef NS 10018815Ssklower case AF_NS: 10118815Ssklower ifq = &nsintrq; 10218815Ssklower if (IF_QFULL(ifq)) { 10318815Ssklower IF_DROP(ifq); 10418815Ssklower m_freem(m0); 10518815Ssklower splx(s); 10618815Ssklower return (ENOBUFS); 10718815Ssklower } 10818815Ssklower IF_ENQUEUE(ifq, m0); 10918815Ssklower schednetisr(NETISR_NS); 11018815Ssklower break; 11118815Ssklower #endif 1125122Swnj default: 1135122Swnj splx(s); 1146337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1156337Ssam dst->sa_family); 1166337Ssam m_freem(m0); 1176544Sfeldman return (EAFNOSUPPORT); 1185122Swnj } 1195172Swnj ifp->if_ipackets++; 1205122Swnj splx(s); 1216544Sfeldman return (0); 1225122Swnj } 12313066Ssam 12413066Ssam /* 12513066Ssam * Process an ioctl request. 12613066Ssam */ 12718370Skarels /* ARGSUSED */ 12813066Ssam loioctl(ifp, cmd, data) 12913066Ssam register struct ifnet *ifp; 13013066Ssam int cmd; 13113066Ssam caddr_t data; 13213066Ssam { 13318370Skarels int error = 0; 13413066Ssam 13513066Ssam switch (cmd) { 13613066Ssam 13713066Ssam case SIOCSIFADDR: 13818370Skarels ifp->if_flags |= IFF_UP; 13918370Skarels /* 14018370Skarels * Everything else is done at a higher level. 14118370Skarels */ 14213066Ssam break; 14313066Ssam 14413066Ssam default: 14513066Ssam error = EINVAL; 14613066Ssam } 14713066Ssam return (error); 14813066Ssam } 149