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