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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      sys/net/if_ethersubr.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: if_ethersubr.c,v 1.32 1999/12/08 06:50:17 itojun Exp $        */
34
/*      $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $        */
35
 
36
/*
37
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
38
 * All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. Neither the name of the project nor the names of its contributors
49
 *    may be used to endorse or promote products derived from this software
50
 *    without specific prior written permission.
51
 *
52
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
53
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
56
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62
 * SUCH DAMAGE.
63
 */
64
 
65
/*
66
 * Copyright (c) 1982, 1989, 1993
67
 *      The Regents of the University of California.  All rights reserved.
68
 *
69
 * Redistribution and use in source and binary forms, with or without
70
 * modification, are permitted provided that the following conditions
71
 * are met:
72
 * 1. Redistributions of source code must retain the above copyright
73
 *    notice, this list of conditions and the following disclaimer.
74
 * 2. Redistributions in binary form must reproduce the above copyright
75
 *    notice, this list of conditions and the following disclaimer in the
76
 *    documentation and/or other materials provided with the distribution.
77
 * 3. All advertising materials mentioning features or use of this software
78
 *    must display the following acknowledgement:
79
 *      This product includes software developed by the University of
80
 *      California, Berkeley and its contributors.
81
 * 4. Neither the name of the University nor the names of its contributors
82
 *    may be used to endorse or promote products derived from this software
83
 *    without specific prior written permission.
84
 *
85
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
86
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
88
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
89
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
90
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
91
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
95
 * SUCH DAMAGE.
96
 *
97
 *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
98
 */
99
 
100
/*
101
%%% portions-copyright-nrl-95
102
Portions of this software are Copyright 1995-1998 by Randall Atkinson,
103
Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
104
Reserved. All rights under this copyright have been assigned to the US
105
Naval Research Laboratory (NRL). The NRL Copyright Notice and License
106
Agreement Version 1.1 (January 17, 1995) applies to these portions of the
107
software.
108
You should have received a copy of the license with this software. If you
109
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
110
*/
111
 
112
#include <sys/param.h>
113
#ifndef __ECOS
114
#include <sys/systm.h>
115
#endif
116
#include <sys/kernel.h>
117
#include <sys/malloc.h>
118
#include <sys/mbuf.h>
119
#include <sys/protosw.h>
120
#include <sys/socket.h>
121
#include <sys/ioctl.h>
122
#include <sys/errno.h>
123
#ifndef __ECOS
124
#include <sys/syslog.h>
125
#endif
126
 
127
#include <machine/cpu.h>
128
 
129
#include <net/if.h>
130
#include <net/netisr.h>
131
#include <net/route.h>
132
#include <net/if_llc.h>
133
#include <net/if_dl.h>
134
#include <net/if_types.h>
135
 
136
#include <netinet/in.h>
137
#ifdef INET
138
#include <netinet/in_var.h>
139
#endif
140
#include <netinet/if_ether.h>
141
 
142
#ifndef __ECOS
143
#include "bridge.h"
144
#endif
145
#if NBRIDGE > 0
146
#include <net/if_bridge.h>
147
#endif
148
 
149
#ifdef INET6
150
#ifndef INET
151
#include <netinet/in.h>
152
#endif
153
#include <netinet6/in6_var.h>
154
#include <netinet6/nd6.h>
155
#endif
156
 
157
#ifdef NS
158
#include <netns/ns.h>
159
#include <netns/ns_if.h>
160
#endif
161
 
162
#ifdef IPX
163
#include <netipx/ipx.h>
164
#include <netipx/ipx_if.h>
165
#endif
166
 
167
#ifdef ISO
168
#include <netiso/argo_debug.h>
169
#include <netiso/iso.h>
170
#include <netiso/iso_var.h>
171
#include <netiso/iso_snpac.h>
172
#endif
173
 
174
#ifdef CCITT
175
#include <netccitt/x25.h>
176
#include <netccitt/pk.h>
177
#include <netccitt/pk_extern.h>
178
#include <netccitt/dll.h>
179
#include <netccitt/llc_var.h>
180
#endif
181
 
182
#ifdef NETATALK
183
#include <netatalk/at.h>
184
#include <netatalk/at_var.h>
185
#include <netatalk/at_extern.h>
186
 
187
#define llc_snap_org_code llc_un.type_snap.org_code
188
#define llc_snap_ether_type llc_un.type_snap.ether_type
189
 
190
extern u_char   at_org_code[ 3 ];
191
extern u_char   aarp_org_code[ 3 ];
192
#endif /* NETATALK */
193
 
194
#if defined(CCITT)
195
#include <sys/socketvar.h>
196
#endif
197
 
198
#if 0   /*NRL INET6*/
199
#include <netinet6/in6.h>
200
#include <netinet6/in6_var.h>
201
#endif /* INET6 */
202
 
203
u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
204
#define senderr(e) { error = (e); goto bad;}
205
 
