|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1982, 1986, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 ! 55: */ ! 56: ! 57: /* ! 58: * Loopback interface driver for protocol testing and timing. ! 59: */ ! 60: #include "loop.h" ! 61: #if NLOOP > 0 ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/kernel.h> ! 66: #include <sys/mbuf.h> ! 67: #include <sys/socket.h> ! 68: #include <sys/sockio.h> ! 69: ! 70: #include <net/if.h> ! 71: #include <net/if_types.h> ! 72: #include <net/netisr.h> ! 73: #include <net/route.h> ! 74: #include <net/bpf.h> ! 75: #include <sys/malloc.h> ! 76: ! 77: #if INET ! 78: #include <netinet/in.h> ! 79: #include <netinet/in_var.h> ! 80: #endif ! 81: ! 82: #if IPX ! 83: #include <netipx/ipx.h> ! 84: #include <netipx/ipx_if.h> ! 85: #endif ! 86: ! 87: #if NS ! 88: #include <netns/ns.h> ! 89: #include <netns/ns_if.h> ! 90: #endif ! 91: ! 92: #if ISO ! 93: #include <netiso/iso.h> ! 94: #include <netiso/iso_var.h> ! 95: #endif ! 96: ! 97: #include <net/dlil.h> ! 98: ! 99: #if NETAT ! 100: extern struct ifqueue atalkintrq; ! 101: #endif ! 102: ! 103: #include "bpfilter.h" ! 104: #if NBPFILTER > 0 ! 105: #include <net/bpfdesc.h> ! 106: #endif ! 107: ! 108: ! 109: #define NLOOP_ATTACHMENTS (NLOOP * 12) ! 110: ! 111: struct lo_statics_str { ! 112: int bpf_mode; ! 113: int (*bpf_callback)(struct ifnet *, struct mbuf *); ! 114: }; ! 115: ! 116: static struct if_proto *lo_array[NLOOP_ATTACHMENTS]; ! 117: static struct lo_statics_str lo_statics[NLOOP]; ! 118: static lo_count = 0; ! 119: ! 120: ! 121: #ifdef TINY_LOMTU ! 122: #define LOMTU (1024+512) ! 123: #else ! 124: #define LOMTU 16384 ! 125: #endif ! 126: ! 127: struct ifnet loif[NLOOP]; ! 128: ! 129: void lo_reg_if_mods(); ! 130: ! 131: ! 132: ! 133: ! 134: int lo_demux(ifp, m, frame_header, proto) ! 135: struct ifnet *ifp; ! 136: struct mbuf *m; ! 137: char *frame_header; ! 138: struct if_proto **proto; ! 139: { ! 140: int i; ! 141: struct if_proto **proto_ptr; ! 142: ! 143: proto_ptr = mtod(m, struct if_proto **); ! 144: *proto = *proto_ptr; ! 145: m_adj(m, sizeof(u_long)); ! 146: return 0; ! 147: } ! 148: ! 149: ! 150: int lo_framer(ifp, m, dest, dest_linkaddr, frame_type) ! 151: struct ifnet *ifp; ! 152: struct mbuf **m; ! 153: struct sockaddr *dest; ! 154: char *dest_linkaddr; ! 155: char *frame_type; ! 156: ! 157: { ! 158: char *to_ptr; ! 159: ! 160: M_PREPEND(*m, (4 * sizeof(u_long)), M_WAITOK); ! 161: to_ptr = mtod(*m, char *); ! 162: bcopy(dest_linkaddr, to_ptr, (4 * sizeof(u_long))); ! 163: return 0; ! 164: } ! 165: ! 166: static ! 167: int lo_add_if(struct ifnet *ifp) ! 168: { ! 169: ifp->if_demux = lo_demux; ! 170: ifp->if_framer = lo_framer; ! 171: return 0; ! 172: } ! 173: ! 174: static ! 175: int lo_del_if(struct ifnet *ifp) ! 176: { ! 177: return 0; ! 178: } ! 179: ! 180: ! 181: ! 182: ! 183: static ! 184: int lo_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag) ! 185: { ! 186: int i; ! 187: ! 188: for (i=0; i < lo_count; i++) ! 189: if (lo_array[i] == 0) { ! 190: lo_array[lo_count] = proto; ! 191: return 0; ! 192: } ! 193: ! 194: if ((i == lo_count) && (lo_count == NLOOP_ATTACHMENTS)) ! 195: panic("lo_add_proto -- Too many attachments\n"); ! 196: ! 197: lo_array[lo_count++] = proto; ! 198: return 0; ! 199: } ! 200: ! 201: ! 202: static ! 203: int lo_del_proto(struct if_proto *proto, u_long dl_tag) ! 204: { ! 205: int i; ! 206: ! 207: for (i=0; i < lo_count; i++) ! 208: if (lo_array[i] == proto) { ! 209: lo_array[i] = 0; ! 210: return 0; ! 211: } ! 212: ! 213: return ENOENT; ! 214: } ! 215: ! 216: static int ! 217: lo_output(ifp, m) ! 218: struct ifnet *ifp; ! 219: register struct mbuf *m; ! 220: { u_int *prepend_ptr; ! 221: u_int af; ! 222: u_long saved_header[3]; ! 223: ! 224: if ((m->m_flags & M_PKTHDR) == 0) ! 225: panic("lo_output: no HDR"); ! 226: ! 227: m->m_pkthdr.rcvif = ifp; ! 228: ! 229: prepend_ptr = mtod(m, u_int *); ! 230: af = *prepend_ptr; ! 231: m_adj(m, sizeof(u_int)); ! 232: ! 233: ! 234: #if NBPFILTER > 0 ! 235: if (lo_statics[ifp->if_unit].bpf_mode != BPF_TAP_DISABLE) { ! 236: struct mbuf m0, *n; ! 237: ! 238: bcopy(mtod(m, caddr_t), &saved_header[0], (3 * sizeof(u_long))); ! 239: m_adj(m, (3 * sizeof(u_long))); ! 240: ! 241: n = m; ! 242: if (ifp->if_bpf->bif_dlt == DLT_NULL) { ! 243: /* ! 244: * We need to prepend the address family as ! 245: * a four byte field. Cons up a dummy header ! 246: * to pacify bpf. This is safe because bpf ! 247: * will only read from the mbuf (i.e., it won't ! 248: * try to free it or keep a pointer a to it). ! 249: */ ! 250: m0.m_next = m; ! 251: m0.m_len = 4; ! 252: m0.m_data = (char *)⁡ ! 253: n = &m0; ! 254: } ! 255: ! 256: (*lo_statics[ifp->if_unit].bpf_callback)(ifp, n); ! 257: ! 258: M_PREPEND(m, (3 * sizeof(u_long)), M_WAITOK); ! 259: bcopy(&saved_header[0], mtod(m, caddr_t), (3 * sizeof(u_long))); ! 260: ! 261: } ! 262: #endif ! 263: ! 264: /* ! 265: * Turn this code back on when iokit starts incrementing these counters. ! 266: /* ! 267: /* ! 268: ifp->if_ibytes += m->m_pkthdr.len; ! 269: ifp->if_obytes += m->m_pkthdr.len; ! 270: */ ! 271: ifp->if_opackets++; ! 272: ifp->if_ipackets++; ! 273: ! 274: return dlil_input(ifp, m, mtod(m, char *)); ! 275: } ! 276: ! 277: ! 278: /* ! 279: * This is a common pre-output route used by INET, AT, etc. This could ! 280: * (should?) be split into separate pre-output routines for each protocol. ! 281: */ ! 282: ! 283: static int ! 284: lo_pre_output(ifp, m, dst, route, frame_type, dst_addr, dl_tag) ! 285: struct ifnet *ifp; ! 286: register struct mbuf **m; ! 287: struct sockaddr *dst; ! 288: void *route; ! 289: char *frame_type; ! 290: char *dst_addr; ! 291: u_long dl_tag; ! 292: ! 293: { ! 294: int s, isr; ! 295: register struct ifqueue *ifq = 0; ! 296: u_long *prepend_ptr; ! 297: register struct rtentry *rt = (struct rtentry *) route; ! 298: ! 299: prepend_ptr = (u_long *) dst_addr; ! 300: if (((*m)->m_flags & M_PKTHDR) == 0) ! 301: panic("looutput no HDR"); ! 302: ! 303: if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { ! 304: if (rt->rt_flags & RTF_BLACKHOLE) { ! 305: m_freem(*m); ! 306: return EJUSTRETURN; ! 307: } ! 308: else ! 309: return ((rt->rt_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH); ! 310: } ! 311: ! 312: switch (dst->sa_family) { ! 313: #if INET ! 314: case AF_INET: ! 315: ifq = &ipintrq; ! 316: isr = NETISR_IP; ! 317: break; ! 318: #endif ! 319: #if IPX ! 320: case AF_IPX: ! 321: ifq = &ipxintrq; ! 322: isr = NETISR_IPX; ! 323: break; ! 324: #endif ! 325: #if NS ! 326: case AF_NS: ! 327: ifq = &nsintrq; ! 328: isr = NETISR_NS; ! 329: break; ! 330: #endif ! 331: #if ISO ! 332: case AF_ISO: ! 333: ifq = &clnlintrq; ! 334: isr = NETISR_ISO; ! 335: break; ! 336: #endif ! 337: #if NETAT ! 338: case AF_APPLETALK: ! 339: ifq = &atalkintrq; ! 340: isr = NETISR_APPLETALK; ! 341: break; ! 342: #endif NETAT ! 343: default: ! 344: return (EAFNOSUPPORT); ! 345: } ! 346: ! 347: *prepend_ptr++ = dst->sa_family; /* For lo_output(BPF) */ ! 348: *prepend_ptr++ = dlttoproto(dl_tag); /* For lo_demux */ ! 349: *prepend_ptr++ = (u_long) ifq; /* For lo_input */ ! 350: *prepend_ptr = isr; /* For lo_input */ ! 351: ! 352: return 0; ! 353: } ! 354: ! 355: ! 356: ! 357: ! 358: /* ! 359: * lo_input - This should work for all attached protocols that use the ! 360: * ifq/schednetisr input mechanism. ! 361: */ ! 362: ! 363: ! 364: int ! 365: lo_input(m, fh, ifp, dl_tag, sync_ok) ! 366: register struct mbuf *m; ! 367: char *fh; ! 368: struct ifnet *ifp; ! 369: u_long dl_tag; ! 370: int sync_ok; ! 371: ! 372: { ! 373: u_long *prepend_ptr; ! 374: int s, isr; ! 375: register struct ifqueue *ifq = 0; ! 376: ! 377: prepend_ptr = mtod(m, u_long *); ! 378: ifq = (struct ifqueue *) *prepend_ptr++; ! 379: isr = *prepend_ptr; ! 380: m_adj(m, (2 * sizeof(u_long))); ! 381: ! 382: s = splimp(); ! 383: if (IF_QFULL(ifq)) { ! 384: IF_DROP(ifq); ! 385: m_freem(m); ! 386: splx(s); ! 387: return (EJUSTRETURN); ! 388: } ! 389: ! 390: IF_ENQUEUE(ifq, m); ! 391: schednetisr(isr); ! 392: splx(s); ! 393: return (0); ! 394: } ! 395: ! 396: ! 397: ! 398: ! 399: /* ARGSUSED */ ! 400: static void ! 401: lortrequest(cmd, rt, sa) ! 402: int cmd; ! 403: struct rtentry *rt; ! 404: struct sockaddr *sa; ! 405: { ! 406: if (rt) { ! 407: rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ ! 408: /* ! 409: * For optimal performance, the send and receive buffers ! 410: * should be at least twice the MTU plus a little more for ! 411: * overhead. ! 412: */ ! 413: rt->rt_rmx.rmx_recvpipe = ! 414: rt->rt_rmx.rmx_sendpipe = 3 * LOMTU; ! 415: } ! 416: } ! 417: ! 418: /* ! 419: * Process an ioctl request. ! 420: */ ! 421: /* ARGSUSED */ ! 422: static int ! 423: loioctl(ifp, cmd, data) ! 424: register struct ifnet *ifp; ! 425: u_long cmd; ! 426: void *data; ! 427: { ! 428: register struct ifaddr *ifa; ! 429: register struct ifreq *ifr = (struct ifreq *)data; ! 430: register int error = 0; ! 431: ! 432: switch (cmd) { ! 433: ! 434: case SIOCSIFADDR: ! 435: ifp->if_flags |= IFF_UP | IFF_RUNNING; ! 436: ifa = (struct ifaddr *)data; ! 437: ifa->ifa_rtrequest = lortrequest; ! 438: /* ! 439: * Everything else is done at a higher level. ! 440: */ ! 441: break; ! 442: ! 443: case SIOCADDMULTI: ! 444: case SIOCDELMULTI: ! 445: if (ifr == 0) { ! 446: error = EAFNOSUPPORT; /* XXX */ ! 447: break; ! 448: } ! 449: switch (ifr->ifr_addr.sa_family) { ! 450: ! 451: #if INET ! 452: case AF_INET: ! 453: break; ! 454: #endif ! 455: ! 456: default: ! 457: error = EAFNOSUPPORT; ! 458: break; ! 459: } ! 460: break; ! 461: ! 462: case SIOCSIFMTU: ! 463: ifp->if_mtu = ifr->ifr_mtu; ! 464: break; ! 465: ! 466: case SIOCSIFFLAGS: ! 467: break; ! 468: ! 469: default: ! 470: error = EINVAL; ! 471: } ! 472: return (error); ! 473: } ! 474: #endif /* NLOOP > 0 */ ! 475: ! 476: ! 477: int lo_shutdown() ! 478: { ! 479: return 0; ! 480: } ! 481: ! 482: ! 483: void lo_reg_if_mods() ! 484: { ! 485: ! 486: if (dlil_reg_if_modules(APPLE_IF_FAM_LOOPBACK, lo_add_if, lo_del_if, ! 487: lo_add_proto, lo_del_proto, ! 488: lo_shutdown)) ! 489: panic("Couldn't register lo modules\n"); ! 490: ! 491: } ! 492: ! 493: ! 494: u_long lo_attach_inet(struct ifnet *ifp) ! 495: { ! 496: struct dlil_proto_reg_str reg; ! 497: struct dlil_demux_desc desc; ! 498: u_long dl_tag=0; ! 499: short native=0; ! 500: int stat; ! 501: int i; ! 502: ! 503: for (i=0; i < lo_count; i++) { ! 504: if ((lo_array[i]) && (lo_array[i]->ifp == ifp)) { ! 505: if (lo_array[i]->protocol_family == PF_INET) ! 506: return lo_array[i]->dl_tag; ! 507: } ! 508: } ! 509: ! 510: TAILQ_INIT(®.demux_desc_head); ! 511: desc.type = DLIL_DESC_RAW; ! 512: desc.variants.bitmask.proto_id_length = 0; ! 513: desc.variants.bitmask.proto_id = 0; ! 514: desc.variants.bitmask.proto_id_mask = 0; ! 515: desc.native_type = (char *) &native; ! 516: TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next); ! 517: reg.interface_family = ifp->if_family; ! 518: reg.unit_number = ifp->if_unit; ! 519: reg.input = lo_input; ! 520: reg.pre_output = lo_pre_output; ! 521: reg.event = 0; ! 522: reg.offer = 0; ! 523: reg.ioctl = loioctl; ! 524: reg.default_proto = 0; ! 525: reg.protocol_family = PF_INET; ! 526: ! 527: stat = dlil_attach_protocol(®, &dl_tag); ! 528: if (stat) { ! 529: panic("ether_attach_inet can't attach interface\n"); ! 530: } ! 531: ! 532: return dl_tag; ! 533: } ! 534: ! 535: ! 536: int lo_set_bpf_tap(struct ifnet *ifp, int mode, int (*bpf_callback)(struct ifnet *, struct mbuf *)) ! 537: { ! 538: ! 539: /* ! 540: * NEED MUTEX HERE XXX ! 541: */ ! 542: if (mode == BPF_TAP_DISABLE) { ! 543: lo_statics[ifp->if_unit].bpf_mode = mode; ! 544: lo_statics[ifp->if_unit].bpf_callback = bpf_callback; ! 545: } ! 546: else { ! 547: lo_statics[ifp->if_unit].bpf_callback = bpf_callback; ! 548: lo_statics[ifp->if_unit].bpf_mode = mode; ! 549: } ! 550: ! 551: return 0; ! 552: } ! 553: ! 554: ! 555: /* ARGSUSED */ ! 556: void ! 557: loopattach(dummy) ! 558: void *dummy; ! 559: { ! 560: register struct ifnet *ifp; ! 561: register int i = 0; ! 562: ! 563: lo_reg_if_mods(); ! 564: ! 565: for (ifp = loif; i < NLOOP; ifp++) { ! 566: lo_statics[i].bpf_callback = 0; ! 567: lo_statics[i].bpf_mode = BPF_TAP_DISABLE; ! 568: ifp->if_name = "lo"; ! 569: ifp->if_family = APPLE_IF_FAM_LOOPBACK; ! 570: ifp->if_unit = i++; ! 571: ifp->if_mtu = LOMTU; ! 572: ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; ! 573: ifp->if_ioctl = 0; ! 574: ifp->if_set_bpf_tap = lo_set_bpf_tap; ! 575: ifp->if_output = lo_output; ! 576: ifp->if_type = IFT_LOOP; ! 577: dlil_if_attach(ifp); ! 578: #if NBPFILTER > 0 ! 579: bpfattach(ifp, DLT_NULL, sizeof(u_int)); ! 580: #endif ! 581: } ! 582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.