123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 544464Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*48727Ssklower * @(#)if_loop.c 7.13 (Berkeley) 04/26/91 823174Smckusick */ 95122Swnj 105122Swnj /* 115122Swnj * Loopback interface driver for protocol testing and timing. 125122Swnj */ 135122Swnj 1417058Sbloom #include "param.h" 1517058Sbloom #include "systm.h" 1617058Sbloom #include "mbuf.h" 1717058Sbloom #include "socket.h" 1817058Sbloom #include "errno.h" 1917058Sbloom #include "ioctl.h" 2010907Ssam 2110907Ssam #include "../net/if.h" 2238988Skarels #include "../net/if_types.h" 2310907Ssam #include "../net/netisr.h" 2410907Ssam #include "../net/route.h" 2510907Ssam 2637500Smckusick #include "machine/mtpr.h" 2729922Skarels 2824771Skarels #ifdef INET 2924771Skarels #include "../netinet/in.h" 3024771Skarels #include "../netinet/in_systm.h" 3129071Skarels #include "../netinet/in_var.h" 3224771Skarels #include "../netinet/ip.h" 3324771Skarels #endif 345122Swnj 3518815Ssklower #ifdef NS 3618815Ssklower #include "../netns/ns.h" 3718815Ssklower #include "../netns/ns_if.h" 3818815Ssklower #endif 3918815Ssklower 4037472Ssklower #ifdef ISO 4137472Ssklower #include "../netiso/iso.h" 4237472Ssklower #include "../netiso/iso_var.h" 4337472Ssklower #endif 4437472Ssklower 455207Swnj #define LOMTU (1024+512) 465122Swnj 475122Swnj struct ifnet loif; 4813066Ssam int looutput(), loioctl(); 495122Swnj 505122Swnj loattach() 515122Swnj { 525122Swnj register struct ifnet *ifp = &loif; 535122Swnj 545172Swnj ifp->if_name = "lo"; 555122Swnj ifp->if_mtu = LOMTU; 5626091Skarels ifp->if_flags = IFF_LOOPBACK; 5713066Ssam ifp->if_ioctl = loioctl; 585122Swnj ifp->if_output = looutput; 5937472Ssklower ifp->if_type = IFT_LOOP; 6037472Ssklower ifp->if_hdrlen = 0; 6137472Ssklower ifp->if_addrlen = 0; 625161Swnj if_attach(ifp); 635122Swnj } 645122Swnj 6545198Ssklower looutput(ifp, m, dst, rt) 665122Swnj struct ifnet *ifp; 6735795Skarels register struct mbuf *m; 686337Ssam struct sockaddr *dst; 6945198Ssklower register struct rtentry *rt; 705122Swnj { 7145523Ssklower int s, isr; 7245523Ssklower register struct ifqueue *ifq = 0; 735122Swnj 7435795Skarels if ((m->m_flags & M_PKTHDR) == 0) 7535795Skarels panic("looutput no HDR"); 7635795Skarels m->m_pkthdr.rcvif = ifp; 7735795Skarels 7845198Ssklower if (rt && rt->rt_flags & RTF_REJECT) { 7945198Ssklower m_freem(m); 8045198Ssklower return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 8145198Ssklower } 825172Swnj ifp->if_opackets++; 8339187Ssklower ifp->if_obytes += m->m_pkthdr.len; 846337Ssam switch (dst->sa_family) { 855122Swnj 865122Swnj #ifdef INET 876337Ssam case AF_INET: 886209Swnj ifq = &ipintrq; 8945523Ssklower isr = NETISR_IP; 905122Swnj break; 915122Swnj #endif 9218815Ssklower #ifdef NS 9318815Ssklower case AF_NS: 9418815Ssklower ifq = &nsintrq; 9545523Ssklower isr = NETISR_NS; 9618815Ssklower break; 9718815Ssklower #endif 9837472Ssklower #ifdef ISO 9937472Ssklower case AF_ISO: 10037472Ssklower ifq = &clnlintrq; 10145523Ssklower isr = NETISR_ISO; 10237472Ssklower break; 10337472Ssklower #endif 1045122Swnj default: 1056337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1066337Ssam dst->sa_family); 10735795Skarels m_freem(m); 1086544Sfeldman return (EAFNOSUPPORT); 1095122Swnj } 110*48727Ssklower s = splimp(); 11145523Ssklower if (IF_QFULL(ifq)) { 11245523Ssklower IF_DROP(ifq); 11345523Ssklower m_freem(m); 11445523Ssklower splx(s); 11545523Ssklower return (ENOBUFS); 11645523Ssklower } 11745523Ssklower IF_ENQUEUE(ifq, m); 11845523Ssklower schednetisr(isr); 1195172Swnj ifp->if_ipackets++; 12039187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1215122Swnj splx(s); 1226544Sfeldman return (0); 1235122Swnj } 12413066Ssam 125*48727Ssklower /* ARGSUSED */ 126*48727Ssklower lortrequest(cmd, rt, sa) 127*48727Ssklower struct rtentry *rt; 128*48727Ssklower struct sockaddr *sa; 129*48727Ssklower { 130*48727Ssklower if (rt) 131*48727Ssklower rt->rt_rmx.rmx_mtu = LOMTU; 132*48727Ssklower } 133*48727Ssklower 13413066Ssam /* 13513066Ssam * Process an ioctl request. 13613066Ssam */ 13718370Skarels /* ARGSUSED */ 13813066Ssam loioctl(ifp, cmd, data) 13913066Ssam register struct ifnet *ifp; 14013066Ssam int cmd; 14113066Ssam caddr_t data; 14213066Ssam { 143*48727Ssklower register struct ifaddr *ifa; 14418370Skarels int error = 0; 14513066Ssam 14613066Ssam switch (cmd) { 14713066Ssam 14813066Ssam case SIOCSIFADDR: 14918370Skarels ifp->if_flags |= IFF_UP; 150*48727Ssklower ifa = (struct ifaddr *)data; 151*48727Ssklower if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 152*48727Ssklower ifa->ifa_rtrequest = lortrequest; 15318370Skarels /* 15418370Skarels * Everything else is done at a higher level. 15518370Skarels */ 15613066Ssam break; 15713066Ssam 15813066Ssam default: 15913066Ssam error = EINVAL; 16013066Ssam } 16113066Ssam return (error); 16213066Ssam } 163