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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [net/] [if_ethersubr.c] - Blame information for rev 773

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

Line No. Rev Author Line
1 30 unneback
/*
2
 * Copyright (c) 1982, 1989, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
34
 * $Id: if_ethersubr.c,v 1.2 2001-09-27 12:01:54 chris Exp $
35
 */
36
 
37
#include <sys/param.h>
38
#include <sys/systm.h>
39
#include <sys/kernel.h>
40
#include <sys/malloc.h>
41
#include <sys/mbuf.h>
42
#include <sys/protosw.h>
43
#include <sys/socket.h>
44
#include <sys/ioctl.h>
45
#include <sys/errno.h>
46
#include <sys/syslog.h>
47
#include <sys/sysctl.h>
48
 
49
#include <net/if.h>
50
#include <net/netisr.h>
51
#include <net/route.h>
52
#include <net/if_llc.h>
53
#include <net/if_dl.h>
54
#include <net/if_types.h>
55
#include <net/ethernet.h>
56
 
57
#ifdef INET
58
#include <netinet/in.h>
59
#include <netinet/in_var.h>
60
#endif
61
#include <netinet/if_ether.h>
62
 
63
#ifdef IPX
64
#include <netipx/ipx.h>
65
#include <netipx/ipx_if.h>
66
#endif
67
 
68
#ifdef NS
69
#include <netns/ns.h>
70
#include <netns/ns_if.h>
71
ushort ns_nettype;
72
int ether_outputdebug = 0;
73
int ether_inputdebug = 0;
74
#endif
75
 
76
#ifdef ISO
77
#include <netiso/argo_debug.h>
78
#include <netiso/iso.h>
79
#include <netiso/iso_var.h>
80
#include <netiso/iso_snpac.h>
81
#endif
82
 
83
/*#ifdef LLC
84
#include <netccitt/dll.h>
85
#include <netccitt/llc_var.h>
86
#endif*/
87
 
88
#if defined(LLC) && defined(CCITT)
89
extern struct ifqueue pkintrq;
90
#endif
91
 
92
#ifdef NETATALK
93
#include <netatalk/at.h>
94
#include <netatalk/at_var.h>
95
#include <netatalk/at_extern.h>
96
 
97
#define llc_snap_org_code llc_un.type_snap.org_code
98
#define llc_snap_ether_type llc_un.type_snap.ether_type
99
 
100
extern u_char   at_org_code[ 3 ];
101
extern u_char   aarp_org_code[ 3 ];
102
#endif NETATALK
103
 
104
u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
105
#define senderr(e) { error = (e); goto bad;}
106
 
107
/*
108
 * Ethernet output routine.
109
 * Encapsulate a packet of type family for the local net.
110
 * Use trailer local net encapsulation if enough data in first
111
 * packet leaves a multiple of 512 bytes of data in remainder.
112
 * Assumes that ifp is actually pointer to arpcom structure.
113
 */
114
int
115
ether_output(ifp, m0, dst, rt0)
116
        register struct ifnet *ifp;
117
        struct mbuf *m0;
118
        struct sockaddr *dst;
119
        struct rtentry *rt0;
120
{
121
        short type;
122
        int s, error = 0;
123
#ifdef NS
124
        u_char *cp
125
        register struct ifqueue *inq;
126
        register struct mbuf *m2;
127
#endif
128
        u_char  edst[6];
129
        register struct mbuf *m = m0;
130
        register struct rtentry *rt;
131
        struct mbuf *mcopy = (struct mbuf *)0;
132
        register struct ether_header *eh;
133
        int off, len = m->m_pkthdr.len;
134
        struct arpcom *ac = (struct arpcom *)ifp;
135
#ifdef NETATALK
136
        struct at_ifaddr *aa;
137
#endif NETATALK
138
 
139
        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
140
                senderr(ENETDOWN);
141
        rt = rt0;
142
        if (rt) {
143
                if ((rt->rt_flags & RTF_UP) == 0) {
144
                        rt0 = rt = rtalloc1(dst, 1, 0UL);
145
                        if (rt0)
146
                                rt->rt_refcnt--;
147
                        else
148
                                senderr(EHOSTUNREACH);
149
                }
150
                if (rt->rt_flags & RTF_GATEWAY) {
151
                        if (rt->rt_gwroute == 0)
152
                                goto lookup;
153
                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
154
                                rtfree(rt); rt = rt0;
155
                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
156
                                                          0UL);
157
                                if ((rt = rt->rt_gwroute) == 0)
158
                                        senderr(EHOSTUNREACH);
159
                        }
160
                }