206
 
207
int
208
ether_ioctl(ifp, arp, cmd, data)
209
        register struct ifnet *ifp;
210
        struct arpcom *arp;
211
        u_long cmd;
212
        caddr_t data;
213
{
214
        struct ifaddr *ifa = (struct ifaddr *)data;
215
        int     error = 0;
216
 
217
        switch (cmd) {
218
 
219
#if defined(CCITT)
220
        case SIOCSIFCONF_X25:
221
                ifp->if_flags |= IFF_UP;
222
                ifa->ifa_rtrequest = cons_rtrequest;
223
                error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
224
                break;
225
#endif /* CCITT */
226
        case SIOCSIFADDR:
227
                switch (ifa->ifa_addr->sa_family) {
228
#ifdef IPX
229
                case AF_IPX:
230
                    {
231
                        struct ipx_addr *ina = &IA_SIPX(ifa)->sipx_addr;
232
 
233
                        if (ipx_nullhost(*ina))
234
                                ina->ipx_host =
235
                                    *(union ipx_host *)(arp->ac_enaddr);
236
                        else
237
                                bcopy(ina->ipx_host.c_host,
238
                                    arp->ac_enaddr, sizeof(arp->ac_enaddr));
239
                        break;
240
                    }
241
#endif /* IPX */
242
#ifdef NETATALK
243
                case AF_APPLETALK:
244
                        /* Nothing to do. */
245
                        break;
246
#endif /* NETATALK */
247
#ifdef NS
248
                /* XXX - This code is probably wrong. */
249
                case AF_NS:
250
                    {
251
                        struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
252
 
253
                        if (ns_nullhost(*ina))
254
                                ina->x_host =
255
                                    *(union ns_host *)(arp->ac_enaddr);
256
                        else
257
                                bcopy(ina->x_host.c_host,
258
                                    arp->ac_enaddr, sizeof(arp->ac_enaddr));
259
                        break;
260
                    }
261
#endif /* NS */
262
                }
263
                break;
264
        default:
265
                break;
266
        }
267
 
268
        return error;
269
}
270
 
271
/*
272
 * Ethernet output routine.
273
 * Encapsulate a packet of type family for the local net.
274
 * Assumes that ifp is actually pointer to arpcom structure.
275
 */
276
int
277
ether_output(ifp, m0, dst, rt0)
278
        register struct ifnet *ifp;
279
        struct mbuf *m0;
280
        struct sockaddr *dst;
281
        struct rtentry *rt0;
282
{
283
        u_int16_t etype;
284
        int s, error = 0;
285
        u_char edst[6];
286
        register struct mbuf *m = m0;
287
        register struct rtentry *rt;
288
        struct mbuf *mcopy = (struct mbuf *)0;
289
        register struct ether_header *eh;
290
        struct arpcom *ac = (struct arpcom *)ifp;
291
 
292
        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
293
                senderr(ENETDOWN);
294
        ifp->if_lastchange = time;
295
        if ((rt = rt0) != NULL) {
296
                if ((rt->rt_flags & RTF_UP) == 0) {
297
                        if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
298
                                rt->rt_refcnt--;
299
                        else
300
                                senderr(EHOSTUNREACH);
301
                }
302
                if (rt->rt_flags & RTF_GATEWAY) {
303
                        if (rt->rt_gwroute == 0)
304
                                goto lookup;
305
                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
306
                                rtfree(rt); rt = rt0;
307
                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
308
                                if ((rt = rt->rt_gwroute) == 0)
309
                                        senderr(EHOSTUNREACH);
310
                        }
311
                }
312
                if (rt->rt_flags & RTF_REJECT)
313
                        if (rt->rt_rmx.rmx_expire == 0 ||
314
                            time.tv_sec < rt->rt_rmx.rmx_expire)
315
                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
316
        }
317
        switch (dst->sa_family) {
318
 
319
#ifdef INET
320
        case AF_INET:
321
                if (!arpresolve(ac, rt, m, dst, edst))
322
                        return (0);      /* if not yet resolved */
323
                /* If broadcasting on a simplex interface, loopback a copy */
324
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
325
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
326
                etype = htons(ETHERTYPE_IP);
327
                break;
328
#endif
329
#ifdef INET6
330
        case AF_INET6:
331
#ifndef OLDIP6OUTPUT
332
                if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
333
                        return(0); /* it must be impossible, but... */
334
#else
335
                if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst))
336
                        return(0);       /* if not yet resolves */
337
#endif
338
                etype = htons(ETHERTYPE_IPV6);
339
                break;
340
#endif
341
#ifdef NS
342
        case AF_NS:
343
                etype = htons(ETHERTYPE_NS);
344
                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
345
                    (caddr_t)edst, sizeof (edst));
346
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
347
                        return (looutput(ifp, m, dst, rt));
348
                /* If broadcasting on a simplex interface, loopback a copy */
