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