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