1*17058Sbloom /* if_loop.c 6.2 84/08/29 */ 25122Swnj 35122Swnj /* 45122Swnj * Loopback interface driver for protocol testing and timing. 55122Swnj */ 65122Swnj 7*17058Sbloom #include "param.h" 8*17058Sbloom #include "systm.h" 9*17058Sbloom #include "mbuf.h" 10*17058Sbloom #include "socket.h" 11*17058Sbloom #include "errno.h" 12*17058Sbloom #include "ioctl.h" 1310907Ssam 1410907Ssam #include "../net/if.h" 1510907Ssam #include "../net/netisr.h" 1610907Ssam #include "../net/route.h" 1710907Ssam 18*17058Sbloom #include "in.h" 19*17058Sbloom #include "in_systm.h" 20*17058Sbloom #include "ip.h" 21*17058Sbloom #include "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; 3213066Ssam 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; 4513066Ssam sin->sin_addr = if_makeaddr(LONET, LOHOST); 4613066Ssam ifp->if_flags = IFF_UP | IFF_RUNNING; 4713066Ssam 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 } 8813066Ssam 8913066Ssam /* 9013066Ssam * Process an ioctl request. 9113066Ssam */ 9213066Ssam loioctl(ifp, cmd, data) 9313066Ssam register struct ifnet *ifp; 9413066Ssam int cmd; 9513066Ssam caddr_t data; 9613066Ssam { 9713066Ssam struct ifreq *ifr = (struct ifreq *)data; 9813066Ssam struct sockaddr_in *sin; 9913066Ssam int s = splimp(), error = 0; 10013066Ssam 10113066Ssam switch (cmd) { 10213066Ssam 10313066Ssam case SIOCSIFADDR: 10413066Ssam if (ifp->if_flags & IFF_RUNNING) 10513066Ssam if_rtinit(ifp, -1); /* delete previous route */ 10613066Ssam ifp->if_addr = ifr->ifr_addr; 10713066Ssam sin = (struct sockaddr_in *)&ifp->if_addr; 10813066Ssam ifp->if_net = in_netof(sin->sin_addr); 10913066Ssam ifp->if_host[0] = in_lnaof(sin->sin_addr); 11013066Ssam if_rtinit(ifp, RTF_UP); 11113066Ssam break; 11213066Ssam 11313066Ssam default: 11413066Ssam error = EINVAL; 11513066Ssam } 11613066Ssam splx(s); 11713066Ssam return (error); 11813066Ssam } 119