Annotation of XNU/bsd/net/dlil.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.