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