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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [net/] [if_ethersubr.c] - Blame information for rev 311

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

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/net/if_ethersubr.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*
23
 * Copyright (c) 1982, 1989, 1993
24
 *      The Regents of the University of California.  All rights reserved.
25
 *
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions
28
 * are met:
29
 * 1. Redistributions of source code must retain the above copyright
30
 *    notice, this list of conditions and the following disclaimer.
31
 * 2. Redistributions in binary form must reproduce the above copyright
32
 *    notice, this list of conditions and the following disclaimer in the
33
 *    documentation and/or other materials provided with the distribution.
34
 * 3. All advertising materials mentioning features or use of this software
35
 *    must display the following acknowledgement:
36
 *      This product includes software developed by the University of
37
 *      California, Berkeley and its contributors.
38
 * 4. Neither the name of the University nor the names of its contributors
39
 *    may be used to endorse or promote products derived from this software
40
 *    without specific prior written permission.
41
 *
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52
 * SUCH DAMAGE.
53
 *
54
 *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
55
 * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.70.2.17 2001/08/01 00:47:49 fenner Exp $
56
 */
57
 
58
#include <sys/param.h>
59
#include <sys/malloc.h>
60
#include <sys/mbuf.h>
61
#include <sys/socket.h>
62
#include <sys/sockio.h>
63
 
64
#include <net/if.h>
65
#include <net/netisr.h>
66
#include <net/route.h>
67
#include <net/if_dl.h>
68
#include <net/if_types.h>
69
#include <net/ethernet.h>
70
 
71
#if defined(INET) || defined(INET6)
72
#include <netinet/in.h>
73
#include <netinet/in_var.h>
74
#include <netinet/if_ether.h>
75
#endif
76
#ifdef INET6
77
#include <netinet6/nd6.h>
78
#endif
79
 
80
#ifdef IPX
81
#include <netipx/ipx.h>
82
#include <netipx/ipx_if.h>
83
int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
84
int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
85
                struct sockaddr *dst, short *tp, int *hlen);
86
#endif
87
 
88
#ifdef NS
89
#include <netns/ns.h>
90
#include <netns/ns_if.h>
91
ushort ns_nettype;
92
int ether_outputdebug = 0;
93
int ether_inputdebug = 0;
94
#endif
95
 
96
#ifdef NETATALK
97
#include <netatalk/at.h>
98
#include <netatalk/at_var.h>
99
#include <netatalk/at_extern.h>
100
 
101
#define llc_snap_org_code llc_un.type_snap.org_code
102
#define llc_snap_ether_type llc_un.type_snap.ether_type
103
 
104
extern u_char   at_org_code[3];
105
extern u_char   aarp_org_code[3];
106
#endif /* NETATALK */
107
 
108
#ifdef BRIDGE
109
#include <net/bridge.h>
110
#endif
111
 
112
#define NVLAN 0
113
#if NVLAN > 0
114
#include <net/if_vlan_var.h>
115
#endif /* NVLAN > 0 */
116
 
117
/* netgraph node hooks for ng_ether(4) */
118
void    (*ng_ether_input_p)(struct ifnet *ifp,
119
                struct mbuf **mp, struct ether_header *eh);
120
void    (*ng_ether_input_orphan_p)(struct ifnet *ifp,
121
                struct mbuf *m, struct ether_header *eh);
122
int     (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
123
void    (*ng_ether_attach_p)(struct ifnet *ifp);
124
void    (*ng_ether_detach_p)(struct ifnet *ifp);
125
 
126
static  int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
127
                                    struct sockaddr *));
128
u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
129
#define senderr(e) do { error = (e); goto bad;} while (0)
130
#define IFP2AC(IFP) ((struct arpcom *)IFP)
131
 
132
/*
133
 * Ethernet output routine.
134
 * Encapsulate a packet of type family for the local net.
135
 * Use trailer local net encapsulation if enough data in first
136
 * packet leaves a multiple of 512 bytes of data in remainder.
137
 * Assumes that ifp is actually pointer to arpcom structure.
138
 */
