Annotation of XNU/bsd/net/dlil.c, revision 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.