OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [net/] [if_bridge.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      sys/net/if_bridge.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    Jason L. Wright (jason@thought.net)  
22
// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
23
// Date:         2000-07-18
24
// Purpose:      Ethernet bridge
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
/*      $OpenBSD: if_bridge.c,v 1.33 2000/06/20 05:50:16 jason Exp $    */
32
 
33
/*
34
 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
35
 * All rights reserved.
36
 *
37
 * Redistribution and use in source and binary forms, with or without
38
 * modification, are permitted provided that the following conditions
39
 * are met:
40
 * 1. Redistributions of source code must retain the above copyright
41
 *    notice, this list of conditions and the following disclaimer.
42
 * 2. Redistributions in binary form must reproduce the above copyright
43
 *    notice, this list of conditions and the following disclaimer in the
44
 *    documentation and/or other materials provided with the distribution.
45
 * 3. All advertising materials mentioning features or use of this software
46
 *    must display the following acknowledgement:
47
 *      This product includes software developed by Jason L. Wright
48
 * 4. The name of the author may not be used to endorse or promote products
49
 *    derived from this software without specific prior written permission.
50
 *
51
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
55
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
57
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
60
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61
 * POSSIBILITY OF SUCH DAMAGE.
62
 */
63
 
64
#ifdef __ECOS
65
#include <pkgconf/net.h>
66
#else
67
#include "bridge.h"
68
#include "bpfilter.h"
69
#include "enc.h"
70
#endif
71
 
72
#include <sys/param.h>
73
#ifndef __ECOS
74
#include <sys/proc.h>
75
#include <sys/systm.h>
76
#endif
77
#include <sys/mbuf.h>
78
#include <sys/socket.h>
79
#include <sys/ioctl.h>
80
#include <sys/errno.h>
81
#ifndef __ECOS
82
#include <sys/device.h>
83
#endif
84
#include <sys/kernel.h>
85
#include <machine/cpu.h>
86
 
87
#include <net/if.h>
88
#include <net/if_types.h>
89
#include <net/if_llc.h>
90
#include <net/route.h>
91
#include <net/netisr.h>
92
 
93
#ifdef INET
94
#include <netinet/in.h>
95
#include <netinet/in_systm.h>
96
#include <netinet/in_var.h>
97
#include <netinet/ip.h>
98
#include <netinet/if_ether.h>
99
#include <netinet/ip_ipsp.h>
100
 
101
#ifndef __ECOS
102
#include <net/if_enc.h>
103
#endif
104
#ifdef IPFILTER
105
#include <netinet/ip_fil_compat.h>
106
#include <netinet/ip_fil.h>
107
#endif
108
#endif
109
 
110
#if NBPFILTER > 0
111
#include <net/bpf.h>
112
#endif
113
 
114
#include <net/if_bridge.h>
115
 
116
#ifdef __ECOS
117
#include <stdio.h> /* for sprintf */
118
#endif 
119
 
120
#ifndef BRIDGE_RTABLE_SIZE
121
#define BRIDGE_RTABLE_SIZE      1024
122
#endif
123
#define BRIDGE_RTABLE_MASK      (BRIDGE_RTABLE_SIZE - 1)
124
 
125
/*
126
 * Maximum number of addresses to cache
127
 */
128
#ifndef BRIDGE_RTABLE_MAX
129
#define BRIDGE_RTABLE_MAX       100
130
#endif
131
 
132
/*
133
 * Timeout (in seconds) for entries learned dynamically
134
 */
135
#ifndef BRIDGE_RTABLE_TIMEOUT
136
#define BRIDGE_RTABLE_TIMEOUT   300
137
#endif
138
 
139
extern int ifqmaxlen;
140
 
141
/*
142
 * Bridge filtering rules
143
 */
144
struct brl_node {
145
        SIMPLEQ_ENTRY(brl_node) brl_next;       /* next rule */
146
        struct ether_addr       brl_src;        /* source mac address */
147
        struct ether_addr       brl_dst;        /* destination mac address */
148
        u_int8_t                brl_action;     /* what to do with match */
149
        u_int8_t                brl_flags;      /* comparision flags */
150
};
151
 
152
/*
153
 * Bridge interface list
154
 */
155
struct bridge_iflist {
156
        LIST_ENTRY(bridge_iflist)       next;           /* next in list */
157
        SIMPLEQ_HEAD(, brl_node)        bif_brlin;      /* input rules */
158
        SIMPLEQ_HEAD(, brl_node)        bif_brlout;     /* output rules */
159
        struct                          ifnet *ifp;     /* member interface */
160
        u_int32_t                       bif_flags;      /* member flags */
161
};
162
 
163
/*
164
 * Bridge route node
165
 */
166
struct bridge_rtnode {
167
        LIST_ENTRY(bridge_rtnode)       brt_next;       /* next in list */
168
        struct                          ifnet *brt_if;  /* destination ifs */
169
        u_int8_t                        brt_flags;      /* address flags */
170
        u_int8_t                        brt_age;        /* age counter */
171
        struct                          ether_addr brt_addr;    /* dst addr */
172
};
173
 
174
/*
175
 * Software state for each bridge
176
 */
177
struct bridge_softc {
178
        struct                          ifnet sc_if;    /* the interface */
179
        u_int32_t                       sc_brtmax;      /* max # addresses */
180
        u_int32_t                       sc_brtcnt;      /* current # addrs */
181
        u_int32_t                       sc_brttimeout;  /* timeout ticks */
182
        LIST_HEAD(, bridge_iflist)      sc_iflist;      /* interface list */
183
        LIST_HEAD(bridge_rthead, bridge_rtnode) *sc_rts;/* hash table */
184
};
185
 
186
/* SNAP LLC header */
187
struct snap {
188
        u_int8_t dsap;
189
        u_int8_t ssap;
190
        u_int8_t control;
191
        u_int8_t org[3];
192
        u_int16_t type;
193
};
194
 
195
struct bridge_softc bridgectl[CYGNUM_NET_BRIDGES];
196
 
197
void    bridgeattach __P((int));
198
int     bridge_ioctl __P((struct ifnet *, u_long, caddr_t));
199
void    bridge_start __P((struct ifnet *));
200
void    bridgeintr_frame __P((struct bridge_softc *, struct mbuf *));
201
void    bridge_broadcast __P((struct bridge_softc *, struct ifnet *,
202
    struct ether_header *, struct mbuf *)) __attribute ((weak));
203
void    bridge_stop __P((struct bridge_softc *));
204
void    bridge_init __P((struct bridge_softc *));
205
int     bridge_bifconf __P((struct bridge_softc *, struct ifbifconf *));
206
 
207
int     bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *));
208
void    bridge_rtage __P((void *));
209
void    bridge_rttrim __P((struct bridge_softc *));
210
void    bridge_rtdelete __P((struct bridge_softc *, struct ifnet *));
211
int     bridge_rtdaddr __P((struct bridge_softc *, struct ether_addr *));
212
int     bridge_rtflush __P((struct bridge_softc *, int));
213
struct ifnet *  bridge_rtupdate __P((struct bridge_softc *,
214
    struct ether_addr *, struct ifnet *ifp, int, u_int8_t));
215
struct ifnet *  bridge_rtlookup __P((struct bridge_softc *,
216
    struct ether_addr *));
217
u_int32_t       bridge_hash __P((struct ether_addr *));
218
int bridge_blocknonip __P((struct ether_header *, struct mbuf *));
219
int             bridge_addrule __P((struct bridge_iflist *,
220
    struct ifbrlreq *, int out));
221
int             bridge_flushrule __P((struct bridge_iflist *));
222
int     bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *));
223
u_int8_t bridge_filterrule __P((struct brl_node *, struct ether_header *));
224
 
225
#define ETHERADDR_IS_IP_MCAST(a) \
226
        /* struct etheraddr *a; */                              \
227
        ((a)->ether_addr_octet[0] == 0x01 &&                     \
228
         (a)->ether_addr_octet[1] == 0x00 &&                    \
229
         (a)->ether_addr_octet[2] == 0x5e)
230
 
231
 
232
#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
233
/*
234
 * Filter hooks
235
 */
236
struct mbuf *bridge_filter __P((struct bridge_softc *, struct ifnet *,
237
    struct ether_header *, struct mbuf *m));
238
#endif
239
 
240
void
241
bridgeattach(unused)
242
        int unused;
243
{
244
        int i;
245
        struct ifnet *ifp;
246
 
247
        for (i = 0; i < CYGNUM_NET_BRIDGES; i++) {
248
                bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX;
249
                bridgectl[i].sc_brttimeout = (BRIDGE_RTABLE_TIMEOUT * hz) / 2;
250
                LIST_INIT(&bridgectl[i].sc_iflist);
251
                ifp = &bridgectl[i].sc_if;
252
                sprintf(ifp->if_xname, "bridge%d", i);
253
                ifp->if_softc = &bridgectl[i];
254
                ifp->if_mtu = ETHERMTU;
255
                ifp->if_ioctl = bridge_ioctl;
256
                ifp->if_output = bridge_output;
257
                ifp->if_start = bridge_start;
258
                ifp->if_type = IFT_PROPVIRTUAL;
259
                ifp->if_snd.ifq_maxlen = ifqmaxlen;
260
                ifp->if_hdrlen = sizeof(struct ether_header);
261
                if_attach(ifp);
262
#if NBPFILTER > 0
263
                bpfattach(&bridgectl[i].sc_if.if_bpf, ifp,
264
                    DLT_EN10MB, sizeof(struct ether_header));
265
#endif
266
        }
267
}
268
 