139
int
140
ether_output(ifp, m, dst, rt0)
141
        register struct ifnet *ifp;
142
        struct mbuf *m;
143
        struct sockaddr *dst;
144
        struct rtentry *rt0;
145
{
146
        short type;
147
        int error = 0, hdrcmplt = 0;
148
        u_char esrc[6], edst[6];
149
        register struct rtentry *rt;
150
        register struct ether_header *eh;
151
        int off, loop_copy = 0;
152
        int hlen;       /* link layer header lenght */
153
        struct arpcom *ac = IFP2AC(ifp);
154
 
155
        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
156
                senderr(ENETDOWN);
157
        rt = rt0;
158
        if (rt) {
159
                if ((rt->rt_flags & RTF_UP) == 0) {
160
                        rt0 = rt = rtalloc1(dst, 1, 0UL);
161
                        if (rt0)
162
                                rt->rt_refcnt--;
163
                        else
164
                                senderr(EHOSTUNREACH);
165
                }
166
                if (rt->rt_flags & RTF_GATEWAY) {
167
                        if (rt->rt_gwroute == 0)
168
                                goto lookup;
169
                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
170
                                rtfree(rt); rt = rt0;
171
                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
172
                                                          0UL);
173
                                if ((rt = rt->rt_gwroute) == 0)
174
                                        senderr(EHOSTUNREACH);
175
                        }
176
                }
177
                if (rt->rt_flags & RTF_REJECT)
178
                        if (rt->rt_rmx.rmx_expire == 0 ||
179
                            time_second < rt->rt_rmx.rmx_expire)
180
                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
181
        }
182
        hlen = ETHER_HDR_LEN;
183
        switch (dst->sa_family) {
184
#ifdef INET
185
        case AF_INET:
186
                if (!arpresolve(ac, rt, m, dst, edst, rt0))
187
                        return (0);      /* if not yet resolved */
188
                off = m->m_pkthdr.len - m->m_len;
189
                type = htons(ETHERTYPE_IP);
190
                break;
191
#endif
192
#ifdef INET6
193
        case AF_INET6:
194
                if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
195
                        /* Something bad happened */
196
                        return(0);
197
                }
198
                off = m->m_pkthdr.len - m->m_len;
199
                type = htons(ETHERTYPE_IPV6);
200
                break;
201
#endif
202
#ifdef IPX
203
        case AF_IPX:
204
                if (ef_outputp) {
205
                    error = ef_outputp(ifp, &m, dst, &type, &hlen);
206
                    if (error)
207
                        goto bad;
208
                } else
209
                    type = htons(ETHERTYPE_IPX);
210
                bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
211
                    (caddr_t)edst, sizeof (edst));
212
                break;
213
#endif
214
#ifdef NETATALK
215
        case AF_APPLETALK:
216
          {
217
            struct at_ifaddr *aa;
218
 
219
            if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
220
                    goto bad;
221
            }
222
            if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
223
                    return (0);
224
            /*
225
             * In the phase 2 case, need to prepend an mbuf for the llc header.
226
             * Since we must preserve the value of m, which is passed to us by
227
             * value, we m_copy() the first mbuf, and use it for our llc header.
228
             */
229
            if ( aa->aa_flags & AFA_PHASE2 ) {
230
                struct llc llc;
231
 
232
                M_PREPEND(m, sizeof(struct llc), M_WAIT);
233
                llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
234
                llc.llc_control = LLC_UI;
235
                bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
236
                llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
237
                bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
238
                type = htons(m->m_pkthdr.len);
239
                hlen = sizeof(struct llc) + ETHER_HDR_LEN;
240
            } else {
241
                type = htons(ETHERTYPE_AT);
242
            }
243
            break;
244
          }
245
#endif /* NETATALK */
246
#ifdef NS
247
        case AF_NS:
248
                switch(ns_nettype){
249
                default:
250
                case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
251
                        type = 0x8137;
252
                        break;
253
                case 0x0: /* Novell 802.3 */
254
                        type = htons( m->m_pkthdr.len);
255
                        break;
256
                case 0xe0e0: /* Novell 802.2 and Token-Ring */
257
                        M_PREPEND(m, 3, M_WAIT);
258
                        type = htons( m->m_pkthdr.len);
259
                        cp = mtod(m, u_char *);
260
                        *cp++ = 0xE0;
261
                        *cp++ = 0xE0;
262
                        *cp++ = 0x03;
263
                        break;
264
                }
265
                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
266
                    (caddr_t)edst, sizeof (edst));
267
                /*
268
                 * XXX if ns_thishost is the same as the node's ethernet
269
                 * address then just the default code will catch this anyhow.
270
                 * So I'm not sure if this next clause should be here at all?
271
                 * [JRE]
272
                 */
273
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
274
                        m->m_pkthdr.rcvif = ifp;
275
                        schednetisr(NETISR_NS);
276
                        inq = &nsintrq;
277
                        s = splimp();
278
                        if (IF_QFULL(inq)) {
279
                                IF_DROP(inq);
280
                                m_freem(m);
281
                        } else
282
                                IF_ENQUEUE(inq, m);
283
                        splx(s);
284
                        return (error);
285
                }
286
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
287
                        m->m_flags |= M_BCAST;
288
                }
289
                break;
290
#endif /* NS */
291
 
292
        case pseudo_AF_HDRCMPLT:
293
                hdrcmplt = 1;
294
                eh = (struct ether_header *)dst->sa_data;
295
                (void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
296
                /* FALLTHROUGH */
297
 
298
        case AF_UNSPEC:
299
                loop_copy = -1; /* if this is for us, don't do it */
300
                eh = (struct ether_header *)dst->sa_data;
301
                (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
302
                type = eh->ether_type;
303
                break;
304
 
305
        default:
306
                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
307
                        dst->sa_family);
308
                senderr(EAFNOSUPPORT);
309
        }
310
 
311
        /*
312
         * Add local net header.  If no space in first mbuf,
313
         * allocate another.
314
         */
315
        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
316
        if (m == 0)
317
                senderr(ENOBUFS);
318
        eh = mtod(m, struct ether_header *);
319
        (void)memcpy(&eh->ether_type, &type,
320
                sizeof(eh->ether_type));
321
        (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
322
        if (hdrcmplt)
323
                (void)memcpy(eh->ether_shost, esrc,
324
                        sizeof(eh->ether_shost));
325
        else
326
                (void)memcpy(eh->ether_shost, ac->ac_enaddr,
327
                        sizeof(eh->ether_shost));
328
 
329
        /*
330
         * If a simplex interface, and the packet is being sent to our
331
         * Ethernet address or a broadcast address, loopback a copy.
332
         * XXX To make a simplex device behave exactly like a duplex
333
         * device, we should copy in the case of sending to our own
334
         * ethernet address (thus letting the original actually appear
335
         * on the wire). However, we don't do that here for security
336
         * reasons and compatibility with the original behavior.
337
         */
338
        if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
339
                if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
340
                        struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
341
 
342
                        (void) if_simloop(ifp, n, dst->sa_family, hlen);
343
                } else if (bcmp(eh->ether_dhost,
344
                    eh->ether_shost, ETHER_ADDR_LEN) == 0) {
345
                        (void) if_simloop(ifp, m, dst->sa_family, hlen);
346
                        return (0);      /* XXX */
347
                }
348
        }
349
 
350
        /* Handle ng_ether(4) processing, if any */
351
        if (ng_ether_output_p != NULL) {
352
                if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
353
bad:                    if (m != NULL)
354
                                m_freem(m);
355
                        return (error);
356
                }
357
                if (m == NULL)
