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