161
                if (rt->rt_flags & RTF_REJECT)
162
                        if (rt->rt_rmx.rmx_expire == 0 ||
163
                            rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire)
164
                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
165
        }
166
        switch (dst->sa_family) {
167
 
168
#ifdef INET
169
        case AF_INET:
170
                if (!arpresolve(ac, rt, m, dst, edst, rt0))
171
                        return (0);      /* if not yet resolved */
172
                /* If broadcasting on a simplex interface, loopback a copy */
173
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
174
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
175
                off = m->m_pkthdr.len - m->m_len;
176
                type = htons(ETHERTYPE_IP);
177
                break;
178
#endif
179
#ifdef IPX
180
        case AF_IPX:
181
                {
182
                struct ifaddr *ia;
183
 
184
                type = htons(ETHERTYPE_IPX);
185
                bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
186
                    (caddr_t)edst, sizeof (edst));
187
                for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next)
188
                        if(ia->ifa_addr->sa_family == AF_IPX &&
189
                           !bcmp((caddr_t)edst,
190
                                 (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host,
191
                                 sizeof(edst)))
192
                                return (looutput(ifp, m, dst, rt));
193
                /* If broadcasting on a simplex interface, loopback a copy */
194
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
195
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
196
                break;
197
                }
198
#endif
199
#ifdef NETATALK
200
        case AF_APPLETALK:
201
            {
202
                struct sockaddr_at *sat = (struct sockaddr_at *)dst;
203
 
204
                /*
205
                 * super hack..
206
                 * Most of this loopback code should move into the appletalk
207
                 * code, but it's here for now.. remember to move it! [JRE]
208
                 * This may not get the same interface we started with
209
                 * fix asap. XXX
210
                 */
211
                aa = at_ifawithnet( sat );
212
                if (aa == NULL) {
213
                        goto bad;
214
                }
215
                if( aa->aa_ifa.ifa_ifp != ifp ) {
216
                        (*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp,
217
                                                        m,dst,rt);
218
                }
219
                if (((sat->sat_addr.s_net == ATADDR_ANYNET)
220
                  && (sat->sat_addr.s_node == ATADDR_ANYNODE))
221
                || ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net )
222
                  && (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) {
223
                        (void) looutput(ifp, m, dst, rt);
224
                        return(0);
225
                }
226
 
227
                if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
228
#ifdef NETATALKDEBUG
229
                        extern char *prsockaddr(struct sockaddr *);
230
                        printf("aarpresolv: failed for %s\n", prsockaddr(dst));
231
#endif NETATALKDEBUG
232
                        return (0);
233
                }
234
 
235
                /*
236
                 * If broadcasting on a simplex interface, loopback a copy
237
                 */
238
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
239
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
240
            }
241
            /*
242
             * In the phase 2 case, we need to prepend an mbuf for the llc header.
243
             * Since we must preserve the value of m, which is passed to us by
244
             * value, we m_copy() the first mbuf, and use it for our llc header.
245
             */
246
            if ( aa->aa_flags & AFA_PHASE2 ) {
247
                struct llc llc;
248
 
249
                M_PREPEND(m, sizeof(struct llc), M_WAIT);
250
                len += sizeof(struct llc);
251
                llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
252
                llc.llc_control = LLC_UI;
253
                bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
254
                llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
255
                bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
256
                type = htons(m->m_pkthdr.len);
257
            } else {
258
                type = htons(ETHERTYPE_AT);
259
            }
260
            break;
261
#endif NETATALK
262
#ifdef NS
263
        case AF_NS:
264
                switch(ns_nettype){
265
                default:
266
                case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
267
                        type = 0x8137;
268
                        break;
269
                case 0x0: /* Novell 802.3 */
270
                        type = htons( m->m_pkthdr.len);
271
                        break;
272
                case 0xe0e0: /* Novell 802.2 and Token-Ring */
273
                        M_PREPEND(m, 3, M_WAIT);
274
                        type = htons( m->m_pkthdr.len);
275
                        cp = mtod(m, u_char *);
276
                        *cp++ = 0xE0;
277
                        *cp++ = 0xE0;
278
                        *cp++ = 0x03;
279
                        break;
280
                }
281
                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
282
                    (caddr_t)edst, sizeof (edst));
283
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
284
                        m->m_pkthdr.rcvif = ifp;
285
                        schednetisr(NETISR_NS);
286
                        inq = &nsintrq;
287
                        s = splimp();
288
                        if (IF_QFULL(inq)) {
289
                                IF_DROP(inq);
290
                                m_freem(m);
291
                        } else
292
                                IF_ENQUEUE(inq, m);
293
                        splx(s);
294
                        return (error);
295
                }
296
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
297
                        m2 = m_copy(m, 0, (int)M_COPYALL);
298
                        m2->m_pkthdr.rcvif = ifp;
299
                        schednetisr(NETISR_NS);
300
                        inq = &nsintrq;
301
                        s = splimp();
302
                        if (IF_QFULL(inq)) {
303
                                IF_DROP(inq);
304
                                m_freem(m2);
305
                        } else
306
                                IF_ENQUEUE(inq, m2);
307
                        splx(s);
308
                }
309
                /* If broadcasting on a simplex interface, loopback a copy */
310
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){
311
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
312
                }
313
                break;
314
#endif /* NS */
315
#ifdef  ISO
316
        case AF_ISO: {
317
                int     snpalen;
318
                struct  llc *l;
319
                register struct sockaddr_dl *sdl;
320
 
321
                if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
322
                    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
323
                        bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
324
                } else if (error =
325
                            iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
326
                                            (char *)edst, &snpalen))
327
                        goto bad; /* Not Resolved */
328
                /* If broadcasting on a simplex interface, loopback a copy */
329
                if (*edst & 1)
330
                        m->m_flags |= (M_BCAST|M_MCAST);
331
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
332
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
333
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
334
                        if (mcopy) {
335
                                eh = mtod(mcopy, struct ether_header *);
336
                                bcopy((caddr_t)edst,
337
                                      (caddr_t)eh->ether_dhost, sizeof (edst));
338
                                bcopy((caddr_t)ac->ac_enaddr,
339
                                      (caddr_t)eh->ether_shost, sizeof (edst));
340
                        }
341
                }
342
                M_PREPEND(m, 3, M_DONTWAIT);
343
                if (m == NULL)
344
                        return (0);
345
                type = htons(m->m_pkthdr.len);
346
                l = mtod(m, struct llc *);
347
                l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
348
                l->llc_control = LLC_UI;
349
                len += 3;
350
                IFDEBUG(D_ETHER)
351
                        int i;
352
                        printf("unoutput: sending pkt to: ");
353
                        for (i=0; i<6; i++)
354
                                printf("%x ", edst[i] & 0xff);
355
                        printf("\n");
356
                ENDDEBUG
357
                } break;
358
#endif /* ISO */
359
#ifdef  LLC
360
/*      case AF_NSAP: */
361
        case AF_CCITT: {
362
                register struct sockaddr_dl *sdl =
363
                        (struct sockaddr_dl *) rt -> rt_gateway;
364
 
365
                if (sdl && sdl->sdl_family == AF_LINK
366
                    && sdl->sdl_alen > 0) {
367
                        bcopy(LLADDR(sdl), (char *)edst,
368
                                sizeof(edst));
369
                } else goto bad; /* Not a link interface ? Funny ... */
370
                if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
371
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
372
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
373
                        if (mcopy) {
374
                                eh = mtod(mcopy, struct ether_header *);
375
                                bcopy((caddr_t)edst,
376
                                      (caddr_t)eh->ether_dhost, sizeof (edst));
377
                                bcopy((caddr_t)ac->ac_enaddr,
378
                                      (caddr_t)eh->ether_shost, sizeof (edst));
379
                        }
380
                }
