123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 3*33183Sbostic * All rights reserved. 423174Smckusick * 5*33183Sbostic * Redistribution and use in source and binary forms are permitted 6*33183Sbostic * provided that this notice is preserved and that due credit is given 7*33183Sbostic * to the University of California at Berkeley. The name of the University 8*33183Sbostic * may not be used to endorse or promote products derived from this 9*33183Sbostic * software without specific prior written permission. This software 10*33183Sbostic * is provided ``as is'' without express or implied warranty. 11*33183Sbostic * 12*33183Sbostic * @(#)if_loop.c 7.3 (Berkeley) 12/30/87 1323174Smckusick */ 145122Swnj 155122Swnj /* 165122Swnj * Loopback interface driver for protocol testing and timing. 175122Swnj */ 185122Swnj 1917058Sbloom #include "param.h" 2017058Sbloom #include "systm.h" 2117058Sbloom #include "mbuf.h" 2217058Sbloom #include "socket.h" 2317058Sbloom #include "errno.h" 2417058Sbloom #include "ioctl.h" 2510907Ssam 2610907Ssam #include "../net/if.h" 2710907Ssam #include "../net/netisr.h" 2810907Ssam #include "../net/route.h" 2910907Ssam 3029922Skarels #include "../machine/mtpr.h" 3129922Skarels 3224771Skarels #ifdef INET 3324771Skarels #include "../netinet/in.h" 3424771Skarels #include "../netinet/in_systm.h" 3529071Skarels #include "../netinet/in_var.h" 3624771Skarels #include "../netinet/ip.h" 3724771Skarels #endif 385122Swnj 3918815Ssklower #ifdef NS 4018815Ssklower #include "../netns/ns.h" 4118815Ssklower #include "../netns/ns_if.h" 4218815Ssklower #endif 4318815Ssklower 445207Swnj #define LOMTU (1024+512) 455122Swnj 465122Swnj struct ifnet loif; 4713066Ssam int looutput(), loioctl(); 485122Swnj 495122Swnj loattach() 505122Swnj { 515122Swnj register struct ifnet *ifp = &loif; 525122Swnj 535172Swnj ifp->if_name = "lo"; 545122Swnj ifp->if_mtu = LOMTU; 5526091Skarels ifp->if_flags = IFF_LOOPBACK; 5613066Ssam ifp->if_ioctl = loioctl; 575122Swnj ifp->if_output = looutput; 585161Swnj if_attach(ifp); 595122Swnj } 605122Swnj 616337Ssam looutput(ifp, m0, dst) 625122Swnj struct ifnet *ifp; 6324771Skarels register struct mbuf *m0; 646337Ssam struct sockaddr *dst; 655122Swnj { 6624771Skarels int s; 676209Swnj register struct ifqueue *ifq; 6824771Skarels struct mbuf *m; 695122Swnj 7024771Skarels /* 7124771Skarels * Place interface pointer before the data 7224771Skarels * for the receiving protocol. 7324771Skarels */ 7424771Skarels if (m0->m_off <= MMAXOFF && 7524771Skarels m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { 7624771Skarels m0->m_off -= sizeof(struct ifnet *); 7724771Skarels m0->m_len += sizeof(struct ifnet *); 7824771Skarels } else { 7924771Skarels MGET(m, M_DONTWAIT, MT_HEADER); 8024771Skarels if (m == (struct mbuf *)0) 8124771Skarels return (ENOBUFS); 8224771Skarels m->m_off = MMINOFF; 8324771Skarels m->m_len = sizeof(struct ifnet *); 8424771Skarels m->m_next = m0; 8524771Skarels m0 = m; 8624771Skarels } 8724771Skarels *(mtod(m0, struct ifnet **)) = ifp; 8824771Skarels s = splimp(); 895172Swnj ifp->if_opackets++; 906337Ssam switch (dst->sa_family) { 915122Swnj 925122Swnj #ifdef INET 936337Ssam case AF_INET: 946209Swnj ifq = &ipintrq; 956209Swnj if (IF_QFULL(ifq)) { 966209Swnj IF_DROP(ifq); 976337Ssam m_freem(m0); 986209Swnj splx(s); 996544Sfeldman return (ENOBUFS); 1006209Swnj } 1016209Swnj IF_ENQUEUE(ifq, m0); 1026262Swnj schednetisr(NETISR_IP); 1035122Swnj break; 1045122Swnj #endif 10518815Ssklower #ifdef NS 10618815Ssklower case AF_NS: 10718815Ssklower ifq = &nsintrq; 10818815Ssklower if (IF_QFULL(ifq)) { 10918815Ssklower IF_DROP(ifq); 11018815Ssklower m_freem(m0); 11118815Ssklower splx(s); 11218815Ssklower return (ENOBUFS); 11318815Ssklower } 11418815Ssklower IF_ENQUEUE(ifq, m0); 11518815Ssklower schednetisr(NETISR_NS); 11618815Ssklower break; 11718815Ssklower #endif 1185122Swnj default: 1195122Swnj splx(s); 1206337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1216337Ssam dst->sa_family); 1226337Ssam m_freem(m0); 1236544Sfeldman return (EAFNOSUPPORT); 1245122Swnj } 1255172Swnj ifp->if_ipackets++; 1265122Swnj splx(s); 1276544Sfeldman return (0); 1285122Swnj } 12913066Ssam 13013066Ssam /* 13113066Ssam * Process an ioctl request. 13213066Ssam */ 13318370Skarels /* ARGSUSED */ 13413066Ssam loioctl(ifp, cmd, data) 13513066Ssam register struct ifnet *ifp; 13613066Ssam int cmd; 13713066Ssam caddr_t data; 13813066Ssam { 13918370Skarels int error = 0; 14013066Ssam 14113066Ssam switch (cmd) { 14213066Ssam 14313066Ssam case SIOCSIFADDR: 14418370Skarels ifp->if_flags |= IFF_UP; 14518370Skarels /* 14618370Skarels * Everything else is done at a higher level. 14718370Skarels */ 14813066Ssam break; 14913066Ssam 15013066Ssam default: 15113066Ssam error = EINVAL; 15213066Ssam } 15313066Ssam return (error); 15413066Ssam } 155