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