1 /* $OpenBSD: if_loop.c,v 1.20 2001/07/04 23:14:54 espie Exp $ */ 2 /* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1986, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 66 */ 67 68 /* 69 %%% portions-copyright-nrl-95 70 Portions of this software are Copyright 1995-1998 by Randall Atkinson, 71 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights 72 Reserved. All rights under this copyright have been assigned to the US 73 Naval Research Laboratory (NRL). The NRL Copyright Notice and License 74 Agreement Version 1.1 (January 17, 1995) applies to these portions of the 75 software. 76 You should have received a copy of the license with this software. If you 77 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. 78 */ 79 80 /* 81 * Loopback interface driver for protocol testing and timing. 82 */ 83 84 #include "bpfilter.h" 85 86 #include <sys/param.h> 87 #include <sys/systm.h> 88 #include <sys/kernel.h> 89 #include <sys/mbuf.h> 90 #include <sys/socket.h> 91 #include <sys/errno.h> 92 #include <sys/ioctl.h> 93 #include <sys/time.h> 94 95 #include <machine/cpu.h> 96 97 #include <net/if.h> 98 #include <net/if_types.h> 99 #include <net/netisr.h> 100 #include <net/route.h> 101 102 #ifdef INET 103 #include <netinet/in.h> 104 #include <netinet/in_systm.h> 105 #include <netinet/in_var.h> 106 #include <netinet/ip.h> 107 #endif 108 109 #ifdef INET6 110 #ifndef INET 111 #include <netinet/in.h> 112 #endif 113 #include <netinet6/in6_var.h> 114 #include <netinet/ip6.h> 115 #endif 116 117 #ifdef NS 118 #include <netns/ns.h> 119 #include <netns/ns_if.h> 120 #endif 121 122 #ifdef IPX 123 #include <netipx/ipx.h> 124 #include <netipx/ipx_if.h> 125 #endif 126 127 #ifdef ISO 128 #include <netiso/iso.h> 129 #include <netiso/iso_var.h> 130 #endif 131 132 #ifdef NETATALK 133 #include <netinet/if_ether.h> 134 #include <netatalk/at.h> 135 #include <netatalk/at_var.h> 136 #endif 137 138 #if NBPFILTER > 0 139 #include <net/bpf.h> 140 #endif 141 142 #if defined(LARGE_LOMTU) 143 #define LOMTU (131072 + MHLEN + MLEN) 144 #else 145 #define LOMTU (32768 + MHLEN + MLEN) 146 #endif 147 148 #ifdef ALTQ 149 static void lo_altqstart __P((struct ifnet *)); 150 #endif 151 152 void 153 loopattach(n) 154 int n; 155 { 156 register int i; 157 register struct ifnet *ifp; 158 159 for (i = n; i--; ) { 160 MALLOC(ifp, struct ifnet *, sizeof(*ifp), M_DEVBUF, M_NOWAIT); 161 if (ifp == NULL) 162 return; 163 bzero(ifp, sizeof(struct ifnet)); 164 if (i == 0) 165 lo0ifp = ifp; 166 sprintf(ifp->if_xname, "lo%d", i); 167 ifp->if_softc = NULL; 168 ifp->if_mtu = LOMTU; 169 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 170 ifp->if_ioctl = loioctl; 171 ifp->if_output = looutput; 172 ifp->if_type = IFT_LOOP; 173 ifp->if_hdrlen = sizeof(u_int32_t); 174 ifp->if_addrlen = 0; 175 IFQ_SET_READY(&ifp->if_snd); 176 #ifdef ALTQ 177 ifp->if_start = lo_altqstart; 178 #endif 179 if_attachhead(ifp); 180 #if NBPFILTER > 0 181 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); 182 #endif 183 } 184 } 185 186 int 187 looutput(ifp, m, dst, rt) 188 struct ifnet *ifp; 189 register struct mbuf *m; 190 struct sockaddr *dst; 191 register struct rtentry *rt; 192 { 193 int s, isr; 194 register struct ifqueue *ifq = 0; 195 196 if ((m->m_flags & M_PKTHDR) == 0) 197 panic("looutput: no header mbuf"); 198 #if NBPFILTER > 0 199 /* 200 * only send packets to bpf if they are real loopback packets; 201 * looutput() is also called for SIMPLEX interfaces to duplicate 202 * packets for local use. But don't dup them to bpf. 203 */ 204 if (ifp->if_bpf && (ifp->if_flags&IFF_LOOPBACK)) { 205 /* 206 * We need to prepend the address family as 207 * a four byte field. Cons up a dummy header 208 * to pacify bpf. This is safe because bpf 209 * will only read from the mbuf (i.e., it won't 210 * try to free it or keep a pointer to it). 211 */ 212 struct mbuf m0; 213 u_int32_t af = htonl(dst->sa_family); 214 215 m0.m_next = m; 216 m0.m_len = sizeof(af); 217 m0.m_data = (char *)⁡ 218 219 bpf_mtap(ifp->if_bpf, &m0); 220 } 221 #endif 222 m->m_pkthdr.rcvif = ifp; 223 224 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 225 m_freem(m); 226 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 227 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 228 } 229 230 ifp->if_opackets++; 231 ifp->if_obytes += m->m_pkthdr.len; 232 #ifdef ALTQ 233 /* 234 * altq for loop is just for debugging. 235 * only used when called for loop interface (not for 236 * a simplex interface). 237 */ 238 if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) 239 && ifp->if_start == lo_altqstart) { 240 struct altq_pktattr pktattr; 241 int32_t *afp; 242 int error; 243 244 /* 245 * if the queueing discipline needs packet classification, 246 * do it before prepending link headers. 247 */ 248 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); 249 250 M_PREPEND(m, sizeof(int32_t), M_DONTWAIT); 251 if (m == 0) 252 return(ENOBUFS); 253 afp = mtod(m, int32_t *); 254 *afp = (int32_t)dst->sa_family; 255 256 s = splimp(); 257 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); 258 (*ifp->if_start)(ifp); 259 splx(s); 260 return (error); 261 } 262 #endif /* ALTQ */ 263 switch (dst->sa_family) { 264 265 #ifdef INET 266 case AF_INET: 267 ifq = &ipintrq; 268 isr = NETISR_IP; 269 break; 270 #endif 271 #ifdef INET6 272 case AF_INET6: 273 ifq = &ip6intrq; 274 isr = NETISR_IPV6; 275 break; 276 #endif /* INET6 */ 277 #ifdef NS 278 case AF_NS: 279 ifq = &nsintrq; 280 isr = NETISR_NS; 281 break; 282 #endif 283 #ifdef IPX 284 case AF_IPX: 285 ifq = &ipxintrq; 286 isr = NETISR_IPX; 287 break; 288 #endif 289 #ifdef ISO 290 case AF_ISO: 291 ifq = &clnlintrq; 292 isr = NETISR_ISO; 293 break; 294 #endif 295 #ifdef NETATALK 296 case AF_APPLETALK: 297 ifq = &atintrq2; 298 isr = NETISR_ATALK; 299 break; 300 #endif /* NETATALK */ 301 default: 302 printf("%s: can't handle af%d\n", ifp->if_xname, 303 dst->sa_family); 304 m_freem(m); 305 return (EAFNOSUPPORT); 306 } 307 s = splimp(); 308 if (IF_QFULL(ifq)) { 309 IF_DROP(ifq); 310 m_freem(m); 311 splx(s); 312 return (ENOBUFS); 313 } 314 IF_ENQUEUE(ifq, m); 315 schednetisr(isr); 316 ifp->if_ipackets++; 317 ifp->if_ibytes += m->m_pkthdr.len; 318 splx(s); 319 return (0); 320 } 321 322 #ifdef ALTQ 323 static void 324 lo_altqstart(ifp) 325 struct ifnet *ifp; 326 { 327 struct ifqueue *ifq; 328 struct mbuf *m; 329 int32_t af, *afp; 330 int s, isr; 331 332 while (1) { 333 s = splimp(); 334 IFQ_DEQUEUE(&ifp->if_snd, m); 335 splx(s); 336 if (m == NULL) 337 return; 338 339 afp = mtod(m, int32_t *); 340 af = *afp; 341 m_adj(m, sizeof(int32_t)); 342 343 switch (af) { 344 #ifdef INET 345 case AF_INET: 346 ifq = &ipintrq; 347 isr = NETISR_IP; 348 break; 349 #endif 350 #ifdef INET6 351 case AF_INET6: 352 m->m_flags |= M_LOOP; 353 ifq = &ip6intrq; 354 isr = NETISR_IPV6; 355 break; 356 #endif 357 #ifdef IPX 358 case AF_IPX: 359 ifq = &ipxintrq; 360 isr = NETISR_IPX; 361 break; 362 #endif 363 #ifdef NS 364 case AF_NS: 365 ifq = &nsintrq; 366 isr = NETISR_NS; 367 break; 368 #endif 369 #ifdef ISO 370 case AF_ISO: 371 ifq = &clnlintrq; 372 isr = NETISR_ISO; 373 break; 374 #endif 375 #ifdef NETATALK 376 case AF_APPLETALK: 377 ifq = &atintrq2; 378 isr = NETISR_ATALK; 379 break; 380 #endif /* NETATALK */ 381 default: 382 printf("lo_altqstart: can't handle af%d\n", af); 383 m_freem(m); 384 return; 385 } 386 387 s = splimp(); 388 if (IF_QFULL(ifq)) { 389 IF_DROP(ifq); 390 m_freem(m); 391 splx(s); 392 return; 393 } 394 IF_ENQUEUE(ifq, m); 395 schednetisr(isr); 396 ifp->if_ipackets++; 397 ifp->if_ibytes += m->m_pkthdr.len; 398 splx(s); 399 } 400 } 401 #endif /* ALTQ */ 402 403 /* ARGSUSED */ 404 void 405 lortrequest(cmd, rt, info) 406 int cmd; 407 struct rtentry *rt; 408 struct rt_addrinfo *info; 409 { 410 411 if (rt) 412 rt->rt_rmx.rmx_mtu = LOMTU; 413 } 414 415 /* 416 * Process an ioctl request. 417 */ 418 /* ARGSUSED */ 419 int 420 loioctl(ifp, cmd, data) 421 register struct ifnet *ifp; 422 u_long cmd; 423 caddr_t data; 424 { 425 register struct ifaddr *ifa; 426 register struct ifreq *ifr; 427 register int error = 0; 428 429 switch (cmd) { 430 431 case SIOCSIFADDR: 432 ifp->if_flags |= IFF_UP; 433 ifa = (struct ifaddr *)data; 434 if (ifa != 0 /*&& ifa->ifa_addr->sa_family == AF_ISO*/) 435 ifa->ifa_rtrequest = lortrequest; 436 /* 437 * Everything else is done at a higher level. 438 */ 439 break; 440 441 case SIOCADDMULTI: 442 case SIOCDELMULTI: 443 ifr = (struct ifreq *)data; 444 if (ifr == 0) { 445 error = EAFNOSUPPORT; /* XXX */ 446 break; 447 } 448 switch (ifr->ifr_addr.sa_family) { 449 450 #ifdef INET 451 case AF_INET: 452 break; 453 #endif 454 #ifdef INET6 455 case AF_INET6: 456 break; 457 #endif /* INET6 */ 458 459 default: 460 error = EAFNOSUPPORT; 461 break; 462 } 463 break; 464 465 default: 466 error = EINVAL; 467 } 468 return (error); 469 } 470