349
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
350
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
351
                break;
352
#endif
353
#ifdef IPX
354
        case AF_IPX:
355
                etype = htons(ETHERTYPE_IPX);
356
                bcopy((caddr_t)&satosipx(dst)->sipx_addr.ipx_host,
357
                    (caddr_t)edst, sizeof (edst));
358
                if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst)))
359
                        return (looutput(ifp, m, dst, rt));
360
                /* If broadcasting on a simplex interface, loopback a copy */
361
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
362
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
363
                break;
364
#endif
365
#if 0   /*NRL INET6*/
366
        case AF_INET6:
367
                /*
368
                 * The bottom line here is to either queue the outgoing packet
369
                 * in the discovery engine, or fill in edst with something
370
                 * that'll work.
371
                 */
372
                if (m->m_flags & M_MCAST) {
373
                        /*
374
                         * If multicast dest., then use IPv6 -> Ethernet
375
                         * mcast mapping.  Really simple.
376
                         */
377
                        ETHER_MAP_IPV6_MULTICAST(&((struct sockaddr_in6 *)dst)->sin6_addr,
378
                            edst);
379
                } else {
380
                        /* Do unicast neighbor discovery stuff. */
381
                        if (!ipv6_discov_resolve(ifp, rt, m, dst, edst))
382
                                return 0;
383
                }
384
                etype = htons(ETHERTYPE_IPV6);
385
                break;
386
#endif /* INET6 */
387
#ifdef NETATALK
388
        case AF_APPLETALK: {
389
                struct at_ifaddr *aa;
390
 
391
                if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
392
#ifdef NETATALKDEBUG
393
                        extern char *prsockaddr(struct sockaddr *);
394
                        printf("aarpresolv: failed for %s\n", prsockaddr(dst));
395
#endif /* NETATALKDEBUG */
396
                        return (0);
397
                }
398
 
399
                /*
400
                 * ifaddr is the first thing in at_ifaddr
401
                 */
402
                aa = (struct at_ifaddr *)at_ifawithnet(
403
                        (struct sockaddr_at *)dst,
404
                        ifp->if_addrlist.tqh_first);
405
                if (aa == 0)
406
                        goto bad;
407
 
408
                /*
409
                 * In the phase 2 case, we need to prepend an mbuf for the llc
410
                 * header. Since we must preserve the value of m, which is
411
                 * passed to us by value, we m_copy() the first mbuf,
412
                 * and use it for our llc header.
413
                 */
414
                if ( aa->aa_flags & AFA_PHASE2 ) {
415
                        struct llc llc;
416
 
417
                        /* XXX Really this should use netisr too */
418
                        M_PREPEND(m, AT_LLC_SIZE, M_WAIT);
419
                        /*
420
                         * FreeBSD doesn't count the LLC len in
421
                         * ifp->obytes, so they increment a length
422
                         * field here. We don't do this.
423
                         */
424
                        llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
425
                        llc.llc_control = LLC_UI;
426
                        bcopy(at_org_code, llc.llc_snap_org_code,
427
                                sizeof(at_org_code));
428
                        llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
429
                        bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE);
430
                        etype = htons(m->m_pkthdr.len);
431
                } else {
432
                        etype = htons(ETHERTYPE_AT);
433
                }
434
                } break;
435
#endif /* NETATALK */
436
#ifdef  ISO
437
        case AF_ISO: {
438
                int     snpalen;
439
                struct  llc *l;
440
                register struct sockaddr_dl *sdl;
441
 
442
                if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
443
                    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
444
                        bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
445
                } else {
446
                        error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
447
                                                (char *)edst, &snpalen);
448
                        if (error)
449
                                goto bad; /* Not Resolved */
450
                }
451
                /* If broadcasting on a simplex interface, loopback a copy */
452
                if (*edst & 1)
453
                        m->m_flags |= (M_BCAST|M_MCAST);
454
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
455
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
456
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
457
                        if (mcopy) {
458
                                eh = mtod(mcopy, struct ether_header *);
459
                                bcopy(edst, eh->ether_dhost, sizeof (edst));
460
                                bcopy(ac->ac_enaddr, eh->ether_shost,
461
                                    sizeof (edst));
462
                        }
463
                }
464
                M_PREPEND(m, 3, M_DONTWAIT);
465
                if (m == NULL)
466
                        return (0);
467
                etype = htons(m->m_pkthdr.len);
468
                l = mtod(m, struct llc *);
469
                l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
470
                l->llc_control = LLC_UI;
471
#ifdef ARGO_DEBUG
472
                if (argo_debug[D_ETHER]) {
473
                        int i;
474
                        printf("unoutput: sending pkt to: ");
475
                        for (i=0; i<6; i++)
476
                                printf("%x ", edst[i] & 0xff);
477
                        printf("\n");
478
                }
479
#endif
480
                } break;
