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.51 1998/06/14 20:58:14 julian Exp $ 35 */ 36 37 #include "opt_atalk.h" 38 #include "opt_inet.h" 39 #include "opt_ipx.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/socket.h> 47 #include <sys/sockio.h> 48 #include <sys/sysctl.h> 49 50 #include <net/if.h> 51 #include <net/netisr.h> 52 #include <net/route.h> 53 #include <net/if_llc.h> 54 #include <net/if_dl.h> 55 #include <net/if_types.h> 56 57 #ifdef INET 58 #include <netinet/in.h> 59 #include <netinet/in_var.h> 60 #include <netinet/if_ether.h> 61 #endif 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> 71 ushort ns_nettype; 72 int ether_outputdebug = 0; 73 int 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) 89 extern 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 100 extern u_char at_org_code[3]; 101 extern u_char aarp_org_code[3]; 102 #endif /* NETATALK */ 103 104 #include "vlan.h" 105 #if NVLAN > 0 106 #include <net/if_vlan_var.h> 107 #endif /* NVLAN > 0 */ 108 109 static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 110 struct sockaddr *)); 111 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 112 #define senderr(e) { error = (e); goto bad;} 113 114 /* 115 * Ethernet output routine. 116 * Encapsulate a packet of type family for the local net. 117 * Use trailer local net encapsulation if enough data in first 118 * packet leaves a multiple of 512 bytes of data in remainder. 119 * Assumes that ifp is actually pointer to arpcom structure. 120 */ 121 int 122 ether_output(ifp, m0, dst, rt0) 123 register struct ifnet *ifp; 124 struct mbuf *m0; 125 struct sockaddr *dst; 126 struct rtentry *rt0; 127 { 128 short type; 129 int s, error = 0; 130 u_char edst[6]; 131 register struct mbuf *m = m0; 132 register struct rtentry *rt; 133 register struct ether_header *eh; 134 int off, len = m->m_pkthdr.len, loop_copy = 0; 135 int hlen; /* link layer header lenght */ 136 struct arpcom *ac = (struct arpcom *)ifp; 137 138 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 139 senderr(ENETDOWN); 140 rt = rt0; 141 if (rt) { 142 if ((rt->rt_flags & RTF_UP) == 0) { 143 rt0 = rt = rtalloc1(dst, 1, 0UL); 144 if (rt0) 145 rt->rt_refcnt--; 146 else 147 senderr(EHOSTUNREACH); 148 } 149 if (rt->rt_flags & RTF_GATEWAY) { 150 if (rt->rt_gwroute == 0) 151 goto lookup; 152 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 153 rtfree(rt); rt = rt0; 154 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 155 0UL); 156 if ((rt = rt->rt_gwroute) == 0) 157 senderr(EHOSTUNREACH); 158 } 159 } 160 if (rt->rt_flags & RTF_REJECT) 161 if (rt->rt_rmx.rmx_expire == 0 || 162 time_second < rt->rt_rmx.rmx_expire) 163 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 164 } 165 hlen = ETHER_HDR_LEN; 166 switch (dst->sa_family) { 167 #ifdef INET 168 case AF_INET: 169 if (!arpresolve(ac, rt, m, dst, edst, rt0)) 170 return (0); /* if not yet resolved */ 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 break; 181 #endif 182 #ifdef NETATALK 183 case AF_APPLETALK: 184 { 185 struct at_ifaddr *aa; 186 187 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) { 188 goto bad; 189 } 190 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 191 return (0); 192 /* 193 * In the phase 2 case, need to prepend an mbuf for the llc header. 194 * Since we must preserve the value of m, which is passed to us by 195 * value, we m_copy() the first mbuf, and use it for our llc header. 196 */ 197 if ( aa->aa_flags & AFA_PHASE2 ) { 198 struct llc llc; 199 200 M_PREPEND(m, sizeof(struct llc), M_WAIT); 201 len += sizeof(struct llc); 202 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 203 llc.llc_control = LLC_UI; 204 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 205 llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); 206 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 207 type = htons(m->m_pkthdr.len); 208 hlen = sizeof(struct llc) + ETHER_HDR_LEN; 209 } else { 210 type = htons(ETHERTYPE_AT); 211 } 212 break; 213 } 214 #endif NETATALK 215 #ifdef NS 216 case AF_NS: 217 switch(ns_nettype){ 218 default: 219 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 220 type = 0x8137; 221 break; 222 case 0x0: /* Novell 802.3 */ 223 type = htons( m->m_pkthdr.len); 224 break; 225 case 0xe0e0: /* Novell 802.2 and Token-Ring */ 226 M_PREPEND(m, 3, M_WAIT); 227 type = htons( m->m_pkthdr.len); 228 cp = mtod(m, u_char *); 229 *cp++ = 0xE0; 230 *cp++ = 0xE0; 231 *cp++ = 0x03; 232 break; 233 } 234 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 235 (caddr_t)edst, sizeof (edst)); 236 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ 237 m->m_pkthdr.rcvif = ifp; 238 schednetisr(NETISR_NS); 239 inq = &nsintrq; 240 s = splimp(); 241 if (IF_QFULL(inq)) { 242 IF_DROP(inq); 243 m_freem(m); 244 } else 245 IF_ENQUEUE(inq, m); 246 splx(s); 247 return (error); 248 } 249 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ 250 m2 = m_copy(m, 0, (int)M_COPYALL); 251 m2->m_pkthdr.rcvif = ifp; 252 schednetisr(NETISR_NS); 253 inq = &nsintrq; 254 s = splimp(); 255 if (IF_QFULL(inq)) { 256 IF_DROP(inq); 257 m_freem(m2); 258 } else 259 IF_ENQUEUE(inq, m2); 260 splx(s); 261 } 262 break; 263 #endif /* NS */ 264 #ifdef ISO 265 case AF_ISO: { 266 int snpalen; 267 struct llc *l; 268 register struct sockaddr_dl *sdl; 269 270 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 271 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 272 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 273 } else if (error = 274 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 275 (char *)edst, &snpalen)) 276 goto bad; /* Not Resolved */ 277 /* If broadcasting on a simplex interface, loopback a copy */ 278 if (*edst & 1) 279 m->m_flags |= (M_BCAST|M_MCAST); 280 M_PREPEND(m, 3, M_DONTWAIT); 281 if (m == NULL) 282 return (0); 283 type = htons(m->m_pkthdr.len); 284 l = mtod(m, struct llc *); 285 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 286 l->llc_control = LLC_UI; 287 len += 3; 288 IFDEBUG(D_ETHER) 289 int i; 290 printf("unoutput: sending pkt to: "); 291 for (i=0; i<6; i++) 292 printf("%x ", edst[i] & 0xff); 293 printf("\n"); 294 ENDDEBUG 295 } break; 296 #endif /* ISO */ 297 #ifdef LLC 298 /* case AF_NSAP: */ 299 case AF_CCITT: { 300 register struct sockaddr_dl *sdl = 301 (struct sockaddr_dl *) rt -> rt_gateway; 302 303 if (sdl && sdl->sdl_family == AF_LINK 304 && sdl->sdl_alen > 0) { 305 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst)); 306 } else goto bad; /* Not a link interface ? Funny ... */ 307 if (*edst & 1) 308 loop_copy = 1; 309 type = htons(m->m_pkthdr.len); 310 #ifdef LLC_DEBUG 311 { 312 int i; 313 register struct llc *l = mtod(m, struct llc *); 314 315 printf("ether_output: sending LLC2 pkt to: "); 316 for (i=0; i<6; i++) 317 printf("%x ", edst[i] & 0xff); 318 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 319 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 320 l->llc_control & 0xff); 321 322 } 323 #endif /* LLC_DEBUG */ 324 } break; 325 #endif /* LLC */ 326 327 case AF_UNSPEC: 328 loop_copy = -1; /* if this is for us, don't do it */ 329 eh = (struct ether_header *)dst->sa_data; 330 (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); 331 type = eh->ether_type; 332 break; 333 334 default: 335 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 336 dst->sa_family); 337 senderr(EAFNOSUPPORT); 338 } 339 340 /* 341 * Add local net header. If no space in first mbuf, 342 * allocate another. 343 */ 344 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 345 if (m == 0) 346 senderr(ENOBUFS); 347 eh = mtod(m, struct ether_header *); 348 (void)memcpy(&eh->ether_type, &type, 349 sizeof(eh->ether_type)); 350 (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); 351 (void)memcpy(eh->ether_shost, ac->ac_enaddr, 352 sizeof(eh->ether_shost)); 353 354 /* 355 * If a simplex interface, and the packet is being sent to our 356 * Ethernet address or a broadcast address, loopback a copy. 357 * XXX To make a simplex device behave exactly like a duplex 358 * device, we should copy in the case of sending to our own 359 * ethernet address (thus letting the original actually appear 360 * on the wire). However, we don't do that here for security 361 * reasons and compatibility with the original behavior. 362 */ 363 if ((ifp->if_flags & IFF_SIMPLEX) && 364 (loop_copy != -1)) { 365 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 366 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 367 368 (void) if_simloop(ifp, n, dst, hlen); 369 } else if (bcmp(eh->ether_dhost, 370 eh->ether_shost, ETHER_ADDR_LEN) == 0) { 371 (void) if_simloop(ifp, m, dst, hlen); 372 return(0); /* XXX */ 373 } 374 } 375 376 s = splimp(); 377 /* 378 * Queue message on interface, and start output if interface 379 * not yet active. 380 */ 381 if (IF_QFULL(&ifp->if_snd)) { 382 IF_DROP(&ifp->if_snd); 383 splx(s); 384 senderr(ENOBUFS); 385 } 386 IF_ENQUEUE(&ifp->if_snd, m); 387 if ((ifp->if_flags & IFF_OACTIVE) == 0) 388 (*ifp->if_start)(ifp); 389 splx(s); 390 ifp->if_obytes += len + sizeof (struct ether_header); 391 if (m->m_flags & M_MCAST) 392 ifp->if_omcasts++; 393 return (error); 394 395 bad: 396 if (m) 397 m_freem(m); 398 return (error); 399 } 400 401 /* 402 * Process a received Ethernet packet; 403 * the packet is in the mbuf chain m without 404 * the ether header, which is provided separately. 405 */ 406 void 407 ether_input(ifp, eh, m) 408 struct ifnet *ifp; 409 register struct ether_header *eh; 410 struct mbuf *m; 411 { 412 register struct ifqueue *inq; 413 u_short ether_type; 414 int s; 415 #if defined (ISO) || defined (LLC) || defined(NETATALK) 416 register struct llc *l; 417 #endif 418 419 if ((ifp->if_flags & IFF_UP) == 0) { 420 m_freem(m); 421 return; 422 } 423 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 424 if (eh->ether_dhost[0] & 1) { 425 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 426 sizeof(etherbroadcastaddr)) == 0) 427 m->m_flags |= M_BCAST; 428 else 429 m->m_flags |= M_MCAST; 430 } 431 if (m->m_flags & (M_BCAST|M_MCAST)) 432 ifp->if_imcasts++; 433 434 ether_type = ntohs(eh->ether_type); 435 436 #if NVLAN > 0 437 if (ether_type == vlan_proto) { 438 if (vlan_input(eh, m) < 0) 439 ifp->if_data.ifi_noproto++; 440 return; 441 } 442 #endif /* NVLAN > 0 */ 443 444 switch (ether_type) { 445 #ifdef INET 446 case ETHERTYPE_IP: 447 if (ipflow_fastforward(m)) 448 return; 449 schednetisr(NETISR_IP); 450 inq = &ipintrq; 451 break; 452 453 case ETHERTYPE_ARP: 454 schednetisr(NETISR_ARP); 455 inq = &arpintrq; 456 break; 457 #endif 458 #ifdef IPX 459 case ETHERTYPE_IPX: 460 schednetisr(NETISR_IPX); 461 inq = &ipxintrq; 462 break; 463 #endif 464 #ifdef NS 465 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 466 schednetisr(NETISR_NS); 467 inq = &nsintrq; 468 break; 469 470 #endif /* NS */ 471 #ifdef NETATALK 472 case ETHERTYPE_AT: 473 schednetisr(NETISR_ATALK); 474 inq = &atintrq1; 475 break; 476 case ETHERTYPE_AARP: 477 /* probably this should be done with a NETISR as well */ 478 aarpinput((struct arpcom *)ifp, m); /* XXX */ 479 return; 480 #endif NETATALK 481 default: 482 #ifdef NS 483 checksum = mtod(m, ushort *); 484 /* Novell 802.3 */ 485 if ((ether_type <= ETHERMTU) && 486 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ 487 if(*checksum == 0xE0E0) { 488 m->m_pkthdr.len -= 3; 489 m->m_len -= 3; 490 m->m_data += 3; 491 } 492 schednetisr(NETISR_NS); 493 inq = &nsintrq; 494 break; 495 } 496 #endif /* NS */ 497 #if defined (ISO) || defined (LLC) || defined(NETATALK) 498 if (ether_type > ETHERMTU) 499 goto dropanyway; 500 l = mtod(m, struct llc *); 501 switch (l->llc_dsap) { 502 #ifdef NETATALK 503 case LLC_SNAP_LSAP: 504 switch (l->llc_control) { 505 case LLC_UI: 506 if (l->llc_ssap != LLC_SNAP_LSAP) 507 goto dropanyway; 508 509 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 510 sizeof(at_org_code)) == 0 && 511 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 512 inq = &atintrq2; 513 m_adj( m, sizeof( struct llc )); 514 schednetisr(NETISR_ATALK); 515 break; 516 } 517 518 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 519 sizeof(aarp_org_code)) == 0 && 520 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 521 m_adj( m, sizeof( struct llc )); 522 aarpinput((struct arpcom *)ifp, m); /* XXX */ 523 return; 524 } 525 526 default: 527 goto dropanyway; 528 } 529 break; 530 #endif NETATALK 531 #ifdef ISO 532 case LLC_ISO_LSAP: 533 switch (l->llc_control) { 534 case LLC_UI: 535 /* LLC_UI_P forbidden in class 1 service */ 536 if ((l->llc_dsap == LLC_ISO_LSAP) && 537 (l->llc_ssap == LLC_ISO_LSAP)) { 538 /* LSAP for ISO */ 539 if (m->m_pkthdr.len > ether_type) 540 m_adj(m, ether_type - m->m_pkthdr.len); 541 m->m_data += 3; /* XXX */ 542 m->m_len -= 3; /* XXX */ 543 m->m_pkthdr.len -= 3; /* XXX */ 544 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 545 if (m == 0) 546 return; 547 *mtod(m, struct ether_header *) = *eh; 548 IFDEBUG(D_ETHER) 549 printf("clnp packet"); 550 ENDDEBUG 551 schednetisr(NETISR_ISO); 552 inq = &clnlintrq; 553 break; 554 } 555 goto dropanyway; 556 557 case LLC_XID: 558 case LLC_XID_P: 559 if(m->m_len < 6) 560 goto dropanyway; 561 l->llc_window = 0; 562 l->llc_fid = 9; 563 l->llc_class = 1; 564 l->llc_dsap = l->llc_ssap = 0; 565 /* Fall through to */ 566 case LLC_TEST: 567 case LLC_TEST_P: 568 { 569 struct sockaddr sa; 570 register struct ether_header *eh2; 571 int i; 572 u_char c = l->llc_dsap; 573 574 l->llc_dsap = l->llc_ssap; 575 l->llc_ssap = c; 576 if (m->m_flags & (M_BCAST | M_MCAST)) 577 bcopy((caddr_t)ac->ac_enaddr, 578 (caddr_t)eh->ether_dhost, 6); 579 sa.sa_family = AF_UNSPEC; 580 sa.sa_len = sizeof(sa); 581 eh2 = (struct ether_header *)sa.sa_data; 582 for (i = 0; i < 6; i++) { 583 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 584 eh2->ether_dhost[i] = 585 eh->ether_dhost[i] = eh->ether_shost[i]; 586 eh->ether_shost[i] = c; 587 } 588 ifp->if_output(ifp, m, &sa, NULL); 589 return; 590 } 591 default: 592 m_freem(m); 593 return; 594 } 595 break; 596 #endif /* ISO */ 597 #ifdef LLC 598 case LLC_X25_LSAP: 599 { 600 if (m->m_pkthdr.len > ether_type) 601 m_adj(m, ether_type - m->m_pkthdr.len); 602 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 603 if (m == 0) 604 return; 605 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 606 eh->ether_dhost, LLC_X25_LSAP, 6, 607 mtod(m, struct sdl_hdr *))) 608 panic("ETHER cons addr failure"); 609 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; 610 #ifdef LLC_DEBUG 611 printf("llc packet\n"); 612 #endif /* LLC_DEBUG */ 613 schednetisr(NETISR_CCITT); 614 inq = &llcintrq; 615 break; 616 } 617 #endif /* LLC */ 618 dropanyway: 619 default: 620 m_freem(m); 621 return; 622 } 623 #else /* ISO || LLC || NETATALK */ 624 m_freem(m); 625 return; 626 #endif /* ISO || LLC || NETATALK */ 627 } 628 629 s = splimp(); 630 if (IF_QFULL(inq)) { 631 IF_DROP(inq); 632 m_freem(m); 633 } else 634 IF_ENQUEUE(inq, m); 635 splx(s); 636 } 637 638 /* 639 * Perform common duties while attaching to interface list 640 */ 641 void 642 ether_ifattach(ifp) 643 register struct ifnet *ifp; 644 { 645 register struct ifaddr *ifa; 646 register struct sockaddr_dl *sdl; 647 648 ifp->if_type = IFT_ETHER; 649 ifp->if_addrlen = 6; 650 ifp->if_hdrlen = 14; 651 ifp->if_mtu = ETHERMTU; 652 ifp->if_resolvemulti = ether_resolvemulti; 653 if (ifp->if_baudrate == 0) 654 ifp->if_baudrate = 10000000; 655 ifa = ifnet_addrs[ifp->if_index - 1]; 656 if (ifa == 0) { 657 printf("ether_ifattach: no lladdr!\n"); 658 return; 659 } 660 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 661 sdl->sdl_type = IFT_ETHER; 662 sdl->sdl_alen = ifp->if_addrlen; 663 bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 664 } 665 666 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); 667 668 int 669 ether_ioctl(ifp, command, data) 670 struct ifnet *ifp; 671 int command; 672 caddr_t data; 673 { 674 struct ifaddr *ifa = (struct ifaddr *) data; 675 struct ifreq *ifr = (struct ifreq *) data; 676 int error = 0; 677 678 switch (command) { 679 case SIOCSIFADDR: 680 ifp->if_flags |= IFF_UP; 681 682 switch (ifa->ifa_addr->sa_family) { 683 #ifdef INET 684 case AF_INET: 685 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 686 arp_ifinit((struct arpcom *)ifp, ifa); 687 break; 688 #endif 689 #ifdef IPX 690 /* 691 * XXX - This code is probably wrong 692 */ 693 case AF_IPX: 694 { 695 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 696 struct arpcom *ac = (struct arpcom *) (ifp->if_softc); 697 698 if (ipx_nullhost(*ina)) 699 ina->x_host = 700 *(union ipx_host *) 701 ac->ac_enaddr; 702 else { 703 bcopy((caddr_t) ina->x_host.c_host, 704 (caddr_t) ac->ac_enaddr, 705 sizeof(ac->ac_enaddr)); 706 } 707 708 /* 709 * Set new address 710 */ 711 ifp->if_init(ifp->if_softc); 712 break; 713 } 714 #endif 715 #ifdef NS 716 /* 717 * XXX - This code is probably wrong 718 */ 719 case AF_NS: 720 { 721 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 722 struct arpcom *ac = (struct arpcom *) (ifp->if_softc); 723 724 if (ns_nullhost(*ina)) 725 ina->x_host = 726 *(union ns_host *) (ac->ac_enaddr); 727 else { 728 bcopy((caddr_t) ina->x_host.c_host, 729 (caddr_t) ac->ac_enaddr, 730 sizeof(ac->ac_enaddr)); 731 } 732 733 /* 734 * Set new address 735 */ 736 ifp->if_init(ifp->if_softc); 737 break; 738 } 739 #endif 740 default: 741 ifp->if_init(ifp->if_softc); 742 break; 743 } 744 break; 745 746 case SIOCGIFADDR: 747 { 748 struct sockaddr *sa; 749 750 sa = (struct sockaddr *) & ifr->ifr_data; 751 bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr, 752 (caddr_t) sa->sa_data, ETHER_ADDR_LEN); 753 } 754 break; 755 756 case SIOCSIFMTU: 757 /* 758 * Set the interface MTU. 759 */ 760 if (ifr->ifr_mtu > ETHERMTU) { 761 error = EINVAL; 762 } else { 763 ifp->if_mtu = ifr->ifr_mtu; 764 } 765 break; 766 } 767 return (error); 768 } 769 770 int 771 ether_resolvemulti(ifp, llsa, sa) 772 struct ifnet *ifp; 773 struct sockaddr **llsa; 774 struct sockaddr *sa; 775 { 776 struct sockaddr_dl *sdl; 777 struct sockaddr_in *sin; 778 u_char *e_addr; 779 780 switch(sa->sa_family) { 781 case AF_LINK: 782 /* 783 * No mapping needed. Just check that it's a valid MC address. 784 */ 785 sdl = (struct sockaddr_dl *)sa; 786 e_addr = LLADDR(sdl); 787 if ((e_addr[0] & 1) != 1) 788 return EADDRNOTAVAIL; 789 *llsa = 0; 790 return 0; 791 792 #ifdef INET 793 case AF_INET: 794 sin = (struct sockaddr_in *)sa; 795 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 796 return EADDRNOTAVAIL; 797 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 798 M_WAITOK); 799 sdl->sdl_len = sizeof *sdl; 800 sdl->sdl_family = AF_LINK; 801 sdl->sdl_index = ifp->if_index; 802 sdl->sdl_type = IFT_ETHER; 803 sdl->sdl_nlen = 0; 804 sdl->sdl_alen = ETHER_ADDR_LEN; 805 sdl->sdl_slen = 0; 806 e_addr = LLADDR(sdl); 807 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); 808 *llsa = (struct sockaddr *)sdl; 809 return 0; 810 #endif 811 812 default: 813 /* 814 * Well, the text isn't quite right, but it's the name 815 * that counts... 816 */ 817 return EAFNOSUPPORT; 818 } 819 } 820