1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)if_loop.c 7.13 (Berkeley) 4/26/91 34 */ 35 36 /* 37 * Loopback interface driver for protocol testing and timing. 38 */ 39 40 #include "param.h" 41 #include "systm.h" 42 #include "mbuf.h" 43 #include "socket.h" 44 #include "errno.h" 45 #include "ioctl.h" 46 #include "protosw.h" 47 48 #include "../net/if.h" 49 #include "../net/if_types.h" 50 #include "../net/netisr.h" 51 #include "../net/route.h" 52 53 #include "machine/mtpr.h" 54 55 #ifdef INET 56 #include "../netinet/in.h" 57 #include "../netinet/in_systm.h" 58 #include "../netinet/in_var.h" 59 #include "../netinet/ip.h" 60 #endif 61 62 #ifdef NS 63 #include "../netns/ns.h" 64 #include "../netns/ns_if.h" 65 #endif 66 67 #ifdef ISO 68 #include "../netiso/iso.h" 69 #include "../netiso/iso_var.h" 70 #endif 71 72 #include "bpfilter.h" 73 #if NBPFILTER > 0 74 #include <sys/time.h> 75 #include <net/bpf.h> 76 static caddr_t lo_bpf; 77 #endif 78 79 #define LOMTU (1024+512) 80 81 struct ifnet loif; 82 int looutput(), loioctl(); 83 84 loattach() 85 { 86 register struct ifnet *ifp = &loif; 87 88 ifp->if_name = "lo"; 89 ifp->if_mtu = LOMTU; 90 ifp->if_flags = IFF_LOOPBACK; 91 ifp->if_ioctl = loioctl; 92 ifp->if_output = looutput; 93 ifp->if_type = IFT_LOOP; 94 ifp->if_hdrlen = 0; 95 ifp->if_addrlen = 0; 96 if_attach(ifp); 97 #if NBPFILTER > 0 98 bpfattach(&lo_bpf, ifp, DLT_NULL, sizeof(u_int)); 99 #endif 100 } 101 102 looutput(ifp, m, dst, rt) 103 struct ifnet *ifp; 104 register struct mbuf *m; 105 struct sockaddr *dst; 106 register struct rtentry *rt; 107 { 108 int s, isr; 109 register struct ifqueue *ifq = 0; 110 111 if ((m->m_flags & M_PKTHDR) == 0) 112 panic("looutput no HDR"); 113 #if NBPFILTER > 0 114 if (lo_bpf) { 115 /* 116 * We need to prepend the address family as 117 * a four byte field. Cons up a dummy header 118 * to pacify bpf. This is safe because bpf 119 * will only read from the mbuf (i.e., it won't 120 * try to free it or keep a pointer to it). 121 */ 122 struct mbuf m0; 123 u_int af = dst->sa_family; 124 125 m0.m_next = m; 126 m0.m_len = 4; 127 m0.m_data = (char *)⁡ 128 129 bpf_mtap(lo_bpf, &m0); 130 } 131 #endif 132 m->m_pkthdr.rcvif = ifp; 133 134 if (rt && rt->rt_flags & RTF_REJECT) { 135 m_freem(m); 136 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 137 } 138 ifp->if_opackets++; 139 ifp->if_obytes += m->m_pkthdr.len; 140 switch (dst->sa_family) { 141 142 #ifdef INET 143 case AF_INET: 144 ifq = &ipintrq; 145 isr = NETISR_IP; 146 break; 147 #endif 148 #ifdef NS 149 case AF_NS: 150 ifq = &nsintrq; 151 isr = NETISR_NS; 152 break; 153 #endif 154 #ifdef ISO 155 case AF_ISO: 156 ifq = &clnlintrq; 157 isr = NETISR_ISO; 158 break; 159 #endif 160 default: 161 printf("lo%d: can't handle af%d\n", ifp->if_unit, 162 dst->sa_family); 163 m_freem(m); 164 return (EAFNOSUPPORT); 165 } 166 s = splimp(); 167 if (IF_QFULL(ifq)) { 168 IF_DROP(ifq); 169 m_freem(m); 170 splx(s); 171 return (ENOBUFS); 172 } 173 IF_ENQUEUE(ifq, m); 174 schednetisr(isr); 175 ifp->if_ipackets++; 176 ifp->if_ibytes += m->m_pkthdr.len; 177 splx(s); 178 return (0); 179 } 180 181 /* ARGSUSED */ 182 lortrequest(cmd, rt, sa) 183 struct rtentry *rt; 184 struct sockaddr *sa; 185 { 186 if (rt) 187 rt->rt_rmx.rmx_mtu = LOMTU; 188 } 189 190 /* 191 * Process an ioctl request. 192 */ 193 /* ARGSUSED */ 194 loioctl(ifp, cmd, data) 195 register struct ifnet *ifp; 196 int cmd; 197 caddr_t data; 198 { 199 register struct ifaddr *ifa; 200 int error = 0; 201 202 switch (cmd) { 203 204 case SIOCSIFADDR: 205 ifp->if_flags |= IFF_UP; 206 ifa = (struct ifaddr *)data; 207 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 208 ifa->ifa_rtrequest = lortrequest; 209 /* 210 * Everything else is done at a higher level. 211 */ 212 break; 213 214 default: 215 error = EINVAL; 216 } 217 return (error); 218 } 219