481
#endif /* ISO */
482
/*      case AF_NSAP: */
483
        case AF_CCITT: {
484
                register struct sockaddr_dl *sdl =
485
                        (struct sockaddr_dl *) rt -> rt_gateway;
486
 
487
                if (sdl && sdl->sdl_family == AF_LINK
488
                    && sdl->sdl_alen > 0) {
489
                        bcopy(LLADDR(sdl), (char *)edst,
490
                                sizeof(edst));
491
                } else goto bad; /* Not a link interface ? Funny ... */
492
                if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
493
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
494
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
495
                        if (mcopy) {
496
                                eh = mtod(mcopy, struct ether_header *);
497
                                bcopy(edst, eh->ether_dhost, sizeof (edst));
498
                                bcopy(ac->ac_enaddr, eh->ether_shost,
499
                                    sizeof (edst));
500
                        }
501
                }
502
                etype = htons(m->m_pkthdr.len);
503
#ifdef LLC_DEBUG
504
                {
505
                        int i;
506
                        register struct llc *l = mtod(m, struct llc *);
507
 
508
                        printf("ether_output: sending LLC2 pkt to: ");
509
                        for (i=0; i<6; i++)
510
                                printf("%x ", edst[i] & 0xff);
511
                        printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
512
                            m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
513
                            l->llc_control & 0xff);
514
 
515
                }
516
#endif /* LLC_DEBUG */
517
                } break;
518
 
519
        case AF_UNSPEC:
520
                eh = (struct ether_header *)dst->sa_data;
521
                bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
522
                /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
523
                etype = eh->ether_type;
524
                break;
525
 
526
        default:
527
#ifdef __ECOS
528
//              diag_printf("%s: can't handle af%d\n", ifp->if_xname,
529
//                            dst->sa_family);
530
#else
531
                printf("%s: can't handle af%d\n", ifp->if_xname,
532
                        dst->sa_family);
533
#endif
534
                senderr(EAFNOSUPPORT);
535
        }
536
 
537
        if (mcopy)
538
                (void) looutput(ifp, mcopy, dst, rt);
539
 
540
        /*
541
         * Add local net header.  If no space in first mbuf,
542
         * allocate another.
543
         */
544
        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
545
        if (m == 0)
546
                senderr(ENOBUFS);
547
        eh = mtod(m, struct ether_header *);
548
        bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
549
                sizeof(eh->ether_type));
550
        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
551
        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
552
            sizeof(eh->ether_shost));
553
 
554
#if NBRIDGE > 0
555
        /*
556
         * Interfaces that are bridge members need special handling
557
         * for output.
558
         */
559
        if (ifp->if_bridge) {
560
                bridge_output(ifp, m, NULL, NULL);
561
                return (error);
562
        }
563
#endif
564
 
565
        s = splimp();
566
        /*
567
         * Queue message on interface, and start output if interface
568
         * not yet active.
569
         */
570
        if (IF_QFULL(&ifp->if_snd)) {
571
                // Let the interface try a dequeue anyway, in case the
572
                // interface has "got better" from whatever made the queue
573
                // fill up - being unplugged for example.
574
                if ((ifp->if_flags & IFF_OACTIVE) == 0)
575
                    (*ifp->if_start)(ifp);
576
                IF_DROP(&ifp->if_snd);
577
                splx(s);
578
                senderr(ENOBUFS);
579
        }
580
        ifp->if_obytes += m->m_pkthdr.len;
581
        IF_ENQUEUE(&ifp->if_snd, m);
582
        if (m->m_flags & M_MCAST)
583
                ifp->if_omcasts++;
584
        if ((ifp->if_flags & IFF_OACTIVE) == 0)
585
                (*ifp->if_start)(ifp);
586
        splx(s);
587
        return (error);
588
 
589
bad:
590
        if (m)
591
                m_freem(m);
592
        return (error);
593
}
594
 
595
/*
596
 * Process a received Ethernet packet;
597
 * the packet is in the mbuf chain m without
598
 * the ether header, which is provided separately.
599
 */
600
void
601
ether_input(ifp, eh, m)
602
        struct ifnet *ifp;
603
        register struct ether_header *eh;
604
        struct mbuf *m;
605
{
606
        register struct ifqueue *inq;
607
        u_int16_t etype;
608
        int s, llcfound = 0;
609
        register struct llc *l;
610
        struct arpcom *ac = (struct arpcom *)ifp;
611
#ifdef __ECOS
612
        unsigned int sched_what;
613
#endif
614
 
615
        if ((ifp->if_flags & IFF_UP) == 0) {
616
                m_freem(m);
617
                return;
618
        }
619
        ifp->if_lastchange = time;
620
        ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
621
        if (eh->ether_dhost[0] & 1) {
622
                if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
623
                    sizeof(etherbroadcastaddr)) == 0)
624
                        m->m_flags |= M_BCAST;
625
                else
