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