269
int
270
bridge_ioctl(ifp, cmd, data)
271
        struct ifnet *ifp;
272
        u_long cmd;
273
        caddr_t data;
274
{
275
#ifndef __ECOS
276
        struct proc *prc = curproc;             /* XXX */
277
#endif
278
        struct ifnet *ifs;
279
        struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
280
        struct ifbreq *req = (struct ifbreq *)data;
281
        struct ifbaconf *baconf = (struct ifbaconf *)data;
282
        struct ifbareq *bareq = (struct ifbareq *)data;
283
        struct ifbcachereq *bcachereq = (struct ifbcachereq *)data;
284
        struct ifbifconf *bifconf = (struct ifbifconf *)data;
285
        struct ifbcachetoreq *bcacheto = (struct ifbcachetoreq *)data;
286
        struct ifbrlreq *brlreq = (struct ifbrlreq *)data;
287
        struct ifbrlconf *brlconf = (struct ifbrlconf *)data;
288
        struct ifreq ifreq;
289
        int error = 0, s;
290
        struct bridge_iflist *p;
291
 
292
        s = splimp();
293
        switch (cmd) {
294
        case SIOCBRDGADD:
295
#ifndef __ECOS
296
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
297
                        break;
298
#endif
299
                ifs = ifunit(req->ifbr_ifsname);
300
                if (ifs == NULL) {                      /* no such interface */
301
                        error = ENOENT;
302
                        break;
303
                }
304
                if (ifs->if_bridge == (caddr_t)sc) {
305
                        error = EEXIST;
306
                        break;
307
                }
308
                if (ifs->if_bridge != NULL) {
309
                        error = EBUSY;
310
                        break;
311
                }
312
 
313
                if (ifs->if_type == IFT_ETHER) {
314
                        if ((ifs->if_flags & IFF_UP) == 0) {
315
                                /*
316
                                 * Bring interface up long enough to set
317
                                 * promiscuous flag, then shut it down again.
318
                                 */
319
                                strncpy(ifreq.ifr_name, req->ifbr_ifsname,
320
                                    sizeof(ifreq.ifr_name) - 1);
321
                                ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0';
322
                                ifs->if_flags |= IFF_UP;
323
                                ifreq.ifr_flags = ifs->if_flags;
324
                                error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
325
                                    (caddr_t)&ifreq);
326
                                if (error != 0)
327
                                        break;
328
 
329
                                error = ifpromisc(ifs, 1);
330
                                if (error != 0)
331
                                        break;
332
 
333
                                strncpy(ifreq.ifr_name, req->ifbr_ifsname,
334
                                    sizeof(ifreq.ifr_name) - 1);
335
                                ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0';
336
                                ifs->if_flags &= ~IFF_UP;
337
                                ifreq.ifr_flags = ifs->if_flags;
338
                                error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
339
                                    (caddr_t)&ifreq);
340
                                if (error != 0) {
341
                                        ifpromisc(ifs, 0);
342
                                        break;
343
                                }
344
                        } else {
345
                                error = ifpromisc(ifs, 1);
346
                                if (error != 0)
347
                                        break;
348
                        }
349
                }
350
#ifndef __ECOS
351
#if NENC > 0
352
                else if (ifs->if_type == IFT_ENC) {
353
                        /* Can't bind enc0 to a bridge */
354
                        if (ifs->if_softc == &encif[0]) {
355
                                error = EINVAL;
356
                                break;
357
                        }
358
                }
359
#endif /* NENC */
360
#endif
361
                else {
362
                        error = EINVAL;
363
                        break;
364
                }
365
 
366
                p = (struct bridge_iflist *) malloc(
367
                    sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT);
368
                if (p == NULL && ifs->if_type == IFT_ETHER) {
369
                        error = ENOMEM;
370
                        ifpromisc(ifs, 0);
371
                        break;
372
                }
373
 
374
                p->ifp = ifs;
375
                p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
376
                SIMPLEQ_INIT(&p->bif_brlin);
377
                SIMPLEQ_INIT(&p->bif_brlout);
378
                LIST_INSERT_HEAD(&sc->sc_iflist, p, next);
379
                ifs->if_bridge = (caddr_t)sc;
380
                break;
381
        case SIOCBRDGDEL:
382
#ifndef __ECOS
383
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
384
                        break;
385
#endif
386
                p = LIST_FIRST(&sc->sc_iflist);
387
                while (p != NULL) {
388
                        if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
389
                            sizeof(p->ifp->if_xname)) == 0) {
390
                                p->ifp->if_bridge = NULL;
391
 
392
                                error = ifpromisc(p->ifp, 0);
393
 
394
                                LIST_REMOVE(p, next);
395
                                bridge_rtdelete(sc, p->ifp);
396
                                bridge_flushrule(p);
397
                                free(p, M_DEVBUF);
398
                                break;
399
                        }
400
                        p = LIST_NEXT(p, next);
401
                }
402
                if (p == NULL) {
403
                        error = ENOENT;
404
                        break;
405
                }
406
                break;
407
        case SIOCBRDGIFS:
408
                error = bridge_bifconf(sc, bifconf);
409
                break;
410
        case SIOCBRDGGIFFLGS:
411
                ifs = ifunit(req->ifbr_ifsname);
412
                if (ifs == NULL) {
413
                        error = ENOENT;
414
                        break;
415
                }
416
                if ((caddr_t)sc != ifs->if_bridge) {
417
                        error = ESRCH;
418
                        break;
419
                }
420
                p = LIST_FIRST(&sc->sc_iflist);
421
                while (p != NULL && p->ifp != ifs) {
422
                        p = LIST_NEXT(p, next);
423
                }
424
                if (p == NULL) {
425
                        error = ESRCH;
426
                        break;
427
                }
428
                req->ifbr_ifsflags = p->bif_flags;
429
                break;
430
        case SIOCBRDGSIFFLGS:
431
#ifndef __ECOS
432
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
433
                        break;
434
#endif
435
                ifs = ifunit(req->ifbr_ifsname);
436
                if (ifs == NULL) {
437
                        error = ENOENT;
438
                        break;
439
                }
440
                if ((caddr_t)sc != ifs->if_bridge) {
441
                        error = ESRCH;
442
                        break;
443
                }
444
                p = LIST_FIRST(&sc->sc_iflist);
445
                while (p != NULL && p->ifp != ifs) {
446
                        p = LIST_NEXT(p, next);
447
                }
448
                if (p == NULL) {
449
                        error = ESRCH;
450
                        break;
451
                }
452
                p->bif_flags = req->ifbr_ifsflags;
453
                break;
454
        case SIOCBRDGRTS:
455
                error = bridge_rtfind(sc, baconf);
456
                break;
457
        case SIOCBRDGFLUSH:
458
#ifndef __ECOS
459
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
460
                        break;
461
#endif
462
                error = bridge_rtflush(sc, req->ifbr_ifsflags);
463
                break;
464
        case SIOCBRDGSADDR:
465
#ifndef __ECOS
466
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
467
                        break;
468
#endif
469
                ifs = ifunit(bareq->ifba_ifsname);
470
                if (ifs == NULL) {                      /* no such interface */
471
                        error = ENOENT;
472
                        break;
473
                }
474
 
475
                if (ifs->if_bridge == NULL ||
476
                    ifs->if_bridge != (caddr_t)sc) {
477
                        error = ESRCH;
478
                        break;
479
                }
480
 
481
                ifs = bridge_rtupdate(sc, &bareq->ifba_dst, ifs, 1,
482
                    bareq->ifba_flags);
483
                if (ifs == NULL)
484
                        error = ENOMEM;
485
                break;
486
        case SIOCBRDGDADDR:
487
#ifndef __ECOS
488
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
489
                        break;
490
#endif
491
                error = bridge_rtdaddr(sc, &bareq->ifba_dst);
492
                break;
493
        case SIOCBRDGGCACHE:
494
                bcachereq->ifbc_size = sc->sc_brtmax;
495
                break;
496
        case SIOCBRDGSCACHE:
497
#ifndef __ECOS
498
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
499
                        break;
500
#endif
501
                sc->sc_brtmax = bcachereq->ifbc_size;
502
                bridge_rttrim(sc);
503
                break;
504
        case SIOCBRDGSTO:
505
#ifndef __ECOS
506
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
507
                        break;
508
#endif
509
                sc->sc_brttimeout = (bcacheto->ifbct_time * hz) / 2;
510
                untimeout(bridge_rtage, sc);
511
                if (bcacheto->ifbct_time != 0)
512
                        timeout(bridge_rtage, sc, sc->sc_brttimeout);
513
                break;
514
        case SIOCBRDGGTO:
515
                bcacheto->ifbct_time = (2 * sc->sc_brttimeout) / hz;