626
                        m->m_flags |= M_MCAST;
627
        }
628
        if (m->m_flags & (M_BCAST|M_MCAST))
629
                ifp->if_imcasts++;
630
 
631
#if NBRIDGE > 0
632
        /*
633
         * Tap the packet off here for a bridge, if configured and
634
         * active for this interface.  bridge_input returns
635
         * NULL if it has consumed the packet, otherwise, it
636
         * gets processed as normal.
637
         */
638
        if (ifp->if_bridge) {
639
                m = bridge_input(ifp, eh, m);
640
                if (m == NULL)
641
                        return;
642
                /* The bridge has determined it's for us. */
643
                goto decapsulate;
644
        }
645
#endif
646
        /*
647
         * If packet is unicast and we're in promiscuous mode, make sure it
648
         * is for us.  Drop otherwise.
649
         */
650
        if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
651
            (ifp->if_flags & IFF_PROMISC)) {
652
                if (bcmp(ac->ac_enaddr, (caddr_t)eh->ether_dhost,
653
                    ETHER_ADDR_LEN)) {
654
                        m_freem(m);
655
                        return;
656
                }
657
        }
658
 
659
decapsulate:
660
        etype = ntohs(eh->ether_type);
661
        switch (etype) {
662
#ifdef INET
663
        case ETHERTYPE_IP:
664
#ifdef __ECOS
665
                sched_what = NETISR_IP;
666
#else
667
                schednetisr(NETISR_IP);
668
#endif
669
                inq = &ipintrq;
670
                break;
671
 
672
        case ETHERTYPE_ARP:
673
                if (ifp->if_flags & IFF_NOARP)
674
                        goto dropanyway;
675
#ifdef __ECOS
676
                sched_what = NETISR_ARP;
677
#else
678
                schednetisr(NETISR_ARP);
679
#endif
680
                inq = &arpintrq;
681
                break;
682
 
683
        case ETHERTYPE_REVARP:
684
                if (ifp->if_flags & IFF_NOARP)
685
                        goto dropanyway;
686
                revarpinput(m); /* XXX queue? */
687
                return;
688
 
689
#endif
690
#ifdef INET6
691
        /*
692
         * Schedule IPv6 software interrupt for incoming IPv6 packet.
693
         */
694
        case ETHERTYPE_IPV6:
695
#ifdef __ECOS
696
                sched_what = NETISR_IPV6;
697
#else
698
                schednetisr(NETISR_IPV6);
699
#endif
700
                inq = &ip6intrq;
701
                break;
702
#endif /* INET6 */
703
#ifdef IPX
704
        case ETHERTYPE_IPX:
705
#ifdef __ECOS
706
                sched_what = NETISR_IPX;
707
#else
708
                schednetisr(NETISR_IPX);
709
#endif
710
                inq = &ipxintrq;
711
                break;
712
#endif
713
#ifdef NS
714
        case ETHERTYPE_NS:
715
#ifdef __ECOS
716
                sched_what = NETISR_NS;
717
#else
718
                schednetisr(NETISR_NS);
719
#endif
720
                inq = &nsintrq;
721
                break;
722
#endif
723
#ifdef NETATALK
724
        case ETHERTYPE_AT:
725
#ifdef __ECOS
726
                sched_what = NETISR_ATALK;
727
#else
728
                schednetisr(NETISR_ATALK);
729
#endif
730
                inq = &atintrq1;
731
                break;
732
        case ETHERTYPE_AARP:
733
                /* probably this should be done with a NETISR as well */
734
                /* XXX queue this */
735
                aarpinput((struct arpcom *)ifp, m);
736
                return;
737
#endif
738
        default:
739
                if (llcfound || etype > ETHERMTU)
740
                        goto dropanyway;
741
                llcfound = 1;
742
                l = mtod(m, struct llc *);
743
                switch (l->llc_dsap) {
744
                case LLC_SNAP_LSAP:
745
#ifdef NETATALK
746
                        /*
747
                         * Some protocols (like Appletalk) need special
748
                         * handling depending on if they are type II
749
                         * or SNAP encapsulated. Everything else
750
                         * gets handled by stripping off the SNAP header
751
                         * and going back up to decapsulate.
752
                         */
753
                        if (l->llc_control == LLC_UI &&
754
                            l->llc_ssap == LLC_SNAP_LSAP &&
755
                            Bcmp(&(l->llc_snap_org_code)[0],
756
                            at_org_code, sizeof(at_org_code)) == 0 &&
757
                            ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
758
                                inq = &atintrq2;
759
                                m_adj(m, AT_LLC_SIZE);
760
#ifdef __ECOS
761
                                sched_what = NETISR_ATALK;
762
#else
763
                                schednetisr(NETISR_ATALK);
764
#endif
765
                                break;
766
                        }
767
 
768
                        if (l->llc_control == LLC_UI &&
769
                            l->llc_ssap == LLC_SNAP_LSAP &&
770
                            Bcmp(&(l->llc_snap_org_code)[0],
771
                            aarp_org_code, sizeof(aarp_org_code)) == 0 &&
772
                            ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
773
                                m_adj(m, AT_LLC_SIZE);
774
                                /* XXX Really this should use netisr too */
775
                                aarpinput((struct arpcom *)ifp, m);
776
                                return;
777
                        }
778
#endif /* NETATALK */
779
                        if (l->llc_control == LLC_UI &&
780
                            l->llc_dsap == LLC_SNAP_LSAP &&
781
                            l->llc_ssap == LLC_SNAP_LSAP) {
782
                                /* SNAP */
783
                                if (m->m_pkthdr.len > etype)
784
                                        m_adj(m, etype - m->m_pkthdr.len);
785
                                m->m_data += 6;         /* XXX */
786
                                m->m_len -= 6;          /* XXX */
787
                                m->m_pkthdr.len -= 6;   /* XXX */
788
                                M_PREPEND(m, sizeof *eh, M_DONTWAIT);
789
                                if (m == 0)
790
                                        return;
791
                                *mtod(m, struct ether_header *) = *eh;
792
                                goto decapsulate;
793
                        }
794
                        goto dropanyway;
795
#ifdef  ISO
796
                case LLC_ISO_LSAP:
797
                        switch (l->llc_control) {
798
                        case LLC_UI:
799
                                /* LLC_UI_P forbidden in class 1 service */
800
                                if ((l->llc_dsap == LLC_ISO_LSAP) &&
801
                                    (l->llc_ssap == LLC_ISO_LSAP)) {
802
                                        /* LSAP for ISO */
803
                                        if (m->m_pkthdr.len > etype)
804
                                                m_adj(m, etype - m->m_pkthdr.len);
805
                                        m->m_data += 3;         /* XXX */
806
                                        m->m_len -= 3;          /* XXX */
807
                                        m->m_pkthdr.len -= 3;   /* XXX */
808
                                        M_PREPEND(m, sizeof *eh, M_DONTWAIT);
809
                                        if (m == 0)
810
                                                return;
811
                                        *mtod(m, struct ether_header *) = *eh;
812
#ifdef ARGO_DEBUG
813
                                        if (argo_debug[D_ETHER])
814
                                                printf("clnp packet");
815
#endif
816
#ifdef __ECOS
817
                                        sched_what = NETISR_ISO;
818
#else
819
                                        schednetisr(NETISR_ISO);
820
#endif
821
                                        inq = &clnlintrq;
822
                                        break;
823
                                }
824
                                goto dropanyway;
825
 
826
                        case LLC_XID:
827
                        case LLC_XID_P:
828
                                if(m->m_len < 6)
829
                                        goto dropanyway;
830
                                l->llc_window = 0;
831
                                l->llc_fid = 9;
832
                                l->llc_class = 1;
833
                                l->llc_dsap = l->llc_ssap = 0;
834
                                /* Fall through to */
835
                        case LLC_TEST:
836
                        case LLC_TEST_P:
837
                        {
838
                                struct sockaddr sa;
839
                                register struct ether_header *eh2;
840
                                int i;
841
                                u_char c = l->llc_dsap;
842
 
843
                                l->llc_dsap = l->llc_ssap;
844
                                l->llc_ssap = c;
845
                                if (m->m_flags & (M_BCAST | M_MCAST))
846
                                        bcopy(ac->ac_enaddr,
847
                                            eh->ether_dhost, 6);
848
                                sa.sa_family = AF_UNSPEC;
849
                                sa.sa_len = sizeof(sa);
850
                                eh2 = (struct ether_header *)sa.sa_data;
851
                                for (i = 0; i < 6; i++) {
852
                                        eh2->ether_shost[i] = c = eh->ether_dhost[i];
853
                                        eh2->ether_dhost[i] =
854
                                                eh->ether_dhost[i] = eh->ether_shost[i];
855
                                        eh->ether_shost[i] = c;
856
                                }
857
                                ifp->if_output(ifp, m, &sa, NULL);
858
                                return;
859
                        }
860
                        break;
861
                        }
862
#endif /* ISO */
863
#ifdef CCITT
864
                case LLC_X25_LSAP:
865
                        if (m->m_pkthdr.len > etype)
866
                                m_adj(m, etype - m->m_pkthdr.len);
867
                        M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
868
                        if (m == 0)
869
                                return;
870
                        if (!sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
871
                            eh->ether_dhost, LLC_X25_LSAP, 6,
872
                            mtod(m, struct sdl_hdr *)))
873
                                panic("ETHER cons addr failure");
874
                        mtod(m, struct sdl_hdr *)->sdlhdr_len = etype;
875
#ifdef LLC_DEBUG
876
                        printf("llc packet\n");
877
#endif /* LLC_DEBUG */
878
#ifdef __ECOS
879
                        sched_what = NETISR_CCITT;
880
#else
881
                        schednetisr(NETISR_CCITT);
882
#endif
883
                        inq = &llcintrq;
884
                        break;
885
#endif /* CCITT */
886
                dropanyway:
887
                default:
888
                        m_freem(m);
889
                        return;
890
                }
