1 /* $NetBSD: if_loop.c,v 1.41 2002/09/26 16:07:03 darrenr 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.41 2002/09/26 16:07:03 darrenr 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 145 #ifdef ALTQ 146 void lostart(struct ifnet *); 147 #endif 148 149 void 150 loopattach(n) 151 int n; 152 { 153 int i; 154 struct ifnet *ifp; 155 156 for (i = 0; i < NLOOP; i++) { 157 ifp = &loif[i]; 158 sprintf(ifp->if_xname, "lo%d", i); 159 ifp->if_softc = NULL; 160 ifp->if_mtu = LOMTU; 161 ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; 162 ifp->if_ioctl = loioctl; 163 ifp->if_output = looutput; 164 #ifdef ALTQ 165 ifp->if_start = lostart; 166 #endif 167 ifp->if_type = IFT_LOOP; 168 ifp->if_hdrlen = 0; 169 ifp->if_addrlen = 0; 170 ifp->if_dlt = DLT_NULL; 171 IFQ_SET_READY(&ifp->if_snd); 172 if_attach(ifp); 173 if_alloc_sadl(ifp); 174 #if NBPFILTER > 0 175 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 176 #endif 177 } 178 } 179 180 int 181 looutput(ifp, m, dst, rt) 182 struct ifnet *ifp; 183 struct mbuf *m; 184 struct sockaddr *dst; 185 struct rtentry *rt; 186 { 187 int s, isr; 188 struct ifqueue *ifq = 0; 189 190 if ((m->m_flags & M_PKTHDR) == 0) 191 panic("looutput: no header mbuf"); 192 #if NBPFILTER > 0 193 if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK)) { 194 /* 195 * We need to prepend the address family as 196 * a four byte field. Cons up a dummy header 197 * to pacify bpf. This is safe because bpf 198 * will only read from the mbuf (i.e., it won't 199 * try to free it or keep a pointer to it). 200 */ 201 struct mbuf m0; 202 u_int32_t af = dst->sa_family; 203 204 M_COPY_PKTHDR(&m0, m); 205 m0.m_next = m; 206 m0.m_len = 4; 207 m0.m_data = (char *)⁡ 208 m0.m_pkthdr.len += m0.m_len; 209 210 bpf_mtap(ifp->if_bpf, &m0); 211 } 212 #endif 213 m->m_pkthdr.rcvif = ifp; 214 215 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 216 m_freem(m); 217 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 218 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 219 } 220 221 #ifndef PULLDOWN_TEST 222 /* 223 * KAME requires that the packet to be contiguous on the 224 * mbuf. We need to make that sure. 225 * this kind of code should be avoided. 226 * XXX other conditions to avoid running this part? 227 */ 228 if (m->m_len != m->m_pkthdr.len) { 229 struct mbuf *n = NULL; 230 int maxlen; 231 232 MGETHDR(n, M_DONTWAIT, MT_HEADER); 233 maxlen = MHLEN; 234 if (n) 235 M_COPY_PKTHDR(n, m); 236 if (n && m->m_pkthdr.len > maxlen) { 237 MCLGET(n, M_DONTWAIT); 238 maxlen = MCLBYTES; 239 if ((n->m_flags & M_EXT) == 0) { 240 m_free(n); 241 n = NULL; 242 } 243 } 244 if (!n) { 245 printf("looutput: mbuf allocation failed\n"); 246 m_freem(m); 247 return ENOBUFS; 248 } 249 250 if (m->m_pkthdr.len <= maxlen) { 251 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); 252 n->m_len = m->m_pkthdr.len; 253 n->m_next = NULL; 254 m_freem(m); 255 } else { 256 m_copydata(m, 0, maxlen, mtod(n, caddr_t)); 257 m_adj(m, maxlen); 258 n->m_len = maxlen; 259 n->m_next = m; 260 m->m_flags &= ~M_PKTHDR; 261 } 262 m = n; 263 } 264 #if 0 265 if (m && m->m_next != NULL) { 266 printf("loop: not contiguous...\n"); 267 m_freem(m); 268 return ENOBUFS; 269 } 270 #endif 271 #endif 272 273 ifp->if_opackets++; 274 ifp->if_obytes += m->m_pkthdr.len; 275 276 #ifdef ALTQ 277 /* 278 * ALTQ on the loopback interface is just for debugging. It's 279 * used only for loopback interfaces, not for a simplex interface. 280 */ 281 if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) && 282 ifp->if_start == lostart) { 283 struct altq_pktattr pktattr; 284 int error; 285 286 /* 287 * If the queueing discipline needs packet classification, 288 * do it before prepending the link headers. 289 */ 290 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); 291 292 M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); 293 if (m == NULL) 294 return (ENOBUFS); 295 *(mtod(m, uint32_t *)) = dst->sa_family; 296 297 s = splnet(); 298 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); 299 (*ifp->if_start)(ifp); 300 splx(s); 301 return (error); 302 } 303 #endif /* ALTQ */ 304 305 switch (dst->sa_family) { 306 307 #ifdef INET 308 case AF_INET: 309 ifq = &ipintrq; 310 isr = NETISR_IP; 311 break; 312 #endif 313 #ifdef INET6 314 case AF_INET6: 315 m->m_flags |= M_LOOP; 316 ifq = &ip6intrq; 317 isr = NETISR_IPV6; 318 break; 319 #endif 320 #ifdef NS 321 case AF_NS: 322 ifq = &nsintrq; 323 isr = NETISR_NS; 324 break; 325 #endif 326 #ifdef ISO 327 case AF_ISO: 328 ifq = &clnlintrq; 329 isr = NETISR_ISO; 330 break; 331 #endif 332 #ifdef IPX 333 case AF_IPX: 334 ifq = &ipxintrq; 335 isr = NETISR_IPX; 336 break; 337 #endif 338 #ifdef NETATALK 339 case AF_APPLETALK: 340 ifq = &atintrq2; 341 isr = NETISR_ATALK; 342 break; 343 #endif 344 default: 345 printf("%s: can't handle af%d\n", ifp->if_xname, 346 dst->sa_family); 347 m_freem(m); 348 return (EAFNOSUPPORT); 349 } 350 s = splnet(); 351 if (IF_QFULL(ifq)) { 352 IF_DROP(ifq); 353 m_freem(m); 354 splx(s); 355 return (ENOBUFS); 356 } 357 IF_ENQUEUE(ifq, m); 358 schednetisr(isr); 359 ifp->if_ipackets++; 360 ifp->if_ibytes += m->m_pkthdr.len; 361 splx(s); 362 return (0); 363 } 364 365 #ifdef ALTQ 366 void 367 lostart(struct ifnet *ifp) 368 { 369 struct ifqueue *ifq; 370 struct mbuf *m; 371 uint32_t af; 372 int s, isr; 373 374 for (;;) { 375 IFQ_DEQUEUE(&ifp->if_snd, m); 376 if (m == NULL) 377 return; 378 379 af = *(mtod(m, uint32_t *)); 380 m_adj(m, sizeof(uint32_t)); 381 382 switch (af) { 383 #ifdef INET 384 case AF_INET: 385 ifq = &ipintrq; 386 isr = NETISR_IP; 387 break; 388 #endif 389 #ifdef INET6 390 case AF_INET6: 391 m->m_flags |= M_LOOP; 392 ifq = &ip6intrq; 393 isr = NETISR_IPV6; 394 break; 395 #endif 396 #ifdef IPX 397 case AF_IPX: 398 ifq = &ipxintrq; 399 isr = NETISR_IPX; 400 break; 401 #endif 402 #ifdef NS 403 case AF_NS: 404 ifq = &nsintrq; 405 isr = NETISR_NS; 406 break; 407 #endif 408 #ifdef ISO 409 case AF_ISO: 410 ifq = &clnlintrq; 411 isr = NETISR_ISO; 412 break; 413 #endif 414 #ifdef NETATALK 415 case AF_APPLETALK: 416 ifq = &atintrq2; 417 isr = NETISR_ATALK; 418 break; 419 #endif 420 default: 421 printf("%s: can't handle af%d\n", ifp->if_xname, af); 422 m_freem(m); 423 return; 424 } 425 426 s = splnet(); 427 if (IF_QFULL(ifq)) { 428 IF_DROP(ifq); 429 splx(s); 430 m_freem(m); 431 return; 432 } 433 IF_ENQUEUE(ifq, m); 434 schednetisr(isr); 435 ifp->if_ipackets++; 436 ifp->if_ibytes += m->m_pkthdr.len; 437 splx(s); 438 } 439 } 440 #endif /* ALTQ */ 441 442 /* ARGSUSED */ 443 void 444 lortrequest(cmd, rt, info) 445 int cmd; 446 struct rtentry *rt; 447 struct rt_addrinfo *info; 448 { 449 450 if (rt) 451 rt->rt_rmx.rmx_mtu = LOMTU; 452 } 453 454 /* 455 * Process an ioctl request. 456 */ 457 /* ARGSUSED */ 458 int 459 loioctl(ifp, cmd, data) 460 struct ifnet *ifp; 461 u_long cmd; 462 caddr_t data; 463 { 464 struct ifaddr *ifa; 465 struct ifreq *ifr; 466 int error = 0; 467 468 switch (cmd) { 469 470 case SIOCSIFADDR: 471 ifp->if_flags |= IFF_UP; 472 ifa = (struct ifaddr *)data; 473 if (ifa != 0 /*&& ifa->ifa_addr->sa_family == AF_ISO*/) 474 ifa->ifa_rtrequest = lortrequest; 475 /* 476 * Everything else is done at a higher level. 477 */ 478 break; 479 480 case SIOCADDMULTI: 481 case SIOCDELMULTI: 482 ifr = (struct ifreq *)data; 483 if (ifr == 0) { 484 error = EAFNOSUPPORT; /* XXX */ 485 break; 486 } 487 switch (ifr->ifr_addr.sa_family) { 488 489 #ifdef INET 490 case AF_INET: 491 break; 492 #endif 493 #ifdef INET6 494 case AF_INET6: 495 break; 496 #endif 497 498 default: 499 error = EAFNOSUPPORT; 500 break; 501 } 502 break; 503 504 default: 505 error = EINVAL; 506 } 507 return (error); 508 } 509