516
                break;
517
        case SIOCSIFFLAGS:
518
                if ((ifp->if_flags & IFF_UP) == IFF_UP)
519
                        bridge_init(sc);
520
 
521
                if ((ifp->if_flags & IFF_UP) == 0)
522
                        bridge_stop(sc);
523
 
524
                break;
525
        case SIOCBRDGARL:
526
#ifndef __ECOS
527
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
528
                        break;
529
#endif
530
                ifs = ifunit(brlreq->ifbr_ifsname);
531
                if (ifs == NULL) {
532
                        error = ENOENT;
533
                        break;
534
                }
535
                if (ifs->if_bridge == NULL ||
536
                    ifs->if_bridge != (caddr_t)sc) {
537
                        error = ESRCH;
538
                        break;
539
                }
540
                p = LIST_FIRST(&sc->sc_iflist);
541
                while (p != NULL && p->ifp != ifs) {
542
                        p = LIST_NEXT(p, next);
543
                }
544
                if (p == NULL) {
545
                        error = ESRCH;
546
                        break;
547
                }
548
                if ((brlreq->ifbr_action != BRL_ACTION_BLOCK &&
549
                    brlreq->ifbr_action != BRL_ACTION_PASS) ||
550
                    (brlreq->ifbr_flags & (BRL_FLAG_IN|BRL_FLAG_OUT)) == 0) {
551
                        error = EINVAL;
552
                        break;
553
                }
554
                if (brlreq->ifbr_flags & BRL_FLAG_IN) {
555
                        error = bridge_addrule(p, brlreq, 0);
556
                        if (error)
557
                                break;
558
                }
559
                if (brlreq->ifbr_flags & BRL_FLAG_OUT) {
560
                        error = bridge_addrule(p, brlreq, 1);
561
                        if (error)
562
                                break;
563
                }
564
                break;
565
        case SIOCBRDGFRL:
566
#ifndef __ECOS
567
                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
568
                        break;
569
#endif
570
                ifs = ifunit(brlreq->ifbr_ifsname);
571
                if (ifs == NULL) {
572
                        error = ENOENT;
573
                        break;
574
                }
575
                if (ifs->if_bridge == NULL ||
576
                    ifs->if_bridge != (caddr_t)sc) {
577
                        error = ESRCH;
578
                        break;
579
                }
580
                p = LIST_FIRST(&sc->sc_iflist);
581
                while (p != NULL && p->ifp != ifs) {
582
                        p = LIST_NEXT(p, next);
583
                }
584
                if (p == NULL) {
585
                        error = ESRCH;
586
                        break;
587
                }
588
                error = bridge_flushrule(p);
589
                break;
590
        case SIOCBRDGGRL:
591
                error = bridge_brlconf(sc, brlconf);
592
                break;
593
        default:
594
                error = EINVAL;
595
        }
596
        splx(s);
597
        return (error);
598
}
599
 
600
/* Detach an interface from a bridge.  */
601
void
602
bridge_ifdetach(ifp)
603
        struct ifnet *ifp;
604
{
605
        struct bridge_softc *bsc = (struct bridge_softc *)ifp->if_bridge;
606
        struct bridge_iflist *bif;
607
 
608
        for (bif = LIST_FIRST(&bsc->sc_iflist); bif;
609
            bif = LIST_NEXT(bif, next))
610
                if (bif->ifp == ifp) {
611
                        LIST_REMOVE(bif, next);
612
                        bridge_rtdelete(bsc, ifp);
613
                        bridge_flushrule(bif);
614
                        free(bif, M_DEVBUF);
615
                        ifp->if_bridge = NULL;
616
                        break;
617
                }
618
}
619
 
620
int
621
bridge_bifconf(sc, bifc)
622
        struct bridge_softc *sc;
623
        struct ifbifconf *bifc;