891
        }
892
 
893
        s = splimp();
894
        if (IF_QFULL(inq)) {
895
                IF_DROP(inq);
896
                m_freem(m);
897
        } else
898
                IF_ENQUEUE(inq, m);
899
        splx(s);
900
#ifdef __ECOS
901
        schednetisr(sched_what);
902
#endif
903
}
904
 
905
/*
906
 * Convert Ethernet address to printable (loggable) representation.
907
 */
908
static char digits[] = "0123456789abcdef";
909
char *
910
ether_sprintf(ap)
911
        register u_char *ap;
912
{
913
        register int i;
914
        static char etherbuf[18];
915
        register char *cp = etherbuf;
916
 
917
        for (i = 0; i < 6; i++) {
918
                *cp++ = digits[*ap >> 4];
919
                *cp++ = digits[*ap++ & 0xf];
920
                *cp++ = ':';
921
        }
922
        *--cp = 0;
923
        return (etherbuf);
924
}
925
 
926
/*
927
 * Perform common duties while attaching to interface list
928
 */
929
void
930
ether_ifattach(ifp)
931
        register struct ifnet *ifp;
932
{
933
        register struct ifaddr *ifa;
934
        register struct sockaddr_dl *sdl;
935
 
936
        ifp->if_type = IFT_ETHER;
937
        ifp->if_addrlen = 6;
938
        ifp->if_hdrlen = 14;
939
        ifp->if_mtu = ETHERMTU;
940
        ifp->if_output = ether_output;
941
        for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
942
            ifa = ifa->ifa_list.tqe_next)
