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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [bsd_tcpip/] [current/] [src/] [sys/] [net/] [if_ethersubr.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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