624
{
625
        struct bridge_iflist *p;
626
        u_int32_t total = 0, i;
627
        int error = 0;
628
        struct ifbreq breq;
629
 
630
        p = LIST_FIRST(&sc->sc_iflist);
631
        while (p != NULL) {
632
                total++;
633
                p = LIST_NEXT(p, next);
634
        }
635
 
636
        if (bifc->ifbic_len == 0) {
637
                i = total;
638
                goto done;
639
        }
640
 
641
        p = LIST_FIRST(&sc->sc_iflist);
642
        i = 0;
643
        while (p != NULL && bifc->ifbic_len > i * sizeof(breq)) {
644
                strncpy(breq.ifbr_name, sc->sc_if.if_xname,
645
                    sizeof(breq.ifbr_name)-1);
646
                breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0';
647
                strncpy(breq.ifbr_ifsname, p->ifp->if_xname,
648
                    sizeof(breq.ifbr_ifsname)-1);
649
                breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0';
650
                breq.ifbr_ifsflags = p->bif_flags;
651
                error = copyout((caddr_t)&breq,
652
                    (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
653
                if (error)
654
                        goto done;
655
                p = LIST_NEXT(p, next);
656
                i++;
657
                bifc->ifbic_len -= sizeof(breq);
658
        }
659
done:
660
        bifc->ifbic_len = i * sizeof(breq);
661
        return (error);
662
}
663
 
664
int
665
bridge_brlconf(sc, bc)
666
        struct bridge_softc *sc;
667
        struct ifbrlconf *bc;
668
{
669
        struct ifnet *ifp;
670
        struct bridge_iflist *ifl;
671
        struct brl_node *n;
672
        struct ifbrlreq req;
673
        int error = 0;
674
        u_int32_t i, total=0;
675
 
676
        ifp = ifunit(bc->ifbrl_ifsname);
677
        if (ifp == NULL)
678
                return (ENOENT);
679
        if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc)
680
                return (ESRCH);
681
        ifl = LIST_FIRST(&sc->sc_iflist);
682
        while (ifl != NULL && ifl->ifp != ifp)
683
                ifl = LIST_NEXT(ifl, next);
684
        if (ifl == NULL)
685
                return (ESRCH);
686
 
687
        n = SIMPLEQ_FIRST(&ifl->bif_brlin);
688
        while (n != NULL) {
689
                total++;
690
                n = SIMPLEQ_NEXT(n, brl_next);
691
        }
692
        n = SIMPLEQ_FIRST(&ifl->bif_brlout);
693
        while (n != NULL) {
694
                total++;
695
                n = SIMPLEQ_NEXT(n, brl_next);
696
        }
697
 
698
        if (bc->ifbrl_len == 0) {
699
                i = total;
700
                goto done;
701
        }
702
 
703
        i = 0;
704
        n = SIMPLEQ_FIRST(&ifl->bif_brlin);
705
        while (n != NULL && bc->ifbrl_len > i * sizeof(req)) {
706
                strncpy(req.ifbr_name, sc->sc_if.if_xname,
707
                    sizeof(req.ifbr_name) - 1);
708
                req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0';
709
                strncpy(req.ifbr_ifsname, ifl->ifp->if_xname,
710
                    sizeof(req.ifbr_ifsname) - 1);
711
                req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0';
712
                req.ifbr_action = n->brl_action;
713
                req.ifbr_flags = n->brl_flags;
714
                req.ifbr_src = n->brl_src;
715
                req.ifbr_dst = n->brl_dst;
716
                error = copyout((caddr_t)&req,
717
                    (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
718
                if (error)
719
                        goto done;
720
                n = SIMPLEQ_NEXT(n, brl_next);
721
                i++;
722
                bc->ifbrl_len -= sizeof(req);
723
        }
724
 
725
        n = SIMPLEQ_FIRST(&ifl->bif_brlout);
726
        while (n != NULL && bc->ifbrl_len > i * sizeof(req)) {
727
                strncpy(req.ifbr_name, sc->sc_if.if_xname,
728
                    sizeof(req.ifbr_name) - 1);
729
                req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0';
730
                strncpy(req.ifbr_ifsname, ifl->ifp->if_xname,
731
                    sizeof(req.ifbr_ifsname) - 1);
732
                req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0';
733
                req.ifbr_action = n->brl_action;
734
                req.ifbr_flags = n->brl_flags;
735
                req.ifbr_src = n->brl_src;
736
                req.ifbr_dst = n->brl_dst;
737
                error = copyout((caddr_t)&req,
738
                    (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
739
                if (error)
740
                        goto done;
741
                n = SIMPLEQ_NEXT(n, brl_next);
742
                i++;
743
                bc->ifbrl_len -= sizeof(req);
744
        }
745
 
746
done:
747
        bc->ifbrl_len = i * sizeof(req);
748
        return (error);
749
}
750
 
751
void
752
bridge_init(sc)
753
        struct bridge_softc *sc;
754
{
755
        struct ifnet *ifp = &sc->sc_if;
756
        int i, s;
757
 
758
        if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
759
                return;
760
 
761
        s = splhigh();
762
        if (sc->sc_rts == NULL) {
763
                sc->sc_rts = (struct bridge_rthead *)malloc(
764
                    BRIDGE_RTABLE_SIZE * (sizeof(struct bridge_rthead)),
765
                    M_DEVBUF, M_NOWAIT);
766
                if (sc->sc_rts == NULL) {
767
                        splx(s);
768
                        return;
769
                }
770
                for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
771
                        LIST_INIT(&sc->sc_rts[i]);
772
                }
773
        }
774
        ifp->if_flags |= IFF_RUNNING;
775
        splx(s);
776
 
777
        if (sc->sc_brttimeout != 0)
778
                timeout(bridge_rtage, sc, sc->sc_brttimeout);
779
}
780
 
781
/*
782
 * Stop the bridge and deallocate the routing table.
783
 */
784
void
785
bridge_stop(sc)
786
        struct bridge_softc *sc;
787
{
788
        struct ifnet *ifp = &sc->sc_if;
789
 
790
        /*
791
         * If we're not running, there's nothing to do.
792
         */
793
        if ((ifp->if_flags & IFF_RUNNING) == 0)
794
                return;
795
 
796
        untimeout(bridge_rtage, sc);
797
 
798
        bridge_rtflush(sc, IFBF_FLUSHDYN);
799
 
800
        ifp->if_flags &= ~IFF_RUNNING;
801
}
802
 
803
/*
804
 * Send output from the bridge.  The mbuf has the ethernet header
805
 * already attached.  We must enqueue or free the mbuf before exiting.
806
 */
807
int
808
bridge_output(ifp, m, sa, rt)
809
        struct ifnet *ifp;
810
        struct mbuf *m;
811
        struct sockaddr *sa;
812
        struct rtentry *rt;
813
{
814
        struct ether_header *eh;
815
        struct ifnet *dst_if;
816
        struct ether_addr *src, *dst;
817
        struct bridge_softc *sc;
818
        int s;
819
 
820
        if (m->m_len < sizeof(*eh)) {
821
                m = m_pullup(m, sizeof(*eh));
822
                if (m == NULL)
823
                        return (0);
824
        }
825
        eh = mtod(m, struct ether_header *);
826
        dst = (struct ether_addr *)&eh->ether_dhost[0];
827
        src = (struct ether_addr *)&eh->ether_shost[0];
828
        sc = (struct bridge_softc *)ifp->if_bridge;
829
 
830
        s = splimp();
831
 
832
        /*
833
         * If bridge is down, but original output interface is up,
834
         * go ahead and send out that interface.  Otherwise the packet
835
         * is dropped below.
836
         */
837
        if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
838
                dst_if = ifp;
839
                goto sendunicast;
840
        }
841
 
842
        /*
843
         * If the packet is a broadcast or we don't know a better way to
844
         * get there, send to all interfaces.
845
         */
846
        dst_if = bridge_rtlookup(sc, dst);
847
        if (dst_if == NULL || eh->ether_dhost[0] & 1) {
848
                struct bridge_iflist *p;
849
                struct mbuf *mc;
850
                int used = 0;
851
 
852
                for (p = LIST_FIRST(&sc->sc_iflist); p != NULL;
853
                     p = LIST_NEXT(p, next)) {
854
                        if ((p->ifp->if_flags & IFF_RUNNING) == 0)
855
                                continue;
856
                        if (IF_QFULL(&p->ifp->if_snd)) {
857
                                sc->sc_if.if_oerrors++;
858
                                continue;
859
                        }
860
 
861
                        if (LIST_NEXT(p, next) == NULL) {
862
                                used = 1;
863
                                mc = m;
864
                        } else {
865
                                mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
866
                                if (mc == NULL) {
867
                                        sc->sc_if.if_oerrors++;
868
                                        continue;
869
                                }
870
                        }
871
 
872
                        sc->sc_if.if_opackets++;
873
                        sc->sc_if.if_obytes += m->m_pkthdr.len;
874
                        // Also count the bytes in the outgoing interface; normally
875
                        // done in if_ethersubr.c but here we bypass that route.
876
                        p->ifp->if_obytes += m->m_pkthdr.len;
877
                        IF_ENQUEUE(&p->ifp->if_snd, mc);
878
                        if ((p->ifp->if_flags & IFF_OACTIVE) == 0)
879
                                (*p->ifp->if_start)(p->ifp);
880
                }
881
                if (!used)
882
                        m_freem(m);
883
                splx(s);
884
                return (0);
885
        }
886
 
887
sendunicast:
888
        if ((dst_if->if_flags & IFF_RUNNING) == 0) {
889
                m_freem(m);
890
                splx(s);
891
                return (0);
892
        }
893
        if (IF_QFULL(&dst_if->if_snd)) {
894
                sc->sc_if.if_oerrors++;
895
                m_freem(m);
896
                splx(s);
897
                return (0);
898
        }
899
        sc->sc_if.if_opackets++;
900
        sc->sc_if.if_obytes += m->m_pkthdr.len;
901
        // Also count the bytes in the outgoing interface; normally
902
        // done in if_ethersubr.c but here we bypass that route.
903
        dst_if->if_obytes += m->m_pkthdr.len;
904
        IF_ENQUEUE(&dst_if->if_snd, m);
905
        if ((dst_if->if_flags & IFF_OACTIVE) == 0)
906
                (*dst_if->if_start)(dst_if);
907
        splx(s);
908
        return (0);
909
}
910
 
911
/*
912
 * Start output on the bridge.  This function should never be called.
913
 */
914
void
915
bridge_start(ifp)
916
        struct ifnet *ifp;
917
{
918
}
919
 
920
void
921
bridgeintr(void)
922
{
923
        struct bridge_softc *sc;
924
        struct mbuf *m;
925
        int i, s;
926
 
927
        for (i = 0; i < CYGNUM_NET_BRIDGES; i++) {
928
                sc = &bridgectl[i];
929
                for (;;) {
930
                        s = splimp();
931
                        IF_DEQUEUE(&sc->sc_if.if_snd, m);
932
                        splx(s);
933
                        if (m == NULL)
934
                                break;
935
                        bridgeintr_frame(sc, m);
936
                }
937
        }
938
}
939
 
940
/*
941
 * Loop through each bridge interface and process their input queues.
942
 */
943
void
944
bridgeintr_frame(sc, m)
945
        struct bridge_softc *sc;
946
        struct mbuf *m;
947
{
948
        int s;
949
        struct ifnet *src_if, *dst_if;
950
        struct bridge_iflist *ifl;
951
        struct ether_addr *dst, *src;
952
        struct ether_header eh;
953
 
954
        if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
955
                m_freem(m);
956
                return;
957
        }
958
 
959
        src_if = m->m_pkthdr.rcvif;
960
 
961
#if NBPFILTER > 0
962
        if (sc->sc_if.if_bpf)
963
                bpf_mtap(sc->sc_if.if_bpf, m);
964
#endif
965
 
966
        sc->sc_if.if_lastchange = time;
967
        sc->sc_if.if_ipackets++;
968
        sc->sc_if.if_ibytes += m->m_pkthdr.len;
969
 
970
        ifl = LIST_FIRST(&sc->sc_iflist);
971
        while (ifl != NULL && ifl->ifp != src_if) {
972
                ifl = LIST_NEXT(ifl, next);
973
        }
974
        if (ifl == NULL) {
975
                m_freem(m);
976
                return;
977
        }
978
 
979
        if (m->m_pkthdr.len < sizeof(eh)) {
980
                m_freem(m);
981
                return;
982
        }
983
        m_copydata(m, 0, sizeof(struct ether_header), (caddr_t)&eh);
984
        dst = (struct ether_addr *)&eh.ether_dhost[0];
985
        src = (struct ether_addr *)&eh.ether_shost[0];
986
 
987
        /*
988
         * If interface is learning, and if source address
989
         * is not broadcast or multicast, record it's address.
990
         */
991
        if ((ifl->bif_flags & IFBIF_LEARNING) &&
992
            (eh.ether_shost[0] & 1) == 0 &&
993
            !(eh.ether_shost[0] == 0 &&
994
              eh.ether_shost[1] == 0 &&
995
              eh.ether_shost[2] == 0 &&
996
              eh.ether_shost[3] == 0 &&
997
              eh.ether_shost[4] == 0 &&
998
              eh.ether_shost[5] == 0))
999
                bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC);
1000
 
1001
        /*
1002
         * If packet is unicast, destined for someone on "this"
1003
         * side of the bridge, drop it.
1004
         */
1005
        if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) {
1006
                dst_if = bridge_rtlookup(sc, dst);
1007
                if (dst_if == src_if) {
1008
                        m_freem(m);
1009
                        return;
1010
                }
1011
        } else
1012
                dst_if = NULL;
1013
 
1014
        /*
1015
         * Multicast packets get handled a little differently:
1016
         * If interface is:
1017
         *      -link0,-link1   (default) Forward all multicast
1018
         *                      as broadcast.
1019
         *      -link0,link1    Drop non-IP multicast, forward
1020
         *                      as broadcast IP multicast.
1021
         *      link0,-link1    Drop IP multicast, forward as
1022
         *                      broadcast non-IP multicast.
1023
         *      link0,link1     Drop all multicast.
1024
         */
1025
        if (m->m_flags & M_MCAST) {
1026
                if ((sc->sc_if.if_flags &
1027
                    (IFF_LINK0 | IFF_LINK1)) ==
1028
                    (IFF_LINK0 | IFF_LINK1)) {
1029
                        m_freem(m);
1030
                        return;
1031
                }
1032
                if (sc->sc_if.if_flags & IFF_LINK0 &&
1033
                    ETHERADDR_IS_IP_MCAST(dst)) {
1034
                        m_freem(m);
1035
                        return;
1036
                }
1037
                if (sc->sc_if.if_flags & IFF_LINK1 &&
1038
                    !ETHERADDR_IS_IP_MCAST(dst)) {
1039
                        m_freem(m);
1040
                        return;
1041
                }
1042
        }
1043
 
1044
        if (ifl->bif_flags & IFBIF_BLOCKNONIP && bridge_blocknonip(&eh, m)) {
1045
                m_freem(m);
1046
                return;
1047
        }
1048
 
1049
        if (SIMPLEQ_FIRST(&ifl->bif_brlin) &&
1050
            bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlin), &eh) ==