943
                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
944
                    sdl->sdl_family == AF_LINK) {
945
                        sdl->sdl_type = IFT_ETHER;
946
                        sdl->sdl_alen = ifp->if_addrlen;
947
                        bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
948
                            LLADDR(sdl), ifp->if_addrlen);
949
                        break;
950
                }
951
        LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs);
952
}
953
 
954
void
955
ether_ifdetach(ifp)
956
        struct ifnet *ifp;
957
{
958
        struct arpcom *ac = (struct arpcom *)ifp;
959
        struct ether_multi *enm;
960
 
961
        for (enm = LIST_FIRST(&ac->ac_multiaddrs); enm;
962
            enm = LIST_FIRST(&ac->ac_multiaddrs)) {
963
                LIST_REMOVE(enm, enm_list);
964
                free(enm, M_IFMADDR);
965
        }
966
}
967
 
968
u_char  ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
969
u_char  ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
970
 
971
#ifdef INET6
972
u_char  ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
973
u_char  ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
974
#endif
975
 
976
/*
977
 * Add an Ethernet multicast address or range of addresses to the list for a
978
 * given interface.
979
 */
980
int
981
ether_addmulti(ifr, ac)
982
        struct ifreq *ifr;
983
        register struct arpcom *ac;
984
{
985
        register struct ether_multi *enm;
986
        struct sockaddr_in *sin;
987
#ifdef INET6
988
        struct sockaddr_in6 *sin6;
989
#endif /* INET6 */
990
        u_char addrlo[6];
991
        u_char addrhi[6];
992
        int s = splimp();
993
 
994
        switch (ifr->ifr_addr.sa_family) {
995
 
996
        case AF_UNSPEC:
997
                bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
998
                bcopy(addrlo, addrhi, 6);
999
                break;
1000
 
1001
#ifdef INET
1002
        case AF_INET:
1003
                sin = (struct sockaddr_in *)&(ifr->ifr_addr);
1004
                if (sin->sin_addr.s_addr == INADDR_ANY) {
1005
                        /*
1006
                         * An IP address of INADDR_ANY means listen to all
1007
                         * of the Ethernet multicast addresses used for IP.
1008
                         * (This is for the sake of IP multicast routers.)
1009
                         */
1010
                        bcopy(ether_ipmulticast_min, addrlo, 6);
1011
                        bcopy(ether_ipmulticast_max, addrhi, 6);
1012
                }
1013
                else {
1014
                        ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
1015
                        bcopy(addrlo, addrhi, 6);
1016
                }
1017
                break;
1018
#endif
1019
#ifdef INET6
1020
        case AF_INET6:
1021
                sin6 = (struct sockaddr_in6 *)
1022
                        &(((struct in6_ifreq *)ifr)->ifr_addr);
1023
                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1024
                        /*
1025
                         * An unspecified IPv6 address means listen to all
1026
                         * of the IPv6 multicast addresses on this Ethernet.
1027
                         * (Multicast routers like this.)
1028
                         */
1029
                        bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
1030
                        bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
1031
                } else {
1032
                        ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
1033
                        bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1034
                }
1035
                break;
1036
#endif /* INET6 */
1037
 
1038
        default:
1039
                splx(s);
1040
                return (EAFNOSUPPORT);
1041
        }
