]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_ethersubr.c
This commit was generated by cvs2svn to compensate for changes in r53910,
[FreeBSD/FreeBSD.git] / sys / net / if_ethersubr.c
1 /*
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  * $FreeBSD$
35  */
36
37 #include "opt_atalk.h"
38 #include "opt_inet.h"
39 #include "opt_ipx.h"
40 #include "opt_bdg.h"
41 #include "opt_netgraph.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51
52 #include <net/if.h>
53 #include <net/netisr.h>
54 #include <net/route.h>
55 #include <net/if_llc.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58
59 #if defined(INET) || defined(INET6)
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/if_ether.h>
63 #endif
64 #ifdef INET6
65 #include <netinet6/nd6.h>
66 #include <netinet6/in6_ifattach.h>
67 #endif
68
69 #ifdef IPX
70 #include <netipx/ipx.h>
71 #include <netipx/ipx_if.h>
72 #endif
73
74 #ifdef NS
75 #include <netns/ns.h>
76 #include <netns/ns_if.h>
77 ushort ns_nettype;
78 int ether_outputdebug = 0;
79 int ether_inputdebug = 0;
80 #endif
81
82 #ifdef ISO
83 #include <netiso/argo_debug.h>
84 #include <netiso/iso.h>
85 #include <netiso/iso_var.h>
86 #include <netiso/iso_snpac.h>
87 #endif
88
89 /*#ifdef LLC
90 #include <netccitt/dll.h>
91 #include <netccitt/llc_var.h>
92 #endif*/
93
94 #if defined(LLC) && defined(CCITT)
95 extern struct ifqueue pkintrq;
96 #endif
97
98 #ifdef NETATALK
99 #include <netatalk/at.h>
100 #include <netatalk/at_var.h>
101 #include <netatalk/at_extern.h>
102
103 #define llc_snap_org_code llc_un.type_snap.org_code
104 #define llc_snap_ether_type llc_un.type_snap.ether_type
105
106 extern u_char   at_org_code[3];
107 extern u_char   aarp_org_code[3];
108 #endif /* NETATALK */
109
110 #ifdef BRIDGE
111 #include <net/bridge.h>
112 #endif
113
114 #include "vlan.h"
115 #if NVLAN > 0
116 #include <net/if_vlan_var.h>
117 #endif /* NVLAN > 0 */
118
119 static  int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
120                                     struct sockaddr *));
121 u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
122 #define senderr(e) do { error = (e); goto bad;} while (0)
123 #define IFP2AC(IFP) ((struct arpcom *)IFP)
124
125 #ifdef NETGRAPH
126 #include <netgraph/ng_ether.h>
127 #include <netgraph/ng_message.h>
128 #include <netgraph/netgraph.h>
129
130 static  void    ngether_init(void* ignored);
131 static void     ngether_send(struct arpcom *ac,
132                         struct ether_header *eh, struct mbuf *m);
133 static  ng_constructor_t        ngether_constructor;
134 static  ng_rcvmsg_t             ngether_rcvmsg;
135 static  ng_shutdown_t           ngether_rmnode;
136 static  ng_newhook_t            ngether_newhook;
137 static  ng_connect_t            ngether_connect;
138 static  ng_rcvdata_t            ngether_rcvdata;
139 static  ng_disconnect_t         ngether_disconnect;
140
141 static struct ng_type typestruct = {
142         NG_VERSION,
143         NG_ETHER_NODE_TYPE,
144         NULL,
145         ngether_constructor,
146         ngether_rcvmsg,
147         ngether_rmnode,
148         ngether_newhook,
149         NULL,
150         ngether_connect,
151         ngether_rcvdata,
152         ngether_rcvdata,
153         ngether_disconnect
154 };
155
156 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
157 #define NGEF_DIVERT NGF_TYPE1   /* all packets sent to netgraph */
158 #endif /* NETGRAPH */
159
160 /*
161  * Ethernet output routine.
162  * Encapsulate a packet of type family for the local net.
163  * Use trailer local net encapsulation if enough data in first
164  * packet leaves a multiple of 512 bytes of data in remainder.
165  * Assumes that ifp is actually pointer to arpcom structure.
166  */
167 int
168 ether_output(ifp, m0, dst, rt0)
169         register struct ifnet *ifp;
170         struct mbuf *m0;
171         struct sockaddr *dst;
172         struct rtentry *rt0;
173 {
174         short type;
175         int s, error = 0, hdrcmplt = 0;
176         u_char esrc[6], edst[6];
177         register struct mbuf *m = m0;
178         register struct rtentry *rt;
179         register struct ether_header *eh;
180         int off, len = m->m_pkthdr.len, loop_copy = 0;
181         int hlen;       /* link layer header lenght */
182         struct arpcom *ac = IFP2AC(ifp);
183
184         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
185                 senderr(ENETDOWN);
186         rt = rt0;
187         if (rt) {
188                 if ((rt->rt_flags & RTF_UP) == 0) {
189                         rt0 = rt = rtalloc1(dst, 1, 0UL);
190                         if (rt0)
191                                 rt->rt_refcnt--;
192                         else
193                                 senderr(EHOSTUNREACH);
194                 }
195                 if (rt->rt_flags & RTF_GATEWAY) {
196                         if (rt->rt_gwroute == 0)
197                                 goto lookup;
198                         if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
199                                 rtfree(rt); rt = rt0;
200                         lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
201                                                           0UL);
202                                 if ((rt = rt->rt_gwroute) == 0)
203                                         senderr(EHOSTUNREACH);
204                         }
205                 }
206                 if (rt->rt_flags & RTF_REJECT)
207                         if (rt->rt_rmx.rmx_expire == 0 ||
208                             time_second < rt->rt_rmx.rmx_expire)
209                                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
210         }
211         hlen = ETHER_HDR_LEN;
212         switch (dst->sa_family) {
213 #ifdef INET
214         case AF_INET:
215                 if (!arpresolve(ac, rt, m, dst, edst, rt0))
216                         return (0);     /* if not yet resolved */
217                 off = m->m_pkthdr.len - m->m_len;
218                 type = htons(ETHERTYPE_IP);
219                 break;
220 #endif
221 #ifdef INET6
222         case AF_INET6:
223                 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
224                         /* this must be impossible, so we bark */
225                         printf("nd6_storelladdr failed\n");
226                         return(0);
227                 }
228                 off = m->m_pkthdr.len - m->m_len;
229                 type = htons(ETHERTYPE_IPV6);
230                 break;
231 #endif
232 #ifdef IPX
233         case AF_IPX:
234                 type = htons(ETHERTYPE_IPX);
235                 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
236                     (caddr_t)edst, sizeof (edst));
237                 break;
238 #endif
239 #ifdef NETATALK
240         case AF_APPLETALK:
241           {
242             struct at_ifaddr *aa;
243
244             if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
245                     goto bad;
246             }
247             if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
248                     return (0);
249             /*
250              * In the phase 2 case, need to prepend an mbuf for the llc header.
251              * Since we must preserve the value of m, which is passed to us by
252              * value, we m_copy() the first mbuf, and use it for our llc header.
253              */
254             if ( aa->aa_flags & AFA_PHASE2 ) {
255                 struct llc llc;
256
257                 M_PREPEND(m, sizeof(struct llc), M_WAIT);
258                 len += sizeof(struct llc);
259                 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
260                 llc.llc_control = LLC_UI;
261                 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
262                 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
263                 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
264                 type = htons(m->m_pkthdr.len);
265                 hlen = sizeof(struct llc) + ETHER_HDR_LEN;
266             } else {
267                 type = htons(ETHERTYPE_AT);
268             }
269             break;
270           }
271 #endif NETATALK
272 #ifdef NS
273         case AF_NS:
274                 switch(ns_nettype){
275                 default:
276                 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
277                         type = 0x8137;
278                         break;
279                 case 0x0: /* Novell 802.3 */
280                         type = htons( m->m_pkthdr.len);
281                         break;
282                 case 0xe0e0: /* Novell 802.2 and Token-Ring */
283                         M_PREPEND(m, 3, M_WAIT);
284                         type = htons( m->m_pkthdr.len);
285                         cp = mtod(m, u_char *);
286                         *cp++ = 0xE0;
287                         *cp++ = 0xE0;
288                         *cp++ = 0x03;
289                         break;
290                 }
291                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
292                     (caddr_t)edst, sizeof (edst));
293                 /*
294                  * XXX if ns_thishost is the same as the node's ethernet
295                  * address then just the default code will catch this anyhow.
296                  * So I'm not sure if this next clause should be here at all?
297                  * [JRE]
298                  */
299                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
300                         m->m_pkthdr.rcvif = ifp;
301                         schednetisr(NETISR_NS);
302                         inq = &nsintrq;
303                         s = splimp();
304                         if (IF_QFULL(inq)) {
305                                 IF_DROP(inq);
306                                 m_freem(m);
307                         } else
308                                 IF_ENQUEUE(inq, m);
309                         splx(s);
310                         return (error);
311                 }
312                 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
313                         m->m_flags |= M_BCAST;
314                 }
315                 break;
316 #endif /* NS */
317 #ifdef  ISO
318         case AF_ISO: {
319                 int     snpalen;
320                 struct  llc *l;
321                 register struct sockaddr_dl *sdl;
322
323                 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
324                     sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
325                         bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
326                 } else if (error =
327                             iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
328                                             (char *)edst, &snpalen))
329                         goto bad; /* Not Resolved */
330                 /* If broadcasting on a simplex interface, loopback a copy */
331                 if (*edst & 1)
332                         m->m_flags |= (M_BCAST|M_MCAST);
333                 M_PREPEND(m, 3, M_DONTWAIT);
334                 if (m == NULL)
335                         return (0);
336                 type = htons(m->m_pkthdr.len);
337                 l = mtod(m, struct llc *);
338                 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
339                 l->llc_control = LLC_UI;
340                 len += 3;
341                 IFDEBUG(D_ETHER)
342                         int i;
343                         printf("unoutput: sending pkt to: ");
344                         for (i=0; i<6; i++)
345                                 printf("%x ", edst[i] & 0xff);
346                         printf("\n");
347                 ENDDEBUG
348                 } break;
349 #endif /* ISO */
350 #ifdef  LLC
351 /*      case AF_NSAP: */
352         case AF_CCITT: {
353                 register struct sockaddr_dl *sdl =
354                         (struct sockaddr_dl *) rt -> rt_gateway;
355
356                 if (sdl && sdl->sdl_family == AF_LINK
357                     && sdl->sdl_alen > 0) {
358                         bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
359                 } else goto bad; /* Not a link interface ? Funny ... */
360                 if (*edst & 1)
361                         loop_copy = 1;
362                 type = htons(m->m_pkthdr.len);
363 #ifdef LLC_DEBUG
364                 {
365                         int i;
366                         register struct llc *l = mtod(m, struct llc *);
367
368                         printf("ether_output: sending LLC2 pkt to: ");
369                         for (i=0; i<6; i++)
370                                 printf("%x ", edst[i] & 0xff);
371                         printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
372                                type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
373                                l->llc_control & 0xff);
374
375                 }
376 #endif /* LLC_DEBUG */
377                 } break;
378 #endif /* LLC */
379
380         case pseudo_AF_HDRCMPLT:
381                 hdrcmplt = 1;
382                 eh = (struct ether_header *)dst->sa_data;
383                 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
384                 /* FALLTHROUGH */
385
386         case AF_UNSPEC:
387                 loop_copy = -1; /* if this is for us, don't do it */
388                 eh = (struct ether_header *)dst->sa_data;
389                 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
390                 type = eh->ether_type;
391                 break;
392
393         default:
394                 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
395                         dst->sa_family);
396                 senderr(EAFNOSUPPORT);
397         }
398
399         /*
400          * Add local net header.  If no space in first mbuf,
401          * allocate another.
402          */
403         M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
404         if (m == 0)
405                 senderr(ENOBUFS);
406         eh = mtod(m, struct ether_header *);
407         (void)memcpy(&eh->ether_type, &type,
408                 sizeof(eh->ether_type));
409         (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
410         if (hdrcmplt)
411                 (void)memcpy(eh->ether_shost, esrc,
412                         sizeof(eh->ether_shost));
413         else
414                 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
415                         sizeof(eh->ether_shost));
416
417         /*
418          * If a simplex interface, and the packet is being sent to our
419          * Ethernet address or a broadcast address, loopback a copy.
420          * XXX To make a simplex device behave exactly like a duplex
421          * device, we should copy in the case of sending to our own
422          * ethernet address (thus letting the original actually appear
423          * on the wire). However, we don't do that here for security
424          * reasons and compatibility with the original behavior.
425          */
426         if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
427                 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
428                         struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
429
430                         (void) if_simloop(ifp, n, dst, hlen);
431                 } else if (bcmp(eh->ether_dhost,
432                     eh->ether_shost, ETHER_ADDR_LEN) == 0) {
433                         (void) if_simloop(ifp, m, dst, hlen);
434                         return (0);     /* XXX */
435                 }
436         }
437 #ifdef BRIDGE
438         if (do_bridge) {
439                 struct mbuf *m0 = m ;
440
441                 if (m->m_pkthdr.rcvif)
442                         m->m_pkthdr.rcvif = NULL ;
443                 ifp = bridge_dst_lookup(m);
444                 bdg_forward(&m0, ifp);
445                 if (m0)
446                         m_freem(m0);
447                 return (0);
448         }
449 #endif
450         s = splimp();
451         /*
452          * Queue message on interface, and start output if interface
453          * not yet active.
454          */
455         if (IF_QFULL(&ifp->if_snd)) {
456                 IF_DROP(&ifp->if_snd);
457                 splx(s);
458                 senderr(ENOBUFS);
459         }
460         IF_ENQUEUE(&ifp->if_snd, m);
461         if ((ifp->if_flags & IFF_OACTIVE) == 0)
462                 (*ifp->if_start)(ifp);
463         splx(s);
464         ifp->if_obytes += len + sizeof (struct ether_header);
465         if (m->m_flags & M_MCAST)
466                 ifp->if_omcasts++;
467         return (error);
468
469 bad:
470         if (m)
471                 m_freem(m);
472         return (error);
473 }
474
475 /*
476  * Process a received Ethernet packet;
477  * the packet is in the mbuf chain m without
478  * the ether header, which is provided separately.
479  */
480 void
481 ether_input(ifp, eh, m)
482         struct ifnet *ifp;
483         register struct ether_header *eh;
484         struct mbuf *m;
485 {
486         register struct ifqueue *inq;
487         u_short ether_type;
488         int s;
489 #if defined (ISO) || defined (LLC) || defined(NETATALK)
490         register struct llc *l;
491 #endif
492
493         if ((ifp->if_flags & IFF_UP) == 0) {
494                 m_freem(m);
495                 return;
496         }
497         ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
498         if (eh->ether_dhost[0] & 1) {
499                 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
500                          sizeof(etherbroadcastaddr)) == 0)
501                         m->m_flags |= M_BCAST;
502                 else
503                         m->m_flags |= M_MCAST;
504         }
505         if (m->m_flags & (M_BCAST|M_MCAST))
506                 ifp->if_imcasts++;
507
508         ether_type = ntohs(eh->ether_type);
509
510 #ifdef  NETGRAPH
511         {
512                 struct arpcom *ac = IFP2AC(ifp);
513                 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
514                         ngether_send(ac, eh, m);
515                         return;
516                 }
517         }
518 #endif  /* NETGRAPH */
519                 
520 #if NVLAN > 0
521         if (ether_type == vlan_proto) {
522                 if (vlan_input(eh, m) < 0)
523                         ifp->if_data.ifi_noproto++;
524                 return;
525         }
526 #endif /* NVLAN > 0 */
527
528         switch (ether_type) {
529 #ifdef INET
530         case ETHERTYPE_IP:
531                 if (ipflow_fastforward(m))
532                         return;
533                 schednetisr(NETISR_IP);
534                 inq = &ipintrq;
535                 break;
536
537         case ETHERTYPE_ARP:
538                 schednetisr(NETISR_ARP);
539                 inq = &arpintrq;
540                 break;
541 #endif
542 #ifdef IPX
543         case ETHERTYPE_IPX:
544                 schednetisr(NETISR_IPX);
545                 inq = &ipxintrq;
546                 break;
547 #endif
548 #ifdef INET6
549         case ETHERTYPE_IPV6:
550                 schednetisr(NETISR_IPV6);
551                 inq = &ip6intrq;
552                 break;
553 #endif
554 #ifdef NS
555         case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
556                 schednetisr(NETISR_NS);
557                 inq = &nsintrq;
558                 break;
559
560 #endif /* NS */
561 #ifdef NETATALK
562         case ETHERTYPE_AT:
563                 schednetisr(NETISR_ATALK);
564                 inq = &atintrq1;
565                 break;
566         case ETHERTYPE_AARP:
567                 /* probably this should be done with a NETISR as well */
568                 aarpinput(IFP2AC(ifp), m); /* XXX */
569                 return;
570 #endif NETATALK
571         default:
572 #ifdef NS
573                 checksum = mtod(m, ushort *);
574                 /* Novell 802.3 */
575                 if ((ether_type <= ETHERMTU) &&
576                         ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
577                         if(*checksum == 0xE0E0) {
578                                 m->m_pkthdr.len -= 3;
579                                 m->m_len -= 3;
580                                 m->m_data += 3;
581                         }
582                                 schednetisr(NETISR_NS);
583                                 inq = &nsintrq;
584                                 break;
585                 }
586 #endif /* NS */
587 #if defined (ISO) || defined (LLC) || defined(NETATALK)
588                 if (ether_type > ETHERMTU)
589                         goto dropanyway;
590                 l = mtod(m, struct llc *);
591                 switch (l->llc_dsap) {
592 #ifdef NETATALK
593                 case LLC_SNAP_LSAP:
594                     switch (l->llc_control) {
595                     case LLC_UI:
596                         if (l->llc_ssap != LLC_SNAP_LSAP)
597                             goto dropanyway;
598         
599                         if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
600                                    sizeof(at_org_code)) == 0 &&
601                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
602                             inq = &atintrq2;
603                             m_adj( m, sizeof( struct llc ));
604                             schednetisr(NETISR_ATALK);
605                             break;
606                         }
607
608                         if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
609                                    sizeof(aarp_org_code)) == 0 &&
610                              ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
611                             m_adj( m, sizeof( struct llc ));
612                             aarpinput(IFP2AC(ifp), m); /* XXX */
613                             return;
614                         }
615                 
616                     default:
617                         goto dropanyway;
618                     }
619                     break;
620 #endif NETATALK 
621 #ifdef  ISO
622                 case LLC_ISO_LSAP:
623                         switch (l->llc_control) {
624                         case LLC_UI:
625                                 /* LLC_UI_P forbidden in class 1 service */
626                                 if ((l->llc_dsap == LLC_ISO_LSAP) &&
627                                     (l->llc_ssap == LLC_ISO_LSAP)) {
628                                         /* LSAP for ISO */
629                                         if (m->m_pkthdr.len > ether_type)
630                                                 m_adj(m, ether_type - m->m_pkthdr.len);
631                                         m->m_data += 3;         /* XXX */
632                                         m->m_len -= 3;          /* XXX */
633                                         m->m_pkthdr.len -= 3;   /* XXX */
634                                         M_PREPEND(m, sizeof *eh, M_DONTWAIT);
635                                         if (m == 0)
636                                                 return;
637                                         *mtod(m, struct ether_header *) = *eh;
638                                         IFDEBUG(D_ETHER)
639                                                 printf("clnp packet");
640                                         ENDDEBUG
641                                         schednetisr(NETISR_ISO);
642                                         inq = &clnlintrq;
643                                         break;
644                                 }
645                                 goto dropanyway;
646
647                         case LLC_XID:
648                         case LLC_XID_P:
649                                 if(m->m_len < 6)
650                                         goto dropanyway;
651                                 l->llc_window = 0;
652                                 l->llc_fid = 9;
653                                 l->llc_class = 1;
654                                 l->llc_dsap = l->llc_ssap = 0;
655                                 /* Fall through to */
656                         case LLC_TEST:
657                         case LLC_TEST_P:
658                         {
659                                 struct sockaddr sa;
660                                 register struct ether_header *eh2;
661                                 int i;
662                                 u_char c = l->llc_dsap;
663
664                                 l->llc_dsap = l->llc_ssap;
665                                 l->llc_ssap = c;
666                                 if (m->m_flags & (M_BCAST | M_MCAST))
667                                         bcopy((caddr_t)ac->ac_enaddr,
668                                               (caddr_t)eh->ether_dhost, 6);
669                                 sa.sa_family = AF_UNSPEC;
670                                 sa.sa_len = sizeof(sa);
671                                 eh2 = (struct ether_header *)sa.sa_data;
672                                 for (i = 0; i < 6; i++) {
673                                         eh2->ether_shost[i] = c = eh->ether_dhost[i];
674                                         eh2->ether_dhost[i] =
675                                                 eh->ether_dhost[i] = eh->ether_shost[i];
676                                         eh->ether_shost[i] = c;
677                                 }
678                                 ifp->if_output(ifp, m, &sa, NULL);
679                                 return;
680                         }
681                         default:
682                                 m_freem(m);
683                                 return;
684                         }
685                         break;
686 #endif /* ISO */
687 #ifdef LLC
688                 case LLC_X25_LSAP:
689                 {
690                         if (m->m_pkthdr.len > ether_type)
691                                 m_adj(m, ether_type - m->m_pkthdr.len);
692                         M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
693                         if (m == 0)
694                                 return;
695                         if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
696                                             eh->ether_dhost, LLC_X25_LSAP, 6,
697                                             mtod(m, struct sdl_hdr *)))
698                                 panic("ETHER cons addr failure");
699                         mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
700 #ifdef LLC_DEBUG
701                                 printf("llc packet\n");
702 #endif /* LLC_DEBUG */
703                         schednetisr(NETISR_CCITT);
704                         inq = &llcintrq;
705                         break;
706                 }
707 #endif /* LLC */
708                 dropanyway:
709                 default:
710 #ifdef  NETGRAPH
711                         ngether_send(IFP2AC(ifp), eh, m);
712 #else   /* NETGRAPH */
713                         m_freem(m);
714 #endif  /* NETGRAPH */
715                         return;
716                 }
717 #else /* ISO || LLC || NETATALK */
718 #ifdef  NETGRAPH
719             ngether_send(IFP2AC(ifp), eh, m);
720 #else   /* NETGRAPH */
721             m_freem(m);
722 #endif  /* NETGRAPH */
723             return;
724 #endif /* ISO || LLC || NETATALK */
725         }
726
727         s = splimp();
728         if (IF_QFULL(inq)) {
729                 IF_DROP(inq);
730                 m_freem(m);
731         } else
732                 IF_ENQUEUE(inq, m);
733         splx(s);
734 }
735
736 /*
737  * Perform common duties while attaching to interface list
738  */
739 void
740 ether_ifattach(ifp)
741         register struct ifnet *ifp;
742 {
743         register struct ifaddr *ifa;
744         register struct sockaddr_dl *sdl;
745
746         ifp->if_type = IFT_ETHER;
747         ifp->if_addrlen = 6;
748         ifp->if_hdrlen = 14;
749         ifp->if_mtu = ETHERMTU;
750         ifp->if_resolvemulti = ether_resolvemulti;
751         if (ifp->if_baudrate == 0)
752             ifp->if_baudrate = 10000000;
753         ifa = ifnet_addrs[ifp->if_index - 1];
754         if (ifa == 0) {
755                 printf("ether_ifattach: no lladdr!\n");
756                 return;
757         }
758         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
759         sdl->sdl_type = IFT_ETHER;
760         sdl->sdl_alen = ifp->if_addrlen;
761         bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
762 #ifdef  NETGRAPH
763         ngether_init(ifp);
764 #endif /* NETGRAPH */
765 #ifdef INET6
766         in6_ifattach_getifid(ifp);
767 #endif
768 }
769
770 SYSCTL_DECL(_net_link);
771 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
772
773 int
774 ether_ioctl(ifp, command, data)
775         struct ifnet *ifp;
776         int command;
777         caddr_t data;
778 {
779         struct ifaddr *ifa = (struct ifaddr *) data;
780         struct ifreq *ifr = (struct ifreq *) data;
781         int error = 0;
782
783         switch (command) {
784         case SIOCSIFADDR:
785                 ifp->if_flags |= IFF_UP;
786
787                 switch (ifa->ifa_addr->sa_family) {
788 #ifdef INET
789                 case AF_INET:
790                         ifp->if_init(ifp->if_softc);    /* before arpwhohas */
791                         arp_ifinit(IFP2AC(ifp), ifa);
792                         break;
793 #endif
794 #ifdef IPX
795                 /*
796                  * XXX - This code is probably wrong
797                  */
798                 case AF_IPX:
799                         {
800                         register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
801                         struct arpcom *ac = IFP2AC(ifp);
802
803                         if (ipx_nullhost(*ina))
804                                 ina->x_host =
805                                     *(union ipx_host *)
806                                     ac->ac_enaddr;
807                         else {
808                                 bcopy((caddr_t) ina->x_host.c_host,
809                                       (caddr_t) ac->ac_enaddr,
810                                       sizeof(ac->ac_enaddr));
811                         }
812
813                         /*
814                          * Set new address
815                          */
816                         ifp->if_init(ifp->if_softc);
817                         break;
818                         }
819 #endif
820 #ifdef NS
821                 /*
822                  * XXX - This code is probably wrong
823                  */
824                 case AF_NS:
825                 {
826                         register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
827                         struct arpcom *ac = IFP2AC(ifp);
828
829                         if (ns_nullhost(*ina))
830                                 ina->x_host =
831                                     *(union ns_host *) (ac->ac_enaddr);
832                         else {
833                                 bcopy((caddr_t) ina->x_host.c_host,
834                                       (caddr_t) ac->ac_enaddr,
835                                       sizeof(ac->ac_enaddr));
836                         }
837
838                         /*
839                          * Set new address
840                          */
841                         ifp->if_init(ifp->if_softc);
842                         break;
843                 }
844 #endif
845                 default:
846                         ifp->if_init(ifp->if_softc);
847                         break;
848                 }
849                 break;
850
851         case SIOCGIFADDR:
852                 {
853                         struct sockaddr *sa;
854
855                         sa = (struct sockaddr *) & ifr->ifr_data;
856                         bcopy(IFP2AC(ifp)->ac_enaddr,
857                               (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
858                 }
859                 break;
860
861         case SIOCSIFMTU:
862                 /*
863                  * Set the interface MTU.
864                  */
865                 if (ifr->ifr_mtu > ETHERMTU) {
866                         error = EINVAL;
867                 } else {
868                         ifp->if_mtu = ifr->ifr_mtu;
869                 }
870                 break;
871         }
872         return (error);
873 }
874
875 int
876 ether_resolvemulti(ifp, llsa, sa)
877         struct ifnet *ifp;
878         struct sockaddr **llsa;
879         struct sockaddr *sa;
880 {
881         struct sockaddr_dl *sdl;
882         struct sockaddr_in *sin;
883 #ifdef INET6
884         struct sockaddr_in6 *sin6;
885 #endif
886         u_char *e_addr;
887
888         switch(sa->sa_family) {
889         case AF_LINK:
890                 /*
891                  * No mapping needed. Just check that it's a valid MC address.
892                  */
893                 sdl = (struct sockaddr_dl *)sa;
894                 e_addr = LLADDR(sdl);
895                 if ((e_addr[0] & 1) != 1)
896                         return EADDRNOTAVAIL;
897                 *llsa = 0;
898                 return 0;
899
900 #ifdef INET
901         case AF_INET:
902                 sin = (struct sockaddr_in *)sa;
903                 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
904                         return EADDRNOTAVAIL;
905                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
906                        M_WAITOK);
907                 sdl->sdl_len = sizeof *sdl;
908                 sdl->sdl_family = AF_LINK;
909                 sdl->sdl_index = ifp->if_index;
910                 sdl->sdl_type = IFT_ETHER;
911                 sdl->sdl_nlen = 0;
912                 sdl->sdl_alen = ETHER_ADDR_LEN;
913                 sdl->sdl_slen = 0;
914                 e_addr = LLADDR(sdl);
915                 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
916                 *llsa = (struct sockaddr *)sdl;
917                 return 0;
918 #endif
919 #ifdef INET6
920         case AF_INET6:
921                 sin6 = (struct sockaddr_in6 *)sa;
922                 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
923                         return EADDRNOTAVAIL;
924                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
925                        M_WAITOK);
926                 sdl->sdl_len = sizeof *sdl;
927                 sdl->sdl_family = AF_LINK;
928                 sdl->sdl_index = ifp->if_index;
929                 sdl->sdl_type = IFT_ETHER;
930                 sdl->sdl_nlen = 0;
931                 sdl->sdl_alen = ETHER_ADDR_LEN;
932                 sdl->sdl_slen = 0;
933                 e_addr = LLADDR(sdl);
934                 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
935                 *llsa = (struct sockaddr *)sdl;
936                 return 0;
937 #endif
938
939         default:
940                 /*
941                  * Well, the text isn't quite right, but it's the name
942                  * that counts...
943                  */
944                 return EAFNOSUPPORT;
945         }
946 }
947
948 #ifdef  NETGRAPH
949
950 /***********************************************************************
951  * This section contains the methods for the Netgraph interface
952  ***********************************************************************/
953 /* It's Ascii-art time!
954  * The ifnet is the first part of the arpcom which must be
955  * the first part of the device's softc.. yuk.
956  *
957  *      +--------------------------+-----+---------+
958  *      |   struct ifnet (*ifp)    |     |         |
959  *      |                          |     |         |
960  *      +--------------------------+     |         |
961  *   +--|[ac_ng]     struct arpcom (*ac) |         |
962  *   |  +--------------------------------+         |
963  *   |  |   struct softc (*ifp->if_softc) (device) |
964  *   |  +------------------------------------------+
965  *   |               ^
966  * AC2NG()           |
967  *   |               v
968  *   |       +----------------------+
969  *   |       |   [private] [flags]  |
970  *   +------>| struct ng_node       |
971  *           |    [hooks]           | ** we only allow one hook
972  *           +----------------------+
973  *                   ^
974  *                   |
975  *                   v
976  *           +-------------+
977  *           |    [node]   |
978  *           |    hook     |
979  *           |    [private]|-- *unused*
980  *           +-------------+
981  */
982
983 /*
984  * called during interface attaching
985  */
986 static void
987 ngether_init(void *ifpvoid)
988 {
989         struct  ifnet *ifp = ifpvoid;
990         struct arpcom *ac = IFP2AC(ifp);
991         static int      ngether_done_init;
992         char    namebuf[32];
993         node_p node;
994
995         /*
996          * we have found a node, make sure our 'type' is availabe.
997          */
998         if (ngether_done_init == 0) {
999                 if (ng_newtype(&typestruct)) {
1000                         printf("ngether install failed\n");
1001                         return;
1002                 }
1003                 ngether_done_init = 1;
1004         }
1005         if (ng_make_node_common(&typestruct, &node) != 0)
1006                 return;
1007         ac->ac_ng = node;
1008         node->private = ifp;
1009         sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
1010         ng_name_node(AC2NG(ac), namebuf);
1011 }
1012
1013 /*
1014  * It is not possible or allowable to create a node of this type.
1015  * If the hardware exists, it will already have created it.
1016  */
1017 static  int
1018 ngether_constructor(node_p *nodep)
1019 {
1020         return (EINVAL);
1021 }
1022
1023 /*
1024  * Give our ok for a hook to be added...
1025  *
1026  * Allow one hook at a time (rawdata).
1027  * It can eiteh rdivert everything or only unclaimed packets.
1028  */
1029 static  int
1030 ngether_newhook(node_p node, hook_p hook, const char *name)
1031 {
1032
1033         /* check if there is already a hook */
1034         if (LIST_FIRST(&(node->hooks)))
1035                 return(EISCONN);
1036         /*
1037          * Check for which mode hook we want.
1038          */
1039         if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
1040                 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
1041                         return (EINVAL);
1042                 }
1043                 node->flags |= NGEF_DIVERT;
1044         } else {
1045                 node->flags &= ~NGEF_DIVERT;
1046         }
1047         return (0);
1048 }
1049
1050 /*
1051  * incoming messages.
1052  * Just respond to the generic TEXT_STATUS message
1053  */
1054 static  int
1055 ngether_rcvmsg(node_p node,
1056         struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
1057 {
1058         struct ifnet    *ifp;
1059         int error = 0;
1060
1061         ifp = node->private;
1062         switch (msg->header.typecookie) {
1063             case        NGM_ETHER_COOKIE:
1064                 error = EINVAL;
1065                 break;
1066             case        NGM_GENERIC_COOKIE:
1067                 switch(msg->header.cmd) {
1068                     case NGM_TEXT_STATUS: {
1069                             char        *arg;
1070                             int pos = 0;
1071                             int resplen = sizeof(struct ng_mesg) + 512;
1072                             MALLOC(*resp, struct ng_mesg *, resplen,
1073                                         M_NETGRAPH, M_NOWAIT);
1074                             if (*resp == NULL) {
1075                                 error = ENOMEM;
1076                                 break;
1077                             }
1078                             bzero(*resp, resplen);
1079                             arg = (*resp)->data;
1080
1081                             /*
1082                              * Put in the throughput information.
1083                              */
1084                             pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
1085                             ifp->if_ibytes, ifp->if_obytes);
1086                             pos += sprintf(arg + pos,
1087                                 "%ld output errors\n",
1088                                 ifp->if_oerrors);
1089                             pos += sprintf(arg + pos,
1090                                 "ierrors = %ld\n",
1091                                 ifp->if_ierrors);
1092
1093                             (*resp)->header.version = NG_VERSION;
1094                             (*resp)->header.arglen = strlen(arg) + 1;
1095                             (*resp)->header.token = msg->header.token;
1096                             (*resp)->header.typecookie = NGM_ETHER_COOKIE;
1097                             (*resp)->header.cmd = msg->header.cmd;
1098                             strncpy((*resp)->header.cmdstr, "status",
1099                                         NG_CMDSTRLEN);
1100                         }
1101                         break;
1102                     default:
1103                         error = EINVAL;
1104                         break;
1105                     }
1106                 break;
1107             default:
1108                 error = EINVAL;
1109                 break;
1110         }
1111         free(msg, M_NETGRAPH);
1112         return (error);
1113 }
1114
1115 /*
1116  * Receive a completed ethernet packet.
1117  * Queue it for output.
1118  */
1119 static  int
1120 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1121 {
1122         struct ifnet *ifp;
1123         int     error = 0;
1124         int     s;
1125         struct ether_header *eh;
1126         
1127         ifp = hook->node->private;
1128
1129         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1130                 senderr(ENETDOWN);
1131         /* drop in the MAC address */
1132         eh = mtod(m, struct ether_header *);
1133         bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6);
1134         /*
1135          * If a simplex interface, and the packet is being sent to our
1136          * Ethernet address or a broadcast address, loopback a copy.
1137          * XXX To make a simplex device behave exactly like a duplex
1138          * device, we should copy in the case of sending to our own
1139          * ethernet address (thus letting the original actually appear
1140          * on the wire). However, we don't do that here for security
1141          * reasons and compatibility with the original behavior.
1142          */
1143         if (ifp->if_flags & IFF_SIMPLEX) {
1144                 if (m->m_flags & M_BCAST) {
1145                         struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
1146
1147                         ng_queue_data(hook, n, meta);
1148                 } else if (bcmp(eh->ether_dhost,
1149                     eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1150                         ng_queue_data(hook, m, meta);
1151                         return (0);     /* XXX */
1152                 }
1153         }
1154         s = splimp();
1155         /*
1156          * Queue message on interface, and start output if interface
1157          * not yet active.
1158          * XXX if we lookead at the priority in the meta data we could
1159          * queue high priority items at the head.
1160          */
1161         if (IF_QFULL(&ifp->if_snd)) {
1162                 IF_DROP(&ifp->if_snd);
1163                 splx(s);
1164                 senderr(ENOBUFS);
1165         }
1166         IF_ENQUEUE(&ifp->if_snd, m);
1167         if ((ifp->if_flags & IFF_OACTIVE) == 0)
1168                 (*ifp->if_start)(ifp);
1169         splx(s);
1170         ifp->if_obytes += m->m_pkthdr.len;
1171         if (m->m_flags & M_MCAST)
1172                 ifp->if_omcasts++;
1173         return (error);
1174
1175 bad:
1176         NG_FREE_DATA(m, meta);
1177         return (error);
1178 }
1179
1180 /*
1181  * pass an mbuf out to the connected hook
1182  * More complicated than just an m_prepend, as it tries to save later nodes
1183  * from needing to do lots of m_pullups.
1184  */     
1185 static void
1186 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
1187 {
1188         int room;
1189         node_p node = AC2NG(ac);
1190         struct ether_header *eh2;
1191                 
1192         if (node && LIST_FIRST(&(node->hooks))) {
1193                 /*
1194                  * Possibly the header is already on the front,
1195                  */
1196                 eh2 = mtod(m, struct ether_header *) - 1;
1197                 if ( eh == eh2) {
1198                         /*
1199                          * This is the case so just move the markers back to
1200                          * re-include it. We lucked out.
1201                          * This allows us to avoid a yucky m_pullup
1202                          * in later nodes if it works.
1203                          */
1204                         m->m_len += sizeof(*eh);
1205                         m->m_data -= sizeof(*eh);
1206                         m->m_pkthdr.len += sizeof(*eh);
1207                 } else {
1208                         /*
1209                          * Alternatively there may be room even though
1210                          * it is stored somewhere else. If so, copy it in.
1211                          * This only safe because we KNOW that this packet has
1212                          * just been generated by an ethernet card, so there
1213                          * are no aliases to the buffer. (unlike in outgoing
1214                          * packets).
1215                          * Nearly all ethernet cards will end up producing mbufs
1216                          * that fall into these cases. So we are not optimising
1217                          * contorted cases.
1218                          */
1219         
1220                         if (m->m_flags & M_EXT) {
1221                                 room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
1222                                 if (room > m->m_ext.ext_size) /* garbage */
1223                                         room = 0; /* fail immediatly */
1224                         } else {
1225                                 room = (mtod(m, caddr_t) - m->m_pktdat);
1226                         }
1227                         if (room > sizeof (*eh)) {
1228                                 /* we have room, just copy it and adjust */
1229                                 m->m_len += sizeof(*eh);
1230                                 m->m_data -= sizeof(*eh);
1231                                 m->m_pkthdr.len += sizeof(*eh);
1232                         } else {
1233                                 /*
1234                                  * Doing anything more is likely to get more
1235                                  * expensive than it's worth..
1236                                  * it's probable that everything else is in one
1237                                  * big lump. The next node will do an m_pullup()
1238                                  * for exactly the amount of data it needs and
1239                                  * hopefully everything after that will not
1240                                  * need one. So let's just use M_PREPEND.
1241                                  */
1242                                 M_PREPEND(m, sizeof (*eh), M_DONTWAIT);
1243                                 if (m == NULL)
1244                                         return;
1245                         }
1246                         bcopy ((caddr_t)eh, mtod(m, struct ether_header *),
1247                             sizeof(*eh));
1248                 }
1249                 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
1250         } else {
1251                 m_freem(m);
1252         }
1253 }
1254
1255 /*
1256  * do local shutdown processing..
1257  * This node will refuse to go away, unless the hardware says to..
1258  * don't unref the node, or remove our name. just clear our links up.
1259  */
1260 static  int
1261 ngether_rmnode(node_p node)
1262 {
1263         ng_cutlinks(node);
1264         node->flags &= ~NG_INVALID; /* bounce back to life */
1265         return (0);
1266 }
1267
1268 /* already linked */
1269 static  int
1270 ngether_connect(hook_p hook)
1271 {
1272         /* be really amiable and just say "YUP that's OK by me! " */
1273         return (0);
1274 }
1275
1276 /*
1277  * notify on hook disconnection (destruction)
1278  *
1279  * For this type, removal of the last lins no effect. The interface can run
1280  * independently.
1281  * Since we have no per-hook information, this is rather simple.
1282  */
1283 static  int
1284 ngether_disconnect(hook_p hook)
1285 {
1286         hook->node->flags &= ~NGEF_DIVERT;
1287         return (0);
1288 }
1289 #endif /* NETGRAPH */
1290
1291 /********************************** END *************************************/