1*23174Smckusick /* 2*23174Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23174Smckusick * All rights reserved. The Berkeley software License Agreement 4*23174Smckusick * specifies the terms and conditions for redistribution. 5*23174Smckusick * 6*23174Smckusick * @(#)if_loop.c 6.6 (Berkeley) 06/08/85 7*23174Smckusick */ 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 2417058Sbloom #include "in.h" 2517058Sbloom #include "in_systm.h" 2617058Sbloom #include "ip.h" 2717058Sbloom #include "ip_var.h" 285122Swnj 2912460Ssam #ifdef vax 3012460Ssam #include "../vax/mtpr.h" 3112460Ssam #endif 3210907Ssam 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; 466337Ssam register struct sockaddr_in *sin; 475122Swnj 485172Swnj ifp->if_name = "lo"; 495122Swnj ifp->if_mtu = LOMTU; 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; 575122Swnj struct mbuf *m0; 586337Ssam struct sockaddr *dst; 595122Swnj { 605122Swnj int s = splimp(); 616209Swnj register struct ifqueue *ifq; 625122Swnj 635172Swnj ifp->if_opackets++; 646337Ssam switch (dst->sa_family) { 655122Swnj 665122Swnj #ifdef INET 676337Ssam case AF_INET: 686209Swnj ifq = &ipintrq; 696209Swnj if (IF_QFULL(ifq)) { 706209Swnj IF_DROP(ifq); 716337Ssam m_freem(m0); 726209Swnj splx(s); 736544Sfeldman return (ENOBUFS); 746209Swnj } 756209Swnj IF_ENQUEUE(ifq, m0); 766262Swnj schednetisr(NETISR_IP); 775122Swnj break; 785122Swnj #endif 7918815Ssklower #ifdef NS 8018815Ssklower case AF_NS: 8118815Ssklower ifq = &nsintrq; 8218815Ssklower if (IF_QFULL(ifq)) { 8318815Ssklower IF_DROP(ifq); 8418815Ssklower m_freem(m0); 8518815Ssklower splx(s); 8618815Ssklower return (ENOBUFS); 8718815Ssklower } 8818815Ssklower IF_ENQUEUE(ifq, m0); 8918815Ssklower schednetisr(NETISR_NS); 9018815Ssklower break; 9118815Ssklower #endif 925122Swnj default: 935122Swnj splx(s); 946337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 956337Ssam dst->sa_family); 966337Ssam m_freem(m0); 976544Sfeldman return (EAFNOSUPPORT); 985122Swnj } 995172Swnj ifp->if_ipackets++; 1005122Swnj splx(s); 1016544Sfeldman return (0); 1025122Swnj } 10313066Ssam 10413066Ssam /* 10513066Ssam * Process an ioctl request. 10613066Ssam */ 10718370Skarels /* ARGSUSED */ 10813066Ssam loioctl(ifp, cmd, data) 10913066Ssam register struct ifnet *ifp; 11013066Ssam int cmd; 11113066Ssam caddr_t data; 11213066Ssam { 11318370Skarels int error = 0; 11413066Ssam 11513066Ssam switch (cmd) { 11613066Ssam 11713066Ssam case SIOCSIFADDR: 11818370Skarels ifp->if_flags |= IFF_UP; 11918370Skarels /* 12018370Skarels * Everything else is done at a higher level. 12118370Skarels */ 12213066Ssam break; 12313066Ssam 12413066Ssam default: 12513066Ssam error = EINVAL; 12613066Ssam } 12713066Ssam return (error); 12813066Ssam } 129