1051
            BRL_ACTION_BLOCK) {
1052
                m_freem(m);
1053
                return;
1054
        }
1055
 
1056
#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
1057
        m = bridge_filter(sc, src_if, &eh, m);
1058
        if (m == NULL)
1059
                return;
1060
#endif
1061
 
1062
        /*
1063
         * If the packet is a multicast or broadcast OR if we don't
1064
         * know any better, forward it to all interfaces.
1065
         */
1066
        if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) {
1067
                sc->sc_if.if_imcasts++;
1068
                s = splimp();
1069
                bridge_broadcast(sc, src_if, &eh, m);
1070
                splx(s);
1071
                return;
1072
        }
1073
 
1074
        /*
1075
         * At this point, we're dealing with a unicast frame going to a
1076
         * different interface
1077
         */
1078
        if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1079
                m_freem(m);
1080
                return;
1081
        }
1082
        ifl = LIST_FIRST(&sc->sc_iflist);
1083
        while (ifl != NULL && ifl->ifp != dst_if)
1084
                ifl = LIST_NEXT(ifl, next);
1085
        if (SIMPLEQ_FIRST(&ifl->bif_brlout) &&
1086
            bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlout), &eh) ==
1087
            BRL_ACTION_BLOCK) {
1088
                m_freem(m);
1089
                return;
1090
        }
1091
        s = splimp();
1092
        if (IF_QFULL(&dst_if->if_snd)) {
1093
                sc->sc_if.if_oerrors++;
1094
                m_freem(m);
1095
                splx(s);
1096
                return;
1097
        }
1098
        sc->sc_if.if_opackets++;
1099
        sc->sc_if.if_obytes += m->m_pkthdr.len;
1100
        // Also count the bytes in the outgoing interface; normally
1101
        // done in if_ethersubr.c but here we bypass that route.
1102
        dst_if->if_obytes += m->m_pkthdr.len;
1103
        IF_ENQUEUE(&dst_if->if_snd, m);
1104
        if ((dst_if->if_flags & IFF_OACTIVE) == 0)
1105
                (*dst_if->if_start)(dst_if);
1106
        splx(s);
1107
}
1108
 
1109
/*
1110
 * Receive input from an interface.  Queue the packet for bridging if its
1111
 * not for us, and schedule an interrupt.
1112
 */
1113
struct mbuf *
1114
bridge_input(ifp, eh, m)
1115
        struct ifnet *ifp;
1116
        struct ether_header *eh;
1117
        struct mbuf *m;
1118
{
1119
        struct bridge_softc *sc;
1120
        int s;
1121
        struct bridge_iflist *ifl;
1122
        struct arpcom *ac;
1123
        struct mbuf *mc;
1124
 
1125
        /*
1126
         * Make sure this interface is a bridge member.
1127
         */
1128
        if (ifp == NULL || ifp->if_bridge == NULL || m == NULL)
1129
                return (m);
1130
 
1131
        if ((m->m_flags & M_PKTHDR) == 0)
1132
                panic("bridge_input(): no HDR");
1133
 
1134
        sc = (struct bridge_softc *)ifp->if_bridge;
1135
        if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1136
                return (m);
1137
 
1138
        if (m->m_flags & (M_BCAST | M_MCAST)) {
1139
                /*
1140
                 * make a copy of 'm' with 'eh' tacked on to the
1141
                 * beginning.  Return 'm' for local processing
1142
                 * and enqueue the copy.  Schedule netisr.
1143
                 */
1144
                mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT);
1145
                if (mc == NULL)
1146
                        return (m);
1147
                M_PREPEND(mc, sizeof(struct ether_header), M_DONTWAIT);
1148
                if (mc == NULL)
1149
                        return (m);
1150
                bcopy(eh, mtod(mc, caddr_t), sizeof(struct ether_header));
1151
                s = splimp();
1152
                if (IF_QFULL(&sc->sc_if.if_snd)) {
1153
                        m_freem(mc);
1154
                        splx(s);
1155
                        return (m);
1156
                }
1157
                IF_ENQUEUE(&sc->sc_if.if_snd, mc);
1158
                splx(s);
1159
                schednetisr(NETISR_BRIDGE);
1160
                return (m);
1161
        }
1162
 
1163
        /*
1164
         * Unicast, make sure it's not for us.
1165
         */
1166
        for (ifl = LIST_FIRST(&sc->sc_iflist);ifl; ifl = LIST_NEXT(ifl,next)) {
1167
                if (ifl->ifp->if_type != IFT_ETHER)
1168
                        continue;
1169
                ac = (struct arpcom *)ifl->ifp;
1170
                if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) {
1171
                        if (ifl->bif_flags & IFBIF_LEARNING)
1172
                                bridge_rtupdate(sc,
1173
                                    (struct ether_addr *)&eh->ether_shost,
1174
                                    ifp, 0, IFBAF_DYNAMIC);
1175
                        m->m_pkthdr.rcvif = ifl->ifp;
1176
                        return (m);
1177
                }
1178
                if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1179
                        m_freem(m);
1180
                        return (NULL);
1181
                }
1182
        }
1183
        M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
1184
        if (m == NULL)
1185
                return (NULL);
1186
        bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header));
1187
        s = splimp();
1188
        if (IF_QFULL(&sc->sc_if.if_snd)) {
1189
                m_freem(m);
1190
                splx(s);
1191
                return (NULL);
1192
        }
1193
        IF_ENQUEUE(&sc->sc_if.if_snd, m);
1194
        splx(s);
1195
        schednetisr(NETISR_BRIDGE);
1196
        return (NULL);
1197
}
1198
 
1199
/*
1200
 * Send a frame to all interfaces that are members of the bridge
1201
 * (except the one it came in on).  This code assumes that it is
1202
 * running at splnet or higher.
1203
 */
1204
void
1205
bridge_broadcast(sc, ifp, eh, m)
1206
        struct bridge_softc *sc;
1207
        struct ifnet *ifp;
1208
        struct ether_header *eh;
1209
        struct mbuf *m;
1210
{
1211
        struct bridge_iflist *p;
1212
        struct mbuf *mc;
1213
        int used = 0;
1214
 
1215
        for (p = LIST_FIRST(&sc->sc_iflist); p; p = LIST_NEXT(p, next)) {
1216
                /*
1217
                 * Don't retransmit out of the same interface where
1218
                 * the packet was received from.
1219
                 */
1220
                if (p->ifp->if_index == ifp->if_index)
1221
                        continue;
1222
 
1223
                if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
1224
                    (m->m_flags & (M_BCAST | M_MCAST)) == 0)
1225
                        continue;
1226
 
1227
                if ((p->ifp->if_flags & IFF_RUNNING) == 0)
1228
                        continue;
1229
 
1230
                if (IF_QFULL(&p->ifp->if_snd)) {
1231
                        sc->sc_if.if_oerrors++;
1232
                        continue;
1233
                }
1234
 
1235
                if (SIMPLEQ_FIRST(&p->bif_brlout) &&
1236
                    bridge_filterrule(SIMPLEQ_FIRST(&p->bif_brlout), eh) ==
1237
                    BRL_ACTION_BLOCK)
1238
                        continue;
1239
 
1240
                /* If last one, reuse the passed-in mbuf */
1241
                if (LIST_NEXT(p, next) == NULL) {
1242
                        mc = m;
1243
                        used = 1;
1244
                } else {
1245
                        mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1246
                        if (mc == NULL) {
1247
                                sc->sc_if.if_oerrors++;
1248
                                continue;
1249
                        }
1250
                }
1251
 
1252
                if (p->bif_flags & IFBIF_BLOCKNONIP &&
1253
                    bridge_blocknonip(eh, mc)) {
1254
                        m_freem(mc);
1255
                        continue;
1256
                }
1257
 
1258
                sc->sc_if.if_opackets++;
1259
                sc->sc_if.if_obytes += mc->m_pkthdr.len;
1260
                if (ifp && ((eh->ether_shost[0] & 1) == 0) )
1261
                        ifp->if_omcasts++;
1262
                // Also count the bytes in the outgoing interface; normally
1263
                // done in if_ethersubr.c but here we bypass that route.
1264
                p->ifp->if_obytes += m->m_pkthdr.len;
1265
                IF_ENQUEUE(&p->ifp->if_snd, mc);
1266
                if ((p->ifp->if_flags & IFF_OACTIVE) == 0)
1267
                        (*p->ifp->if_start)(p->ifp);
1268
        }
