123174Smckusick /* 229071Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423174Smckusick * 544464Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*61362Sbostic * @(#)if_loop.c 7.22 (Berkeley) 06/04/93 823174Smckusick */ 95122Swnj 105122Swnj /* 115122Swnj * Loopback interface driver for protocol testing and timing. 125122Swnj */ 135122Swnj 1456529Sbostic #include <sys/param.h> 1556529Sbostic #include <sys/systm.h> 1656529Sbostic #include <sys/kernel.h> 1756529Sbostic #include <sys/mbuf.h> 1856529Sbostic #include <sys/socket.h> 1956529Sbostic #include <sys/errno.h> 2056529Sbostic #include <sys/ioctl.h> 2156529Sbostic #include <sys/time.h> 2256529Sbostic #include <machine/cpu.h> 2310907Ssam 2456529Sbostic #include <net/if.h> 2556529Sbostic #include <net/if_types.h> 2656529Sbostic #include <net/netisr.h> 2756529Sbostic #include <net/route.h> 2856529Sbostic #include <net/bpf.h> 2910907Ssam 3024771Skarels #ifdef INET 3156529Sbostic #include <netinet/in.h> 3256529Sbostic #include <netinet/in_systm.h> 3356529Sbostic #include <netinet/in_var.h> 3456529Sbostic #include <netinet/ip.h> 3524771Skarels #endif 365122Swnj 3718815Ssklower #ifdef NS 3856529Sbostic #include <netns/ns.h> 3956529Sbostic #include <netns/ns_if.h> 4018815Ssklower #endif 4118815Ssklower 4237472Ssklower #ifdef ISO 4356529Sbostic #include <netiso/iso.h> 4456529Sbostic #include <netiso/iso_var.h> 4537472Ssklower #endif 4637472Ssklower 4754718Ssklower #include "bpfilter.h" 4854718Ssklower 495207Swnj #define LOMTU (1024+512) 505122Swnj 515122Swnj struct ifnet loif; 525122Swnj 5359123Storek /* ARGSUSED */ 5459123Storek void 5559123Storek loopattach(n) 5659123Storek int n; 575122Swnj { 585122Swnj register struct ifnet *ifp = &loif; 595122Swnj 6059123Storek #ifdef lint 6159123Storek n = n; /* Highlander: there can only be one... */ 6259123Storek #endif 635172Swnj ifp->if_name = "lo"; 645122Swnj ifp->if_mtu = LOMTU; 6554718Ssklower ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 6613066Ssam ifp->if_ioctl = loioctl; 675122Swnj ifp->if_output = looutput; 6837472Ssklower ifp->if_type = IFT_LOOP; 6937472Ssklower ifp->if_hdrlen = 0; 7037472Ssklower ifp->if_addrlen = 0; 715161Swnj if_attach(ifp); 7254718Ssklower #if NBPFILTER > 0 7354718Ssklower bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int)); 7454718Ssklower #endif 755122Swnj } 765122Swnj 77*61362Sbostic int 7845198Ssklower looutput(ifp, m, dst, rt) 795122Swnj struct ifnet *ifp; 8035795Skarels register struct mbuf *m; 816337Ssam struct sockaddr *dst; 8245198Ssklower register struct rtentry *rt; 835122Swnj { 8445523Ssklower int s, isr; 8545523Ssklower register struct ifqueue *ifq = 0; 865122Swnj 8735795Skarels if ((m->m_flags & M_PKTHDR) == 0) 8835795Skarels panic("looutput no HDR"); 8954718Ssklower ifp->if_lastchange = time; 9054718Ssklower #if NBPFILTER > 0 9154718Ssklower if (loif.if_bpf) { 9254718Ssklower /* 9354718Ssklower * We need to prepend the address family as 9454718Ssklower * a four byte field. Cons up a dummy header 9554718Ssklower * to pacify bpf. This is safe because bpf 9654718Ssklower * will only read from the mbuf (i.e., it won't 9754718Ssklower * try to free it or keep a pointer a to it). 9854718Ssklower */ 9954718Ssklower struct mbuf m0; 10054718Ssklower u_int af = dst->sa_family; 10154718Ssklower 10254718Ssklower m0.m_next = m; 10354718Ssklower m0.m_len = 4; 10454718Ssklower m0.m_data = (char *)⁡ 10554718Ssklower 10654718Ssklower bpf_mtap(loif.if_bpf, &m0); 10754718Ssklower } 10854718Ssklower #endif 10935795Skarels m->m_pkthdr.rcvif = ifp; 11035795Skarels 11159009Ssklower if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 11245198Ssklower m_freem(m); 11359009Ssklower return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 11459009Ssklower rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 11545198Ssklower } 1165172Swnj ifp->if_opackets++; 11739187Ssklower ifp->if_obytes += m->m_pkthdr.len; 1186337Ssam switch (dst->sa_family) { 1195122Swnj 1205122Swnj #ifdef INET 1216337Ssam case AF_INET: 1226209Swnj ifq = &ipintrq; 12345523Ssklower isr = NETISR_IP; 1245122Swnj break; 1255122Swnj #endif 12618815Ssklower #ifdef NS 12718815Ssklower case AF_NS: 12818815Ssklower ifq = &nsintrq; 12945523Ssklower isr = NETISR_NS; 13018815Ssklower break; 13118815Ssklower #endif 13237472Ssklower #ifdef ISO 13337472Ssklower case AF_ISO: 13437472Ssklower ifq = &clnlintrq; 13545523Ssklower isr = NETISR_ISO; 13637472Ssklower break; 13737472Ssklower #endif 1385122Swnj default: 1396337Ssam printf("lo%d: can't handle af%d\n", ifp->if_unit, 1406337Ssam dst->sa_family); 14135795Skarels m_freem(m); 1426544Sfeldman return (EAFNOSUPPORT); 1435122Swnj } 14448727Ssklower s = splimp(); 14545523Ssklower if (IF_QFULL(ifq)) { 14645523Ssklower IF_DROP(ifq); 14745523Ssklower m_freem(m); 14845523Ssklower splx(s); 14945523Ssklower return (ENOBUFS); 15045523Ssklower } 15145523Ssklower IF_ENQUEUE(ifq, m); 15245523Ssklower schednetisr(isr); 1535172Swnj ifp->if_ipackets++; 15439187Ssklower ifp->if_ibytes += m->m_pkthdr.len; 1555122Swnj splx(s); 1566544Sfeldman return (0); 1575122Swnj } 15813066Ssam 15948727Ssklower /* ARGSUSED */ 16054718Ssklower void 16148727Ssklower lortrequest(cmd, rt, sa) 16252947Storek int cmd; 16352947Storek struct rtentry *rt; 16452947Storek struct sockaddr *sa; 16548727Ssklower { 16652947Storek 16748727Ssklower if (rt) 16848727Ssklower rt->rt_rmx.rmx_mtu = LOMTU; 16948727Ssklower } 17048727Ssklower 17113066Ssam /* 17213066Ssam * Process an ioctl request. 17313066Ssam */ 17418370Skarels /* ARGSUSED */ 175*61362Sbostic int 17613066Ssam loioctl(ifp, cmd, data) 17713066Ssam register struct ifnet *ifp; 17813066Ssam int cmd; 17913066Ssam caddr_t data; 18013066Ssam { 18148727Ssklower register struct ifaddr *ifa; 18254718Ssklower register struct ifreq *ifr; 18354718Ssklower register int error = 0; 18413066Ssam 18513066Ssam switch (cmd) { 18613066Ssam 18713066Ssam case SIOCSIFADDR: 18818370Skarels ifp->if_flags |= IFF_UP; 18948727Ssklower ifa = (struct ifaddr *)data; 19048727Ssklower if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 19148727Ssklower ifa->ifa_rtrequest = lortrequest; 19218370Skarels /* 19318370Skarels * Everything else is done at a higher level. 19418370Skarels */ 19513066Ssam break; 19613066Ssam 19754718Ssklower case SIOCADDMULTI: 19854718Ssklower case SIOCDELMULTI: 19954718Ssklower ifr = (struct ifreq *)data; 20054718Ssklower if (ifr == 0) { 20154718Ssklower error = EAFNOSUPPORT; /* XXX */ 20254718Ssklower break; 20354718Ssklower } 20454718Ssklower switch (ifr->ifr_addr.sa_family) { 20554718Ssklower 20654718Ssklower #ifdef INET 20754718Ssklower case AF_INET: 20854718Ssklower break; 20954718Ssklower #endif 21054718Ssklower 21154718Ssklower default: 21254718Ssklower error = EAFNOSUPPORT; 21354718Ssklower break; 21454718Ssklower } 21554718Ssklower break; 21654718Ssklower 21713066Ssam default: 21813066Ssam error = EINVAL; 21913066Ssam } 22013066Ssam return (error); 22113066Ssam } 222