381
                type = htons(m->m_pkthdr.len);
382
#ifdef LLC_DEBUG
383
                {
384
                        int i;
385
                        register struct llc *l = mtod(m, struct llc *);
386
 
387
                        printf("ether_output: sending LLC2 pkt to: ");
388
                        for (i=0; i<6; i++)
389
                                printf("%x ", edst[i] & 0xff);
390
                        printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
391
                               type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
392
                               l->llc_control & 0xff);
393
 
394
                }
395
#endif /* LLC_DEBUG */
396
                } break;
397
#endif /* LLC */
398
 
399
        case AF_UNSPEC:
400
                eh = (struct ether_header *)dst->sa_data;
401
                (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
402
                type = eh->ether_type;
403
                break;
404
 
405
        default:
406
                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
407
                        dst->sa_family);
408
                senderr(EAFNOSUPPORT);
409
        }
410
 
411
 
412
        if (mcopy)
413
                (void) looutput(ifp, mcopy, dst, rt);
414
        /*
415
         * Add local net header.  If no space in first mbuf,
416
         * allocate another.
417
         */
418
        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
419
        if (m == 0)
420
                senderr(ENOBUFS);
421
        eh = mtod(m, struct ether_header *);
422
        (void)memcpy(&eh->ether_type, &type,
423
                sizeof(eh->ether_type));
424
        (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
425
        (void)memcpy(eh->ether_shost, ac->ac_enaddr,
426
            sizeof(eh->ether_shost));
427
        s = splimp();
428
        /*
429
         * Queue message on interface, and start output if interface
430
         * not yet active.
431
         */
432
        if (IF_QFULL(&ifp->if_snd)) {
433
                IF_DROP(&ifp->if_snd);
434
                splx(s);
435
                senderr(ENOBUFS);
436
        }
437
        IF_ENQUEUE(&ifp->if_snd, m);
438
        if ((ifp->if_flags & IFF_OACTIVE) == 0)
439
                (*ifp->if_start)(ifp);
440
        splx(s);
441
        ifp->if_obytes += len + sizeof (struct ether_header);
442
        if (m->m_flags & M_MCAST)
443
                ifp->if_omcasts++;
444
        return (error);
445
 
446
bad:
447
        if (m)
448
                m_freem(m);
449
        return (error);
450
}
451
 
452
/*
453
 * Process a received Ethernet packet;
454
 * the packet is in the mbuf chain m without
455
 * the ether header, which is provided separately.
456
 */
457
void
458
ether_input(ifp, eh, m)
459
        struct ifnet *ifp;
460
        register struct ether_header *eh;
461
        struct mbuf *m;
462
{
463
        register struct ifqueue *inq;
464
        u_short ether_type;
465
#ifdef NS
466
        u_short *checksum;
467
#endif
468
        int s;
469
#if defined (ISO) || defined (LLC) || defined(NETATALK)
470
        register struct llc *l;
471
#endif
472
 
473
        if ((ifp->if_flags & IFF_UP) == 0) {
474
                m_freem(m);
475
                return;
476
        }
477
        ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
478
        if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
479
            sizeof(etherbroadcastaddr)) == 0)
480
                m->m_flags |= M_BCAST;
481
        else if (eh->ether_dhost[0] & 1)
482
                m->m_flags |= M_MCAST;
483
        if (m->m_flags & (M_BCAST|M_MCAST))
484
                ifp->if_imcasts++;
485
 
486
        /*
487
         * RTEMS addition -- allow application to `tap into'
488
         * the incoming packet stream.
489
         */
490
        if (ifp->if_tap && (*ifp->if_tap)(ifp, eh, m)) {
491
                m_freem(m);
492
                return;
493
        }
494
 
495
        ether_type = ntohs(eh->ether_type);
496
 