1269
 
1270
        if (!used)
1271
                m_freem(m);
1272
}
1273
 
1274
struct ifnet *
1275
bridge_rtupdate(sc, ea, ifp, setflags, flags)
1276
        struct bridge_softc *sc;
1277
        struct ether_addr *ea;
1278
        struct ifnet *ifp;
1279
        int setflags;
1280
        u_int8_t flags;
1281
{
1282
        struct bridge_rtnode *p, *q;
1283
        u_int32_t h;
1284
        int s, dir;
1285
 
1286
        s = splhigh();
1287
        if (sc->sc_rts == NULL) {
1288
                if (setflags && flags == IFBAF_STATIC) {
1289
                        sc->sc_rts = (struct bridge_rthead *)malloc(
1290
                            BRIDGE_RTABLE_SIZE *
1291
                            (sizeof(struct bridge_rthead)),M_DEVBUF,M_NOWAIT);
1292
 
1293
                        if (sc->sc_rts == NULL)
1294
                                goto done;
1295
 
1296
                        for (h = 0; h < BRIDGE_RTABLE_SIZE; h++)
1297
                                LIST_INIT(&sc->sc_rts[h]);
1298
                } else
1299
                        goto done;
1300
        }
1301
 
1302
        h = bridge_hash(ea);
1303
        p = LIST_FIRST(&sc->sc_rts[h]);
1304
        if (p == NULL) {
1305
                if (sc->sc_brtcnt >= sc->sc_brtmax)
1306
                        goto done;
1307
                p = (struct bridge_rtnode *)malloc(
1308
                    sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1309
                if (p == NULL)
1310
                        goto done;
1311
 
1312
                bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1313
                p->brt_if = ifp;
1314
                p->brt_age = 1;
1315
 
1316
                if (setflags)
1317
                        p->brt_flags = flags;
1318
                else
1319
                        p->brt_flags = IFBAF_DYNAMIC;
1320
 
1321
                LIST_INSERT_HEAD(&sc->sc_rts[h], p, brt_next);
1322
                sc->sc_brtcnt++;
1323
                goto want;
1324
        }
1325
 
1326
        do {
1327
                q = p;
1328
                p = LIST_NEXT(p, brt_next);
1329
 
1330
                dir = memcmp(ea, &q->brt_addr, sizeof(q->brt_addr));
1331
                if (dir == 0) {
1332
                        if (setflags) {
1333
                                q->brt_if = ifp;
1334
                                q->brt_flags = flags;
1335
                        }
1336
 
1337
                        if (q->brt_if == ifp)
1338
                                q->brt_age = 1;
1339
                        ifp = q->brt_if;
1340
                        goto want;
1341
                }
1342
 
1343
                if (dir > 0) {
1344
                        if (sc->sc_brtcnt >= sc->sc_brtmax)
1345
                                goto done;
1346
                        p = (struct bridge_rtnode *)malloc(
1347
                            sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1348
                        if (p == NULL)
1349
                                goto done;
1350
 
1351
                        bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1352
                        p->brt_if = ifp;
1353
                        p->brt_age = 1;
1354
 
1355
                        if (setflags)
1356
                                p->brt_flags = flags;
1357
                        else
1358
                                p->brt_flags = IFBAF_DYNAMIC;
1359
 
1360
                        LIST_INSERT_BEFORE(q, p, brt_next);
1361
                        sc->sc_brtcnt++;
1362
                        goto want;
1363
                }
1364
 
1365
                if (p == NULL) {
1366
                        if (sc->sc_brtcnt >= sc->sc_brtmax)
1367
                                goto done;
1368
                        p = (struct bridge_rtnode *)malloc(
1369
                            sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1370
                        if (p == NULL)
1371
                                goto done;
1372
 
1373
                        bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1374
                        p->brt_if = ifp;
1375
                        p->brt_age = 1;
1376
 
1377
                        if (setflags)
1378
                                p->brt_flags = flags;
1379
                        else
1380
                                p->brt_flags = IFBAF_DYNAMIC;
1381
                        LIST_INSERT_AFTER(q, p, brt_next);
1382
                        sc->sc_brtcnt++;
1383
                        goto want;
1384
                }
1385
        } while (p != NULL);
1386
 
1387
done:
1388
        ifp = NULL;
1389
want:
1390
        splx(s);
1391
        return (ifp);
1392
}
1393
 
1394
struct ifnet *
1395
bridge_rtlookup(sc, ea)
1396
        struct bridge_softc *sc;
1397
        struct ether_addr *ea;
1398
{
1399
        struct bridge_rtnode *p;
1400
        u_int32_t h;
1401
        int s, dir;
1402
 
1403
        /*
1404
         * Lock out everything else
1405
         */
1406
        s = splhigh();
1407
 
1408
        if (sc->sc_rts == NULL)
1409
                goto fail;
1410
 
1411
        h = bridge_hash(ea);
1412
        p = LIST_FIRST(&sc->sc_rts[h]);
1413
        while (p != NULL) {
1414
                dir = memcmp(ea, &p->brt_addr, sizeof(p->brt_addr));
1415
                if (dir == 0) {
1416
                        splx(s);
1417
                        return (p->brt_if);
1418
                }
1419
                if (dir > 0)
1420
                        goto fail;
1421
                p = LIST_NEXT(p, brt_next);
1422
        }
1423
fail:
1424
        splx(s);
1425
        return (NULL);
1426
}
1427
 
1428
/*
1429
 * The following hash function is adapted from 'Hash Functions' by Bob Jenkins
1430
 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1431
 * "You may use this code any way you wish, private, educational, or
1432
 *  commercial.  It's free."
1433
 */
1434
#define mix(a,b,c) \
1435
        do {                                            \
1436
                a -= b; a -= c; a ^= (c >> 13);         \
1437
                b -= c; b -= a; b ^= (a << 8);          \
1438
                c -= a; c -= b; c ^= (b >> 13);         \
1439
                a -= b; a -= c; a ^= (c >> 12);         \
1440
                b -= c; b -= a; b ^= (a << 16);         \
1441
                c -= a; c -= b; c ^= (b >> 5);          \
1442
                a -= b; a -= c; a ^= (c >> 3);          \
1443
                b -= c; b -= a; b ^= (a << 10);         \
1444
                c -= a; c -= b; c ^= (b >> 15);         \
1445
        } while(0)
1446
 
1447
u_int32_t
1448
bridge_hash(addr)
1449
        struct ether_addr *addr;
1450
{
1451
        u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0xdeadbeef;
1452
 
1453
        b += addr->ether_addr_octet[5] << 8;
1454
        b += addr->ether_addr_octet[4];
1455
        a += addr->ether_addr_octet[3] << 24;
1456
        a += addr->ether_addr_octet[2] << 16;
1457
        a += addr->ether_addr_octet[1] << 8;
1458
        a += addr->ether_addr_octet[0];
1459
 
1460
        mix(a, b, c);
1461
        return (c & BRIDGE_RTABLE_MASK);
1462
}
1463
 
1464
/*
1465
 * Trim the routing table so that we've got a number of routes
1466
 * less than or equal to the maximum.
1467
 */
1468
void
1469
bridge_rttrim(sc)
1470
        struct bridge_softc *sc;
1471
{
1472
        struct bridge_rtnode *n, *p;
1473
        int s, i;
1474
 
1475
        s = splhigh();
1476
        if (sc->sc_rts == NULL)
1477
                goto done;
1478
 
1479
        /*
1480
         * Make sure we have to trim the address table
1481
         */
1482
        if (sc->sc_brtcnt <= sc->sc_brtmax)
1483
                goto done;
1484
 
1485
        /*
1486
         * Force an aging cycle, this might trim enough addresses.
1487
         */
1488
        splx(s);
1489
        bridge_rtage(sc);
1490
        s = splhigh();
1491
 
1492
        if (sc->sc_brtcnt <= sc->sc_brtmax)
1493
                goto done;
1494
 
1495
        for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1496
                n = LIST_FIRST(&sc->sc_rts[i]);
1497
                while (n != NULL) {
1498
                        p = LIST_NEXT(n, brt_next);
1499
                        if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1500
                                LIST_REMOVE(n, brt_next);
1501
                                sc->sc_brtcnt--;
1502
                                free(n, M_DEVBUF);
1503
                                n = p;
1504
                                if (sc->sc_brtcnt <= sc->sc_brtmax)
1505
                                        goto done;
1506
                        }
1507
                }
1508
        }
1509
 
1510
done:
1511
        if (sc->sc_rts != NULL && sc->sc_brtcnt == 0 &&
1512
            (sc->sc_if.if_flags & IFF_UP) == 0) {
1513
                free(sc->sc_rts, M_DEVBUF);
1514
                sc->sc_rts = NULL;
1515
        }
1516
 
1517
        splx(s);
1518
}
1519
 
1520
/*
1521
 * Perform an aging cycle
1522
 */
1523
void
1524
bridge_rtage(vsc)
1525
        void *vsc;
1526
{
1527
        struct bridge_softc *sc = (struct bridge_softc *)vsc;
1528
        struct bridge_rtnode *n, *p;
1529
        int s, i;
1530
 
1531
        s = splhigh();
1532
        if (sc->sc_rts == NULL) {
1533
                splx(s);
1534
                return;
1535
        }
1536
 
1537
        for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1538
                n = LIST_FIRST(&sc->sc_rts[i]);
1539
                while (n != NULL) {
1540
                        if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) {
1541
                                n->brt_age = !n->brt_age;
1542
                                if (n->brt_age)
1543
                                        n->brt_age = 0;
1544
                                n = LIST_NEXT(n, brt_next);
1545
                        } else if (n->brt_age) {
1546
                                n->brt_age = 0;
1547
                                n = LIST_NEXT(n, brt_next);
1548
                        } else {
1549
                                p = LIST_NEXT(n, brt_next);
1550
                                LIST_REMOVE(n, brt_next);
1551
                                sc->sc_brtcnt--;
1552
                                free(n, M_DEVBUF);
1553
                                n = p;
1554
                        }
1555
                }
1556
        }
