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