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