1557
        splx(s);
1558
 
1559
        if (sc->sc_brttimeout != 0)
1560
                timeout(bridge_rtage, sc, sc->sc_brttimeout);
1561
}
1562
 
1563
/*
1564
 * Remove all dynamic addresses from the cache
1565
 */
1566
int
1567
bridge_rtflush(sc, full)
1568
        struct bridge_softc *sc;
1569
        int full;
1570
{
1571
        int s, i;
1572
        struct bridge_rtnode *p, *n;
1573
 
1574
        s = splhigh();
1575
        if (sc->sc_rts == NULL)
1576
                goto done;
1577
 
1578
        for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1579
                n = LIST_FIRST(&sc->sc_rts[i]);
1580
                while (n != NULL) {
1581
                        if (full ||
1582
                            (n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1583
                                p = LIST_NEXT(n, brt_next);
1584
                                LIST_REMOVE(n, brt_next);
1585
                                sc->sc_brtcnt--;
1586
                                free(n, M_DEVBUF);
1587
                                n = p;
1588
                        } else
1589
                                n = LIST_NEXT(n, brt_next);
1590
                }
1591
        }
1592
 
1593
        if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
1594
                free(sc->sc_rts, M_DEVBUF);
1595
                sc->sc_rts = NULL;
1596
        }
1597
 
1598
done:
1599
        splx(s);
1600
        return (0);
1601
}
1602
 
1603
/*
1604
 * Remove an address from the cache
1605
 */
1606
int
1607
bridge_rtdaddr(sc, ea)
1608
        struct bridge_softc *sc;
1609
        struct ether_addr *ea;
1610
{
1611
        int h, s;
1612
        struct bridge_rtnode *p;
1613
 
1614
        s = splhigh();
1615
        if (sc->sc_rts == NULL)
1616
                goto done;
1617
 
1618
        h = bridge_hash(ea);
1619
        p = LIST_FIRST(&sc->sc_rts[h]);
1620
        while (p != NULL) {
1621
                if (bcmp(ea, &p->brt_addr, sizeof(p->brt_addr)) == 0) {
1622
                        LIST_REMOVE(p, brt_next);
1623
                        sc->sc_brtcnt--;
1624
                        free(p, M_DEVBUF);
1625
                        if (sc->sc_brtcnt == 0 &&
1626
                            (sc->sc_if.if_flags & IFF_UP) == 0) {
1627
                                free(sc->sc_rts, M_DEVBUF);
1628
                                sc->sc_rts = NULL;
1629
                        }
1630
                        splx(s);
1631
                        return (0);
1632
                }
1633
                p = LIST_NEXT(p, brt_next);
1634
        }
1635
 
1636
done:
1637
        splx(s);
1638
        return (ENOENT);
1639
}
1640
/*
1641
 * Delete routes to a specific interface member.
1642
 */
1643
void
1644
bridge_rtdelete(sc, ifp)
1645
        struct bridge_softc *sc;
1646
        struct ifnet *ifp;
1647
{
1648
        int i, s;
1649
        struct bridge_rtnode *n, *p;
1650
 
1651
        s = splhigh();
1652
        if (sc->sc_rts == NULL)
1653
                goto done;
1654
 
1655
        /*
1656
         * Loop through all of the hash buckets and traverse each
1657
         * chain looking for routes to this interface.
1658
         */
1659
        for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1660
                n = LIST_FIRST(&sc->sc_rts[i]);
1661
                while (n != NULL) {
1662
                        if (n->brt_if == ifp) {         /* found one */
1663
                                p = LIST_NEXT(n, brt_next);
1664
                                LIST_REMOVE(n, brt_next);
1665
                                sc->sc_brtcnt--;
1666
                                free(n, M_DEVBUF);
1667
                                n = p;
1668
                        } else
1669
                                n = LIST_NEXT(n, brt_next);
1670
                }
1671
        }
1672
        if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
1673
                free(sc->sc_rts, M_DEVBUF);
1674
                sc->sc_rts = NULL;
1675
        }
1676
 
1677
done:
1678
        splx(s);
1679
}
1680
 
1681
/*
1682
 * Gather all of the routes for this interface.
1683
 */
1684
int
1685
bridge_rtfind(sc, baconf)
1686
        struct bridge_softc *sc;
1687
        struct ifbaconf *baconf;
1688
{
1689
        int i, s, error = 0;
1690
        u_int32_t cnt = 0;
1691
        struct bridge_rtnode *n;
1692
        struct ifbareq bareq;
1693
 
1694
        s = splhigh();
1695
 
1696
        if (sc->sc_rts == NULL || baconf->ifbac_len == 0)
1697
                goto done;
1698
 
1699
        for (i = 0, cnt = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1700
                n = LIST_FIRST(&sc->sc_rts[i]);
1701
                while (n != NULL) {
1702
                        if (baconf->ifbac_len <
1703
                            (cnt + 1) * sizeof(struct ifbareq))
1704
                                goto done;
1705
                        bcopy(sc->sc_if.if_xname, bareq.ifba_name,
1706
                            sizeof(bareq.ifba_name));
1707
                        bcopy(n->brt_if->if_xname, bareq.ifba_ifsname,
1708
                            sizeof(bareq.ifba_ifsname));
1709
                        bcopy(&n->brt_addr, &bareq.ifba_dst,
1710
                            sizeof(bareq.ifba_dst));
1711
                        bareq.ifba_age = n->brt_age;
1712
                        bareq.ifba_flags = n->brt_flags;
1713
                        error = copyout((caddr_t)&bareq,
1714
                            (caddr_t)(baconf->ifbac_req + cnt), sizeof(bareq));
1715
                        if (error)
1716
                                goto done;
1717
                        n = LIST_NEXT(n, brt_next);
1718
                        cnt++;
1719
                }
1720
        }
1721
done:
1722
        baconf->ifbac_len = cnt * sizeof(struct ifbareq);
1723
        splx(s);
1724
        return (error);
1725
}
1726
 
1727
/*
1728
 * Block non-ip frames:
1729
 * Returns 0 if frame is ip, and 1 if it should be dropped.
1730
 */
1731
int
1732
bridge_blocknonip(eh, m)
1733
        struct ether_header *eh;
1734
        struct mbuf *m;
1735
{
1736
        struct snap snap;
1737
        u_int16_t etype;
1738
 
1739
        if (m->m_pkthdr.len < sizeof(struct ether_header))
1740
                return (1);
1741
 
1742
        etype = ntohs(eh->ether_type);
1743
        switch (etype) {
1744
        case ETHERTYPE_ARP:
1745
        case ETHERTYPE_REVARP:
1746
        case ETHERTYPE_IP:
1747
        case ETHERTYPE_IPV6:
1748
                return (0);
1749
        }
1750
 
1751
        if (etype > ETHERMTU)
1752
                return (1);
1753
 
1754
        if (m->m_pkthdr.len <
1755
            (sizeof(struct ether_header) + sizeof(struct snap)))
1756
                return (1);
1757
 
1758
        m_copydata(m, sizeof(struct ether_header), sizeof(struct snap),
1759
            (caddr_t)&snap);
1760
 
1761
        etype = ntohs(snap.type);
1762
        if (snap.dsap == LLC_SNAP_LSAP && snap.ssap == LLC_SNAP_LSAP &&
1763
            snap.control == LLC_UI &&
1764
            snap.org[0] == 0 && snap.org[1] == 0 && snap.org[2] == 0 &&
1765
            (etype == ETHERTYPE_ARP ||
1766
             etype == ETHERTYPE_REVARP ||
1767
             etype == ETHERTYPE_IP ||
1768
             etype == ETHERTYPE_IPV6)) {
1769
                return (0);
1770
        }
1771
 
1772
        return (1);
1773
}
1774
 
1775
u_int8_t
1776
bridge_filterrule(n, eh)
1777
        struct brl_node *n;
1778
        struct ether_header *eh;
