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