123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 544464Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*45523Ssklower * @(#)if_loop.c 7.12 (Berkeley) 11/06/90 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 45*45523Ssklower #ifdef CCITT 46*45523Ssklower #include "../netccitt/x25.h" 47*45523Ssklower #include "../netccitt/hdlc.h" 48*45523Ssklower #include "../netccitt/hd_var.h" 49*45523Ssklower #endif 50*45523Ssklower 515207Swnj #define LOMTU (1024+512) 525122Swnj 535122Swnj struct ifnet loif; 5413066Ssam int looutput(), loioctl(); 555122Swnj 565122Swnj loattach() 575122Swnj { 585122Swnj register struct ifnet *ifp = &loif; 595122Swnj 605172Swnj ifp->if_name = "lo"; 615122Swnj ifp->if_mtu = LOMTU; 6226091Skarels ifp->if_flags = IFF_LOOPBACK; 6313066Ssam ifp->if_ioctl = loioctl; 645122Swnj ifp->if_output = looutput; 6537472Ssklower ifp->if_type = IFT_LOOP; 6637472Ssklower ifp->if_hdrlen = 0; 6737472Ssklower ifp->if_addrlen = 0; 685161Swnj if_attach(ifp); 695122Swnj } 705122Swnj 7145198Ssklower looutput(ifp, m, dst, rt) 725122Swnj struct ifnet *ifp; 7335795Skarels register struct mbuf *m; 746337Ssam struct sockaddr *dst; 7545198Ssklower register struct rtentry *rt; 765122Swnj { 77*45523Ssklower int s, isr; 78*45523Ssklower register struct ifqueue *ifq = 0; 795122Swnj 8035795Skarels if ((m->m_flags & M_PKTHDR) == 0) 8135795Skarels panic("looutput no HDR"); 8235795Skarels m->m_pkthdr.rcvif = ifp; 8335795Skarels 8445198Ssklower if (rt && rt->rt_flags & RTF_REJECT) { 8545198Ssklower m_freem(m); 8645198Ssklower return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 8745198Ssklower } 8824771Skarels s = splimp(); 895172Swnj ifp->if_opackets++; 9039187Ssklower ifp->if_obytes += m->m_pkthdr.len; 916337Ssam switch (dst->sa_family) { 925122Swnj 935122Swnj #ifdef INET 946337Ssam case AF_INET: 956209Swnj ifq = &ipintrq; 96*45523Ssklower isr = NETISR_IP; 975122Swnj break; 985122Swnj #endif 9918815Ssklower #ifdef NS 10018815Ssklower case AF_NS: 10118815Ssklower ifq = &nsintrq; 102*45523Ssklower isr = NETISR_NS; 10318815Ssklower break; 10418815Ssklower #endif 10537472Ssklower #ifdef ISO 10637472Ssklower case AF_ISO: 10737472Ssklower ifq = &clnlintrq; 108*45523Ssklower isr = NETISR_ISO; 10937472Ssklower break; 11037472Ssklower #endif 111*45523Ssklower #ifdef CCITT 112*45523Ssklower case AF_CCITT: 113*45523Ssklower ifq = &hdintrq; 114*45523Ssklower isr = NETISR_CCITT; 115*45523Ssklower break; 116*45523Ssklower #endif 1175122Swnj default: 1185122Swnj splx(s); 1196337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1206337Ssam dst->sa_family); 12135795Skarels m_freem(m); 1226544Sfeldman return (EAFNOSUPPORT); 1235122Swnj } 124*45523Ssklower if (IF_QFULL(ifq)) { 125*45523Ssklower IF_DROP(ifq); 126*45523Ssklower m_freem(m); 127*45523Ssklower splx(s); 128*45523Ssklower return (ENOBUFS); 129*45523Ssklower } 130*45523Ssklower IF_ENQUEUE(ifq, m); 131*45523Ssklower schednetisr(isr); 1325172Swnj ifp->if_ipackets++; 13339187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1345122Swnj splx(s); 1356544Sfeldman return (0); 1365122Swnj } 13713066Ssam 13813066Ssam /* 13913066Ssam * Process an ioctl request. 14013066Ssam */ 14118370Skarels /* ARGSUSED */ 14213066Ssam loioctl(ifp, cmd, data) 14313066Ssam register struct ifnet *ifp; 14413066Ssam int cmd; 14513066Ssam caddr_t data; 14613066Ssam { 14718370Skarels int error = 0; 14813066Ssam 14913066Ssam switch (cmd) { 15013066Ssam 151*45523Ssklower #ifdef CCITT 152*45523Ssklower case SIOCSIFCONF_X25: 153*45523Ssklower #endif 15413066Ssam case SIOCSIFADDR: 15518370Skarels ifp->if_flags |= IFF_UP; 15618370Skarels /* 15718370Skarels * Everything else is done at a higher level. 15818370Skarels */ 15913066Ssam break; 16013066Ssam 16113066Ssam default: 16213066Ssam error = EINVAL; 16313066Ssam } 16413066Ssam return (error); 16513066Ssam } 166