1779
{
1780
        u_int8_t flags;
1781
 
1782
        for (; n != NULL; n = SIMPLEQ_NEXT(n, brl_next)) {
1783
                flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
1784
                if (flags == 0)
1785
                        return (n->brl_action);
1786
                if (flags == (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID)) {
1787
                        if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
1788
                                continue;
1789
                        if (bcmp(eh->ether_dhost, &n->brl_src, ETHER_ADDR_LEN))
1790
                                continue;
1791
                        return (n->brl_action);
1792
                }
1793
                if (flags == BRL_FLAG_SRCVALID) {
1794
                        if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
1795
                                continue;
1796
                        return (n->brl_action);
1797
                }
1798
                if (flags == BRL_FLAG_DSTVALID) {
1799
                        if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
1800
                                continue;
1801
                        return (n->brl_action);
1802
                }
1803
        }
1804
        return (BRL_ACTION_PASS);
1805
}
1806
 
1807
int
1808
bridge_addrule(bif, req, out)
1809
        struct bridge_iflist *bif;
1810
        struct ifbrlreq *req;
1811
        int out;
1812
{
1813
        struct brl_node *n;
1814
 
1815
        n = (struct brl_node *)malloc(sizeof(struct brl_node), M_DEVBUF, M_NOWAIT);
1816
        if (n == NULL)
1817
                return (ENOMEM);
1818
        bcopy(&req->ifbr_src, &n->brl_src, sizeof(struct ether_addr));
1819
        bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr));
1820
        n->brl_action = req->ifbr_action;
1821
        n->brl_flags = req->ifbr_flags;
1822
        if (out) {
1823
                n->brl_flags &= ~BRL_FLAG_IN;
1824
                n->brl_flags |= BRL_FLAG_OUT;
1825
                SIMPLEQ_INSERT_TAIL(&bif->bif_brlout, n, brl_next);
1826
        } else {
1827
                n->brl_flags &= ~BRL_FLAG_OUT;
1828
                n->brl_flags |= BRL_FLAG_IN;
1829
                SIMPLEQ_INSERT_TAIL(&bif->bif_brlin, n, brl_next);
1830
        }
1831
        return (0);
1832
}
1833
 
1834
int
1835
bridge_flushrule(bif)
1836
        struct bridge_iflist *bif;
1837
{
1838
        struct brl_node *p, *q;
1839
 
1840
        p = SIMPLEQ_FIRST(&bif->bif_brlin);
1841
        while (p != NULL) {
1842
                q = SIMPLEQ_NEXT(p, brl_next);
1843
                SIMPLEQ_REMOVE_HEAD(&bif->bif_brlin, p, brl_next);
1844
                free(p, M_DEVBUF);
1845
                p = q;
1846
        }
1847
        p = SIMPLEQ_FIRST(&bif->bif_brlout);
1848
        while (p != NULL) {
1849
                q = SIMPLEQ_NEXT(p, brl_next);
1850
                SIMPLEQ_REMOVE_HEAD(&bif->bif_brlout, p, brl_next);
1851
                free(p, M_DEVBUF);
1852
                p = q;
1853
        }
1854
        return (0);
1855
}
1856
 
1857
#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
1858
 
1859
/*
1860
 * Maximum sized IP header
1861
 */
1862
union maxip {
1863
        struct ip ip;
1864
        u_int32_t _padding[16];
1865
};
1866
 
1867
/*
1868
 * Filter IP packets by peeking into the ethernet frame.  This violates
1869
 * the ISO model, but allows us to act as a IP filter at the data link
1870
 * layer.  As a result, most of this code will look familiar to those
1871
 * who've read net/if_ethersubr.c and netinet/ip_input.c
1872
 */
1873
struct mbuf *
1874
bridge_filter(sc, ifp, eh, m)
1875
        struct bridge_softc *sc;
1876
        struct ifnet *ifp;
1877
        struct ether_header *eh;
1878
        struct mbuf *m;
1879
{
1880
        struct snap snap;
1881
        int hassnap = 0;
1882
        struct ip *ip;
1883
        int hlen;
1884
 
1885
        if (fr_checkp == NULL)
1886
                return (m);
1887
 
1888
        if (eh->ether_type != htons(ETHERTYPE_IP)) {
1889
                if (eh->ether_type > ETHERMTU ||
1890
                    m->m_pkthdr.len < (sizeof(struct snap) +
1891
                    sizeof(struct ether_header)))
1892
                        return (m);
1893
 
1894
                m_copydata(m, sizeof(struct ether_header),
1895
                    sizeof(struct snap), (caddr_t)&snap);
1896
 
1897
                if (snap.dsap != LLC_SNAP_LSAP || snap.ssap != LLC_SNAP_LSAP ||
1898
                    snap.control != LLC_UI ||
1899
                    snap.org[0] != 0 || snap.org[1] != 0 || snap.org[2] ||
1900
                    snap.type != htons(ETHERTYPE_IP))
1901
                        return (m);
1902
                hassnap = 1;
1903
        }
1904
 
1905
        m_adj(m, sizeof(struct ether_header));
1906
        if (hassnap)
1907
                m_adj(m, sizeof(struct snap));
1908
 
1909
        if (m->m_pkthdr.len < sizeof(struct ip))
1910
                goto dropit;
1911
 
1912
        /* Copy minimal header, and drop invalids */
1913
        if (m->m_len < sizeof(struct ip) &&
1914
            (m = m_pullup(m, sizeof(struct ip))) == NULL)
1915
                return (NULL);
1916
        ip = mtod(m, struct ip *);
1917
 
1918
        if (ip->ip_v != IPVERSION)
1919
                goto dropit;
1920
 
1921
        hlen = ip->ip_hl << 2;  /* get whole header length */
1922
        if (hlen < sizeof(struct ip))
1923
                goto dropit;
1924
        if (hlen > m->m_len) {
1925
                if ((m = m_pullup(m, sizeof(struct ip))) == NULL)
1926
                        return (NULL);
1927
                ip = mtod(m, struct ip *);
1928
        }
1929
 
1930
        if ((ip->ip_sum = in_cksum(m, hlen)) != 0)
1931
                goto dropit;
1932
 
1933
        NTOHS(ip->ip_len);
1934
        if (ip->ip_len < hlen)
1935
                goto dropit;
1936
        NTOHS(ip->ip_id);
1937
        NTOHS(ip->ip_off);
1938
 
1939
        if (m->m_pkthdr.len < ip->ip_len)
1940
                goto dropit;
1941
        if (m->m_pkthdr.len > ip->ip_len) {
1942
                if (m->m_len == m->m_pkthdr.len) {
1943
                        m->m_len = ip->ip_len;
1944
                        m->m_pkthdr.len = ip->ip_len;
1945
                } else
1946
                        m_adj(m, ip->ip_len - m->m_pkthdr.len);
1947
        }
1948
 
1949
        /* Finally, we get to filter the packet! */
1950
        if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m))
1951
                return (NULL);
1952
 
1953
        /* Rebuild the IP header */
1954
        if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
1955
                return (NULL);
1956
        if (m->m_len < sizeof(struct ip))
1957
                goto dropit;
1958
        ip = mtod(m, struct ip *);
1959
        HTONS(ip->ip_len);
1960
        HTONS(ip->ip_id);
1961
        HTONS(ip->ip_off);
1962
        ip->ip_sum = in_cksum(m, hlen);
1963
 
1964
        /* Reattach SNAP header */
1965
        if (hassnap) {
1966
                M_PREPEND(m, sizeof(snap), M_DONTWAIT);
1967
                if (m == NULL)
1968
                        goto dropit;
1969
                bcopy(&snap, mtod(m, caddr_t), sizeof(snap));
1970
        }
1971
 
1972
        /* Reattach ethernet header */
1973
        M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
1974
        if (m == NULL)
1975
                goto dropit;
1976
        bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
1977
 
1978
        return (m);
1979
 
1980
dropit:
1981
        if (m != NULL)
1982
                m_freem(m);
1983
        return (NULL);
1984
}
1985
#endif
1986
 
1987
int
1988
ifpromisc(ifp, pswitch)
1989
        struct ifnet *ifp;
1990
        int pswitch;
1991
{
1992
        struct ifreq ifr;
1993
 
1994
        if (pswitch) {
1995
                /*
1996
                 * If the device is not configured up, we cannot put it in
1997
                 * promiscuous mode.
1998
                 */
1999
                if ((ifp->if_flags & IFF_UP) == 0)
2000
                        return (ENETDOWN);
2001
                if (ifp->if_pcount++ != 0)
2002
                        return (0);
2003
                ifp->if_flags |= IFF_PROMISC;
2004
        } else {
2005
                if (--ifp->if_pcount > 0)
2006
                        return (0);
2007
                ifp->if_flags &= ~IFF_PROMISC;
2008
                /*
2009
                 * If the device is not configured up, we should not need to
2010
                 * turn off promiscuous mode (device should have turned it
2011
                 * off when interface went down; and will look at IFF_PROMISC
2012
                 * again next time interface comes up).
2013
                 */
2014
                if ((ifp->if_flags & IFF_UP) == 0)
2015
                        return (0);
2016
        }
2017
        ifr.ifr_flags = ifp->if_flags;
2018
        return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
2019
}
2020
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.