1 /* $NetBSD: if_ethersubr.c,v 1.54 2000/03/06 21:03:46 thorpej 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 = 0; 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 OLDIP6OUTPUT 268 if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst)) 269 return(0); /* if not yet resolves */ 270 #else 271 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){ 272 /* this must be impossible, so we bark */ 273 printf("nd6_storelladdr failed\n"); 274 return(0); 275 } 276 #endif /* OLDIP6OUTPUT */ 277 etype = htons(ETHERTYPE_IPV6); 278 break; 279 #endif 280 #ifdef NETATALK 281 case AF_APPLETALK: 282 if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) { 283 #ifdef NETATALKDEBUG 284 printf("aarpresolv failed\n"); 285 #endif /* NETATALKDEBUG */ 286 return (0); 287 } 288 /* 289 * ifaddr is the first thing in at_ifaddr 290 */ 291 aa = (struct at_ifaddr *) at_ifawithnet( 292 (struct sockaddr_at *)dst, ifp); 293 if (aa == NULL) 294 goto bad; 295 296 /* 297 * In the phase 2 case, we need to prepend an mbuf for the 298 * llc header. Since we must preserve the value of m, 299 * which is passed to us by value, we m_copy() the first 300 * mbuf, and use it for our llc header. 301 */ 302 if (aa->aa_flags & AFA_PHASE2) { 303 struct llc llc; 304 305 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT); 306 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 307 llc.llc_control = LLC_UI; 308 bcopy(at_org_code, llc.llc_snap_org_code, 309 sizeof(llc.llc_snap_org_code)); 310 llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK); 311 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 312 } else { 313 etype = htons(ETHERTYPE_ATALK); 314 } 315 break; 316 #endif /* NETATALK */ 317 #ifdef NS 318 case AF_NS: 319 etype = htons(ETHERTYPE_NS); 320 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 321 (caddr_t)edst, sizeof (edst)); 322 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) 323 return (looutput(ifp, m, dst, rt)); 324 /* If broadcasting on a simplex interface, loopback a copy */ 325 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 326 mcopy = m_copy(m, 0, (int)M_COPYALL); 327 break; 328 #endif 329 #ifdef IPX 330 case AF_IPX: 331 etype = htons(ETHERTYPE_IPX); 332 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 333 (caddr_t)edst, sizeof (edst)); 334 /* If broadcasting on a simplex interface, loopback a copy */ 335 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) 336 mcopy = m_copy(m, 0, (int)M_COPYALL); 337 break; 338 #endif 339 #ifdef ISO 340 case AF_ISO: { 341 int snpalen; 342 struct llc *l; 343 struct sockaddr_dl *sdl; 344 345 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 346 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 347 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 348 } else { 349 error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 350 (char *)edst, &snpalen); 351 if (error) 352 goto bad; /* Not Resolved */ 353 } 354 /* If broadcasting on a simplex interface, loopback a copy */ 355 if (*edst & 1) 356 m->m_flags |= (M_BCAST|M_MCAST); 357 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && 358 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 359 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 360 if (mcopy) { 361 eh = mtod(mcopy, struct ether_header *); 362 bcopy((caddr_t)edst, 363 (caddr_t)eh->ether_dhost, sizeof (edst)); 364 bcopy(LLADDR(ifp->if_sadl), 365 (caddr_t)eh->ether_shost, sizeof (edst)); 366 } 367 } 368 M_PREPEND(m, 3, M_DONTWAIT); 369 if (m == NULL) 370 return (0); 371 l = mtod(m, struct llc *); 372 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 373 l->llc_control = LLC_UI; 374 #ifdef ARGO_DEBUG 375 if (argo_debug[D_ETHER]) { 376 int i; 377 printf("unoutput: sending pkt to: "); 378 for (i=0; i<6; i++) 379 printf("%x ", edst[i] & 0xff); 380 printf("\n"); 381 } 382 #endif 383 } break; 384 #endif /* ISO */ 385 #ifdef LLC 386 /* case AF_NSAP: */ 387 case AF_CCITT: { 388 struct sockaddr_dl *sdl = 389 (struct sockaddr_dl *) rt -> rt_gateway; 390 391 if (sdl && sdl->sdl_family == AF_LINK 392 && sdl->sdl_alen > 0) { 393 bcopy(LLADDR(sdl), (char *)edst, 394 sizeof(edst)); 395 } else goto bad; /* Not a link interface ? Funny ... */ 396 if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && 397 (mcopy = m_copy(m, 0, (int)M_COPYALL))) { 398 M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); 399 if (mcopy) { 400 eh = mtod(mcopy, struct ether_header *); 401 bcopy((caddr_t)edst, 402 (caddr_t)eh->ether_dhost, sizeof (edst)); 403 bcopy(LLADDR(ifp->if_sadl), 404 (caddr_t)eh->ether_shost, sizeof (edst)); 405 } 406 } 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 /* If no ether type is set, this must be a 802.2 formatted packet. 447 */ 448 if (etype == 0) 449 etype = htons(m->m_pkthdr.len); 450 /* 451 * Add local net header. If no space in first mbuf, 452 * allocate another. 453 */ 454 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 455 if (m == 0) 456 senderr(ENOBUFS); 457 eh = mtod(m, struct ether_header *); 458 bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type, 459 sizeof(eh->ether_type)); 460 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 461 if (hdrcmplt) 462 bcopy((caddr_t)esrc, (caddr_t)eh->ether_shost, 463 sizeof(eh->ether_shost)); 464 else 465 bcopy(LLADDR(ifp->if_sadl), (caddr_t)eh->ether_shost, 466 sizeof(eh->ether_shost)); 467 s = splimp(); 468 /* 469 * Queue message on interface, and start output if interface 470 * not yet active. 471 */ 472 if (IF_QFULL(&ifp->if_snd)) { 473 IF_DROP(&ifp->if_snd); 474 splx(s); 475 senderr(ENOBUFS); 476 } 477 ifp->if_obytes += m->m_pkthdr.len; 478 IF_ENQUEUE(&ifp->if_snd, m); 479 if ((ifp->if_flags & IFF_OACTIVE) == 0) 480 (*ifp->if_start)(ifp); 481 splx(s); 482 if (m->m_flags & M_MCAST) 483 ifp->if_omcasts++; 484 return (error); 485 486 bad: 487 if (m) 488 m_freem(m); 489 return (error); 490 } 491 492 /* 493 * Process a received Ethernet packet; 494 * the packet is in the mbuf chain m with 495 * the ether header. 496 */ 497 static void 498 ether_input(ifp, m) 499 struct ifnet *ifp; 500 struct mbuf *m; 501 { 502 struct ifqueue *inq; 503 u_int16_t etype; 504 int s; 505 struct ether_header *eh; 506 #if defined (ISO) || defined (LLC) || defined(NETATALK) 507 struct llc *l; 508 #endif 509 510 if ((ifp->if_flags & IFF_UP) == 0) { 511 m_freem(m); 512 return; 513 } 514 515 eh = mtod(m, struct ether_header *); 516 517 ifp->if_lastchange = time; 518 ifp->if_ibytes += m->m_pkthdr.len; 519 if (eh->ether_dhost[0] & 1) { 520 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 521 sizeof(etherbroadcastaddr)) == 0) 522 m->m_flags |= M_BCAST; 523 else 524 m->m_flags |= M_MCAST; 525 } 526 if (m->m_flags & (M_BCAST|M_MCAST)) 527 ifp->if_imcasts++; 528 529 etype = ntohs(eh->ether_type); 530 531 /* Strip off the Ethernet header. */ 532 m_adj(m, sizeof(struct ether_header)); 533 534 /* If the CRC is still on the packet, trim it off. */ 535 if (m->m_flags & M_HASFCS) 536 m_adj(m, -ETHER_CRC_LEN); 537 538 switch (etype) { 539 #ifdef INET 540 case ETHERTYPE_IP: 541 #ifdef GATEWAY 542 if (ipflow_fastforward(m)) 543 return; 544 #endif 545 schednetisr(NETISR_IP); 546 inq = &ipintrq; 547 break; 548 549 case ETHERTYPE_ARP: 550 schednetisr(NETISR_ARP); 551 inq = &arpintrq; 552 break; 553 554 case ETHERTYPE_REVARP: 555 revarpinput(m); /* XXX queue? */ 556 return; 557 #endif 558 #ifdef INET6 559 case ETHERTYPE_IPV6: 560 schednetisr(NETISR_IPV6); 561 inq = &ip6intrq; 562 break; 563 #endif 564 #ifdef NS 565 case ETHERTYPE_NS: 566 schednetisr(NETISR_NS); 567 inq = &nsintrq; 568 break; 569 570 #endif 571 #ifdef IPX 572 case ETHERTYPE_IPX: 573 schednetisr(NETISR_IPX); 574 inq = &ipxintrq; 575 break; 576 #endif 577 #ifdef NETATALK 578 case ETHERTYPE_ATALK: 579 schednetisr(NETISR_ATALK); 580 inq = &atintrq1; 581 break; 582 case ETHERTYPE_AARP: 583 /* probably this should be done with a NETISR as well */ 584 aarpinput(ifp, m); /* XXX */ 585 return; 586 #endif /* NETATALK */ 587 default: 588 #if defined (ISO) || defined (LLC) || defined (NETATALK) 589 if (etype > ETHERMTU) 590 goto dropanyway; 591 l = mtod(m, struct llc *); 592 switch (l->llc_dsap) { 593 #ifdef NETATALK 594 case LLC_SNAP_LSAP: 595 switch (l->llc_control) { 596 case LLC_UI: 597 if (l->llc_ssap != LLC_SNAP_LSAP) { 598 goto dropanyway; 599 } 600 601 if (Bcmp(&(l->llc_snap_org_code)[0], 602 at_org_code, sizeof(at_org_code)) == 0 && 603 ntohs(l->llc_snap_ether_type) == 604 ETHERTYPE_ATALK) { 605 inq = &atintrq2; 606 m_adj(m, sizeof(struct llc)); 607 schednetisr(NETISR_ATALK); 608 break; 609 } 610 611 if (Bcmp(&(l->llc_snap_org_code)[0], 612 aarp_org_code, 613 sizeof(aarp_org_code)) == 0 && 614 ntohs(l->llc_snap_ether_type) == 615 ETHERTYPE_AARP) { 616 m_adj( m, sizeof(struct llc)); 617 aarpinput(ifp, m); /* XXX */ 618 return; 619 } 620 621 default: 622 goto dropanyway; 623 } 624 break; 625 #endif /* NETATALK */ 626 #ifdef ISO 627 case LLC_ISO_LSAP: 628 switch (l->llc_control) { 629 case LLC_UI: 630 /* LLC_UI_P forbidden in class 1 service */ 631 if ((l->llc_dsap == LLC_ISO_LSAP) && 632 (l->llc_ssap == LLC_ISO_LSAP)) { 633 /* LSAP for ISO */ 634 if (m->m_pkthdr.len > etype) 635 m_adj(m, etype - m->m_pkthdr.len); 636 m->m_data += 3; /* XXX */ 637 m->m_len -= 3; /* XXX */ 638 m->m_pkthdr.len -= 3; /* XXX */ 639 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 640 if (m == 0) 641 return; 642 *mtod(m, struct ether_header *) = *eh; 643 #ifdef ARGO_DEBUG 644 if (argo_debug[D_ETHER]) 645 printf("clnp packet"); 646 #endif 647 schednetisr(NETISR_ISO); 648 inq = &clnlintrq; 649 break; 650 } 651 goto dropanyway; 652 653 case LLC_XID: 654 case LLC_XID_P: 655 if(m->m_len < 6) 656 goto dropanyway; 657 l->llc_window = 0; 658 l->llc_fid = 9; 659 l->llc_class = 1; 660 l->llc_dsap = l->llc_ssap = 0; 661 /* Fall through to */ 662 case LLC_TEST: 663 case LLC_TEST_P: 664 { 665 struct sockaddr sa; 666 struct ether_header *eh2; 667 int i; 668 u_char c = l->llc_dsap; 669 670 l->llc_dsap = l->llc_ssap; 671 l->llc_ssap = c; 672 if (m->m_flags & (M_BCAST | M_MCAST)) 673 bcopy(LLADDR(ifp->if_sadl), 674 (caddr_t)eh->ether_dhost, 6); 675 sa.sa_family = AF_UNSPEC; 676 sa.sa_len = sizeof(sa); 677 eh2 = (struct ether_header *)sa.sa_data; 678 for (i = 0; i < 6; i++) { 679 eh2->ether_shost[i] = c = 680 eh->ether_dhost[i]; 681 eh2->ether_dhost[i] = 682 eh->ether_dhost[i] = 683 eh->ether_shost[i]; 684 eh->ether_shost[i] = c; 685 } 686 ifp->if_output(ifp, m, &sa, NULL); 687 return; 688 } 689 default: 690 m_freem(m); 691 return; 692 } 693 break; 694 #endif /* ISO */ 695 #ifdef LLC 696 case LLC_X25_LSAP: 697 { 698 if (m->m_pkthdr.len > etype) 699 m_adj(m, etype - m->m_pkthdr.len); 700 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 701 if (m == 0) 702 return; 703 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 704 eh->ether_dhost, LLC_X25_LSAP, 6, 705 mtod(m, struct sdl_hdr *))) 706 panic("ETHER cons addr failure"); 707 mtod(m, struct sdl_hdr *)->sdlhdr_len = etype; 708 #ifdef LLC_DEBUG 709 printf("llc packet\n"); 710 #endif /* LLC_DEBUG */ 711 schednetisr(NETISR_CCITT); 712 inq = &llcintrq; 713 break; 714 } 715 #endif /* LLC */ 716 dropanyway: 717 default: 718 m_freem(m); 719 return; 720 } 721 #else /* ISO || LLC || NETATALK*/ 722 m_freem(m); 723 return; 724 #endif /* ISO || LLC || NETATALK*/ 725 } 726 727 s = splimp(); 728 if (IF_QFULL(inq)) { 729 IF_DROP(inq); 730 m_freem(m); 731 } else 732 IF_ENQUEUE(inq, m); 733 splx(s); 734 } 735 736 /* 737 * Convert Ethernet address to printable (loggable) representation. 738 */ 739 static char digits[] = "0123456789abcdef"; 740 char * 741 ether_sprintf(ap) 742 const u_char *ap; 743 { 744 static char etherbuf[18]; 745 char *cp = etherbuf; 746 int i; 747 748 for (i = 0; i < 6; i++) { 749 *cp++ = digits[*ap >> 4]; 750 *cp++ = digits[*ap++ & 0xf]; 751 *cp++ = ':'; 752 } 753 *--cp = 0; 754 return (etherbuf); 755 } 756 757 /* 758 * Perform common duties while attaching to interface list 759 */ 760 void 761 ether_ifattach(ifp, lla) 762 struct ifnet *ifp; 763 const u_int8_t *lla; 764 { 765 struct sockaddr_dl *sdl; 766 767 ifp->if_type = IFT_ETHER; 768 ifp->if_addrlen = 6; 769 ifp->if_hdrlen = 14; 770 ifp->if_mtu = ETHERMTU; 771 ifp->if_output = ether_output; 772 ifp->if_input = ether_input; 773 if (ifp->if_baudrate == 0) 774 ifp->if_baudrate = IF_Mbps(10); /* just a default */ 775 if ((sdl = ifp->if_sadl) && 776 sdl->sdl_family == AF_LINK) { 777 sdl->sdl_type = IFT_ETHER; 778 sdl->sdl_alen = ifp->if_addrlen; 779 bcopy(lla, LLADDR(sdl), ifp->if_addrlen); 780 } 781 LIST_INIT(&((struct ethercom *)ifp)->ec_multiaddrs); 782 ifp->if_broadcastaddr = etherbroadcastaddr; 783 #ifdef INET6 784 in6_ifattach_getifid(ifp); 785 #endif 786 } 787 788 void 789 ether_ifdetach(ifp) 790 struct ifnet *ifp; 791 { 792 793 /* Nothing. */ 794 } 795 796 u_int32_t 797 ether_crc32_le(buf, len) 798 const u_int8_t *buf; 799 size_t len; 800 { 801 u_int32_t c, crc, carry; 802 size_t i, j; 803 804 crc = 0xffffffffU; /* initial value */ 805 806 for (i = 0; i < len; i++) { 807 c = buf[i]; 808 for (j = 0; j < 8; j++) { 809 carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); 810 crc >>= 1; 811 c >>= 1; 812 if (carry) 813 crc = (crc ^ ETHER_CRC_POLY_LE) | carry; 814 } 815 } 816 817 return (crc); 818 } 819 820 u_int32_t 821 ether_crc32_be(buf, len) 822 const u_int8_t *buf; 823 size_t len; 824 { 825 u_int32_t c, crc, carry; 826 size_t i, j; 827 828 crc = 0xffffffffU; /* initial value */ 829 830 for (i = 0; i < len; i++) { 831 c = buf[i]; 832 for (j = 0; j < 8; j++) { 833 carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); 834 crc <<= 1; 835 c >>= 1; 836 if (carry) 837 crc = (crc ^ ETHER_CRC_POLY_BE) | carry; 838 } 839 } 840 841 return (crc); 842 } 843 844 #ifdef INET 845 u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; 846 u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; 847 #endif 848 #ifdef INET6 849 u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; 850 u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; 851 #endif 852 /* 853 * Add an Ethernet multicast address or range of addresses to the list for a 854 * given interface. 855 */ 856 int 857 ether_addmulti(ifr, ec) 858 struct ifreq *ifr; 859 struct ethercom *ec; 860 { 861 struct ether_multi *enm; 862 #ifdef INET 863 struct sockaddr_in *sin; 864 #endif /* INET */ 865 #ifdef INET6 866 struct sockaddr_in6 *sin6; 867 #endif /* INET6 */ 868 u_char addrlo[6]; 869 u_char addrhi[6]; 870 int s = splimp(); 871 872 switch (ifr->ifr_addr.sa_family) { 873 874 case AF_UNSPEC: 875 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 876 bcopy(addrlo, addrhi, 6); 877 break; 878 879 #ifdef INET 880 case AF_INET: 881 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 882 if (sin->sin_addr.s_addr == INADDR_ANY) { 883 /* 884 * An IP address of INADDR_ANY means listen to all 885 * of the Ethernet multicast addresses used for IP. 886 * (This is for the sake of IP multicast routers.) 887 */ 888 bcopy(ether_ipmulticast_min, addrlo, 6); 889 bcopy(ether_ipmulticast_max, addrhi, 6); 890 } 891 else { 892 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 893 bcopy(addrlo, addrhi, 6); 894 } 895 break; 896 #endif 897 #ifdef INET6 898 case AF_INET6: 899 sin6 = (struct sockaddr_in6 *) 900 &(((struct in6_ifreq *)ifr)->ifr_addr); 901 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 902 /* 903 * An IP6 address of 0 means listen to all 904 * of the Ethernet multicast address used for IP6. 905 * (This is used for multicast routers.) 906 */ 907 bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN); 908 bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN); 909 #if 0 910 set_allmulti = 1; 911 #endif 912 } else { 913 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); 914 bcopy(addrlo, addrhi, ETHER_ADDR_LEN); 915 } 916 break; 917 #endif 918 919 default: 920 splx(s); 921 return (EAFNOSUPPORT); 922 } 923 924 /* 925 * Verify that we have valid Ethernet multicast addresses. 926 */ 927 if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { 928 splx(s); 929 return (EINVAL); 930 } 931 /* 932 * See if the address range is already in the list. 933 */ 934 ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); 935 if (enm != NULL) { 936 /* 937 * Found it; just increment the reference count. 938 */ 939 ++enm->enm_refcount; 940 splx(s); 941 return (0); 942 } 943 /* 944 * New address or range; malloc a new multicast record 945 * and link it into the interface's multicast list. 946 */ 947 enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); 948 if (enm == NULL) { 949 splx(s); 950 return (ENOBUFS); 951 } 952 bcopy(addrlo, enm->enm_addrlo, 6); 953 bcopy(addrhi, enm->enm_addrhi, 6); 954 enm->enm_ec = ec; 955 enm->enm_refcount = 1; 956 LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list); 957 ec->ec_multicnt++; 958 splx(s); 959 /* 960 * Return ENETRESET to inform the driver that the list has changed 961 * and its reception filter should be adjusted accordingly. 962 */ 963 return (ENETRESET); 964 } 965 966 /* 967 * Delete a multicast address record. 968 */ 969 int 970 ether_delmulti(ifr, ec) 971 struct ifreq *ifr; 972 struct ethercom *ec; 973 { 974 struct ether_multi *enm; 975 #ifdef INET 976 struct sockaddr_in *sin; 977 #endif /* INET */ 978 #ifdef INET6 979 struct sockaddr_in6 *sin6; 980 #endif /* INET6 */ 981 u_char addrlo[6]; 982 u_char addrhi[6]; 983 int s = splimp(); 984 985 switch (ifr->ifr_addr.sa_family) { 986 987 case AF_UNSPEC: 988 bcopy(ifr->ifr_addr.sa_data, addrlo, 6); 989 bcopy(addrlo, addrhi, 6); 990 break; 991 992 #ifdef INET 993 case AF_INET: 994 sin = (struct sockaddr_in *)&(ifr->ifr_addr); 995 if (sin->sin_addr.s_addr == INADDR_ANY) { 996 /* 997 * An IP address of INADDR_ANY means stop listening 998 * to the range of Ethernet multicast addresses used 999 * for IP. 1000 */ 1001 bcopy(ether_ipmulticast_min, addrlo, 6); 1002 bcopy(ether_ipmulticast_max, addrhi, 6); 1003 } 1004 else { 1005 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); 1006 bcopy(addrlo, addrhi, 6); 1007 } 1008 break; 1009 #endif 1010 #ifdef INET6 1011 case AF_INET6: 1012 sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr); 1013 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1014 /* 1015 * An IP6 address of all 0 means stop listening 1016 * to the range of Ethernet multicast addresses used 1017 * for IP6 1018 */ 1019 bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN); 1020 bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN); 1021 } else { 1022 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); 1023 bcopy(addrlo, addrhi, ETHER_ADDR_LEN); 1024 } 1025 break; 1026 #endif 1027 1028 default: 1029 splx(s); 1030 return (EAFNOSUPPORT); 1031 } 1032 1033 /* 1034 * Look up the address in our list. 1035 */ 1036 ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm); 1037 if (enm == NULL) { 1038 splx(s); 1039 return (ENXIO); 1040 } 1041 if (--enm->enm_refcount != 0) { 1042 /* 1043 * Still some claims to this record. 1044 */ 1045 splx(s); 1046 return (0); 1047 } 1048 /* 1049 * No remaining claims to this record; unlink and free it. 1050 */ 1051 LIST_REMOVE(enm, enm_list); 1052 free(enm, M_IFMADDR); 1053 ec->ec_multicnt--; 1054 splx(s); 1055 /* 1056 * Return ENETRESET to inform the driver that the list has changed 1057 * and its reception filter should be adjusted accordingly. 1058 */ 1059 return (ENETRESET); 1060 } 1061