358
                        return (0);
359
        }
360
 
361
        /* Continue with link-layer output */
362
        return ether_output_frame(ifp, m);
363
}
364
 
365
/*
366
 * Ethernet link layer output routine to send a raw frame to the device.
367
 *
368
 * This assumes that the 14 byte Ethernet header is present and contiguous
369
 * in the first mbuf (if BRIDGE'ing).
370
 */
371
int
372
ether_output_frame(ifp, m)
373
        struct ifnet *ifp;
374
        struct mbuf *m;
375
{
376
        int s, len, error = 0;
377
        short mflags;
378
#ifdef ALTQ
379
        struct altq_pktattr pktattr;
380
#endif
381
 
382
#ifdef BRIDGE
383
        if (do_bridge && BDG_USED(ifp) ) {
384
                struct ether_header *eh; /* a ptr suffices */
385
 
386
                m->m_pkthdr.rcvif = NULL;
387
                eh = mtod(m, struct ether_header *);
388
                m_adj(m, ETHER_HDR_LEN);
389
                m = bdg_forward(m, eh, ifp);
390
                if (m != NULL)
391
                        m_freem(m);
392
                return (0);
393
        }
394
#endif
395
#ifdef ALTQ
396
        if (ALTQ_IS_ENABLED(&ifp->if_snd))
397
                altq_etherclassify(&ifp->if_snd, m, &pktattr);
398
#endif
399
        mflags = m->m_flags;
400
        len = m->m_pkthdr.len;
401
        s = splimp();
402
        /*
403
         * Queue message on interface, and start output if interface
404
         * not yet active.
405
         */
406
#ifdef ALTQ
407
        IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
408
#else
409
        IFQ_ENQUEUE(&ifp->if_snd, m, error);
410
#endif
411
        if (error) {
412
                /* mbuf is already freed */
413
                splx(s);
414
                return (error);
415
        }
416
        ifp->if_obytes += len;
417
        if (mflags & M_MCAST)
418
                ifp->if_omcasts++;
419
        if ((ifp->if_flags & IFF_OACTIVE) == 0)
420
                (*ifp->if_start)(ifp);
421
        splx(s);
422
        return (error);
423
}
424
 
425
/*
426
 * Process a received Ethernet packet;
427
 * the packet is in the mbuf chain m without
428
 * the ether header, which is provided separately.
429
 *
430
 * First we perform any link layer operations, then continue
431
 * to the upper layers with ether_demux().
432
 */
433
void
434
ether_input(ifp, eh, m)
435
        struct ifnet *ifp;
436
        struct ether_header *eh;
437
        struct mbuf *m;
438
{
439
#ifdef BRIDGE
440
        struct ether_header save_eh;
441
#endif
442
 
443
#ifdef BPF
444
        /* Check for a BPF tap */
445
        if (ifp->if_bpf != NULL) {
446
                struct m_hdr mh;
447
 
448
                /* This kludge is OK; BPF treats the "mbuf" as read-only */
449
                mh.mh_next = m;
450
                mh.mh_data = (char *)eh;
451
                mh.mh_len = ETHER_HDR_LEN;
452
                bpf_mtap(ifp, (struct mbuf *)&mh);
453
        }
454
#endif
455
 
456
        /* Handle ng_ether(4) processing, if any */
457
        if (ng_ether_input_p != NULL) {
458
                (*ng_ether_input_p)(ifp, &m, eh);
459
                if (m == NULL)
460
                        return;
461
        }
462
 
463
#ifdef BRIDGE
464
        /* Check for bridging mode */
465
        if (do_bridge && BDG_USED(ifp) ) {
466
                struct ifnet *bif;
467
 
468
                /* Check with bridging code */
469
                if ((bif = bridge_in(ifp, eh)) == BDG_DROP) {
470
                        m_freem(m);
471
                        return;
472
                }
473
                if (bif != BDG_LOCAL) {
474
                        struct mbuf *oldm = m ;
475
 
476
                        save_eh = *eh ; /* because it might change */
477
                        m = bdg_forward(m, eh, bif);    /* needs forwarding */
478
                        /*
479
                         * Do not continue if bdg_forward() processed our
480
                         * packet (and cleared the mbuf pointer m) or if
481
                         * it dropped (m_free'd) the packet itself.
482
                         */
483
                        if (m == NULL) {
484
                            if (bif == BDG_BCAST || bif == BDG_MCAST)
485
                                printf("bdg_forward drop MULTICAST PKT\n");
486
                            return;
487
                        }
488
                        if (m != oldm) /* m changed! */
489
                            eh = &save_eh ;
490
                }
491
                if (bif == BDG_LOCAL
492
                    || bif == BDG_BCAST
493
                    || bif == BDG_MCAST)
494
                        goto recvLocal;                 /* receive locally */
495
 
496
                /* If not local and not multicast, just drop it */
497
                if (m != NULL)
498
                        m_freem(m);
499
                return;
500
       }
501
#endif
502
 
503
#ifdef BRIDGE
504
recvLocal:
505
#endif
506
        /* Continue with upper layer processing */
507
        ether_demux(ifp, eh, m);
508
}
509
 
