123174Smckusick /* 2*29071Skarels * 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*29071Skarels * @(#)if_loop.c 6.10 (Berkeley) 06/04/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 2424771Skarels #ifdef INET 2524771Skarels #include "../netinet/in.h" 2624771Skarels #include "../netinet/in_systm.h" 27*29071Skarels #include "../netinet/in_var.h" 2824771Skarels #include "../netinet/ip.h" 2924771Skarels #endif 305122Swnj 3112460Ssam #ifdef vax 3212460Ssam #include "../vax/mtpr.h" 3312460Ssam #endif 3410907Ssam 3518815Ssklower #ifdef NS 3618815Ssklower #include "../netns/ns.h" 3718815Ssklower #include "../netns/ns_if.h" 3818815Ssklower #endif 3918815Ssklower 405207Swnj #define LOMTU (1024+512) 415122Swnj 425122Swnj struct ifnet loif; 4313066Ssam int looutput(), loioctl(); 445122Swnj 455122Swnj loattach() 465122Swnj { 475122Swnj register struct ifnet *ifp = &loif; 485122Swnj 495172Swnj ifp->if_name = "lo"; 505122Swnj ifp->if_mtu = LOMTU; 5126091Skarels ifp->if_flags = IFF_LOOPBACK; 5213066Ssam ifp->if_ioctl = loioctl; 535122Swnj ifp->if_output = looutput; 545161Swnj if_attach(ifp); 555122Swnj } 565122Swnj 576337Ssam looutput(ifp, m0, dst) 585122Swnj struct ifnet *ifp; 5924771Skarels register struct mbuf *m0; 606337Ssam struct sockaddr *dst; 615122Swnj { 6224771Skarels int s; 636209Swnj register struct ifqueue *ifq; 6424771Skarels struct mbuf *m; 655122Swnj 6624771Skarels /* 6724771Skarels * Place interface pointer before the data 6824771Skarels * for the receiving protocol. 6924771Skarels */ 7024771Skarels if (m0->m_off <= MMAXOFF && 7124771Skarels m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { 7224771Skarels m0->m_off -= sizeof(struct ifnet *); 7324771Skarels m0->m_len += sizeof(struct ifnet *); 7424771Skarels } else { 7524771Skarels MGET(m, M_DONTWAIT, MT_HEADER); 7624771Skarels if (m == (struct mbuf *)0) 7724771Skarels return (ENOBUFS); 7824771Skarels m->m_off = MMINOFF; 7924771Skarels m->m_len = sizeof(struct ifnet *); 8024771Skarels m->m_next = m0; 8124771Skarels m0 = m; 8224771Skarels } 8324771Skarels *(mtod(m0, struct ifnet **)) = ifp; 8424771Skarels s = splimp(); 855172Swnj ifp->if_opackets++; 866337Ssam switch (dst->sa_family) { 875122Swnj 885122Swnj #ifdef INET 896337Ssam case AF_INET: 906209Swnj ifq = &ipintrq; 916209Swnj if (IF_QFULL(ifq)) { 926209Swnj IF_DROP(ifq); 936337Ssam m_freem(m0); 946209Swnj splx(s); 956544Sfeldman return (ENOBUFS); 966209Swnj } 976209Swnj IF_ENQUEUE(ifq, m0); 986262Swnj schednetisr(NETISR_IP); 995122Swnj break; 1005122Swnj #endif 10118815Ssklower #ifdef NS 10218815Ssklower case AF_NS: 10318815Ssklower ifq = &nsintrq; 10418815Ssklower if (IF_QFULL(ifq)) { 10518815Ssklower IF_DROP(ifq); 10618815Ssklower m_freem(m0); 10718815Ssklower splx(s); 10818815Ssklower return (ENOBUFS); 10918815Ssklower } 11018815Ssklower IF_ENQUEUE(ifq, m0); 11118815Ssklower schednetisr(NETISR_NS); 11218815Ssklower break; 11318815Ssklower #endif 1145122Swnj default: 1155122Swnj splx(s); 1166337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1176337Ssam dst->sa_family); 1186337Ssam m_freem(m0); 1196544Sfeldman return (EAFNOSUPPORT); 1205122Swnj } 1215172Swnj ifp->if_ipackets++; 1225122Swnj splx(s); 1236544Sfeldman return (0); 1245122Swnj } 12513066Ssam 12613066Ssam /* 12713066Ssam * Process an ioctl request. 12813066Ssam */ 12918370Skarels /* ARGSUSED */ 13013066Ssam loioctl(ifp, cmd, data) 13113066Ssam register struct ifnet *ifp; 13213066Ssam int cmd; 13313066Ssam caddr_t data; 13413066Ssam { 13518370Skarels int error = 0; 13613066Ssam 13713066Ssam switch (cmd) { 13813066Ssam 13913066Ssam case SIOCSIFADDR: 14018370Skarels ifp->if_flags |= IFF_UP; 14118370Skarels /* 14218370Skarels * Everything else is done at a higher level. 14318370Skarels */ 14413066Ssam break; 14513066Ssam 14613066Ssam default: 14713066Ssam error = EINVAL; 14813066Ssam } 14913066Ssam return (error); 15013066Ssam } 151