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