510
/*
511
 * Upper layer processing for a received Ethernet packet.
512
 */
513
void
514
ether_demux(ifp, eh, m)
515
        struct ifnet *ifp;
516
        struct ether_header *eh;
517
        struct mbuf *m;
518
{
519
        struct ifqueue *inq;
520
        u_short ether_type;
521
        int s;
522
#if defined(NETATALK)
523
        register struct llc *l;
524
#endif
525
 
526
#ifdef BRIDGE
527
    if (! (do_bridge && BDG_USED(ifp) ) )
528
#endif
529
        /* Discard packet if upper layers shouldn't see it because it was
530
           unicast to a different Ethernet address. If the driver is working
531
           properly, then this situation can only happen when the interface
532
           is in promiscuous mode. */
533
        if ((ifp->if_flags & IFF_PROMISC) != 0
534
            && (eh->ether_dhost[0] & 1) == 0
535
            && bcmp(eh->ether_dhost,
536
              IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) {
537
                m_freem(m);
538
                return;
539
        }
540
 
541
        /* Discard packet if interface is not up */
542
        if ((ifp->if_flags & IFF_UP) == 0) {
543
                m_freem(m);
544
                return;
545
        }
546
        if (eh->ether_dhost[0] & 1) {
547
                /*
548
                 * If this is not a simplex interface, drop the packet
549
                 * if it came from us.
550
                 */
551
                if ((ifp->if_flags & IFF_SIMPLEX) == 0) {
552
                        struct ifaddr *ifa;
553
                        struct sockaddr_dl *sdl = NULL;
554
 
555
                        /* find link-layer address */
556
                        TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
557
                                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
558
                                    sdl->sdl_family == AF_LINK)
559
                                        break;
560
 
561
                        if (sdl && bcmp(LLADDR(sdl), eh->ether_shost,
562
                            ETHER_ADDR_LEN) == 0) {
563
                                m_freem(m);
564
                                return;
565
                        }
566
                }
567
                if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
568
                         sizeof(etherbroadcastaddr)) == 0)
569
                        m->m_flags |= M_BCAST;
570
                else
571
                        m->m_flags |= M_MCAST;
572
        }
573
        if (m->m_flags & (M_BCAST|M_MCAST))
574
                ifp->if_imcasts++;
575
 
576
        ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
577
 
578
        ether_type = ntohs(eh->ether_type);
579
 
580
#if NVLAN > 0
581
        if (ether_type == vlan_proto) {
582
                if (vlan_input(eh, m) < 0)
583
                        ifp->if_data.ifi_noproto++;
584
                return;
585
        }
586
#endif /* NVLAN > 0 */
587
 