497
        switch (ether_type) {
498
#ifdef INET
499
        case ETHERTYPE_IP:
500
                schednetisr(NETISR_IP);
501
                inq = &ipintrq;
502
                break;
503
 
504
        case ETHERTYPE_ARP:
505
                schednetisr(NETISR_ARP);
506
                inq = &arpintrq;
507
                break;
508
#endif
509
#ifdef IPX
510
        case ETHERTYPE_IPX:
511
                schednetisr(NETISR_IPX);
512
                inq = &ipxintrq;
513
                break;
514
#endif
515
#ifdef NS
516
        case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
517
                schednetisr(NETISR_NS);
518
                inq = &nsintrq;
519
                break;
520
 
521
#endif /* NS */
522
#ifdef NETATALK
523
        case ETHERTYPE_AT:
524
                schednetisr(NETISR_ATALK);
525
                inq = &atintrq1;
526
                break;
527
        case ETHERTYPE_AARP:
528
                /* probably this should be done with a NETISR as well */
529
                aarpinput((struct arpcom *)ifp, m); /* XXX */
530
                return;
531
#endif NETATALK
532
        default:
533
#ifdef NS
534
                checksum = mtod(m, ushort *);
535
                /* Novell 802.3 */
536
                if ((ether_type <= ETHERMTU) &&
537
                        ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
538
                        if(*checksum == 0xE0E0) {
539
                                m->m_pkthdr.len -= 3;
540
                                m->m_len -= 3;
541
                                m->m_data += 3;
542
                        }
543
                                schednetisr(NETISR_NS);
544
                                inq = &nsintrq;
545
                                break;
546
                }
547
#endif /* NS */
548
#if defined (ISO) || defined (LLC) || defined(NETATALK)
549
                if (ether_type > ETHERMTU)
550
                        goto dropanyway;
551
                l = mtod(m, struct llc *);
552
                switch (l->llc_dsap) {
553
#ifdef NETATALK
554
                case LLC_SNAP_LSAP:
555
                    switch (l->llc_control) {
556
                    case LLC_UI:
557
                        if (l->llc_ssap != LLC_SNAP_LSAP)
558
                            goto dropanyway;
559
 
560
                        if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
561
                                   sizeof(at_org_code)) == 0 &&
562
                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
563
                            inq = &atintrq2;
564
                            m_adj( m, sizeof( struct llc ));
565
                            schednetisr(NETISR_ATALK);
566
                            break;
567
                        }
568
 
569
                        if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
570
                                   sizeof(aarp_org_code)) == 0 &&
571
                             ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
572
                            m_adj( m, sizeof( struct llc ));
573
                            aarpinput((struct arpcom *)ifp, m); /* XXX */
574
                            return;
575
                        }
576
 
577
                    default:
578
                        goto dropanyway;
579
                    }
580
                    break;
581
#endif NETATALK 
582
#ifdef  ISO
583
                case LLC_ISO_LSAP:
584
                        switch (l->llc_control) {
585
                        case LLC_UI:
586
                                /* LLC_UI_P forbidden in class 1 service */
587
                                if ((l->llc_dsap == LLC_ISO_LSAP) &&
588
                                    (l->llc_ssap == LLC_ISO_LSAP)) {
589
                                        /* LSAP for ISO */
590
                                        if (m->m_pkthdr.len > ether_type)
591
                                                m_adj(m, ether_type - m->m_pkthdr.len);
592
                                        m->m_data += 3;         /* XXX */
593
                                        m->m_len -= 3;          /* XXX */
594
                                        m->m_pkthdr.len -= 3;   /* XXX */
595
                                        M_PREPEND(m, sizeof *eh, M_DONTWAIT);
596
                                        if (m == 0)
597
                                                return;
598
                                        *mtod(m, struct ether_header *) = *eh;
599
                                        IFDEBUG(D_ETHER)
600
                                                printf("clnp packet");
601
                                        ENDDEBUG
602
                                        schednetisr(NETISR_ISO);
603
                                        inq = &clnlintrq;
604
                                        break;
605
                                }
606
                                goto dropanyway;
607
 
608
                        case LLC_XID:
609
                        case LLC_XID_P:
610
                                if(m->m_len < 6)
611
                                        goto dropanyway;
612
                                l->llc_window = 0;
613
                                l->llc_fid = 9;
614
                                l->llc_class = 1;
615
                                l->llc_dsap = l->llc_ssap = 0;
616
                                /* Fall through to */
617
                        case LLC_TEST:
618
                        case LLC_TEST_P:
619
                        {
620
                                struct sockaddr sa;
621
                                register struct ether_header *eh2;
622
                                int i;
623
                                u_char c = l->llc_dsap;
624
 
625
                                l->llc_dsap = l->llc_ssap;
626
                                l->llc_ssap = c;
627
                                if (m->m_flags & (M_BCAST | M_MCAST))
628
                                        bcopy((caddr_t)ac->ac_enaddr,
629
                                              (caddr_t)eh->ether_dhost, 6);
630
                                sa.sa_family = AF_UNSPEC;
631
                                sa.sa_len = sizeof(sa);
632
                                eh2 = (struct ether_header *)sa.sa_data;
633
                                for (i = 0; i < 6; i++) {
634
                                        eh2->ether_shost[i] = c = eh->ether_dhost[i];
635
                                        eh2->ether_dhost[i] =
636
                                                eh->ether_dhost[i] = eh->ether_shost[i];
637
                                        eh->ether_shost[i] = c;
638
                                }
639
                                ifp->if_output(ifp, m, &sa, NULL);
640
                                return;
641
                        }
642
                        default:
643
                                m_freem(m);
644
                                return;
645
                        }
646
                        break;
647
#endif /* ISO */
648
#ifdef LLC
649
                case LLC_X25_LSAP:
650
                {
651
                        if (m->m_pkthdr.len > ether_type)
652
                                m_adj(m, ether_type - m->m_pkthdr.len);
653
                        M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
654
                        if (m == 0)
655
                                return;
656
                        if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
657
                                            eh->ether_dhost, LLC_X25_LSAP, 6,
658
                                            mtod(m, struct sdl_hdr *)))
659
                                panic("ETHER cons addr failure");
660
                        mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
661
#ifdef LLC_DEBUG
662
                                printf("llc packet\n");
663
#endif /* LLC_DEBUG */
664
                        schednetisr(NETISR_CCITT);
665
                        inq = &llcintrq;
666
                        break;
667
                }
668
#endif /* LLC */
669
                dropanyway:
670
                default:
671
                        m_freem(m);
672
                        return;
673
                }
674
#else /* ISO || LLC || NETATALK */
675
            m_freem(m);
676
            return;
677
#endif /* ISO || LLC || NETATALK */
678
        }
679
 
680
        s = splimp();
681
        if (IF_QFULL(inq)) {
682
                IF_DROP(inq);
683
                m_freem(m);
684
        } else
685
                IF_ENQUEUE(inq, m);
686
        splx(s);
687
}
688
 
689
/*
690
 * Perform common duties while attaching to interface list
691
 */
692
void
693
ether_ifattach(ifp)
694
        register struct ifnet *ifp;
695
{
696
        register struct ifaddr *ifa;
697
        register struct sockaddr_dl *sdl;
698
 
699
        ifp->if_type = IFT_ETHER;
700
        ifp->if_addrlen = 6;
701
        ifp->if_hdrlen = 14;
702
        ifp->if_mtu = ETHERMTU;
703
        if (ifp->if_baudrate == 0)
704
            ifp->if_baudrate = 10000000;
705
        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
706
                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
707
                    sdl->sdl_family == AF_LINK) {
708
                        sdl->sdl_type = IFT_ETHER;
709
                        sdl->sdl_alen = ifp->if_addrlen;
710
                        bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
711
                              LLADDR(sdl), ifp->if_addrlen);
712
                        break;
713
                }
714
}
715
 
