1 /* 2 * Copyright (c) 1982, 1986, 1993 3 * The Regents of the University of California. 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 8.1 (Berkeley) 6/10/93 34 * $Id: if_loop.c,v 1.34 1998/06/12 20:03:26 julian Exp $ 35 */ 36 37 /* 38 * Loopback interface driver for protocol testing and timing. 39 */ 40 #include "loop.h" 41 #if NLOOP > 0 42 43 #include "opt_atalk.h" 44 #include "opt_inet.h" 45 #include "opt_ipx.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/mbuf.h> 51 #include <sys/socket.h> 52 #include <sys/sockio.h> 53 54 #include <net/if.h> 55 #include <net/if_types.h> 56 #include <net/netisr.h> 57 #include <net/route.h> 58 #include <net/bpf.h> 59 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/in_var.h> 63 #endif 64 65 #ifdef IPX 66 #include <netipx/ipx.h> 67 #include <netipx/ipx_if.h> 68 #endif 69 70 #ifdef NS 71 #include <netns/ns.h> 72 #include <netns/ns_if.h> 73 #endif 74 75 #ifdef ISO 76 #include <netiso/iso.h> 77 #include <netiso/iso_var.h> 78 #endif 79 80 #ifdef NETATALK 81 #include <netatalk/at.h> 82 #include <netatalk/at_var.h> 83 #endif NETATALK 84 85 #include "bpfilter.h" 86 #if NBPFILTER > 0 87 #include <net/bpfdesc.h> 88 #endif 89 90 static int loioctl __P((struct ifnet *, u_long, caddr_t)); 91 static void lortrequest __P((int, struct rtentry *, struct sockaddr *)); 92 93 static void loopattach __P((void *)); 94 PSEUDO_SET(loopattach, if_loop); 95 96 static int looutput __P((struct ifnet *ifp, 97 struct mbuf *m, struct sockaddr *dst, struct rtentry *rt)); 98 99 #ifdef TINY_LOMTU 100 #define LOMTU (1024+512) 101 #else 102 #define LOMTU 16384 103 #endif 104 105 struct ifnet loif[NLOOP]; 106 107 /* ARGSUSED */ 108 static void 109 loopattach(dummy) 110 void *dummy; 111 { 112 register struct ifnet *ifp; 113 register int i = 0; 114 115 for (ifp = loif; i < NLOOP; ifp++) { 116 ifp->if_name = "lo"; 117 ifp->if_unit = i++; 118 ifp->if_mtu = LOMTU; 119 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 120 ifp->if_ioctl = loioctl; 121 ifp->if_output = looutput; 122 ifp->if_type = IFT_LOOP; 123 if_attach(ifp); 124 #if NBPFILTER > 0 125 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 126 #endif 127 } 128 } 129 130 static int 131 looutput(ifp, m, dst, rt) 132 struct ifnet *ifp; 133 register struct mbuf *m; 134 struct sockaddr *dst; 135 register struct rtentry *rt; 136 { 137 if ((m->m_flags & M_PKTHDR) == 0) 138 panic("looutput no HDR"); 139 140 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 141 m_freem(m); 142 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 143 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 144 } 145 ifp->if_opackets++; 146 ifp->if_obytes += m->m_pkthdr.len; 147 #if 1 /* XXX */ 148 switch (dst->sa_family) { 149 case AF_INET: 150 case AF_IPX: 151 case AF_NS: 152 case AF_ISO: 153 case AF_APPLETALK: 154 default: 155 printf("looutput: af=%d unexpected", dst->sa_family); 156 m_freem(m); 157 return (EAFNOSUPPORT); 158 } 159 #endif 160 return(if_simloop(ifp, m, dst, 0)); 161 } 162 163 /* 164 * if_simloop() 165 * 166 * This function is to support software emulation of hardware loopback, 167 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't 168 * hear their own broadcasts, we create a copy of the packet that we 169 * would normally receive via a hardware loopback. 170 * 171 * This function expects the packet to include the media header of length hlen. 172 */ 173 174 int 175 if_simloop(ifp, m, dst, hlen) 176 struct ifnet *ifp; 177 register struct mbuf *m; 178 struct sockaddr *dst; 179 int hlen; 180 { 181 int s, isr; 182 register struct ifqueue *ifq = 0; 183 184 if ((m->m_flags & M_PKTHDR) == 0) 185 panic("if_simloop: no HDR"); 186 m->m_pkthdr.rcvif = ifp; 187 #if NBPFILTER > 0 188 /* BPF write needs to be handled specially */ 189 if (dst->sa_family == AF_UNSPEC) { 190 dst->sa_family = *(mtod(m, int *)); 191 m->m_len -= sizeof(int); 192 m->m_pkthdr.len -= sizeof(int); 193 m->m_data += sizeof(int); 194 } 195 196 if (ifp->if_bpf) { 197 struct mbuf m0, *n = m; 198 u_int af = dst->sa_family; 199 200 if (ifp->if_bpf->bif_dlt == DLT_NULL) { 201 /* 202 * We need to prepend the address family as 203 * a four byte field. Cons up a dummy header 204 * to pacify bpf. This is safe because bpf 205 * will only read from the mbuf (i.e., it won't 206 * try to free it or keep a pointer a to it). 207 */ 208 m0.m_next = m; 209 m0.m_len = 4; 210 m0.m_data = (char *)⁡ 211 n = &m0; 212 } 213 bpf_mtap(ifp, n); 214 } 215 #endif 216 217 /* Strip away media header */ 218 if (hlen > 0) 219 m_adj(m, hlen); 220 221 switch (dst->sa_family) { 222 #ifdef INET 223 case AF_INET: 224 ifq = &ipintrq; 225 isr = NETISR_IP; 226 break; 227 #endif 228 #ifdef IPX 229 case AF_IPX: 230 ifq = &ipxintrq; 231 isr = NETISR_IPX; 232 break; 233 #endif 234 #ifdef NS 235 case AF_NS: 236 ifq = &nsintrq; 237 isr = NETISR_NS; 238 break; 239 #endif 240 #ifdef ISO 241 case AF_ISO: 242 ifq = &clnlintrq; 243 isr = NETISR_ISO; 244 break; 245 #endif 246 #ifdef NETATALK 247 case AF_APPLETALK: 248 ifq = &atintrq2; 249 isr = NETISR_ATALK; 250 break; 251 #endif NETATALK 252 default: 253 printf("if_simloop: can't handle af=%d\n", dst->sa_family); 254 m_freem(m); 255 return (EAFNOSUPPORT); 256 } 257 s = splimp(); 258 if (IF_QFULL(ifq)) { 259 IF_DROP(ifq); 260 m_freem(m); 261 splx(s); 262 return (ENOBUFS); 263 } 264 IF_ENQUEUE(ifq, m); 265 schednetisr(isr); 266 ifp->if_ipackets++; 267 ifp->if_ibytes += m->m_pkthdr.len; 268 splx(s); 269 return (0); 270 } 271 272 /* ARGSUSED */ 273 static void 274 lortrequest(cmd, rt, sa) 275 int cmd; 276 struct rtentry *rt; 277 struct sockaddr *sa; 278 { 279 if (rt) { 280 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ 281 /* 282 * For optimal performance, the send and receive buffers 283 * should be at least twice the MTU plus a little more for 284 * overhead. 285 */ 286 rt->rt_rmx.rmx_recvpipe = 287 rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; 288 } 289 } 290 291 /* 292 * Process an ioctl request. 293 */ 294 /* ARGSUSED */ 295 static int 296 loioctl(ifp, cmd, data) 297 register struct ifnet *ifp; 298 u_long cmd; 299 caddr_t data; 300 { 301 register struct ifaddr *ifa; 302 register struct ifreq *ifr = (struct ifreq *)data; 303 register int error = 0; 304 305 switch (cmd) { 306 307 case SIOCSIFADDR: 308 ifp->if_flags |= IFF_UP | IFF_RUNNING; 309 ifa = (struct ifaddr *)data; 310 ifa->ifa_rtrequest = lortrequest; 311 /* 312 * Everything else is done at a higher level. 313 */ 314 break; 315 316 case SIOCADDMULTI: 317 case SIOCDELMULTI: 318 if (ifr == 0) { 319 error = EAFNOSUPPORT; /* XXX */ 320 break; 321 } 322 switch (ifr->ifr_addr.sa_family) { 323 324 #ifdef INET 325 case AF_INET: 326 break; 327 #endif 328 329 default: 330 error = EAFNOSUPPORT; 331 break; 332 } 333 break; 334 335 case SIOCSIFMTU: 336 ifp->if_mtu = ifr->ifr_mtu; 337 break; 338 339 case SIOCSIFFLAGS: 340 break; 341 342 default: 343 error = EINVAL; 344 } 345 return (error); 346 } 347 #endif /* NLOOP > 0 */ 348