588
        switch (ether_type) {
589
#ifdef INET
590
        case ETHERTYPE_IP:
591
                if (ipflow_fastforward(m))
592
                        return;
593
                schednetisr(NETISR_IP);
594
                inq = &ipintrq;
595
                break;
596
 
597
        case ETHERTYPE_ARP:
598
                if (ifp->if_flags & IFF_NOARP) {
599
                        /* Discard packet if ARP is disabled on interface */
600
                        m_freem(m);
601
                        return;
602
                }
603
                schednetisr(NETISR_ARP);
604
                inq = &arpintrq;
605
                break;
606
#endif
607
#ifdef IPX
608
        case ETHERTYPE_IPX:
609
                if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
610
                        return;
611
                schednetisr(NETISR_IPX);
612
                inq = &ipxintrq;
613
                break;
614
#endif
615
#ifdef INET6
616
        case ETHERTYPE_IPV6:
617
                schednetisr(NETISR_IPV6);
618
                inq = &ip6intrq;
619
                break;
620
#endif
621
#ifdef NS
622
        case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
623
                schednetisr(NETISR_NS);
624
                inq = &nsintrq;
625
                break;
626
 
627
#endif /* NS */
628
#ifdef NETATALK
629
        case ETHERTYPE_AT:
630
                schednetisr(NETISR_ATALK);
631
                inq = &atintrq1;
632
                break;
633
        case ETHERTYPE_AARP:
634
                /* probably this should be done with a NETISR as well */
635
                aarpinput(IFP2AC(ifp), m); /* XXX */
636
                return;
637
#endif /* NETATALK */
638
        default:
639
#ifdef IPX
640
                if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
641
                        return;
642
#endif /* IPX */
643
#ifdef NS
644
                checksum = mtod(m, ushort *);
645
                /* Novell 802.3 */
646
                if ((ether_type <= ETHERMTU) &&
647
                        ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
648
                        if(*checksum == 0xE0E0) {
649
                                m->m_pkthdr.len -= 3;
650
                                m->m_len -= 3;
651
                                m->m_data += 3;
652
                        }
653
                                schednetisr(NETISR_NS);
654
                                inq = &nsintrq;
655
                                break;
656
                }
657
#endif /* NS */
658
#if defined(NETATALK)
659
                if (ether_type > ETHERMTU)
660
                        goto dropanyway;
661
                l = mtod(m, struct llc *);
662
                switch (l->llc_dsap) {
663
                case LLC_SNAP_LSAP:
664
                    switch (l->llc_control) {
665
                    case LLC_UI:
666
                        if (l->llc_ssap != LLC_SNAP_LSAP)
667
                            goto dropanyway;
668
 
669
                        if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
670
                                   sizeof(at_org_code)) == 0 &&
671
                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
672
                            inq = &atintrq2;
673
                            m_adj( m, sizeof( struct llc ));
674
                            schednetisr(NETISR_ATALK);
675
                            break;
676
                        }
677
 
678
                        if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
679
                                   sizeof(aarp_org_code)) == 0 &&
680
                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
681
                            m_adj( m, sizeof( struct llc ));
682
                            aarpinput(IFP2AC(ifp), m); /* XXX */
683
                            return;
684
                        }
685
 
686
                    default:
687
                        goto dropanyway;
688
                    }
689
                    break;
690
                dropanyway:
691
                default:
692
                        if (ng_ether_input_orphan_p != NULL)
693
                                (*ng_ether_input_orphan_p)(ifp, m, eh);
694
                        else
695
                                m_freem(m);
696
                        return;
697
                }
698
#else /* NETATALK */
699
                if (ng_ether_input_orphan_p != NULL)
700
                        (*ng_ether_input_orphan_p)(ifp, m, eh);
701
                else
702
                        m_freem(m);
703
                return;
704
#endif /* NETATALK */
705
        }
706
 
707
        s = splimp();
