|
|
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) 1999 Apple Computer, Inc. ! 24: * ! 25: * Data Link Inteface Layer ! 26: * Author: Ted Walker ! 27: */ ! 28: ! 29: ! 30: ! 31: #include <sys/param.h> ! 32: #include <sys/systm.h> ! 33: #include <sys/kernel.h> ! 34: #include <sys/malloc.h> ! 35: #include <sys/mbuf.h> ! 36: #include <sys/socket.h> ! 37: #include <net/if_dl.h> ! 38: #include <net/if.h> ! 39: #include <net/if_var.h> ! 40: #include <net/dlil.h> ! 41: ! 42: ! 43: ! 44: #define MAX_DL_TAGS 50 ! 45: #define MAX_DLIL_FILTERS 50 ! 46: #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */ ! 47: #define MAX_LINKADDR 4 /* LONGWORDS */ ! 48: #define M_NKE M_IFADDR ! 49: ! 50: #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter ! 51: #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter ! 52: ! 53: struct dl_tag_str { ! 54: struct ifnet *ifp; ! 55: struct if_proto *proto; ! 56: struct dlil_filterq_head *pr_flt_head; ! 57: }; ! 58: ! 59: ! 60: struct dlil_stats_str { ! 61: int inject_pr_in1; ! 62: int inject_pr_in2; ! 63: int inject_pr_out1; ! 64: int inject_pr_out2; ! 65: int inject_if_in1; ! 66: int inject_if_in2; ! 67: int inject_if_out1; ! 68: int inject_if_out2; ! 69: }; ! 70: ! 71: ! 72: struct dlil_filter_id_str { ! 73: int type; ! 74: struct dlil_filterq_head *head; ! 75: struct dlil_filterq_entry *filter_ptr; ! 76: struct ifnet *ifp; ! 77: struct if_proto *proto; ! 78: }; ! 79: ! 80: ! 81: ! 82: struct if_family_str { ! 83: TAILQ_ENTRY(if_family_str) if_fam_next; ! 84: u_long if_family; ! 85: int refcnt; ! 86: int flags; ! 87: ! 88: #define DLIL_SHUTDOWN 1 ! 89: ! 90: int (*add_if)(struct ifnet *ifp); ! 91: int (*del_if)(struct ifnet *ifp); ! 92: int (*add_proto)(struct ddesc_head_str *demux_desc_head, ! 93: struct if_proto *proto, u_long dl_tag); ! 94: int (*del_proto)(struct if_proto *proto, u_long dl_tag); ! 95: int (*shutdown)(); ! 96: }; ! 97: ! 98: ! 99: ! 100: struct dlil_stats_str dlil_stats; ! 101: ! 102: static ! 103: struct dlil_filter_id_str dlil_filters[MAX_DLIL_FILTERS+1]; ! 104: ! 105: static ! 106: struct dl_tag_str dl_tag_array[MAX_DL_TAGS+1]; ! 107: ! 108: static ! 109: TAILQ_HEAD(, if_family_str) if_family_head; ! 110: ! 111: static ifnet_inited = 0; ! 112: ! 113: /* ! 114: * Internal functions. ! 115: */ ! 116: ! 117: static ! 118: struct if_family_str *find_family_module(u_long if_family) ! 119: { ! 120: struct if_family_str *mod = NULL; ! 121: ! 122: TAILQ_FOREACH(mod, &if_family_head, if_fam_next) { ! 123: if (mod->if_family == if_family) ! 124: break; ! 125: } ! 126: ! 127: return mod; ! 128: } ! 129: ! 130: ! 131: /* ! 132: * Public functions. ! 133: */ ! 134: ! 135: struct ifnet *ifbyfamily(u_long family, short unit) ! 136: { ! 137: struct ifnet *ifp; ! 138: ! 139: TAILQ_FOREACH(ifp, &ifnet, if_link) ! 140: if ((family == ifp->if_family) && ! 141: (ifp->if_unit == unit)) ! 142: return ifp; ! 143: ! 144: return 0; ! 145: } ! 146: ! 147: struct if_proto *dlttoproto(dl_tag) ! 148: u_long dl_tag; ! 149: { ! 150: return dl_tag_array[dl_tag].proto; ! 151: } ! 152: ! 153: ! 154: u_long ifptodlt(struct ifnet *ifp, u_long proto_family) ! 155: { ! 156: struct if_proto *proto; ! 157: struct dlil_proto_head *tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 158: ! 159: ! 160: TAILQ_FOREACH(proto, tmp, next) ! 161: if (proto->ifp == ifp) ! 162: if (proto->protocol_family == proto_family) ! 163: return proto->dl_tag; ! 164: ! 165: return 0; ! 166: } ! 167: ! 168: ! 169: int dlil_find_dltag(u_long if_family, short unit, u_long proto_family, u_long *dl_tag) ! 170: { ! 171: struct ifnet *ifp; ! 172: ! 173: ifp = ifbyfamily(if_family, unit); ! 174: if (!ifp) ! 175: return ENOENT; ! 176: ! 177: *dl_tag = ifptodlt(ifp, proto_family); ! 178: if (*dl_tag == 0) ! 179: return EPROTONOSUPPORT; ! 180: else ! 181: return 0; ! 182: } ! 183: ! 184: ! 185: int dlil_get_next_dl_tag(u_long current_tag, struct dl_tag_attr_str *next) ! 186: { ! 187: int i; ! 188: ! 189: for (i = (current_tag+1); i < MAX_DL_TAGS; i++) ! 190: if (dl_tag_array[i].ifp) { ! 191: next->dl_tag = i; ! 192: next->if_flags = dl_tag_array[i].ifp->if_flags; ! 193: next->if_unit = dl_tag_array[i].ifp->if_unit; ! 194: next->protocol_family = dl_tag_array[i].proto->protocol_family; ! 195: next->if_family = dl_tag_array[i].ifp->if_family; ! 196: return 0; ! 197: } ! 198: ! 199: /* ! 200: * If we got here, there are no more entries ! 201: */ ! 202: ! 203: return ENOENT; ! 204: } ! 205: ! 206: ! 207: void ! 208: dlil_init() ! 209: { ! 210: int i; ! 211: ! 212: TAILQ_INIT(&if_family_head); ! 213: for (i=0; i < MAX_DL_TAGS; i++) ! 214: dl_tag_array[i].ifp = 0; ! 215: ! 216: for (i=0; i < MAX_DLIL_FILTERS; i++) ! 217: dlil_filters[i].type = 0; ! 218: ! 219: bzero(&dlil_stats, sizeof(dlil_stats)); ! 220: } ! 221: ! 222: ! 223: u_long get_new_filter_id() ! 224: { ! 225: u_long i; ! 226: ! 227: for (i=1; i < MAX_DLIL_FILTERS; i++) ! 228: if (dlil_filters[i].type == 0) ! 229: return i; ! 230: ! 231: return 0; ! 232: } ! 233: ! 234: ! 235: int dlil_attach_interface_filter(struct ifnet *ifp, ! 236: struct dlil_if_flt_str *if_filter, ! 237: u_long *filter_id, ! 238: int insertion_point) ! 239: { ! 240: int s; ! 241: int retval; ! 242: struct dlil_filterq_entry *tmp_ptr; ! 243: struct dlil_filterq_entry *if_filt; ! 244: struct dlil_filterq_head *fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 245: ! 246: ! 247: MALLOC(tmp_ptr, struct dlil_filterq_entry *, sizeof(*tmp_ptr), M_NKE, M_WAITOK); ! 248: bcopy((caddr_t) if_filter, (caddr_t) &tmp_ptr->variants.if_filter, ! 249: sizeof(struct dlil_if_flt_str)); ! 250: ! 251: s = splnet(); ! 252: ! 253: if (insertion_point != DLIL_LAST_FILTER) { ! 254: TAILQ_FOREACH(if_filt, fhead, que) ! 255: if (insertion_point == if_filt->filter_id) { ! 256: TAILQ_INSERT_BEFORE(if_filt, tmp_ptr, que); ! 257: break; ! 258: } ! 259: } ! 260: else ! 261: TAILQ_INSERT_TAIL(fhead, tmp_ptr, que); ! 262: ! 263: if (*filter_id = get_new_filter_id()) { ! 264: dlil_filters[*filter_id].filter_ptr = tmp_ptr; ! 265: dlil_filters[*filter_id].head = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 266: dlil_filters[*filter_id].type = DLIL_IF_FILTER; ! 267: dlil_filters[*filter_id].ifp = ifp; ! 268: tmp_ptr->filter_id = *filter_id; ! 269: tmp_ptr->type = DLIL_IF_FILTER; ! 270: retval = 0; ! 271: } ! 272: else { ! 273: kprintf("dlil_attach_interface_filter - can't alloc filter_id\n"); ! 274: TAILQ_REMOVE(fhead, tmp_ptr, que); ! 275: FREE(tmp_ptr, M_NKE); ! 276: retval = EOVERFLOW; ! 277: } ! 278: ! 279: splx(s); ! 280: return retval; ! 281: } ! 282: ! 283: ! 284: int dlil_attach_protocol_filter(u_long dl_tag, ! 285: struct dlil_pr_flt_str *pr_filter, ! 286: u_long *filter_id, ! 287: int insertion_point) ! 288: { ! 289: struct dlil_filterq_entry *tmp_ptr; ! 290: struct dlil_filterq_entry *pr_filt; ! 291: int s; ! 292: int retval; ! 293: ! 294: ! 295: if (dl_tag > MAX_DL_TAGS) ! 296: return ERANGE; ! 297: ! 298: if (dl_tag_array[dl_tag].ifp == 0) ! 299: return ENOENT; ! 300: ! 301: MALLOC(tmp_ptr, struct dlil_filterq_entry *, sizeof(*tmp_ptr), M_NKE, M_WAITOK); ! 302: bcopy((caddr_t) pr_filter, (caddr_t) &tmp_ptr->variants.pr_filter, ! 303: sizeof(struct dlil_pr_flt_str)); ! 304: ! 305: ! 306: s = splnet(); ! 307: if (insertion_point != DLIL_LAST_FILTER) { ! 308: TAILQ_FOREACH(pr_filt, dl_tag_array[dl_tag].pr_flt_head, que) ! 309: if (insertion_point == pr_filt->filter_id) { ! 310: TAILQ_INSERT_BEFORE(pr_filt, tmp_ptr, que); ! 311: break; ! 312: } ! 313: } ! 314: else ! 315: TAILQ_INSERT_TAIL(dl_tag_array[dl_tag].pr_flt_head, tmp_ptr, que); ! 316: ! 317: ! 318: if (*filter_id = get_new_filter_id()) { ! 319: dlil_filters[*filter_id].filter_ptr = tmp_ptr; ! 320: dlil_filters[*filter_id].head = dl_tag_array[dl_tag].pr_flt_head; ! 321: dlil_filters[*filter_id].type = DLIL_PR_FILTER; ! 322: dlil_filters[*filter_id].proto = dl_tag_array[dl_tag].proto; ! 323: dlil_filters[*filter_id].ifp = dl_tag_array[dl_tag].ifp; ! 324: tmp_ptr->filter_id = *filter_id; ! 325: tmp_ptr->type = DLIL_PR_FILTER; ! 326: retval = 0; ! 327: } ! 328: else { ! 329: kprintf("dlil_attach_protocol_filter - can't alloc filter_id\n"); ! 330: TAILQ_REMOVE(dl_tag_array[dl_tag].pr_flt_head, tmp_ptr, que); ! 331: FREE(tmp_ptr, M_NKE); ! 332: retval = EOVERFLOW; ! 333: } ! 334: ! 335: splx(s); ! 336: return retval; ! 337: } ! 338: ! 339: ! 340: int ! 341: dlil_detach_filter(u_long filter_id) ! 342: { ! 343: struct dlil_filter_id_str *flt; ! 344: int s; ! 345: ! 346: if (filter_id > MAX_DLIL_FILTERS) { ! 347: kprintf("dlil_detach_filter - Bad filter_id value %d\n", filter_id); ! 348: return ERANGE; ! 349: } ! 350: ! 351: flt = &dlil_filters[filter_id]; ! 352: if (flt->type == 0) { ! 353: kprintf("dlil_detach_filter - no such filter_id %d\n", filter_id); ! 354: return ENOENT; ! 355: } ! 356: ! 357: s = splnet(); ! 358: if (flt->type == DLIL_IF_FILTER) { ! 359: if (IFILT(flt->filter_ptr).filter_detach) ! 360: (*IFILT(flt->filter_ptr).filter_detach)(IFILT(flt->filter_ptr).cookie); ! 361: } ! 362: else { ! 363: if (flt->type == DLIL_PR_FILTER) { ! 364: if (PFILT(flt->filter_ptr).filter_detach) ! 365: (*PFILT(flt->filter_ptr).filter_detach)(PFILT(flt->filter_ptr).cookie); ! 366: } ! 367: } ! 368: ! 369: TAILQ_REMOVE(flt->head, flt->filter_ptr, que); ! 370: FREE(flt->filter_ptr, M_NKE); ! 371: flt->type = 0; ! 372: splx(s); ! 373: return 0; ! 374: } ! 375: ! 376: ! 377: ! 378: ! 379: int ! 380: dlil_input(struct ifnet *ifp, struct mbuf *m, ! 381: char *frame_header) ! 382: { ! 383: boolean_t funnel_state; ! 384: int ret; ! 385: ! 386: funnel_state = thread_set_funneled(TRUE); ! 387: ! 388: ret = dlil_input_funneled(ifp, m, frame_header); ! 389: ! 390: (void) thread_set_funneled(funnel_state); ! 391: ! 392: return(ret); ! 393: } ! 394: ! 395: int ! 396: dlil_input_funneled(struct ifnet *ifp, struct mbuf *m, ! 397: char *frame_header) ! 398: { ! 399: struct ifnet *orig_ifp = 0; ! 400: struct dlil_filterq_entry *tmp; ! 401: int retval; ! 402: struct if_proto *ifproto = 0; ! 403: struct if_proto *proto; ! 404: struct dlil_filterq_head *fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 405: ! 406: /* ! 407: * Temporary, until all drivers do this. ! 408: */ ! 409: ! 410: ifp->if_ibytes += m->m_pkthdr.len; ! 411: ! 412: ! 413: /* ! 414: * Run interface filters ! 415: */ ! 416: ! 417: while (orig_ifp != ifp) { ! 418: orig_ifp = ifp; ! 419: ! 420: TAILQ_FOREACH_REVERSE(tmp, fhead, que, dlil_filterq_head) { ! 421: if (IFILT(tmp).filter_if_input) { ! 422: retval = (*IFILT(tmp).filter_if_input)(IFILT(tmp).cookie, ! 423: &ifp, ! 424: &m, ! 425: &frame_header); ! 426: if (retval) { ! 427: if (retval == EJUSTRETURN) ! 428: return 0; ! 429: else { ! 430: m_freem(m); ! 431: return retval; ! 432: } ! 433: } ! 434: } ! 435: ! 436: if (ifp != orig_ifp) ! 437: break; ! 438: } ! 439: } ! 440: ! 441: ifp->if_lastchange = time; ! 442: ! 443: /* ! 444: * Call family demux module. If the demux module finds a match ! 445: * for the frame it will fill-in the ifproto pointer. ! 446: */ ! 447: ! 448: retval = (*ifp->if_demux)(ifp, m, frame_header, &ifproto ); ! 449: ! 450: if (m->m_flags & (M_BCAST|M_MCAST)) ! 451: ifp->if_imcasts++; ! 452: ! 453: if ((retval) && (ifp->offercnt)) { ! 454: /* ! 455: * No match was found, look for any offers. ! 456: */ ! 457: struct dlil_proto_head *tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 458: TAILQ_FOREACH(proto, tmp, next) { ! 459: if ((proto->dl_offer) && (proto->dl_offer(m, frame_header) == 0)) { ! 460: ifproto = proto; ! 461: retval = 0; ! 462: break; ! 463: } ! 464: } ! 465: } ! 466: ! 467: if (retval) { ! 468: if (retval != EJUSTRETURN) { ! 469: m_freem(m); ! 470: return retval; ! 471: } ! 472: else ! 473: return 0; ! 474: } ! 475: else ! 476: if (ifproto == 0) { ! 477: printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n"); ! 478: m_freem(m); ! 479: return 0; ! 480: } ! 481: ! 482: /* ! 483: * Call any attached protocol filters. ! 484: */ ! 485: ! 486: TAILQ_FOREACH_REVERSE(tmp, &ifproto->pr_flt_head, que, dlil_filterq_head) { ! 487: if (PFILT(tmp).filter_dl_input) { ! 488: retval = (*PFILT(tmp).filter_dl_input)(PFILT(tmp).cookie, ! 489: &m, ! 490: &frame_header, ! 491: &ifp); ! 492: ! 493: if (retval) { ! 494: if (retval == EJUSTRETURN) ! 495: return 0; ! 496: else { ! 497: m_freem(m); ! 498: return retval; ! 499: } ! 500: } ! 501: } ! 502: } ! 503: ! 504: ! 505: ! 506: retval = (*ifproto->dl_input)(m, frame_header, ! 507: ifp, ifproto->dl_tag, ! 508: (ifp->if_eflags & IFEF_DVR_REENTRY_OK)); ! 509: ! 510: if (retval == EJUSTRETURN) ! 511: retval = 0; ! 512: else ! 513: if (retval) ! 514: m_freem(m); ! 515: ! 516: return retval; ! 517: } ! 518: ! 519: ! 520: ! 521: void ether_input(ifp, eh, m) ! 522: struct ifnet *ifp; ! 523: struct ether_header *eh; ! 524: struct mbuf *m; ! 525: ! 526: { ! 527: kprintf("Someone is calling ether_input!!\n"); ! 528: ! 529: dlil_input(ifp, m, (char *) eh); ! 530: } ! 531: ! 532: ! 533: int ! 534: dlil_event(struct ifnet *ifp, struct event_msg *event) ! 535: { ! 536: return 0; ! 537: } ! 538: ! 539: ! 540: ! 541: int ! 542: dlil_output(u_long dl_tag, ! 543: struct mbuf *m, ! 544: caddr_t route, ! 545: struct sockaddr *dest, ! 546: int raw ! 547: ) ! 548: { ! 549: char *frame_type; ! 550: char *dst_linkaddr; ! 551: struct ifnet *orig_ifp = 0; ! 552: struct ifnet *ifp; ! 553: struct if_proto *proto; ! 554: struct dlil_filterq_entry *tmp; ! 555: int retval = 0; ! 556: char frame_type_buffer[MAX_FRAME_TYPE_SIZE * 4]; ! 557: char dst_linkaddr_buffer[MAX_LINKADDR * 4]; ! 558: struct dlil_filterq_head *fhead; ! 559: ! 560: ! 561: ! 562: ! 563: /* ! 564: * Temporary hackery until all the existing protocols can become fully ! 565: * "dl_tag aware". Some things only have the ifp, so this handles that ! 566: * case for the time being. ! 567: */ ! 568: ! 569: if (dl_tag > MAX_DL_TAGS) { ! 570: /* dl_tag is really an ifnet pointer! */ ! 571: ! 572: ifp = (struct ifnet *) dl_tag; ! 573: dl_tag = ifp->if_data.default_proto; ! 574: if (dl_tag) ! 575: proto = dl_tag_array[dl_tag].proto; ! 576: } ! 577: else { ! 578: if ((dl_tag == 0) || (dl_tag_array[dl_tag].ifp == 0)) ! 579: retval = ENOENT; ! 580: else { ! 581: ifp = dl_tag_array[dl_tag].ifp; ! 582: proto = dl_tag_array[dl_tag].proto; ! 583: } ! 584: } ! 585: ! 586: if (retval) { ! 587: m_freem(m); ! 588: return retval; ! 589: } ! 590: ! 591: frame_type = frame_type_buffer; ! 592: dst_linkaddr = dst_linkaddr_buffer; ! 593: ! 594: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 595: ! 596: if ((raw == 0) && (proto->dl_pre_output)) { ! 597: retval = (*proto->dl_pre_output)(ifp, &m, dest, route, ! 598: frame_type, dst_linkaddr, dl_tag); ! 599: if (retval) { ! 600: if (retval == EJUSTRETURN) ! 601: return 0; ! 602: else { ! 603: m_freem(m); ! 604: return retval; ! 605: } ! 606: } ! 607: } ! 608: ! 609: /* ! 610: * Run any attached protocol filters. ! 611: */ ! 612: ! 613: if (TAILQ_EMPTY(dl_tag_array[dl_tag].pr_flt_head) == 0) { ! 614: TAILQ_FOREACH(tmp, dl_tag_array[dl_tag].pr_flt_head, que) { ! 615: if (PFILT(tmp).filter_dl_output) { ! 616: retval = (*PFILT(tmp).filter_dl_output)(PFILT(tmp).cookie, ! 617: &m, &ifp, &dest, dst_linkaddr, frame_type); ! 618: if (retval) { ! 619: if (retval == EJUSTRETURN) ! 620: return 0; ! 621: else { ! 622: m_freem(m); ! 623: return retval; ! 624: } ! 625: } ! 626: } ! 627: } ! 628: } ! 629: ! 630: ! 631: /* ! 632: * Call framing module ! 633: */ ! 634: if ((raw == 0) && (ifp->if_framer)) { ! 635: retval = (*ifp->if_framer)(ifp, &m, dest, dst_linkaddr, frame_type); ! 636: if (retval) { ! 637: if (retval == EJUSTRETURN) ! 638: return 0; ! 639: else ! 640: { ! 641: m_freem(m); ! 642: return retval; ! 643: } ! 644: } ! 645: } ! 646: ! 647: #if BRIDGE ! 648: if (do_bridge) { ! 649: struct mbuf *m0 = m ; ! 650: ! 651: if (m->m_pkthdr.rcvif) ! 652: m->m_pkthdr.rcvif = NULL ; ! 653: ifp = bridge_dst_lookup(m); ! 654: bdg_forward(&m0, ifp); ! 655: if (m0) ! 656: m_freem(m0); ! 657: ! 658: return 0; ! 659: } ! 660: #endif ! 661: ! 662: ! 663: /* ! 664: * Let interface filters (if any) do their thing ... ! 665: */ ! 666: ! 667: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 668: if (TAILQ_EMPTY(fhead) == 0) { ! 669: while (orig_ifp != ifp) { ! 670: orig_ifp = ifp; ! 671: TAILQ_FOREACH(tmp, fhead, que) { ! 672: if (IFILT(tmp).filter_if_output) { ! 673: retval = (*IFILT(tmp).filter_if_output)(IFILT(tmp).cookie, ! 674: &ifp, ! 675: &m); ! 676: if (retval) { ! 677: if (retval == EJUSTRETURN) ! 678: return 0; ! 679: else { ! 680: m_freem(m); ! 681: return retval; ! 682: } ! 683: } ! 684: ! 685: } ! 686: ! 687: if (ifp != orig_ifp) ! 688: break; ! 689: } ! 690: } ! 691: } ! 692: ! 693: /* ! 694: * Finally, call the driver. ! 695: */ ! 696: if (m->m_hdr.mh_type == 0) { ! 697: printf("ERROR - dlil_output - sending free mbuf\n"); ! 698: m_freem(m); ! 699: return 0; ! 700: } ! 701: /* ! 702: * Temporary, until all drivers do this. ! 703: */ ! 704: ! 705: ifp->if_obytes += m->m_pkthdr.len; ! 706: ! 707: retval = (*ifp->if_output)(ifp, m); ! 708: if ((retval == 0) || (retval == EJUSTRETURN)) ! 709: return 0; ! 710: else ! 711: return retval; ! 712: } ! 713: ! 714: ! 715: int ! 716: dlil_ioctl(u_long dl_tag, ! 717: struct ifnet *ifp, ! 718: u_long ioctl_code, ! 719: caddr_t ioctl_arg) ! 720: { ! 721: struct dlil_filterq_entry *tmp; ! 722: struct dlil_filterq_head *fhead; ! 723: int retval; ! 724: ! 725: ! 726: if (dl_tag) { ! 727: if (dl_tag > MAX_DL_TAGS) ! 728: return ERANGE; ! 729: ! 730: if (dl_tag_array[dl_tag].ifp == 0) ! 731: return ENOENT; ! 732: ! 733: ! 734: /* ! 735: * Run any attached protocol filters. ! 736: */ ! 737: TAILQ_FOREACH(tmp, dl_tag_array[dl_tag].pr_flt_head, que) { ! 738: if (PFILT(tmp).filter_dl_ioctl) { ! 739: retval = ! 740: (*PFILT(tmp).filter_dl_ioctl)(PFILT(tmp).cookie, ! 741: dl_tag_array[dl_tag].ifp, ! 742: ioctl_code, ! 743: ioctl_arg); ! 744: ! 745: if (retval) { ! 746: return 0; ! 747: } ! 748: } ! 749: } ! 750: ! 751: if (dl_tag_array[dl_tag].proto->dl_ioctl) ! 752: retval = (*dl_tag_array[dl_tag].proto->dl_ioctl)(dl_tag, ! 753: dl_tag_array[dl_tag].ifp, ! 754: ioctl_code, ! 755: ioctl_arg); ! 756: ! 757: else ! 758: retval = EINVAL; ! 759: } ! 760: else { ! 761: if (ifp) { ! 762: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 763: TAILQ_FOREACH(tmp, fhead, que) { ! 764: if (IFILT(tmp).filter_if_ioctl) { ! 765: retval = (*IFILT(tmp).filter_if_ioctl)(IFILT(tmp).cookie, ifp, ! 766: ioctl_code, ioctl_arg); ! 767: if (retval) { ! 768: return 0; ! 769: } ! 770: } ! 771: } ! 772: if (ifp->if_ioctl) ! 773: retval = (*ifp->if_ioctl)(ifp, ioctl_code, ioctl_arg); ! 774: else ! 775: return 0; ! 776: } ! 777: else ! 778: retval = EINVAL; ! 779: } ! 780: ! 781: return retval; ! 782: } ! 783: ! 784: ! 785: int ! 786: dlil_attach_protocol(struct dlil_proto_reg_str *proto, ! 787: u_long *dl_tag) ! 788: { ! 789: struct ifnet *ifp; ! 790: struct if_proto *ifproto; ! 791: u_long i; ! 792: struct if_family_str *if_family; ! 793: int error; ! 794: struct dlil_proto_head *tmp; ! 795: int s; ! 796: ! 797: ! 798: if ((proto->protocol_family == 0) || (proto->interface_family == 0)) ! 799: return EINVAL; ! 800: ! 801: s = splnet(); ! 802: if_family = find_family_module(proto->interface_family); ! 803: if ((!if_family) || (if_family->flags & DLIL_SHUTDOWN)) { ! 804: kprintf("dlil_attach_protocol -- no interface family module %d", ! 805: proto->interface_family); ! 806: splx(s); ! 807: return ENOENT; ! 808: } ! 809: ! 810: ifp = ifbyfamily(proto->interface_family, proto->unit_number); ! 811: if (!ifp) { ! 812: kprintf("dlil_attach_protocol -- no such interface %d unit %d\n", ! 813: proto->interface_family, proto->unit_number); ! 814: splx(s); ! 815: return ENOENT; ! 816: } ! 817: ! 818: if (dlil_find_dltag(proto->interface_family, proto->unit_number, ! 819: proto->protocol_family, &i) == 0) ! 820: return EEXIST; ! 821: ! 822: for (i=1; i < MAX_DL_TAGS; i++) ! 823: if (dl_tag_array[i].ifp == 0) ! 824: break; ! 825: ! 826: if (i >= MAX_DL_TAGS) { ! 827: splx(s); ! 828: return EOVERFLOW; ! 829: } ! 830: ! 831: /* ! 832: * Allocate and init a new if_proto structure ! 833: */ ! 834: ! 835: ifproto = _MALLOC(sizeof(struct if_proto), M_IFADDR, M_NOWAIT); ! 836: if (!ifproto) { ! 837: printf("ERROR - DLIL failed if_proto allocation\n"); ! 838: return ENOMEM; ! 839: } ! 840: ! 841: bzero(ifproto, sizeof(struct if_proto)); ! 842: ! 843: dl_tag_array[i].ifp = ifp; ! 844: dl_tag_array[i].proto = ifproto; ! 845: dl_tag_array[i].pr_flt_head = &ifproto->pr_flt_head; ! 846: ifproto->dl_tag = i; ! 847: *dl_tag = i; ! 848: ! 849: if (proto->default_proto) { ! 850: if (ifp->if_data.default_proto == 0) ! 851: ifp->if_data.default_proto = i; ! 852: else ! 853: printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n"); ! 854: } ! 855: ! 856: ifproto->protocol_family = proto->protocol_family; ! 857: ifproto->dl_input = proto->input; ! 858: ifproto->dl_pre_output = proto->pre_output; ! 859: ifproto->dl_event = proto->event; ! 860: ifproto->dl_offer = proto->offer; ! 861: ifproto->dl_ioctl = proto->ioctl; ! 862: ifproto->ifp = ifp; ! 863: TAILQ_INIT(&ifproto->pr_flt_head); ! 864: ! 865: /* ! 866: * Call family module add_proto routine so it can refine the ! 867: * demux descriptors as it wishes. ! 868: */ ! 869: error = (*if_family->add_proto)(&proto->demux_desc_head, ifproto, *dl_tag); ! 870: if (error) { ! 871: dl_tag_array[*dl_tag].ifp = 0; ! 872: FREE(ifproto, M_IFADDR); ! 873: splx(s); ! 874: return error; ! 875: } ! 876: ! 877: ! 878: /* ! 879: * Add to if_proto list for this interface ! 880: */ ! 881: ! 882: tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 883: TAILQ_INSERT_TAIL(tmp, ifproto, next); ! 884: ifp->refcnt++; ! 885: if (ifproto->dl_offer) ! 886: ifp->offercnt++; ! 887: ! 888: splx(s); ! 889: return 0; ! 890: } ! 891: ! 892: ! 893: ! 894: int ! 895: dlil_detach_protocol(u_long dl_tag) ! 896: { ! 897: struct ifnet *ifp; ! 898: struct ifnet *orig_ifp=0; ! 899: struct if_proto *proto; ! 900: struct dlil_proto_head *tmp; ! 901: struct if_family_str *if_family; ! 902: struct dlil_filterq_entry *filter; ! 903: int s, retval; ! 904: struct dlil_filterq_head *fhead; ! 905: ! 906: ! 907: ! 908: if (dl_tag > MAX_DL_TAGS) ! 909: return ERANGE; ! 910: ! 911: s = splnet(); ! 912: if (dl_tag_array[dl_tag].ifp == 0) { ! 913: splx(s); ! 914: return ENOENT; ! 915: } ! 916: ! 917: ifp = dl_tag_array[dl_tag].ifp; ! 918: proto = dl_tag_array[dl_tag].proto; ! 919: ! 920: if_family = find_family_module(ifp->if_family); ! 921: if (if_family == NULL) ! 922: return ENOENT; ! 923: ! 924: tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 925: ! 926: /* ! 927: * Call family module del_proto ! 928: */ ! 929: ! 930: (*if_family->del_proto)(proto, dl_tag); ! 931: ! 932: ! 933: /* ! 934: * Remove and deallocate any attached protocol filters ! 935: */ ! 936: ! 937: while (filter = TAILQ_FIRST(&proto->pr_flt_head)) ! 938: dlil_detach_filter(filter->filter_id); ! 939: ! 940: if (proto->dl_offer) ! 941: ifp->offercnt--; ! 942: ! 943: dl_tag_array[dl_tag].ifp = 0; ! 944: ! 945: TAILQ_REMOVE(tmp, proto, next); ! 946: FREE(proto, M_IFADDR); ! 947: ! 948: if (--ifp->refcnt == 0) { ! 949: if (ifp->if_flags & IFF_UP) ! 950: printf("WARNING - dlil_detach_protocol - ifp refcnt 0, but IF still up\n"); ! 951: ! 952: TAILQ_REMOVE(&ifnet, ifp, if_link); ! 953: ! 954: if (if_family->del_if) ! 955: (*if_family->del_if)(ifp); ! 956: ! 957: ! 958: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 959: while (orig_ifp != ifp) { ! 960: orig_ifp = ifp; ! 961: ! 962: TAILQ_FOREACH(filter, fhead, que) { ! 963: if (IFILT(filter).filter_if_free) { ! 964: retval = (*IFILT(filter).filter_if_free)(IFILT(filter).cookie, ifp); ! 965: if (retval) { ! 966: splx(s); ! 967: return 0; ! 968: } ! 969: } ! 970: if (ifp != orig_ifp) ! 971: break; ! 972: } ! 973: } ! 974: ! 975: (*ifp->if_free)(ifp); ! 976: } ! 977: ! 978: splx(s); ! 979: return 0; ! 980: } ! 981: ! 982: ! 983: ! 984: ! 985: ! 986: int ! 987: dlil_if_attach(struct ifnet *ifp) ! 988: { ! 989: u_long interface_family = ifp->if_family; ! 990: struct if_family_str *if_family; ! 991: struct dlil_proto_head *tmp; ! 992: int stat; ! 993: int s; ! 994: ! 995: ! 996: ! 997: s = splnet(); ! 998: if (ifnet_inited == 0) { ! 999: TAILQ_INIT(&ifnet); ! 1000: ifnet_inited = 1; ! 1001: } ! 1002: ! 1003: if_family = find_family_module(interface_family); ! 1004: ! 1005: if ((!if_family) || (if_family->flags & DLIL_SHUTDOWN)) { ! 1006: splx(s); ! 1007: kprintf("Attempt to attach interface without family module - %d\n", ! 1008: interface_family); ! 1009: return ENODEV; ! 1010: } ! 1011: ! 1012: ! 1013: /* ! 1014: * Call the family module to fill in the appropriate fields in the ! 1015: * ifnet structure. ! 1016: */ ! 1017: ! 1018: stat = (*if_family->add_if)(ifp); ! 1019: if (stat) { ! 1020: splx(s); ! 1021: kprintf("dlil_if_attach -- add_if failed with %d\n", stat); ! 1022: return stat; ! 1023: } ! 1024: ! 1025: /* ! 1026: * Add the ifp to the interface list. ! 1027: */ ! 1028: ! 1029: tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 1030: TAILQ_INIT(tmp); ! 1031: ! 1032: ifp->if_data.default_proto = 0; ! 1033: ifp->refcnt = 1; ! 1034: ifp->offercnt = 0; ! 1035: TAILQ_INIT(&ifp->if_flt_head); ! 1036: old_if_attach(ifp); ! 1037: if_family->refcnt++; ! 1038: ! 1039: splx(s); ! 1040: return 0; ! 1041: } ! 1042: ! 1043: ! 1044: int ! 1045: dlil_if_detach(struct ifnet *ifp) ! 1046: { ! 1047: struct if_proto *proto; ! 1048: struct dlil_filterq_entry *if_filter; ! 1049: struct if_family_str *if_family; ! 1050: struct dlil_filterq_head *fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 1051: int s; ! 1052: ! 1053: s = splnet(); ! 1054: if (ifp->if_flags & IFF_UP) ! 1055: printf("WARNING - dlil_if_detach called for UP interface\n"); ! 1056: ! 1057: if_family = (struct if_family_str *) ifp->if_family; ! 1058: ! 1059: if (!if_family) { ! 1060: kprintf("Attempt to detach interface without family module - %s\n", ! 1061: ifp->if_name); ! 1062: splx(s); ! 1063: return ENODEV; ! 1064: } ! 1065: ! 1066: while (if_filter = TAILQ_FIRST(fhead)) ! 1067: dlil_detach_filter(if_filter->filter_id); ! 1068: ! 1069: if (--ifp->refcnt == 0) { ! 1070: TAILQ_REMOVE(&ifnet, ifp, if_link); ! 1071: ! 1072: if (if_family->del_if) ! 1073: (*if_family->del_if)(ifp); ! 1074: ! 1075: if (--if_family->refcnt == 0) { ! 1076: if (if_family->shutdown) ! 1077: (*if_family->shutdown)(); ! 1078: ! 1079: TAILQ_REMOVE(&if_family_head, if_family, if_fam_next); ! 1080: FREE(if_family, M_IFADDR); ! 1081: } ! 1082: splx(s); ! 1083: return 0; ! 1084: } ! 1085: else ! 1086: { ! 1087: splx(s); ! 1088: return DLIL_WAIT_FOR_FREE; ! 1089: } ! 1090: } ! 1091: ! 1092: ! 1093: int ! 1094: dlil_reg_if_modules(u_long interface_family, ! 1095: int (*add_if)(struct ifnet *ifp), ! 1096: int (*del_if)(struct ifnet *ifp), ! 1097: int (*add_proto)(struct ddesc_head_str *head, ! 1098: struct if_proto *proto, u_long dl_tag), ! 1099: int (*del_proto)(struct if_proto *proto, u_long dl_tag), ! 1100: int (*shutdown)()) ! 1101: { ! 1102: struct if_family_str *if_family; ! 1103: int s; ! 1104: ! 1105: ! 1106: s = splnet(); ! 1107: if (find_family_module(interface_family)) { ! 1108: kprintf("Attempt to register dlil family module more than once - %d\n", ! 1109: interface_family); ! 1110: splx(s); ! 1111: return EEXIST; ! 1112: } ! 1113: ! 1114: if ((!add_if) || (!del_if) || ! 1115: (!add_proto) || (!del_proto)) { ! 1116: kprintf("dlil_reg_if_modules passed at least one null pointer\n"); ! 1117: splx(s); ! 1118: return EINVAL; ! 1119: } ! 1120: ! 1121: if_family = (struct if_family_str *) _MALLOC(sizeof(struct if_family_str), M_IFADDR, M_NOWAIT); ! 1122: if (!if_family) { ! 1123: kprintf("dlil_reg_if_modules failed allocation\n"); ! 1124: splx(s); ! 1125: return ENOMEM; ! 1126: } ! 1127: ! 1128: bzero(if_family, sizeof(struct if_family_str)); ! 1129: ! 1130: if_family->if_family = interface_family; ! 1131: if_family->shutdown = shutdown; ! 1132: if_family->add_if = add_if; ! 1133: if_family->del_if = del_if; ! 1134: if_family->add_proto = add_proto; ! 1135: if_family->del_proto = del_proto; ! 1136: if_family->refcnt = 1; ! 1137: if_family->flags = 0; ! 1138: ! 1139: TAILQ_INSERT_TAIL(&if_family_head, if_family, if_fam_next); ! 1140: splx(s); ! 1141: return 0; ! 1142: } ! 1143: ! 1144: int dlil_dereg_if_modules(u_long interface_family) ! 1145: { ! 1146: struct if_family_str *if_family; ! 1147: int s; ! 1148: ! 1149: ! 1150: s = splnet(); ! 1151: if_family = find_family_module(interface_family); ! 1152: if (if_family == 0) { ! 1153: splx(s); ! 1154: return ENOENT; ! 1155: } ! 1156: ! 1157: if (--if_family->refcnt) { ! 1158: if (if_family->shutdown) ! 1159: (*if_family->shutdown)(); ! 1160: ! 1161: TAILQ_REMOVE(&if_family_head, if_family, if_fam_next); ! 1162: FREE(if_family, M_IFADDR); ! 1163: } ! 1164: else ! 1165: if_family->flags |= DLIL_SHUTDOWN; ! 1166: ! 1167: splx(s); ! 1168: return 0; ! 1169: } ! 1170: ! 1171: ! 1172: ! 1173: ! 1174: ! 1175: /* ! 1176: * Old if_attach no-op'ed function defined here for temporary backwards compatibility ! 1177: */ ! 1178: ! 1179: void if_attach(ifp) ! 1180: struct ifnet *ifp; ! 1181: { ! 1182: dlil_if_attach(ifp); ! 1183: } ! 1184: ! 1185: ! 1186: ! 1187: int ! 1188: dlil_inject_if_input(struct mbuf *m, char *frame_header, u_long from_id) ! 1189: { ! 1190: struct ifnet *orig_ifp = 0; ! 1191: struct ifnet *ifp; ! 1192: struct if_proto *ifproto; ! 1193: struct if_proto *proto; ! 1194: struct dlil_filterq_entry *tmp; ! 1195: int retval = 0; ! 1196: struct dlil_filterq_head *fhead; ! 1197: int match_found; ! 1198: ! 1199: ! 1200: dlil_stats.inject_if_in1++; ! 1201: if (from_id > MAX_DLIL_FILTERS) ! 1202: return ERANGE; ! 1203: ! 1204: if (dlil_filters[from_id].type != DLIL_IF_FILTER) ! 1205: return ENOENT; ! 1206: ! 1207: ifp = dlil_filters[from_id].ifp; ! 1208: ! 1209: /* ! 1210: * Let interface filters (if any) do their thing ... ! 1211: */ ! 1212: ! 1213: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 1214: if (from_id == DLIL_NULL_FILTER) ! 1215: match_found = 1; ! 1216: else ! 1217: match_found = 0; ! 1218: ! 1219: if (TAILQ_EMPTY(fhead) == 0) { ! 1220: while (orig_ifp != ifp) { ! 1221: orig_ifp = ifp; ! 1222: TAILQ_FOREACH_REVERSE(tmp, fhead, que, dlil_filterq_head) { ! 1223: if ((match_found) && (IFILT(tmp).filter_if_input)) { ! 1224: retval = (*IFILT(tmp).filter_if_input)(IFILT(tmp).cookie, ! 1225: &ifp, ! 1226: &m, ! 1227: &frame_header); ! 1228: if (retval) { ! 1229: if (retval == EJUSTRETURN) ! 1230: return 0; ! 1231: else { ! 1232: m_freem(m); ! 1233: return retval; ! 1234: } ! 1235: } ! 1236: ! 1237: } ! 1238: ! 1239: if (ifp != orig_ifp) ! 1240: break; ! 1241: ! 1242: if (from_id == tmp->filter_id) ! 1243: match_found = 1; ! 1244: } ! 1245: } ! 1246: } ! 1247: ! 1248: ifp->if_lastchange = time; ! 1249: ! 1250: /* ! 1251: * Call family demux module. If the demux module finds a match ! 1252: * for the frame it will fill-in the ifproto pointer. ! 1253: */ ! 1254: ! 1255: retval = (*ifp->if_demux)(ifp, m, frame_header, &ifproto ); ! 1256: ! 1257: if (m->m_flags & (M_BCAST|M_MCAST)) ! 1258: ifp->if_imcasts++; ! 1259: ! 1260: if ((retval) && (ifp->offercnt)) { ! 1261: /* ! 1262: * No match was found, look for any offers. ! 1263: */ ! 1264: struct dlil_proto_head *tmp = (struct dlil_proto_head *) &ifp->proto_head; ! 1265: TAILQ_FOREACH(proto, tmp, next) { ! 1266: if ((proto->dl_offer) && (proto->dl_offer(m, frame_header) == 0)) { ! 1267: ifproto = proto; ! 1268: retval = 0; ! 1269: break; ! 1270: } ! 1271: } ! 1272: } ! 1273: ! 1274: if (retval) { ! 1275: if (retval != EJUSTRETURN) { ! 1276: m_freem(m); ! 1277: return retval; ! 1278: } ! 1279: else ! 1280: return 0; ! 1281: } ! 1282: else ! 1283: if (ifproto == 0) { ! 1284: printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n"); ! 1285: m_freem(m); ! 1286: return 0; ! 1287: } ! 1288: ! 1289: /* ! 1290: * Call any attached protocol filters. ! 1291: */ ! 1292: TAILQ_FOREACH_REVERSE(tmp, &ifproto->pr_flt_head, que, dlil_filterq_head) { ! 1293: if (PFILT(tmp).filter_dl_input) { ! 1294: retval = (*PFILT(tmp).filter_dl_input)(PFILT(tmp).cookie, ! 1295: &m, ! 1296: &frame_header, ! 1297: &ifp); ! 1298: ! 1299: if (retval) { ! 1300: if (retval == EJUSTRETURN) ! 1301: return 0; ! 1302: else { ! 1303: m_freem(m); ! 1304: return retval; ! 1305: } ! 1306: } ! 1307: } ! 1308: } ! 1309: ! 1310: ! 1311: ! 1312: retval = (*ifproto->dl_input)(m, frame_header, ! 1313: ifp, ifproto->dl_tag, ! 1314: (ifp->if_eflags & IFEF_DVR_REENTRY_OK)); ! 1315: ! 1316: dlil_stats.inject_if_in2++; ! 1317: if (retval == EJUSTRETURN) ! 1318: retval = 0; ! 1319: else ! 1320: if (retval) ! 1321: m_freem(m); ! 1322: ! 1323: return retval; ! 1324: ! 1325: } ! 1326: ! 1327: ! 1328: ! 1329: ! 1330: ! 1331: int ! 1332: dlil_inject_pr_input(struct mbuf *m, char *frame_header, u_long from_id) ! 1333: { ! 1334: struct ifnet *orig_ifp = 0; ! 1335: struct dlil_filterq_entry *tmp; ! 1336: int retval; ! 1337: struct if_proto *ifproto = 0; ! 1338: int match_found; ! 1339: struct ifnet *ifp; ! 1340: ! 1341: ! 1342: dlil_stats.inject_pr_in1++; ! 1343: if (from_id > MAX_DLIL_FILTERS) ! 1344: return ERANGE; ! 1345: ! 1346: if (dlil_filters[from_id].type != DLIL_PR_FILTER) ! 1347: return ENOENT; ! 1348: ! 1349: ifproto = dlil_filters[from_id].proto; ! 1350: ifp = dlil_filters[from_id].ifp; ! 1351: ! 1352: ! 1353: /* ! 1354: * Call any attached protocol filters. ! 1355: */ ! 1356: ! 1357: if (from_id == DLIL_NULL_FILTER) ! 1358: match_found = 1; ! 1359: else ! 1360: match_found = 0; ! 1361: TAILQ_FOREACH_REVERSE(tmp, &ifproto->pr_flt_head, que, dlil_filterq_head) { ! 1362: if ((match_found) && (PFILT(tmp).filter_dl_input)) { ! 1363: retval = (*PFILT(tmp).filter_dl_input)(PFILT(tmp).cookie, ! 1364: &m, ! 1365: &frame_header, ! 1366: &ifp); ! 1367: ! 1368: if (retval) { ! 1369: if (retval == EJUSTRETURN) ! 1370: return 0; ! 1371: else { ! 1372: m_freem(m); ! 1373: return retval; ! 1374: } ! 1375: } ! 1376: } ! 1377: ! 1378: if (tmp->filter_id == from_id) ! 1379: match_found = 1; ! 1380: } ! 1381: ! 1382: ! 1383: retval = (*ifproto->dl_input)(m, frame_header, ! 1384: ifp, ifproto->dl_tag, ! 1385: (ifp->if_eflags & IFEF_DVR_REENTRY_OK)); ! 1386: ! 1387: if (retval == EJUSTRETURN) ! 1388: retval = 0; ! 1389: else ! 1390: if (retval) ! 1391: m_freem(m); ! 1392: ! 1393: dlil_stats.inject_pr_in2++; ! 1394: return retval; ! 1395: } ! 1396: ! 1397: ! 1398: ! 1399: int ! 1400: dlil_inject_pr_output(struct mbuf *m, ! 1401: struct sockaddr *dest, ! 1402: int raw, ! 1403: char *frame_type, ! 1404: char *dst_linkaddr, ! 1405: u_long from_id) ! 1406: { ! 1407: struct ifnet *orig_ifp = 0; ! 1408: struct ifnet *ifp; ! 1409: struct dlil_filterq_entry *tmp; ! 1410: int retval = 0; ! 1411: char frame_type_buffer[MAX_FRAME_TYPE_SIZE * 4]; ! 1412: char dst_linkaddr_buffer[MAX_LINKADDR * 4]; ! 1413: struct dlil_filterq_head *fhead; ! 1414: int match_found; ! 1415: u_long dl_tag; ! 1416: ! 1417: ! 1418: dlil_stats.inject_pr_out1++; ! 1419: if (raw == 0) { ! 1420: if (frame_type) ! 1421: bcopy(frame_type, &frame_type_buffer[0], MAX_FRAME_TYPE_SIZE * 4); ! 1422: else ! 1423: return EINVAL; ! 1424: ! 1425: if (dst_linkaddr) ! 1426: bcopy(dst_linkaddr, &dst_linkaddr_buffer, MAX_LINKADDR * 4); ! 1427: else ! 1428: return EINVAL; ! 1429: } ! 1430: ! 1431: if (from_id > MAX_DLIL_FILTERS) ! 1432: return ERANGE; ! 1433: ! 1434: if (dlil_filters[from_id].type != DLIL_PR_FILTER) ! 1435: return ENOENT; ! 1436: ! 1437: ifp = dlil_filters[from_id].ifp; ! 1438: dl_tag = dlil_filters[from_id].proto->dl_tag; ! 1439: ! 1440: ! 1441: frame_type = frame_type_buffer; ! 1442: dst_linkaddr = dst_linkaddr_buffer; ! 1443: ! 1444: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 1445: ! 1446: /* ! 1447: * Run any attached protocol filters. ! 1448: */ ! 1449: if (from_id == DLIL_NULL_FILTER) ! 1450: match_found = 1; ! 1451: else ! 1452: match_found = 0; ! 1453: ! 1454: if (TAILQ_EMPTY(dl_tag_array[dl_tag].pr_flt_head) == 0) { ! 1455: TAILQ_FOREACH(tmp, dl_tag_array[dl_tag].pr_flt_head, que) { ! 1456: if ((match_found) && (PFILT(tmp).filter_dl_output)) { ! 1457: retval = (*PFILT(tmp).filter_dl_output)(PFILT(tmp).cookie, ! 1458: &m, &ifp, &dest, dst_linkaddr, frame_type); ! 1459: if (retval) { ! 1460: if (retval == EJUSTRETURN) ! 1461: return 0; ! 1462: else { ! 1463: m_freem(m); ! 1464: return retval; ! 1465: } ! 1466: } ! 1467: } ! 1468: ! 1469: if (tmp->filter_id == from_id) ! 1470: match_found = 1; ! 1471: } ! 1472: } ! 1473: ! 1474: ! 1475: /* ! 1476: * Call framing module ! 1477: */ ! 1478: if ((raw == 0) && (ifp->if_framer)) { ! 1479: retval = (*ifp->if_framer)(ifp, &m, dest, dst_linkaddr, frame_type); ! 1480: if (retval) { ! 1481: if (retval == EJUSTRETURN) ! 1482: return 0; ! 1483: else ! 1484: { ! 1485: m_freem(m); ! 1486: return retval; ! 1487: } ! 1488: } ! 1489: } ! 1490: ! 1491: ! 1492: #if BRIDGE ! 1493: if (do_bridge) { ! 1494: struct mbuf *m0 = m ; ! 1495: ! 1496: if (m->m_pkthdr.rcvif) ! 1497: m->m_pkthdr.rcvif = NULL ; ! 1498: ifp = bridge_dst_lookup(m); ! 1499: bdg_forward(&m0, ifp); ! 1500: if (m0) ! 1501: m_freem(m0); ! 1502: ! 1503: return 0; ! 1504: } ! 1505: #endif ! 1506: ! 1507: ! 1508: /* ! 1509: * Let interface filters (if any) do their thing ... ! 1510: */ ! 1511: ! 1512: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 1513: if (TAILQ_EMPTY(fhead) == 0) { ! 1514: while (orig_ifp != ifp) { ! 1515: orig_ifp = ifp; ! 1516: TAILQ_FOREACH(tmp, fhead, que) { ! 1517: if (IFILT(tmp).filter_if_output) { ! 1518: retval = (*IFILT(tmp).filter_if_output)(IFILT(tmp).cookie, ! 1519: &ifp, ! 1520: &m); ! 1521: if (retval) { ! 1522: if (retval == EJUSTRETURN) ! 1523: return 0; ! 1524: else { ! 1525: m_freem(m); ! 1526: return retval; ! 1527: } ! 1528: } ! 1529: ! 1530: } ! 1531: ! 1532: if (ifp != orig_ifp) ! 1533: break; ! 1534: } ! 1535: } ! 1536: } ! 1537: ! 1538: /* ! 1539: * Finally, call the driver. ! 1540: */ ! 1541: /* ! 1542: * Temporary, until all drivers do this. ! 1543: */ ! 1544: ! 1545: ifp->if_obytes += m->m_pkthdr.len; ! 1546: ! 1547: retval = (*ifp->if_output)(ifp, m); ! 1548: dlil_stats.inject_pr_out2++; ! 1549: if ((retval == 0) || (retval == EJUSTRETURN)) ! 1550: return 0; ! 1551: else ! 1552: return retval; ! 1553: } ! 1554: ! 1555: ! 1556: int ! 1557: dlil_inject_if_output(struct mbuf *m, u_long from_id) ! 1558: { ! 1559: struct ifnet *orig_ifp = 0; ! 1560: struct ifnet *ifp; ! 1561: struct dlil_filterq_entry *tmp; ! 1562: int retval = 0; ! 1563: struct dlil_filterq_head *fhead; ! 1564: int match_found; ! 1565: ! 1566: ! 1567: dlil_stats.inject_if_out1++; ! 1568: if (from_id > MAX_DLIL_FILTERS) ! 1569: return ERANGE; ! 1570: ! 1571: if (dlil_filters[from_id].type != DLIL_IF_FILTER) ! 1572: return ENOENT; ! 1573: ! 1574: ifp = dlil_filters[from_id].ifp; ! 1575: ! 1576: /* ! 1577: * Let interface filters (if any) do their thing ... ! 1578: */ ! 1579: ! 1580: fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; ! 1581: ! 1582: if (from_id == DLIL_NULL_FILTER) ! 1583: match_found = 1; ! 1584: else ! 1585: match_found = 0; ! 1586: ! 1587: if (TAILQ_EMPTY(fhead) == 0) { ! 1588: while (orig_ifp != ifp) { ! 1589: orig_ifp = ifp; ! 1590: TAILQ_FOREACH(tmp, fhead, que) { ! 1591: if ((match_found) && (IFILT(tmp).filter_if_output)) { ! 1592: retval = (*IFILT(tmp).filter_if_output)(IFILT(tmp).cookie, ! 1593: &ifp, ! 1594: &m); ! 1595: if (retval) { ! 1596: if (retval == EJUSTRETURN) ! 1597: return 0; ! 1598: else { ! 1599: m_freem(m); ! 1600: return retval; ! 1601: } ! 1602: } ! 1603: ! 1604: } ! 1605: ! 1606: if (ifp != orig_ifp) ! 1607: break; ! 1608: ! 1609: if (from_id == tmp->filter_id) ! 1610: match_found = 1; ! 1611: } ! 1612: } ! 1613: } ! 1614: ! 1615: /* ! 1616: * Finally, call the driver. ! 1617: */ ! 1618: /* ! 1619: * Temporary, until all drivers do this. ! 1620: */ ! 1621: ! 1622: ifp->if_obytes += m->m_pkthdr.len; ! 1623: ! 1624: retval = (*ifp->if_output)(ifp, m); ! 1625: dlil_stats.inject_if_out2++; ! 1626: if ((retval == 0) || (retval == EJUSTRETURN)) ! 1627: return 0; ! 1628: else ! 1629: return retval; ! 1630: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.