1*13066Ssam /* if_loop.c 4.19 83/06/13 */ 25122Swnj 35122Swnj /* 45122Swnj * Loopback interface driver for protocol testing and timing. 55122Swnj */ 65122Swnj 75122Swnj #include "../h/param.h" 85122Swnj #include "../h/systm.h" 95122Swnj #include "../h/mbuf.h" 105122Swnj #include "../h/socket.h" 1110907Ssam #include "../h/errno.h" 12*13066Ssam #include "../h/ioctl.h" 1310907Ssam 1410907Ssam #include "../net/if.h" 1510907Ssam #include "../net/netisr.h" 1610907Ssam #include "../net/route.h" 1710907Ssam 188397Swnj #include "../netinet/in.h" 198397Swnj #include "../netinet/in_systm.h" 208397Swnj #include "../netinet/ip.h" 218397Swnj #include "../netinet/ip_var.h" 225122Swnj 2312460Ssam #ifdef vax 2412460Ssam #include "../vax/mtpr.h" 2512460Ssam #endif 2610907Ssam 275296Sroot #define LONET 127 2812761Ssam #define LOHOST 1 /* can't be 0, that's broadcast */ 295207Swnj #define LOMTU (1024+512) 305122Swnj 315122Swnj struct ifnet loif; 32*13066Ssam int looutput(), loioctl(); 335122Swnj 345122Swnj loattach() 355122Swnj { 365122Swnj register struct ifnet *ifp = &loif; 376337Ssam register struct sockaddr_in *sin; 385122Swnj 395172Swnj ifp->if_name = "lo"; 405122Swnj ifp->if_mtu = LOMTU; 415122Swnj ifp->if_net = LONET; 4212761Ssam ifp->if_host[0] = LOHOST; 436337Ssam sin = (struct sockaddr_in *)&ifp->if_addr; 446337Ssam sin->sin_family = AF_INET; 45*13066Ssam sin->sin_addr = if_makeaddr(LONET, LOHOST); 46*13066Ssam ifp->if_flags = IFF_UP | IFF_RUNNING; 47*13066Ssam ifp->if_ioctl = loioctl; 485122Swnj ifp->if_output = looutput; 495161Swnj if_attach(ifp); 507154Swnj if_rtinit(ifp, RTF_UP); 515122Swnj } 525122Swnj 536337Ssam looutput(ifp, m0, dst) 545122Swnj struct ifnet *ifp; 555122Swnj struct mbuf *m0; 566337Ssam struct sockaddr *dst; 575122Swnj { 585122Swnj int s = splimp(); 596209Swnj register struct ifqueue *ifq; 605122Swnj 615172Swnj ifp->if_opackets++; 626337Ssam switch (dst->sa_family) { 635122Swnj 645122Swnj #ifdef INET 656337Ssam case AF_INET: 666209Swnj ifq = &ipintrq; 676209Swnj if (IF_QFULL(ifq)) { 686209Swnj IF_DROP(ifq); 696337Ssam m_freem(m0); 706209Swnj splx(s); 716544Sfeldman return (ENOBUFS); 726209Swnj } 736209Swnj IF_ENQUEUE(ifq, m0); 746262Swnj schednetisr(NETISR_IP); 755122Swnj break; 765122Swnj #endif 775122Swnj default: 785122Swnj splx(s); 796337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 806337Ssam dst->sa_family); 816337Ssam m_freem(m0); 826544Sfeldman return (EAFNOSUPPORT); 835122Swnj } 845172Swnj ifp->if_ipackets++; 855122Swnj splx(s); 866544Sfeldman return (0); 875122Swnj } 88*13066Ssam 89*13066Ssam /* 90*13066Ssam * Process an ioctl request. 91*13066Ssam */ 92*13066Ssam loioctl(ifp, cmd, data) 93*13066Ssam register struct ifnet *ifp; 94*13066Ssam int cmd; 95*13066Ssam caddr_t data; 96*13066Ssam { 97*13066Ssam struct ifreq *ifr = (struct ifreq *)data; 98*13066Ssam struct sockaddr_in *sin; 99*13066Ssam int s = splimp(), error = 0; 100*13066Ssam 101*13066Ssam switch (cmd) { 102*13066Ssam 103*13066Ssam case SIOCSIFADDR: 104*13066Ssam if (ifp->if_flags & IFF_RUNNING) 105*13066Ssam if_rtinit(ifp, -1); /* delete previous route */ 106*13066Ssam ifp->if_addr = ifr->ifr_addr; 107*13066Ssam sin = (struct sockaddr_in *)&ifp->if_addr; 108*13066Ssam ifp->if_net = in_netof(sin->sin_addr); 109*13066Ssam ifp->if_host[0] = in_lnaof(sin->sin_addr); 110*13066Ssam if_rtinit(ifp, RTF_UP); 111*13066Ssam break; 112*13066Ssam 113*13066Ssam default: 114*13066Ssam error = EINVAL; 115*13066Ssam } 116*13066Ssam splx(s); 117*13066Ssam return (error); 118*13066Ssam } 119