1042
 
1043
        /*
1044
         * Verify that we have valid Ethernet multicast addresses.
1045
         */
1046
        if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
1047
                splx(s);
1048
                return (EINVAL);
1049
        }
1050
        /*
1051
         * See if the address range is already in the list.
1052
         */
1053
        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
1054
        if (enm != NULL) {
1055
                /*
1056
                 * Found it; just increment the reference count.
1057
                 */
1058
                ++enm->enm_refcount;
1059
                splx(s);
1060
                return (0);
1061
        }
1062
        /*
1063
         * New address or range; malloc a new multicast record
1064
         * and link it into the interface's multicast list.
1065
         */
1066
        enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
1067
        if (enm == NULL) {
1068
                splx(s);
1069
                return (ENOBUFS);
1070
        }
1071
        bcopy(addrlo, enm->enm_addrlo, 6);
1072
        bcopy(addrhi, enm->enm_addrhi, 6);
1073
        enm->enm_ac = ac;
1074
        enm->enm_refcount = 1;
1075
        LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list);
1076
        ac->ac_multicnt++;
1077
        splx(s);
1078
        /*
1079
         * Return ENETRESET to inform the driver that the list has changed
1080
         * and its reception filter should be adjusted accordingly.
1081
         */
1082
        return (ENETRESET);
1083
}
1084
 
1085
/*
1086
 * Delete a multicast address record.
1087
 */
1088
int
1089
ether_delmulti(ifr, ac)
1090
        struct ifreq *ifr;
1091
        register struct arpcom *ac;
1092
{
1093
        register struct ether_multi *enm;
1094
        struct sockaddr_in *sin;
1095
#ifdef INET6
1096
        struct sockaddr_in6 *sin6;
1097
#endif /* INET6 */
1098
        u_char addrlo[6];
1099
        u_char addrhi[6];
1100
        int s = splimp();
1101
 
1102
        switch (ifr->ifr_addr.sa_family) {
1103
 
1104
        case AF_UNSPEC:
1105
                bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
1106
                bcopy(addrlo, addrhi, 6);
1107
                break;
1108
 
1109
#ifdef INET
1110
        case AF_INET:
1111
                sin = (struct sockaddr_in *)&(ifr->ifr_addr);
1112
                if (sin->sin_addr.s_addr == INADDR_ANY) {
1113
                        /*
1114
                         * An IP address of INADDR_ANY means stop listening
1115
                         * to the range of Ethernet multicast addresses used
1116
                         * for IP.
1117
                         */
1118
                        bcopy(ether_ipmulticast_min, addrlo, 6);
1119
                        bcopy(ether_ipmulticast_max, addrhi, 6);
1120
                }
1121
                else {
1122
                        ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
1123
                        bcopy(addrlo, addrhi, 6);
1124
                }
1125
                break;
1126
#endif
1127
#ifdef INET6
1128
        case AF_INET6:
1129
                sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);
1130
                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1131
                        /*
1132
                         * An unspecified IPv6 address means stop listening to
1133
                         * all IPv6 multicast addresses on this Ethernet.'
1134
                         *
1135
                         * (This might not be healthy, given IPv6's reliance on
1136
                         * multicast for things like neighbor discovery.
1137
                         * Perhaps initializing all-nodes, solicited nodes, and
1138
                         * possibly all-routers for this interface afterwards
1139
                         * is not a bad idea.)
1140
                         */
1141
                        bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
1142
                        bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
1143
                } else {
1144
                        ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
1145
                        bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
1146
                }
1147
                break;
1148
#endif /* INET6 */
1149
 
1150
        default:
1151
                splx(s);
1152
                return (EAFNOSUPPORT);
1153
        }
1154
 
1155
        /*
1156
         * Look up the address in our list.
1157
         */
1158
        ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
1159
        if (enm == NULL) {
1160
                splx(s);
1161
                return (ENXIO);
1162
        }
1163
        if (--enm->enm_refcount != 0) {
1164
                /*
1165
                 * Still some claims to this record.
1166
                 */
1167
                splx(s);
1168
                return (0);
1169
        }
1170
        /*
1171
         * No remaining claims to this record; unlink and free it.
1172
         */
1173
        LIST_REMOVE(enm, enm_list);
1174
        free(enm, M_IFMADDR);
1175
        ac->ac_multicnt--;
1176
        splx(s);
1177
        /*
1178
         * Return ENETRESET to inform the driver that the list has changed
1179
         * and its reception filter should be adjusted accordingly.
1180
         */
1181
        return (ENETRESET);
1182
}

powered by: WebSVN 2.1.0

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