716
static u_char ether_ipmulticast_min[6] =
717
        { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
718
static u_char ether_ipmulticast_max[6] =
719
        { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
720
/*
721
 * Add an Ethernet multicast address or range of addresses to the list for a
722
 * given interface.
723
 */
724
int
725
ether_addmulti(ifr, ac)
726
        struct ifreq *ifr;
727
        register struct arpcom *ac;
728
{
729
        register struct ether_multi *enm;
730
        struct sockaddr_in *sin;
731
        u_char addrlo[6];
732
        u_char addrhi[6];
733
        int set_allmulti = 0;
734
        int s = splimp();
735
 
736
        switch (ifr->ifr_addr.sa_family) {
737
 
738
        case AF_UNSPEC:
739
                bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
740
                bcopy(addrlo, addrhi, 6);
741
                break;
742
 
743
#ifdef INET
744
        case AF_INET:
745
                sin = (struct sockaddr_in *)&(ifr->ifr_addr);
746
                if (sin->sin_addr.s_addr == INADDR_ANY) {
747
                        /*
748
                         * An IP address of INADDR_ANY means listen to all
749
                         * of the Ethernet multicast addresses used for IP.
750
                         * (This is for the sake of IP multicast routers.)
751
                         */
752
                        bcopy(ether_ipmulticast_min, addrlo, 6);
753
                        bcopy(ether_ipmulticast_max, addrhi, 6);
754
                      set_allmulti = 1;
755
                }
756
                else {
757
                        ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
758
                        bcopy(addrlo, addrhi, 6);
759
                }
760
                break;
761
#endif
762
 
763
        default:
764
                splx(s);
765
                return (EAFNOSUPPORT);
766
        }
767
 
768
        /*
769
         * Verify that we have valid Ethernet multicast addresses.
770
         */
771
        if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
772
                splx(s);
773
                return (EINVAL);
774
        }
775
        /*
776
         * See if the address range is already in the list.
777
         */
778
        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
779
        if (enm != NULL) {
780
                /*
781
                 * Found it; just increment the reference count.
782
                 */
783
                ++enm->enm_refcount;
784
                splx(s);
785
                return (0);
786
        }
787
        /*
788
         * New address or range; malloc a new multicast record
789
         * and link it into the interface's multicast list.
790
         */
791
        enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
792
        if (enm == NULL) {
793
                splx(s);
794
                return (ENOBUFS);
795
        }
796
        bcopy(addrlo, enm->enm_addrlo, 6);
797
        bcopy(addrhi, enm->enm_addrhi, 6);
798
        enm->enm_ac = ac;
799
        enm->enm_refcount = 1;
800
        enm->enm_next = ac->ac_multiaddrs;
801
        ac->ac_multiaddrs = enm;
802
        ac->ac_multicnt++;
803
        splx(s);
804
        if (set_allmulti)
805
                ac->ac_if.if_flags |= IFF_ALLMULTI;
806
 
807
        /*
808
         * Return ENETRESET to inform the driver that the list has changed
809
         * and its reception filter should be adjusted accordingly.
810
         */
811
        return (ENETRESET);
812
}
813
 
814
/*
815
 * Delete a multicast address record.
816
 */
817
int
818
ether_delmulti(ifr, ac)
819
        struct ifreq *ifr;
820
        register struct arpcom *ac;
821
{
822
        register struct ether_multi *enm;
823
        register struct ether_multi **p;
824
        struct sockaddr_in *sin;
825
        u_char addrlo[6];
826
        u_char addrhi[6];
827
      int unset_allmulti = 0;
828
        int s = splimp();
829
 
830
        switch (ifr->ifr_addr.sa_family) {
831
 
832
        case AF_UNSPEC:
833
                bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
834
                bcopy(addrlo, addrhi, 6);
835
                break;
836
 
837
#ifdef INET
838
        case AF_INET:
839
                sin = (struct sockaddr_in *)&(ifr->ifr_addr);
840
                if (sin->sin_addr.s_addr == INADDR_ANY) {
841
                        /*
842
                         * An IP address of INADDR_ANY means stop listening
843
                         * to the range of Ethernet multicast addresses used
844
                         * for IP.
845
                         */
846
                        bcopy(ether_ipmulticast_min, addrlo, 6);
847
                        bcopy(ether_ipmulticast_max, addrhi, 6);
848
                      unset_allmulti = 1;
849
                }
850
                else {
851
                        ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
852
                        bcopy(addrlo, addrhi, 6);
853
                }
854
                break;
855
#endif
856
 
857
        default:
858
                splx(s);
859
                return (EAFNOSUPPORT);
860
        }
861
 
862
        /*
863
         * Look up the address in our list.
864
         */
865
        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
866
        if (enm == NULL) {
867
                splx(s);
868
                return (ENXIO);
869
        }
870
        if (--enm->enm_refcount != 0) {
871
                /*
872
                 * Still some claims to this record.
873
                 */
874
                splx(s);
875
                return (0);
876
        }
877
        /*
878
         * No remaining claims to this record; unlink and free it.
879
         */
880
        for (p = &enm->enm_ac->ac_multiaddrs;
881
             *p != enm;
882
             p = &(*p)->enm_next)
883
                continue;
884
        *p = (*p)->enm_next;
885
        free(enm, M_IFMADDR);
886
        ac->ac_multicnt--;
887
        splx(s);
888
      if (unset_allmulti)
889
              ac->ac_if.if_flags &= ~IFF_ALLMULTI;
890
 
891
        /*
892
         * Return ENETRESET to inform the driver that the list has changed
893
         * and its reception filter should be adjusted accordingly.
894
         */
895
        return (ENETRESET);
896
}
897
 
898
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
899
 
900
int
901
ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
902
{
903
        struct ifaddr *ifa = (struct ifaddr *) data;
904
        struct ifreq *ifr = (struct ifreq *) data;
905
        int error = 0;
906
 
907
        switch (command) {
908
        case SIOCSIFADDR:
909
                ifp->if_flags |= IFF_UP;
910
 
911
                switch (ifa->ifa_addr->sa_family) {
912
#ifdef INET
913
                case AF_INET:
914
                        ifp->if_init(ifp->if_softc);    /* before arpwhohas */
915
                        arp_ifinit((struct arpcom *)ifp, ifa);
916
                        break;
917
#endif
918
#ifdef IPX
919
                /*
920
                 * XXX - This code is probably wrong
921
                 */
922
                case AF_IPX:
923
                        {
924
                        register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
925
                        struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
926
 
927
                        if (ipx_nullhost(*ina))
928
                                ina->x_host =
929
                                    *(union ipx_host *)
930
                                    ac->ac_enaddr;
931
                        else {
932
                                bcopy((caddr_t) ina->x_host.c_host,
933
                                      (caddr_t) ac->ac_enaddr,
934
                                      sizeof(ac->ac_enaddr));
935
                        }
936
 
937
                        /*
938
                         * Set new address
939
                         */
940
                        ifp->if_init(ifp->if_softc);
941
                        break;
942
                        }
943
#endif
944
#ifdef NS
945
                /*
946
                 * XXX - This code is probably wrong
947
                 */
948
                case AF_NS:
949
                {
950
                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
951
                        struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
952
 
953
                        if (ns_nullhost(*ina))
954
                                ina->x_host =
955
                                    *(union ns_host *) (ac->ac_enaddr);
956
                        else {
957
                                bcopy((caddr_t) ina->x_host.c_host,
958
                                      (caddr_t) ac->ac_enaddr,
959
                                      sizeof(ac->ac_enaddr));
960
                        }
961
 
962
                        /*
963
                         * Set new address
964
                         */
965
                        ifp->if_init(ifp->if_softc);
966
                        break;
967
                }
968
#endif
969
                default:
970
                        ifp->if_init(ifp->if_softc);
971
                        break;
972
                }
973
                break;
974
 
975
        case SIOCGIFADDR:
976
                {
977
                        struct sockaddr *sa;
978
 
979
                        sa = (struct sockaddr *) & ifr->ifr_data;
980
                        bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
981
                              (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
982
                }
983
                break;
984
 
985
        case SIOCSIFMTU:
986
                /*
987
                 * Set the interface MTU.
988
                 */
989
                if (ifr->ifr_mtu > ETHERMTU) {
990
                        error = EINVAL;
991
                } else {
992
                        ifp->if_mtu = ifr->ifr_mtu;
993
                }
994
                break;
995
        }
996
        return (error);
997
}

powered by: WebSVN 2.1.0

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