1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_loop.c 7.13 (Berkeley) 04/26/91 8 */ 9 10 /* 11 * Loopback interface driver for protocol testing and timing. 12 */ 13 14 #include "param.h" 15 #include "systm.h" 16 #include "mbuf.h" 17 #include "socket.h" 18 #include "errno.h" 19 #include "ioctl.h" 20 21 #include "../net/if.h" 22 #include "../net/if_types.h" 23 #include "../net/netisr.h" 24 #include "../net/route.h" 25 26 #include "machine/mtpr.h" 27 28 #ifdef INET 29 #include "../netinet/in.h" 30 #include "../netinet/in_systm.h" 31 #include "../netinet/in_var.h" 32 #include "../netinet/ip.h" 33 #endif 34 35 #ifdef NS 36 #include "../netns/ns.h" 37 #include "../netns/ns_if.h" 38 #endif 39 40 #ifdef ISO 41 #include "../netiso/iso.h" 42 #include "../netiso/iso_var.h" 43 #endif 44 45 #define LOMTU (1024+512) 46 47 struct ifnet loif; 48 int looutput(), loioctl(); 49 50 loattach() 51 { 52 register struct ifnet *ifp = &loif; 53 54 ifp->if_name = "lo"; 55 ifp->if_mtu = LOMTU; 56 ifp->if_flags = IFF_LOOPBACK; 57 ifp->if_ioctl = loioctl; 58 ifp->if_output = looutput; 59 ifp->if_type = IFT_LOOP; 60 ifp->if_hdrlen = 0; 61 ifp->if_addrlen = 0; 62 if_attach(ifp); 63 } 64 65 looutput(ifp, m, dst, rt) 66 struct ifnet *ifp; 67 register struct mbuf *m; 68 struct sockaddr *dst; 69 register struct rtentry *rt; 70 { 71 int s, isr; 72 register struct ifqueue *ifq = 0; 73 74 if ((m->m_flags & M_PKTHDR) == 0) 75 panic("looutput no HDR"); 76 m->m_pkthdr.rcvif = ifp; 77 78 if (rt && rt->rt_flags & RTF_REJECT) { 79 m_freem(m); 80 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 81 } 82 ifp->if_opackets++; 83 ifp->if_obytes += m->m_pkthdr.len; 84 switch (dst->sa_family) { 85 86 #ifdef INET 87 case AF_INET: 88 ifq = &ipintrq; 89 isr = NETISR_IP; 90 break; 91 #endif 92 #ifdef NS 93 case AF_NS: 94 ifq = &nsintrq; 95 isr = NETISR_NS; 96 break; 97 #endif 98 #ifdef ISO 99 case AF_ISO: 100 ifq = &clnlintrq; 101 isr = NETISR_ISO; 102 break; 103 #endif 104 default: 105 printf("lo%d: can't handle af%d\n", ifp->if_unit, 106 dst->sa_family); 107 m_freem(m); 108 return (EAFNOSUPPORT); 109 } 110 s = splimp(); 111 if (IF_QFULL(ifq)) { 112 IF_DROP(ifq); 113 m_freem(m); 114 splx(s); 115 return (ENOBUFS); 116 } 117 IF_ENQUEUE(ifq, m); 118 schednetisr(isr); 119 ifp->if_ipackets++; 120 ifp->if_ibytes += m->m_pkthdr.len; 121 splx(s); 122 return (0); 123 } 124 125 /* ARGSUSED */ 126 lortrequest(cmd, rt, sa) 127 struct rtentry *rt; 128 struct sockaddr *sa; 129 { 130 if (rt) 131 rt->rt_rmx.rmx_mtu = LOMTU; 132 } 133 134 /* 135 * Process an ioctl request. 136 */ 137 /* ARGSUSED */ 138 loioctl(ifp, cmd, data) 139 register struct ifnet *ifp; 140 int cmd; 141 caddr_t data; 142 { 143 register struct ifaddr *ifa; 144 int error = 0; 145 146 switch (cmd) { 147 148 case SIOCSIFADDR: 149 ifp->if_flags |= IFF_UP; 150 ifa = (struct ifaddr *)data; 151 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 152 ifa->ifa_rtrequest = lortrequest; 153 /* 154 * Everything else is done at a higher level. 155 */ 156 break; 157 158 default: 159 error = EINVAL; 160 } 161 return (error); 162 } 163