708
        if (IF_QFULL(inq)) {
709
                IF_DROP(inq);
710
                m_freem(m);
711
        } else
712
                IF_ENQUEUE(inq, m);
713
        splx(s);
714
}
715
 
716
/*
717
 * Perform common duties while attaching to interface list
718
 */
719
void
720
ether_ifattach(ifp, bpf)
721
        register struct ifnet *ifp;
722
        int bpf;
723
{
724
        register struct ifaddr *ifa;
725
        register struct sockaddr_dl *sdl;
726
 
727
        if_attach(ifp);
728
        ifp->if_type = IFT_ETHER;
729
        ifp->if_addrlen = 6;
730
        ifp->if_hdrlen = 14;
731
        ifp->if_mtu = ETHERMTU;
732
        ifp->if_resolvemulti = ether_resolvemulti;
733
        if (ifp->if_baudrate == 0)
734
            ifp->if_baudrate = 10000000;
735
        ifa = ifnet_addrs[ifp->if_index - 1];
736
        sdl = (struct sockaddr_dl *)ifa->ifa_addr;
737
        sdl->sdl_type = IFT_ETHER;
738
        sdl->sdl_alen = ifp->if_addrlen;
739
        bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
740
#ifdef BPF
741
        if (bpf)
742
                bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
743
#endif
744
        if (ng_ether_attach_p != NULL)
745
                (*ng_ether_attach_p)(ifp);
746
}
747
 
748
/*
749
 * Perform common duties while detaching an Ethernet interface
750
 */
751
void
752
ether_ifdetach(ifp, bpf)
753
        struct ifnet *ifp;
754
        int bpf;
755
{
756
        if (ng_ether_detach_p != NULL)
757
                (*ng_ether_detach_p)(ifp);
758
#ifdef BPF
759
        if (bpf)
760
                bpfdetach(ifp);
761
#endif
762
        if_detach(ifp);
763
}
764
 
765
int
766
ether_ioctl(ifp, command, data)
767
        struct ifnet *ifp;
768
        int command;
769
        caddr_t data;
