1 /*
2 * Copyright (c) 1982, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)if_ethersubr.c 8.1 (Berkeley) 06/10/93
8 */
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/kernel.h>
13 #include <sys/malloc.h>
14 #include <sys/mbuf.h>
15 #include <sys/protosw.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/errno.h>
19 #include <sys/syslog.h>
20
21 #include <machine/cpu.h>
22
23 #include <net/if.h>
24 #include <net/netisr.h>
25 #include <net/route.h>
26 #include <net/if_llc.h>
27 #include <net/if_dl.h>
28 #include <net/if_types.h>
29
30 #ifdef INET
31 #include <netinet/in.h>
32 #include <netinet/in_var.h>
33 #endif
34 #include <netinet/if_ether.h>
35
36 #ifdef NS
37 #include <netns/ns.h>
38 #include <netns/ns_if.h>
39 #endif
40
41 #ifdef ISO
42 #include <netiso/argo_debug.h>
43 #include <netiso/iso.h>
44 #include <netiso/iso_var.h>
45 #include <netiso/iso_snpac.h>
46 #endif
47
48 #ifdef LLC
49 #include <netccitt/dll.h>
50 #include <netccitt/llc_var.h>
51 #endif
52
53 #if defined(LLC) && defined(CCITT)
54 extern struct ifqueue pkintrq;
55 #endif
56
57 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
58 extern struct ifnet loif;
59 #define senderr(e) { error = (e); goto bad;}
60
61 /*
62 * Ethernet output routine.
63 * Encapsulate a packet of type family for the local net.
64 * Use trailer local net encapsulation if enough data in first
65 * packet leaves a multiple of 512 bytes of data in remainder.
66 * Assumes that ifp is actually pointer to arpcom structure.
67 */
68 int
ether_output(ifp,m0,dst,rt0)69 ether_output(ifp, m0, dst, rt0)
70 register struct ifnet *ifp;
71 struct mbuf *m0;
72 struct sockaddr *dst;
73 struct rtentry *rt0;
74 {
75 short type;
76 int s, error = 0;
77 u_char edst[6];
78 register struct mbuf *m = m0;
79 register struct rtentry *rt;
80 struct mbuf *mcopy = (struct mbuf *)0;
81 register struct ether_header *eh;
82 int off, len = m->m_pkthdr.len;
83 struct arpcom *ac = (struct arpcom *)ifp;
84
85 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
86 senderr(ENETDOWN);
87 ifp->if_lastchange = time;
88 if (rt = rt0) {
89 if ((rt->rt_flags & RTF_UP) == 0) {
90 if (rt0 = rt = rtalloc1(dst, 1))
91 rt->rt_refcnt--;
92 else
93 senderr(EHOSTUNREACH);
94 }
95 if (rt->rt_flags & RTF_GATEWAY) {
96 if (rt->rt_gwroute == 0)
97 goto lookup;
98 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
99 rtfree(rt); rt = rt0;
100 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
101 if ((rt = rt->rt_gwroute) == 0)
102 senderr(EHOSTUNREACH);
103 }
104 }
105 if (rt->rt_flags & RTF_REJECT)
106 if (rt->rt_rmx.rmx_expire == 0 ||
107 time.tv_sec < rt->rt_rmx.rmx_expire)
108 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
109 }
110 switch (dst->sa_family) {
111
112 #ifdef INET
113 case AF_INET:
114 if (!arpresolve(ac, rt, m, dst, edst))
115 return (0); /* if not yet resolved */
116 /* If broadcasting on a simplex interface, loopback a copy */
117 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
118 mcopy = m_copy(m, 0, (int)M_COPYALL);
119 off = m->m_pkthdr.len - m->m_len;
120 type = ETHERTYPE_IP;
121 break;
122 #endif
123 #ifdef NS
124 case AF_NS:
125 type = ETHERTYPE_NS;
126 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
127 (caddr_t)edst, sizeof (edst));
128 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
129 return (looutput(ifp, m, dst, rt));
130 /* If broadcasting on a simplex interface, loopback a copy */
131 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
132 mcopy = m_copy(m, 0, (int)M_COPYALL);
133 break;
134 #endif
135 #ifdef ISO
136 case AF_ISO: {
137 int snpalen;
138 struct llc *l;
139 register struct sockaddr_dl *sdl;
140
141 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
142 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
143 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
144 } else if (error =
145 iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
146 (char *)edst, &snpalen))
147 goto bad; /* Not Resolved */
148 /* If broadcasting on a simplex interface, loopback a copy */
149 if (*edst & 1)
150 m->m_flags |= (M_BCAST|M_MCAST);
151 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
152 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
153 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
154 if (mcopy) {
155 eh = mtod(mcopy, struct ether_header *);
156 bcopy((caddr_t)edst,
157 (caddr_t)eh->ether_dhost, sizeof (edst));
158 bcopy((caddr_t)ac->ac_enaddr,
159 (caddr_t)eh->ether_shost, sizeof (edst));
160 }
161 }
162 M_PREPEND(m, 3, M_DONTWAIT);
163 if (m == NULL)
164 return (0);
165 type = m->m_pkthdr.len;
166 l = mtod(m, struct llc *);
167 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
168 l->llc_control = LLC_UI;
169 len += 3;
170 IFDEBUG(D_ETHER)
171 int i;
172 printf("unoutput: sending pkt to: ");
173 for (i=0; i<6; i++)
174 printf("%x ", edst[i] & 0xff);
175 printf("\n");
176 ENDDEBUG
177 } break;
178 #endif /* ISO */
179 #ifdef LLC
180 /* case AF_NSAP: */
181 case AF_CCITT: {
182 register struct sockaddr_dl *sdl =
183 (struct sockaddr_dl *) rt -> rt_gateway;
184
185 if (sdl && sdl->sdl_family == AF_LINK
186 && sdl->sdl_alen > 0) {
187 bcopy(LLADDR(sdl), (char *)edst,
188 sizeof(edst));
189 } else goto bad; /* Not a link interface ? Funny ... */
190 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
191 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
192 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
193 if (mcopy) {
194 eh = mtod(mcopy, struct ether_header *);
195 bcopy((caddr_t)edst,
196 (caddr_t)eh->ether_dhost, sizeof (edst));
197 bcopy((caddr_t)ac->ac_enaddr,
198 (caddr_t)eh->ether_shost, sizeof (edst));
199 }
200 }
201 type = m->m_pkthdr.len;
202 #ifdef LLC_DEBUG
203 {
204 int i;
205 register struct llc *l = mtod(m, struct llc *);
206
207 printf("ether_output: sending LLC2 pkt to: ");
208 for (i=0; i<6; i++)
209 printf("%x ", edst[i] & 0xff);
210 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
211 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
212 l->llc_control & 0xff);
213
214 }
215 #endif /* LLC_DEBUG */
216 } break;
217 #endif /* LLC */
218
219 case AF_UNSPEC:
220 eh = (struct ether_header *)dst->sa_data;
221 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
222 type = eh->ether_type;
223 break;
224
225 default:
226 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
227 dst->sa_family);
228 senderr(EAFNOSUPPORT);
229 }
230
231
232 if (mcopy)
233 (void) looutput(ifp, mcopy, dst, rt);
234 /*
235 * Add local net header. If no space in first mbuf,
236 * allocate another.
237 */
238 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
239 if (m == 0)
240 senderr(ENOBUFS);
241 eh = mtod(m, struct ether_header *);
242 type = htons((u_short)type);
243 bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
244 sizeof(eh->ether_type));
245 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
246 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
247 sizeof(eh->ether_shost));
248 s = splimp();
249 /*
250 * Queue message on interface, and start output if interface
251 * not yet active.
252 */
253 if (IF_QFULL(&ifp->if_snd)) {
254 IF_DROP(&ifp->if_snd);
255 splx(s);
256 senderr(ENOBUFS);
257 }
258 IF_ENQUEUE(&ifp->if_snd, m);
259 if ((ifp->if_flags & IFF_OACTIVE) == 0)
260 (*ifp->if_start)(ifp);
261 splx(s);
262 ifp->if_obytes += len + sizeof (struct ether_header);
263 if (m->m_flags & M_MCAST)
264 ifp->if_omcasts++;
265 return (error);
266
267 bad:
268 if (m)
269 m_freem(m);
270 return (error);
271 }
272
273 /*
274 * Process a received Ethernet packet;
275 * the packet is in the mbuf chain m without
276 * the ether header, which is provided separately.
277 */
278 void
ether_input(ifp,eh,m)279 ether_input(ifp, eh, m)
280 struct ifnet *ifp;
281 register struct ether_header *eh;
282 struct mbuf *m;
283 {
284 register struct ifqueue *inq;
285 register struct llc *l;
286 struct arpcom *ac = (struct arpcom *)ifp;
287 int s;
288
289 if ((ifp->if_flags & IFF_UP) == 0) {
290 m_freem(m);
291 return;
292 }
293 ifp->if_lastchange = time;
294 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
295 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
296 sizeof(etherbroadcastaddr)) == 0)
297 m->m_flags |= M_BCAST;
298 else if (eh->ether_dhost[0] & 1)
299 m->m_flags |= M_MCAST;
300 if (m->m_flags & (M_BCAST|M_MCAST))
301 ifp->if_imcasts++;
302
303 switch (eh->ether_type) {
304 #ifdef INET
305 case ETHERTYPE_IP:
306 schednetisr(NETISR_IP);
307 inq = &ipintrq;
308 break;
309
310 case ETHERTYPE_ARP:
311 schednetisr(NETISR_ARP);
312 inq = &arpintrq;
313 break;
314 #endif
315 #ifdef NS
316 case ETHERTYPE_NS:
317 schednetisr(NETISR_NS);
318 inq = &nsintrq;
319 break;
320
321 #endif
322 default:
323 #if defined (ISO) || defined (LLC)
324 if (eh->ether_type > ETHERMTU)
325 goto dropanyway;
326 l = mtod(m, struct llc *);
327 switch (l->llc_dsap) {
328 #ifdef ISO
329 case LLC_ISO_LSAP:
330 switch (l->llc_control) {
331 case LLC_UI:
332 /* LLC_UI_P forbidden in class 1 service */
333 if ((l->llc_dsap == LLC_ISO_LSAP) &&
334 (l->llc_ssap == LLC_ISO_LSAP)) {
335 /* LSAP for ISO */
336 if (m->m_pkthdr.len > eh->ether_type)
337 m_adj(m, eh->ether_type - m->m_pkthdr.len);
338 m->m_data += 3; /* XXX */
339 m->m_len -= 3; /* XXX */
340 m->m_pkthdr.len -= 3; /* XXX */
341 M_PREPEND(m, sizeof *eh, M_DONTWAIT);
342 if (m == 0)
343 return;
344 *mtod(m, struct ether_header *) = *eh;
345 IFDEBUG(D_ETHER)
346 printf("clnp packet");
347 ENDDEBUG
348 schednetisr(NETISR_ISO);
349 inq = &clnlintrq;
350 break;
351 }
352 goto dropanyway;
353
354 case LLC_XID:
355 case LLC_XID_P:
356 if(m->m_len < 6)
357 goto dropanyway;
358 l->llc_window = 0;
359 l->llc_fid = 9;
360 l->llc_class = 1;
361 l->llc_dsap = l->llc_ssap = 0;
362 /* Fall through to */
363 case LLC_TEST:
364 case LLC_TEST_P:
365 {
366 struct sockaddr sa;
367 register struct ether_header *eh2;
368 int i;
369 u_char c = l->llc_dsap;
370
371 l->llc_dsap = l->llc_ssap;
372 l->llc_ssap = c;
373 if (m->m_flags & (M_BCAST | M_MCAST))
374 bcopy((caddr_t)ac->ac_enaddr,
375 (caddr_t)eh->ether_dhost, 6);
376 sa.sa_family = AF_UNSPEC;
377 sa.sa_len = sizeof(sa);
378 eh2 = (struct ether_header *)sa.sa_data;
379 for (i = 0; i < 6; i++) {
380 eh2->ether_shost[i] = c = eh->ether_dhost[i];
381 eh2->ether_dhost[i] =
382 eh->ether_dhost[i] = eh->ether_shost[i];
383 eh->ether_shost[i] = c;
384 }
385 ifp->if_output(ifp, m, &sa, NULL);
386 return;
387 }
388 default:
389 m_freem(m);
390 return;
391 }
392 break;
393 #endif /* ISO */
394 #ifdef LLC
395 case LLC_X25_LSAP:
396 {
397 if (m->m_pkthdr.len > eh->ether_type)
398 m_adj(m, eh->ether_type - m->m_pkthdr.len);
399 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
400 if (m == 0)
401 return;
402 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
403 eh->ether_dhost, LLC_X25_LSAP, 6,
404 mtod(m, struct sdl_hdr *)))
405 panic("ETHER cons addr failure");
406 mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type;
407 #ifdef LLC_DEBUG
408 printf("llc packet\n");
409 #endif /* LLC_DEBUG */
410 schednetisr(NETISR_CCITT);
411 inq = &llcintrq;
412 break;
413 }
414 #endif /* LLC */
415 dropanyway:
416 default:
417 m_freem(m);
418 return;
419 }
420 #else /* ISO || LLC */
421 m_freem(m);
422 return;
423 #endif /* ISO || LLC */
424 }
425
426 s = splimp();
427 if (IF_QFULL(inq)) {
428 IF_DROP(inq);
429 m_freem(m);
430 } else
431 IF_ENQUEUE(inq, m);
432 splx(s);
433 }
434
435 /*
436 * Convert Ethernet address to printable (loggable) representation.
437 */
438 static char digits[] = "0123456789abcdef";
439 char *
ether_sprintf(ap)440 ether_sprintf(ap)
441 register u_char *ap;
442 {
443 register i;
444 static char etherbuf[18];
445 register char *cp = etherbuf;
446
447 for (i = 0; i < 6; i++) {
448 *cp++ = digits[*ap >> 4];
449 *cp++ = digits[*ap++ & 0xf];
450 *cp++ = ':';
451 }
452 *--cp = 0;
453 return (etherbuf);
454 }
455
456 /*
457 * Perform common duties while attaching to interface list
458 */
459 void
ether_ifattach(ifp)460 ether_ifattach(ifp)
461 register struct ifnet *ifp;
462 {
463 register struct ifaddr *ifa;
464 register struct sockaddr_dl *sdl;
465
466 ifp->if_type = IFT_ETHER;
467 ifp->if_addrlen = 6;
468 ifp->if_hdrlen = 14;
469 ifp->if_mtu = ETHERMTU;
470 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
471 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
472 sdl->sdl_family == AF_LINK) {
473 sdl->sdl_type = IFT_ETHER;
474 sdl->sdl_alen = ifp->if_addrlen;
475 bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
476 LLADDR(sdl), ifp->if_addrlen);
477 break;
478 }
479 }
480
481 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
482 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
483 /*
484 * Add an Ethernet multicast address or range of addresses to the list for a
485 * given interface.
486 */
487 int
ether_addmulti(ifr,ac)488 ether_addmulti(ifr, ac)
489 struct ifreq *ifr;
490 register struct arpcom *ac;
491 {
492 register struct ether_multi *enm;
493 struct sockaddr_in *sin;
494 u_char addrlo[6];
495 u_char addrhi[6];
496 int s = splimp();
497
498 switch (ifr->ifr_addr.sa_family) {
499
500 case AF_UNSPEC:
501 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
502 bcopy(addrlo, addrhi, 6);
503 break;
504
505 #ifdef INET
506 case AF_INET:
507 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
508 if (sin->sin_addr.s_addr == INADDR_ANY) {
509 /*
510 * An IP address of INADDR_ANY means listen to all
511 * of the Ethernet multicast addresses used for IP.
512 * (This is for the sake of IP multicast routers.)
513 */
514 bcopy(ether_ipmulticast_min, addrlo, 6);
515 bcopy(ether_ipmulticast_max, addrhi, 6);
516 }
517 else {
518 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
519 bcopy(addrlo, addrhi, 6);
520 }
521 break;
522 #endif
523
524 default:
525 splx(s);
526 return (EAFNOSUPPORT);
527 }
528
529 /*
530 * Verify that we have valid Ethernet multicast addresses.
531 */
532 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
533 splx(s);
534 return (EINVAL);
535 }
536 /*
537 * See if the address range is already in the list.
538 */
539 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
540 if (enm != NULL) {
541 /*
542 * Found it; just increment the reference count.
543 */
544 ++enm->enm_refcount;
545 splx(s);
546 return (0);
547 }
548 /*
549 * New address or range; malloc a new multicast record
550 * and link it into the interface's multicast list.
551 */
552 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
553 if (enm == NULL) {
554 splx(s);
555 return (ENOBUFS);
556 }
557 bcopy(addrlo, enm->enm_addrlo, 6);
558 bcopy(addrhi, enm->enm_addrhi, 6);
559 enm->enm_ac = ac;
560 enm->enm_refcount = 1;
561 enm->enm_next = ac->ac_multiaddrs;
562 ac->ac_multiaddrs = enm;
563 ac->ac_multicnt++;
564 splx(s);
565 /*
566 * Return ENETRESET to inform the driver that the list has changed
567 * and its reception filter should be adjusted accordingly.
568 */
569 return (ENETRESET);
570 }
571
572 /*
573 * Delete a multicast address record.
574 */
575 int
ether_delmulti(ifr,ac)576 ether_delmulti(ifr, ac)
577 struct ifreq *ifr;
578 register struct arpcom *ac;
579 {
580 register struct ether_multi *enm;
581 register struct ether_multi **p;
582 struct sockaddr_in *sin;
583 u_char addrlo[6];
584 u_char addrhi[6];
585 int s = splimp();
586
587 switch (ifr->ifr_addr.sa_family) {
588
589 case AF_UNSPEC:
590 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
591 bcopy(addrlo, addrhi, 6);
592 break;
593
594 #ifdef INET
595 case AF_INET:
596 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
597 if (sin->sin_addr.s_addr == INADDR_ANY) {
598 /*
599 * An IP address of INADDR_ANY means stop listening
600 * to the range of Ethernet multicast addresses used
601 * for IP.
602 */
603 bcopy(ether_ipmulticast_min, addrlo, 6);
604 bcopy(ether_ipmulticast_max, addrhi, 6);
605 }
606 else {
607 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
608 bcopy(addrlo, addrhi, 6);
609 }
610 break;
611 #endif
612
613 default:
614 splx(s);
615 return (EAFNOSUPPORT);
616 }
617
618 /*
619 * Look up the address in our list.
620 */
621 ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
622 if (enm == NULL) {
623 splx(s);
624 return (ENXIO);
625 }
626 if (--enm->enm_refcount != 0) {
627 /*
628 * Still some claims to this record.
629 */
630 splx(s);
631 return (0);
632 }
633 /*
634 * No remaining claims to this record; unlink and free it.
635 */
636 for (p = &enm->enm_ac->ac_multiaddrs;
637 *p != enm;
638 p = &(*p)->enm_next)
639 continue;
640 *p = (*p)->enm_next;
641 free(enm, M_IFMADDR);
642 ac->ac_multicnt--;
643 splx(s);
644 /*
645 * Return ENETRESET to inform the driver that the list has changed
646 * and its reception filter should be adjusted accordingly.
647 */
648 return (ENETRESET);
649 }
650