770
{
771
        struct ifaddr *ifa = (struct ifaddr *) data;
772
        struct ifreq *ifr = (struct ifreq *) data;
773
        int error = 0;
774
 
775
        switch (command) {
776
        case SIOCSIFADDR:
777
                ifp->if_flags |= IFF_UP;
778
 
779
                switch (ifa->ifa_addr->sa_family) {
780
#ifdef INET
781
                case AF_INET:
782
                        ifp->if_init(ifp->if_softc);    /* before arpwhohas */
783
                        arp_ifinit(IFP2AC(ifp), ifa);
784
                        break;
785
#endif
786
#ifdef IPX
787
                /*
788
                 * XXX - This code is probably wrong
789
                 */
790
                case AF_IPX:
791
                        {
792
                        register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
793
                        struct arpcom *ac = IFP2AC(ifp);
794
 
795
                        if (ipx_nullhost(*ina))
796
                                ina->x_host =
797
                                    *(union ipx_host *)
798
                                    ac->ac_enaddr;
799
                        else {
800
                                bcopy((caddr_t) ina->x_host.c_host,
801
                                      (caddr_t) ac->ac_enaddr,
802
                                      sizeof(ac->ac_enaddr));
803
                        }
804
 
805
                        /*
806
                         * Set new address
807
                         */
808
                        ifp->if_init(ifp->if_softc);
809
                        break;
810
                        }
811
#endif
812
#ifdef NS
813
                /*
814
                 * XXX - This code is probably wrong
815
                 */
816
                case AF_NS:
817
                {
818
                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
819
                        struct arpcom *ac = IFP2AC(ifp);
820
 
821
                        if (ns_nullhost(*ina))
822
                                ina->x_host =
823
                                    *(union ns_host *) (ac->ac_enaddr);
824
                        else {
825
                                bcopy((caddr_t) ina->x_host.c_host,
826
                                      (caddr_t) ac->ac_enaddr,
827
                                      sizeof(ac->ac_enaddr));
828
                        }
829
 
830
                        /*
831
                         * Set new address
832
                         */
833
                        ifp->if_init(ifp->if_softc);
834
                        break;
835
                }
836
#endif
837
                default:
838
                        ifp->if_init(ifp->if_softc);
839
                        break;
840
                }
841
                break;
842
 
843
        case SIOCGIFADDR:
844
                {
845
                        struct sockaddr *sa;
846
 
847
                        sa = (struct sockaddr *) & ifr->ifr_data;
848
                        bcopy(IFP2AC(ifp)->ac_enaddr,
849
                              (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
850
                }
851
                break;
852
 
853
        case SIOCSIFMTU:
854
                /*
855
                 * Set the interface MTU.
856
                 */
857
                if (ifr->ifr_mtu > ETHERMTU) {
858
                        error = EINVAL;
859
                } else {
860
                        ifp->if_mtu = ifr->ifr_mtu;
861
                }
862
                break;
863
        }
864
        return (error);
865
}
866
 
867
int
868
ether_resolvemulti(ifp, llsa, sa)
869
        struct ifnet *ifp;
870
        struct sockaddr **llsa;
871
        struct sockaddr *sa;
872
{
873
        struct sockaddr_dl *sdl;
874
        struct sockaddr_in *sin;
875
#ifdef INET6
876
        struct sockaddr_in6 *sin6;
877
#endif
878
        u_char *e_addr;
879
 
880
        switch(sa->sa_family) {
881
        case AF_LINK:
882
                /*
883
                 * No mapping needed. Just check that it's a valid MC address.
884
                 */
885
                sdl = (struct sockaddr_dl *)sa;
886
                e_addr = LLADDR(sdl);
887
                if ((e_addr[0] & 1) != 1)
888
                        return EADDRNOTAVAIL;
889
                *llsa = 0;
890
                return 0;
891
 
892
#ifdef INET
893
        case AF_INET:
894
                sin = (struct sockaddr_in *)sa;
895
                if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
896
                        return EADDRNOTAVAIL;
897
                MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
898
                       M_WAITOK|M_ZERO);
899
                sdl->sdl_len = sizeof *sdl;
900
                sdl->sdl_family = AF_LINK;
901
                sdl->sdl_index = ifp->if_index;
902
                sdl->sdl_type = IFT_ETHER;
903
                sdl->sdl_alen = ETHER_ADDR_LEN;
904
                e_addr = LLADDR(sdl);
905
                ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
906
                *llsa = (struct sockaddr *)sdl;
907
                return 0;
908
#endif
909
#ifdef INET6
910
        case AF_INET6:
911
                sin6 = (struct sockaddr_in6 *)sa;
912
                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
913
                        /*
914
                         * An IP6 address of 0 means listen to all
915
                         * of the Ethernet multicast address used for IP6.
916
                         * (This is used for multicast routers.)
917
                         */
918
                        ifp->if_flags |= IFF_ALLMULTI;
919
                        *llsa = 0;
920
                        return 0;
921
                }
922
                if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
923
                        return EADDRNOTAVAIL;
924
                MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
925
                       M_WAITOK|M_ZERO);
926
                sdl->sdl_len = sizeof *sdl;
927
                sdl->sdl_family = AF_LINK;
928
                sdl->sdl_index = ifp->if_index;
929
                sdl->sdl_type = IFT_ETHER;
930
                sdl->sdl_alen = ETHER_ADDR_LEN;
931
                e_addr = LLADDR(sdl);
932
                ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
933
                *llsa = (struct sockaddr *)sdl;
934
                return 0;
935
#endif
936
 
937
        default:
938
                /*
939
                 * Well, the text isn't quite right, but it's the name
940
                 * that counts...
941
                 */
942
                return EAFNOSUPPORT;
943
        }
944
}

powered by: WebSVN 2.1.0

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