39#include "opt_ipx.h" 40#include "opt_bdg.h" 41#include "opt_netgraph.h" 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/kernel.h> 46#include <sys/malloc.h> 47#include <sys/mbuf.h> 48#include <sys/socket.h> 49#include <sys/sockio.h> 50#include <sys/sysctl.h> 51 52#include <net/if.h> 53#include <net/netisr.h> 54#include <net/route.h> 55#include <net/if_llc.h> 56#include <net/if_dl.h> 57#include <net/if_types.h> 58 59#if defined(INET) || defined(INET6) 60#include <netinet/in.h> 61#include <netinet/in_var.h> 62#include <netinet/if_ether.h> 63#endif 64#ifdef INET6 65#include <netinet6/nd6.h> 66#include <netinet6/in6_ifattach.h> 67#endif 68 69#ifdef IPX 70#include <netipx/ipx.h> 71#include <netipx/ipx_if.h> 72#endif 73 74#ifdef NS 75#include <netns/ns.h> 76#include <netns/ns_if.h> 77ushort ns_nettype; 78int ether_outputdebug = 0; 79int ether_inputdebug = 0; 80#endif 81 82#ifdef ISO 83#include <netiso/argo_debug.h> 84#include <netiso/iso.h> 85#include <netiso/iso_var.h> 86#include <netiso/iso_snpac.h> 87#endif 88 89/*#ifdef LLC 90#include <netccitt/dll.h> 91#include <netccitt/llc_var.h> 92#endif*/ 93 94#if defined(LLC) && defined(CCITT) 95extern struct ifqueue pkintrq; 96#endif 97 98#ifdef NETATALK 99#include <netatalk/at.h> 100#include <netatalk/at_var.h> 101#include <netatalk/at_extern.h> 102 103#define llc_snap_org_code llc_un.type_snap.org_code 104#define llc_snap_ether_type llc_un.type_snap.ether_type 105 106extern u_char at_org_code[3]; 107extern u_char aarp_org_code[3]; 108#endif /* NETATALK */ 109 110#ifdef BRIDGE 111#include <net/bridge.h> 112#endif 113 114#include "vlan.h" 115#if NVLAN > 0 116#include <net/if_vlan_var.h> 117#endif /* NVLAN > 0 */ 118 119static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 120 struct sockaddr *)); 121u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 122#define senderr(e) do { error = (e); goto bad;} while (0) 123#define IFP2AC(IFP) ((struct arpcom *)IFP) 124 125#ifdef NETGRAPH 126#include <netgraph/ng_ether.h> 127#include <netgraph/ng_message.h> 128#include <netgraph/netgraph.h> 129 130static void ngether_init(void* ignored); 131static void ngether_send(struct arpcom *ac, 132 struct ether_header *eh, struct mbuf *m); 133static ng_constructor_t ngether_constructor; 134static ng_rcvmsg_t ngether_rcvmsg; 135static ng_shutdown_t ngether_rmnode; 136static ng_newhook_t ngether_newhook; 137static ng_connect_t ngether_connect; 138static ng_rcvdata_t ngether_rcvdata; 139static ng_disconnect_t ngether_disconnect; 140 141static struct ng_type typestruct = { 142 NG_VERSION, 143 NG_ETHER_NODE_TYPE, 144 NULL, 145 ngether_constructor, 146 ngether_rcvmsg, 147 ngether_rmnode, 148 ngether_newhook, 149 NULL, 150 ngether_connect, 151 ngether_rcvdata, 152 ngether_rcvdata, 153 ngether_disconnect, 154 NULL 155}; 156 157#define AC2NG(AC) ((node_p)((AC)->ac_ng)) 158#define NGEF_DIVERT NGF_TYPE1 /* all packets sent to netgraph */ 159#endif /* NETGRAPH */ 160 161/* 162 * Ethernet output routine. 163 * Encapsulate a packet of type family for the local net. 164 * Use trailer local net encapsulation if enough data in first 165 * packet leaves a multiple of 512 bytes of data in remainder. 166 * Assumes that ifp is actually pointer to arpcom structure. 167 */ 168int 169ether_output(ifp, m0, dst, rt0) 170 register struct ifnet *ifp; 171 struct mbuf *m0; 172 struct sockaddr *dst; 173 struct rtentry *rt0; 174{ 175 short type; 176 int s, error = 0, hdrcmplt = 0; 177 u_char esrc[6], edst[6]; 178 register struct mbuf *m = m0; 179 register struct rtentry *rt; 180 register struct ether_header *eh; 181 int off, len = m->m_pkthdr.len, loop_copy = 0; 182 int hlen; /* link layer header lenght */ 183 struct arpcom *ac = IFP2AC(ifp); 184 185 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 186 senderr(ENETDOWN); 187 rt = rt0; 188 if (rt) { 189 if ((rt->rt_flags & RTF_UP) == 0) { 190 rt0 = rt = rtalloc1(dst, 1, 0UL); 191 if (rt0) 192 rt->rt_refcnt--; 193 else 194 senderr(EHOSTUNREACH); 195 } 196 if (rt->rt_flags & RTF_GATEWAY) { 197 if (rt->rt_gwroute == 0) 198 goto lookup; 199 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 200 rtfree(rt); rt = rt0; 201 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 202 0UL); 203 if ((rt = rt->rt_gwroute) == 0) 204 senderr(EHOSTUNREACH); 205 } 206 } 207 if (rt->rt_flags & RTF_REJECT) 208 if (rt->rt_rmx.rmx_expire == 0 || 209 time_second < rt->rt_rmx.rmx_expire) 210 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 211 } 212 hlen = ETHER_HDR_LEN; 213 switch (dst->sa_family) { 214#ifdef INET 215 case AF_INET: 216 if (!arpresolve(ac, rt, m, dst, edst, rt0)) 217 return (0); /* if not yet resolved */ 218 off = m->m_pkthdr.len - m->m_len; 219 type = htons(ETHERTYPE_IP); 220 break; 221#endif 222#ifdef INET6 223 case AF_INET6: 224 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) { 225 /* this must be impossible, so we bark */ 226 printf("nd6_storelladdr failed\n"); 227 return(0); 228 } 229 off = m->m_pkthdr.len - m->m_len; 230 type = htons(ETHERTYPE_IPV6); 231 break; 232#endif 233#ifdef IPX 234 case AF_IPX: 235 type = htons(ETHERTYPE_IPX); 236 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 237 (caddr_t)edst, sizeof (edst)); 238 break; 239#endif 240#ifdef NETATALK 241 case AF_APPLETALK: 242 { 243 struct at_ifaddr *aa; 244 245 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) { 246 goto bad; 247 } 248 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 249 return (0); 250 /* 251 * In the phase 2 case, need to prepend an mbuf for the llc header. 252 * Since we must preserve the value of m, which is passed to us by 253 * value, we m_copy() the first mbuf, and use it for our llc header. 254 */ 255 if ( aa->aa_flags & AFA_PHASE2 ) { 256 struct llc llc; 257 258 M_PREPEND(m, sizeof(struct llc), M_WAIT); 259 len += sizeof(struct llc); 260 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 261 llc.llc_control = LLC_UI; 262 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 263 llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); 264 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 265 type = htons(m->m_pkthdr.len); 266 hlen = sizeof(struct llc) + ETHER_HDR_LEN; 267 } else { 268 type = htons(ETHERTYPE_AT); 269 } 270 break; 271 } 272#endif NETATALK 273#ifdef NS 274 case AF_NS: 275 switch(ns_nettype){ 276 default: 277 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 278 type = 0x8137; 279 break; 280 case 0x0: /* Novell 802.3 */ 281 type = htons( m->m_pkthdr.len); 282 break; 283 case 0xe0e0: /* Novell 802.2 and Token-Ring */ 284 M_PREPEND(m, 3, M_WAIT); 285 type = htons( m->m_pkthdr.len); 286 cp = mtod(m, u_char *); 287 *cp++ = 0xE0; 288 *cp++ = 0xE0; 289 *cp++ = 0x03; 290 break; 291 } 292 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 293 (caddr_t)edst, sizeof (edst)); 294 /* 295 * XXX if ns_thishost is the same as the node's ethernet 296 * address then just the default code will catch this anyhow. 297 * So I'm not sure if this next clause should be here at all? 298 * [JRE] 299 */ 300 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ 301 m->m_pkthdr.rcvif = ifp; 302 schednetisr(NETISR_NS); 303 inq = &nsintrq; 304 s = splimp(); 305 if (IF_QFULL(inq)) { 306 IF_DROP(inq); 307 m_freem(m); 308 } else 309 IF_ENQUEUE(inq, m); 310 splx(s); 311 return (error); 312 } 313 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ 314 m->m_flags |= M_BCAST; 315 } 316 break; 317#endif /* NS */ 318#ifdef ISO 319 case AF_ISO: { 320 int snpalen; 321 struct llc *l; 322 register struct sockaddr_dl *sdl; 323 324 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 325 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 326 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 327 } else if (error = 328 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 329 (char *)edst, &snpalen)) 330 goto bad; /* Not Resolved */ 331 /* If broadcasting on a simplex interface, loopback a copy */ 332 if (*edst & 1) 333 m->m_flags |= (M_BCAST|M_MCAST); 334 M_PREPEND(m, 3, M_DONTWAIT); 335 if (m == NULL) 336 return (0); 337 type = htons(m->m_pkthdr.len); 338 l = mtod(m, struct llc *); 339 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 340 l->llc_control = LLC_UI; 341 len += 3; 342 IFDEBUG(D_ETHER) 343 int i; 344 printf("unoutput: sending pkt to: "); 345 for (i=0; i<6; i++) 346 printf("%x ", edst[i] & 0xff); 347 printf("\n"); 348 ENDDEBUG 349 } break; 350#endif /* ISO */ 351#ifdef LLC 352/* case AF_NSAP: */ 353 case AF_CCITT: { 354 register struct sockaddr_dl *sdl = 355 (struct sockaddr_dl *) rt -> rt_gateway; 356 357 if (sdl && sdl->sdl_family == AF_LINK 358 && sdl->sdl_alen > 0) { 359 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst)); 360 } else goto bad; /* Not a link interface ? Funny ... */ 361 if (*edst & 1) 362 loop_copy = 1; 363 type = htons(m->m_pkthdr.len); 364#ifdef LLC_DEBUG 365 { 366 int i; 367 register struct llc *l = mtod(m, struct llc *); 368 369 printf("ether_output: sending LLC2 pkt to: "); 370 for (i=0; i<6; i++) 371 printf("%x ", edst[i] & 0xff); 372 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 373 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 374 l->llc_control & 0xff); 375 376 } 377#endif /* LLC_DEBUG */ 378 } break; 379#endif /* LLC */ 380 381 case pseudo_AF_HDRCMPLT: 382 hdrcmplt = 1; 383 eh = (struct ether_header *)dst->sa_data; 384 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc)); 385 /* FALLTHROUGH */ 386 387 case AF_UNSPEC: 388 loop_copy = -1; /* if this is for us, don't do it */ 389 eh = (struct ether_header *)dst->sa_data; 390 (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); 391 type = eh->ether_type; 392 break; 393 394 default: 395 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 396 dst->sa_family); 397 senderr(EAFNOSUPPORT); 398 } 399 400 /* 401 * Add local net header. If no space in first mbuf, 402 * allocate another. 403 */ 404 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 405 if (m == 0) 406 senderr(ENOBUFS); 407 eh = mtod(m, struct ether_header *); 408 (void)memcpy(&eh->ether_type, &type, 409 sizeof(eh->ether_type)); 410 (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); 411 if (hdrcmplt) 412 (void)memcpy(eh->ether_shost, esrc, 413 sizeof(eh->ether_shost)); 414 else 415 (void)memcpy(eh->ether_shost, ac->ac_enaddr, 416 sizeof(eh->ether_shost)); 417 418 /* 419 * If a simplex interface, and the packet is being sent to our 420 * Ethernet address or a broadcast address, loopback a copy. 421 * XXX To make a simplex device behave exactly like a duplex 422 * device, we should copy in the case of sending to our own 423 * ethernet address (thus letting the original actually appear 424 * on the wire). However, we don't do that here for security 425 * reasons and compatibility with the original behavior. 426 */ 427 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 428 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 429 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 430 431 (void) if_simloop(ifp, n, dst, hlen); 432 } else if (bcmp(eh->ether_dhost, 433 eh->ether_shost, ETHER_ADDR_LEN) == 0) { 434 (void) if_simloop(ifp, m, dst, hlen); 435 return (0); /* XXX */ 436 } 437 } 438#ifdef BRIDGE 439 if (do_bridge) { 440 struct mbuf *m0 = m ; 441 442 if (m->m_pkthdr.rcvif) 443 m->m_pkthdr.rcvif = NULL ; 444 ifp = bridge_dst_lookup(m); 445 bdg_forward(&m0, ifp); 446 if (m0) 447 m_freem(m0); 448 return (0); 449 } 450#endif 451 s = splimp(); 452 /* 453 * Queue message on interface, and start output if interface 454 * not yet active. 455 */ 456 if (IF_QFULL(&ifp->if_snd)) { 457 IF_DROP(&ifp->if_snd); 458 splx(s); 459 senderr(ENOBUFS); 460 } 461 IF_ENQUEUE(&ifp->if_snd, m); 462 if ((ifp->if_flags & IFF_OACTIVE) == 0) 463 (*ifp->if_start)(ifp); 464 splx(s); 465 ifp->if_obytes += len + sizeof (struct ether_header); 466 if (m->m_flags & M_MCAST) 467 ifp->if_omcasts++; 468 return (error); 469 470bad: 471 if (m) 472 m_freem(m); 473 return (error); 474} 475 476/* 477 * Process a received Ethernet packet; 478 * the packet is in the mbuf chain m without 479 * the ether header, which is provided separately. 480 */ 481void 482ether_input(ifp, eh, m) 483 struct ifnet *ifp; 484 register struct ether_header *eh; 485 struct mbuf *m; 486{ 487 register struct ifqueue *inq; 488 u_short ether_type; 489 int s; 490#if defined (ISO) || defined (LLC) || defined(NETATALK) 491 register struct llc *l; 492#endif 493 494 if ((ifp->if_flags & IFF_UP) == 0) { 495 m_freem(m); 496 return; 497 } 498 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 499 if (eh->ether_dhost[0] & 1) { 500 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 501 sizeof(etherbroadcastaddr)) == 0) 502 m->m_flags |= M_BCAST; 503 else 504 m->m_flags |= M_MCAST; 505 } 506 if (m->m_flags & (M_BCAST|M_MCAST)) 507 ifp->if_imcasts++; 508 509 ether_type = ntohs(eh->ether_type); 510 511#ifdef NETGRAPH 512 { 513 struct arpcom *ac = IFP2AC(ifp); 514 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) { 515 ngether_send(ac, eh, m); 516 return; 517 } 518 } 519#endif /* NETGRAPH */ 520 521#if NVLAN > 0 522 if (ether_type == vlan_proto) { 523 if (vlan_input(eh, m) < 0) 524 ifp->if_data.ifi_noproto++; 525 return; 526 } 527#endif /* NVLAN > 0 */ 528 529 switch (ether_type) { 530#ifdef INET 531 case ETHERTYPE_IP: 532 if (ipflow_fastforward(m)) 533 return; 534 schednetisr(NETISR_IP); 535 inq = &ipintrq; 536 break; 537 538 case ETHERTYPE_ARP: 539 schednetisr(NETISR_ARP); 540 inq = &arpintrq; 541 break; 542#endif 543#ifdef IPX 544 case ETHERTYPE_IPX: 545 schednetisr(NETISR_IPX); 546 inq = &ipxintrq; 547 break; 548#endif 549#ifdef INET6 550 case ETHERTYPE_IPV6: 551 schednetisr(NETISR_IPV6); 552 inq = &ip6intrq; 553 break; 554#endif 555#ifdef NS 556 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 557 schednetisr(NETISR_NS); 558 inq = &nsintrq; 559 break; 560 561#endif /* NS */ 562#ifdef NETATALK 563 case ETHERTYPE_AT: 564 schednetisr(NETISR_ATALK); 565 inq = &atintrq1; 566 break; 567 case ETHERTYPE_AARP: 568 /* probably this should be done with a NETISR as well */ 569 aarpinput(IFP2AC(ifp), m); /* XXX */ 570 return; 571#endif NETATALK 572 default: 573#ifdef NS 574 checksum = mtod(m, ushort *); 575 /* Novell 802.3 */ 576 if ((ether_type <= ETHERMTU) && 577 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ 578 if(*checksum == 0xE0E0) { 579 m->m_pkthdr.len -= 3; 580 m->m_len -= 3; 581 m->m_data += 3; 582 } 583 schednetisr(NETISR_NS); 584 inq = &nsintrq; 585 break; 586 } 587#endif /* NS */ 588#if defined (ISO) || defined (LLC) || defined(NETATALK) 589 if (ether_type > ETHERMTU) 590 goto dropanyway; 591 l = mtod(m, struct llc *); 592 switch (l->llc_dsap) { 593#ifdef NETATALK 594 case LLC_SNAP_LSAP: 595 switch (l->llc_control) { 596 case LLC_UI: 597 if (l->llc_ssap != LLC_SNAP_LSAP) 598 goto dropanyway; 599 600 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 601 sizeof(at_org_code)) == 0 && 602 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 603 inq = &atintrq2; 604 m_adj( m, sizeof( struct llc )); 605 schednetisr(NETISR_ATALK); 606 break; 607 } 608 609 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 610 sizeof(aarp_org_code)) == 0 && 611 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 612 m_adj( m, sizeof( struct llc )); 613 aarpinput(IFP2AC(ifp), m); /* XXX */ 614 return; 615 } 616 617 default: 618 goto dropanyway; 619 } 620 break; 621#endif NETATALK 622#ifdef ISO 623 case LLC_ISO_LSAP: 624 switch (l->llc_control) { 625 case LLC_UI: 626 /* LLC_UI_P forbidden in class 1 service */ 627 if ((l->llc_dsap == LLC_ISO_LSAP) && 628 (l->llc_ssap == LLC_ISO_LSAP)) { 629 /* LSAP for ISO */ 630 if (m->m_pkthdr.len > ether_type) 631 m_adj(m, ether_type - m->m_pkthdr.len); 632 m->m_data += 3; /* XXX */ 633 m->m_len -= 3; /* XXX */ 634 m->m_pkthdr.len -= 3; /* XXX */ 635 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 636 if (m == 0) 637 return; 638 *mtod(m, struct ether_header *) = *eh; 639 IFDEBUG(D_ETHER) 640 printf("clnp packet"); 641 ENDDEBUG 642 schednetisr(NETISR_ISO); 643 inq = &clnlintrq; 644 break; 645 } 646 goto dropanyway; 647 648 case LLC_XID: 649 case LLC_XID_P: 650 if(m->m_len < 6) 651 goto dropanyway; 652 l->llc_window = 0; 653 l->llc_fid = 9; 654 l->llc_class = 1; 655 l->llc_dsap = l->llc_ssap = 0; 656 /* Fall through to */ 657 case LLC_TEST: 658 case LLC_TEST_P: 659 { 660 struct sockaddr sa; 661 register struct ether_header *eh2; 662 int i; 663 u_char c = l->llc_dsap; 664 665 l->llc_dsap = l->llc_ssap; 666 l->llc_ssap = c; 667 if (m->m_flags & (M_BCAST | M_MCAST)) 668 bcopy((caddr_t)ac->ac_enaddr, 669 (caddr_t)eh->ether_dhost, 6); 670 sa.sa_family = AF_UNSPEC; 671 sa.sa_len = sizeof(sa); 672 eh2 = (struct ether_header *)sa.sa_data; 673 for (i = 0; i < 6; i++) { 674 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 675 eh2->ether_dhost[i] = 676 eh->ether_dhost[i] = eh->ether_shost[i]; 677 eh->ether_shost[i] = c; 678 } 679 ifp->if_output(ifp, m, &sa, NULL); 680 return; 681 } 682 default: 683 m_freem(m); 684 return; 685 } 686 break; 687#endif /* ISO */ 688#ifdef LLC 689 case LLC_X25_LSAP: 690 { 691 if (m->m_pkthdr.len > ether_type) 692 m_adj(m, ether_type - m->m_pkthdr.len); 693 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 694 if (m == 0) 695 return; 696 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 697 eh->ether_dhost, LLC_X25_LSAP, 6, 698 mtod(m, struct sdl_hdr *))) 699 panic("ETHER cons addr failure"); 700 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; 701#ifdef LLC_DEBUG 702 printf("llc packet\n"); 703#endif /* LLC_DEBUG */ 704 schednetisr(NETISR_CCITT); 705 inq = &llcintrq; 706 break; 707 } 708#endif /* LLC */ 709 dropanyway: 710 default: 711#ifdef NETGRAPH 712 ngether_send(IFP2AC(ifp), eh, m); 713#else /* NETGRAPH */ 714 m_freem(m); 715#endif /* NETGRAPH */ 716 return; 717 } 718#else /* ISO || LLC || NETATALK */ 719#ifdef NETGRAPH 720 ngether_send(IFP2AC(ifp), eh, m); 721#else /* NETGRAPH */ 722 m_freem(m); 723#endif /* NETGRAPH */ 724 return; 725#endif /* ISO || LLC || NETATALK */ 726 } 727 728 s = splimp(); 729 if (IF_QFULL(inq)) { 730 IF_DROP(inq); 731 m_freem(m); 732 } else 733 IF_ENQUEUE(inq, m); 734 splx(s); 735} 736 737/* 738 * Perform common duties while attaching to interface list 739 */ 740void 741ether_ifattach(ifp) 742 register struct ifnet *ifp; 743{ 744 register struct ifaddr *ifa; 745 register struct sockaddr_dl *sdl; 746 747 ifp->if_type = IFT_ETHER; 748 ifp->if_addrlen = 6; 749 ifp->if_hdrlen = 14; 750 ifp->if_mtu = ETHERMTU; 751 ifp->if_resolvemulti = ether_resolvemulti; 752 if (ifp->if_baudrate == 0) 753 ifp->if_baudrate = 10000000; 754 ifa = ifnet_addrs[ifp->if_index - 1]; 755 if (ifa == 0) { 756 printf("ether_ifattach: no lladdr!\n"); 757 return; 758 } 759 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 760 sdl->sdl_type = IFT_ETHER; 761 sdl->sdl_alen = ifp->if_addrlen; 762 bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 763#ifdef NETGRAPH 764 ngether_init(ifp); 765#endif /* NETGRAPH */ 766#ifdef INET6 767 in6_ifattach_getifid(ifp); 768#endif 769} 770 771SYSCTL_DECL(_net_link); 772SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); 773 774int 775ether_ioctl(ifp, command, data) 776 struct ifnet *ifp; 777 int command; 778 caddr_t data; 779{ 780 struct ifaddr *ifa = (struct ifaddr *) data; 781 struct ifreq *ifr = (struct ifreq *) data; 782 int error = 0; 783 784 switch (command) { 785 case SIOCSIFADDR: 786 ifp->if_flags |= IFF_UP; 787 788 switch (ifa->ifa_addr->sa_family) { 789#ifdef INET 790 case AF_INET: 791 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 792 arp_ifinit(IFP2AC(ifp), ifa); 793 break; 794#endif 795#ifdef IPX 796 /* 797 * XXX - This code is probably wrong 798 */ 799 case AF_IPX: 800 { 801 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 802 struct arpcom *ac = IFP2AC(ifp); 803 804 if (ipx_nullhost(*ina)) 805 ina->x_host = 806 *(union ipx_host *) 807 ac->ac_enaddr; 808 else { 809 bcopy((caddr_t) ina->x_host.c_host, 810 (caddr_t) ac->ac_enaddr, 811 sizeof(ac->ac_enaddr)); 812 } 813 814 /* 815 * Set new address 816 */ 817 ifp->if_init(ifp->if_softc); 818 break; 819 } 820#endif 821#ifdef NS 822 /* 823 * XXX - This code is probably wrong 824 */ 825 case AF_NS: 826 { 827 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 828 struct arpcom *ac = IFP2AC(ifp); 829 830 if (ns_nullhost(*ina)) 831 ina->x_host = 832 *(union ns_host *) (ac->ac_enaddr); 833 else { 834 bcopy((caddr_t) ina->x_host.c_host, 835 (caddr_t) ac->ac_enaddr, 836 sizeof(ac->ac_enaddr)); 837 } 838 839 /* 840 * Set new address 841 */ 842 ifp->if_init(ifp->if_softc); 843 break; 844 } 845#endif 846 default: 847 ifp->if_init(ifp->if_softc); 848 break; 849 } 850 break; 851 852 case SIOCGIFADDR: 853 { 854 struct sockaddr *sa; 855 856 sa = (struct sockaddr *) & ifr->ifr_data; 857 bcopy(IFP2AC(ifp)->ac_enaddr, 858 (caddr_t) sa->sa_data, ETHER_ADDR_LEN); 859 } 860 break; 861 862 case SIOCSIFMTU: 863 /* 864 * Set the interface MTU. 865 */ 866 if (ifr->ifr_mtu > ETHERMTU) { 867 error = EINVAL; 868 } else { 869 ifp->if_mtu = ifr->ifr_mtu; 870 } 871 break; 872 } 873 return (error); 874} 875 876int 877ether_resolvemulti(ifp, llsa, sa) 878 struct ifnet *ifp; 879 struct sockaddr **llsa; 880 struct sockaddr *sa; 881{ 882 struct sockaddr_dl *sdl; 883 struct sockaddr_in *sin; 884#ifdef INET6 885 struct sockaddr_in6 *sin6; 886#endif 887 u_char *e_addr; 888 889 switch(sa->sa_family) { 890 case AF_LINK: 891 /* 892 * No mapping needed. Just check that it's a valid MC address. 893 */ 894 sdl = (struct sockaddr_dl *)sa; 895 e_addr = LLADDR(sdl); 896 if ((e_addr[0] & 1) != 1) 897 return EADDRNOTAVAIL; 898 *llsa = 0; 899 return 0; 900 901#ifdef INET 902 case AF_INET: 903 sin = (struct sockaddr_in *)sa; 904 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 905 return EADDRNOTAVAIL; 906 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 907 M_WAITOK); 908 sdl->sdl_len = sizeof *sdl; 909 sdl->sdl_family = AF_LINK; 910 sdl->sdl_index = ifp->if_index; 911 sdl->sdl_type = IFT_ETHER; 912 sdl->sdl_nlen = 0; 913 sdl->sdl_alen = ETHER_ADDR_LEN; 914 sdl->sdl_slen = 0; 915 e_addr = LLADDR(sdl); 916 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); 917 *llsa = (struct sockaddr *)sdl; 918 return 0; 919#endif 920#ifdef INET6 921 case AF_INET6: 922 sin6 = (struct sockaddr_in6 *)sa; 923 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 924 return EADDRNOTAVAIL; 925 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 926 M_WAITOK); 927 sdl->sdl_len = sizeof *sdl; 928 sdl->sdl_family = AF_LINK; 929 sdl->sdl_index = ifp->if_index; 930 sdl->sdl_type = IFT_ETHER; 931 sdl->sdl_nlen = 0; 932 sdl->sdl_alen = ETHER_ADDR_LEN; 933 sdl->sdl_slen = 0; 934 e_addr = LLADDR(sdl); 935 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); 936 *llsa = (struct sockaddr *)sdl; 937 return 0; 938#endif 939 940 default: 941 /* 942 * Well, the text isn't quite right, but it's the name 943 * that counts... 944 */ 945 return EAFNOSUPPORT; 946 } 947} 948 949#ifdef NETGRAPH 950 951/*********************************************************************** 952 * This section contains the methods for the Netgraph interface 953 ***********************************************************************/ 954/* It's Ascii-art time! 955 * The ifnet is the first part of the arpcom which must be 956 * the first part of the device's softc.. yuk. 957 * 958 * +--------------------------+-----+---------+ 959 * | struct ifnet (*ifp) | | | 960 * | | | | 961 * +--------------------------+ | | 962 * +--|[ac_ng] struct arpcom (*ac) | | 963 * | +--------------------------------+ | 964 * | | struct softc (*ifp->if_softc) (device) | 965 * | +------------------------------------------+ 966 * | ^ 967 * AC2NG() | 968 * | v 969 * | +----------------------+ 970 * | | [private] [flags] | 971 * +------>| struct ng_node | 972 * | [hooks] | ** we only allow one hook 973 * +----------------------+ 974 * ^ 975 * | 976 * v 977 * +-------------+ 978 * | [node] | 979 * | hook | 980 * | [private]|-- *unused* 981 * +-------------+ 982 */ 983 984/* 985 * called during interface attaching 986 */ 987static void 988ngether_init(void *ifpvoid) 989{ 990 struct ifnet *ifp = ifpvoid; 991 struct arpcom *ac = IFP2AC(ifp); 992 static int ngether_done_init; 993 char namebuf[32]; 994 node_p node; 995 996 /* 997 * we have found a node, make sure our 'type' is availabe. 998 */ 999 if (ngether_done_init == 0) { 1000 if (ng_newtype(&typestruct)) { 1001 printf("ngether install failed\n"); 1002 return; 1003 } 1004 ngether_done_init = 1; 1005 } 1006 if (ng_make_node_common(&typestruct, &node) != 0) 1007 return; 1008 ac->ac_ng = node; 1009 node->private = ifp; 1010 sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit); 1011 ng_name_node(AC2NG(ac), namebuf); 1012} 1013 1014/* 1015 * It is not possible or allowable to create a node of this type. 1016 * If the hardware exists, it will already have created it. 1017 */ 1018static int 1019ngether_constructor(node_p *nodep) 1020{ 1021 return (EINVAL); 1022} 1023 1024/* 1025 * Give our ok for a hook to be added... 1026 * 1027 * Allow one hook at a time (rawdata). 1028 * It can eiteh rdivert everything or only unclaimed packets. 1029 */ 1030static int 1031ngether_newhook(node_p node, hook_p hook, const char *name) 1032{ 1033 1034 /* check if there is already a hook */ 1035 if (LIST_FIRST(&(node->hooks))) 1036 return(EISCONN); 1037 /* 1038 * Check for which mode hook we want. 1039 */ 1040 if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) { 1041 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) { 1042 return (EINVAL); 1043 } 1044 node->flags |= NGEF_DIVERT; 1045 } else { 1046 node->flags &= ~NGEF_DIVERT; 1047 } 1048 return (0); 1049} 1050 1051/* 1052 * incoming messages. 1053 * Just respond to the generic TEXT_STATUS message 1054 */ 1055static int 1056ngether_rcvmsg(node_p node, 1057 struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp) 1058{ 1059 struct ifnet *ifp; 1060 int error = 0; 1061 1062 ifp = node->private; 1063 switch (msg->header.typecookie) { 1064 case NGM_ETHER_COOKIE: 1065 error = EINVAL; 1066 break; 1067 case NGM_GENERIC_COOKIE: 1068 switch(msg->header.cmd) { 1069 case NGM_TEXT_STATUS: { 1070 char *arg; 1071 int pos = 0; 1072 int resplen = sizeof(struct ng_mesg) + 512; 1073 MALLOC(*resp, struct ng_mesg *, resplen, 1074 M_NETGRAPH, M_NOWAIT); 1075 if (*resp == NULL) { 1076 error = ENOMEM; 1077 break; 1078 } 1079 bzero(*resp, resplen); 1080 arg = (*resp)->data; 1081 1082 /* 1083 * Put in the throughput information. 1084 */ 1085 pos = sprintf(arg, "%ld bytes in, %ld bytes out\n", 1086 ifp->if_ibytes, ifp->if_obytes); 1087 pos += sprintf(arg + pos, 1088 "%ld output errors\n", 1089 ifp->if_oerrors); 1090 pos += sprintf(arg + pos, 1091 "ierrors = %ld\n", 1092 ifp->if_ierrors); 1093 1094 (*resp)->header.version = NG_VERSION; 1095 (*resp)->header.arglen = strlen(arg) + 1; 1096 (*resp)->header.token = msg->header.token; 1097 (*resp)->header.typecookie = NGM_ETHER_COOKIE; 1098 (*resp)->header.cmd = msg->header.cmd; 1099 strncpy((*resp)->header.cmdstr, "status", 1100 NG_CMDSTRLEN); 1101 } 1102 break; 1103 default: 1104 error = EINVAL; 1105 break; 1106 } 1107 break; 1108 default: 1109 error = EINVAL; 1110 break; 1111 } 1112 free(msg, M_NETGRAPH); 1113 return (error); 1114} 1115 1116/* 1117 * Receive a completed ethernet packet. 1118 * Queue it for output. 1119 */ 1120static int 1121ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 1122{ 1123 struct ifnet *ifp; 1124 int error = 0; 1125 int s; 1126 struct ether_header *eh; 1127 1128 ifp = hook->node->private; 1129 1130 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1131 senderr(ENETDOWN); 1132 /* drop in the MAC address */ 1133 eh = mtod(m, struct ether_header *); 1134 bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6); 1135 /* 1136 * If a simplex interface, and the packet is being sent to our 1137 * Ethernet address or a broadcast address, loopback a copy. 1138 * XXX To make a simplex device behave exactly like a duplex 1139 * device, we should copy in the case of sending to our own 1140 * ethernet address (thus letting the original actually appear 1141 * on the wire). However, we don't do that here for security 1142 * reasons and compatibility with the original behavior. 1143 */ 1144 if (ifp->if_flags & IFF_SIMPLEX) { 1145 if (m->m_flags & M_BCAST) { 1146 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 1147 1148 ng_queue_data(hook, n, meta); 1149 } else if (bcmp(eh->ether_dhost, 1150 eh->ether_shost, ETHER_ADDR_LEN) == 0) { 1151 ng_queue_data(hook, m, meta); 1152 return (0); /* XXX */ 1153 } 1154 } 1155 s = splimp(); 1156 /* 1157 * Queue message on interface, and start output if interface 1158 * not yet active. 1159 * XXX if we lookead at the priority in the meta data we could 1160 * queue high priority items at the head. 1161 */ 1162 if (IF_QFULL(&ifp->if_snd)) { 1163 IF_DROP(&ifp->if_snd); 1164 splx(s); 1165 senderr(ENOBUFS); 1166 } 1167 IF_ENQUEUE(&ifp->if_snd, m); 1168 if ((ifp->if_flags & IFF_OACTIVE) == 0) 1169 (*ifp->if_start)(ifp); 1170 splx(s); 1171 ifp->if_obytes += m->m_pkthdr.len; 1172 if (m->m_flags & M_MCAST) 1173 ifp->if_omcasts++; 1174 return (error); 1175 1176bad: 1177 NG_FREE_DATA(m, meta); 1178 return (error); 1179} 1180 1181/* 1182 * pass an mbuf out to the connected hook 1183 * More complicated than just an m_prepend, as it tries to save later nodes 1184 * from needing to do lots of m_pullups. 1185 */ 1186static void 1187ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m) 1188{ 1189 int room; 1190 node_p node = AC2NG(ac); 1191 struct ether_header *eh2; 1192 1193 if (node && LIST_FIRST(&(node->hooks))) { 1194 /* 1195 * Possibly the header is already on the front, 1196 */ 1197 eh2 = mtod(m, struct ether_header *) - 1; 1198 if ( eh == eh2) { 1199 /* 1200 * This is the case so just move the markers back to 1201 * re-include it. We lucked out. 1202 * This allows us to avoid a yucky m_pullup 1203 * in later nodes if it works. 1204 */ 1205 m->m_len += sizeof(*eh); 1206 m->m_data -= sizeof(*eh); 1207 m->m_pkthdr.len += sizeof(*eh); 1208 } else { 1209 /* 1210 * Alternatively there may be room even though 1211 * it is stored somewhere else. If so, copy it in. 1212 * This only safe because we KNOW that this packet has 1213 * just been generated by an ethernet card, so there 1214 * are no aliases to the buffer. (unlike in outgoing 1215 * packets). 1216 * Nearly all ethernet cards will end up producing mbufs 1217 * that fall into these cases. So we are not optimising 1218 * contorted cases. 1219 */ 1220 1221 if (m->m_flags & M_EXT) { 1222 room = (mtod(m, caddr_t) - m->m_ext.ext_buf); 1223 if (room > m->m_ext.ext_size) /* garbage */ 1224 room = 0; /* fail immediatly */ 1225 } else { 1226 room = (mtod(m, caddr_t) - m->m_pktdat); 1227 } 1228 if (room > sizeof (*eh)) { 1229 /* we have room, just copy it and adjust */ 1230 m->m_len += sizeof(*eh); 1231 m->m_data -= sizeof(*eh); 1232 m->m_pkthdr.len += sizeof(*eh); 1233 } else { 1234 /* 1235 * Doing anything more is likely to get more 1236 * expensive than it's worth.. 1237 * it's probable that everything else is in one 1238 * big lump. The next node will do an m_pullup() 1239 * for exactly the amount of data it needs and 1240 * hopefully everything after that will not 1241 * need one. So let's just use M_PREPEND. 1242 */ 1243 M_PREPEND(m, sizeof (*eh), M_DONTWAIT); 1244 if (m == NULL) 1245 return; 1246 } 1247 bcopy ((caddr_t)eh, mtod(m, struct ether_header *), 1248 sizeof(*eh)); 1249 } 1250 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL); 1251 } else { 1252 m_freem(m); 1253 } 1254} 1255 1256/* 1257 * do local shutdown processing.. 1258 * This node will refuse to go away, unless the hardware says to.. 1259 * don't unref the node, or remove our name. just clear our links up. 1260 */ 1261static int 1262ngether_rmnode(node_p node) 1263{ 1264 ng_cutlinks(node); 1265 node->flags &= ~NG_INVALID; /* bounce back to life */ 1266 return (0); 1267} 1268 1269/* already linked */ 1270static int 1271ngether_connect(hook_p hook) 1272{ 1273 /* be really amiable and just say "YUP that's OK by me! " */ 1274 return (0); 1275} 1276 1277/* 1278 * notify on hook disconnection (destruction) 1279 * 1280 * For this type, removal of the last lins no effect. The interface can run 1281 * independently. 1282 * Since we have no per-hook information, this is rather simple. 1283 */ 1284static int 1285ngether_disconnect(hook_p hook) 1286{ 1287 hook->node->flags &= ~NGEF_DIVERT; 1288 return (0); 1289} 1290#endif /* NETGRAPH */ 1291 1292/********************************** END *************************************/
| 40#include "opt_ipx.h" 41#include "opt_bdg.h" 42#include "opt_netgraph.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/malloc.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/sockio.h> 51#include <sys/sysctl.h> 52 53#include <net/if.h> 54#include <net/netisr.h> 55#include <net/route.h> 56#include <net/if_llc.h> 57#include <net/if_dl.h> 58#include <net/if_types.h> 59 60#if defined(INET) || defined(INET6) 61#include <netinet/in.h> 62#include <netinet/in_var.h> 63#include <netinet/if_ether.h> 64#endif 65#ifdef INET6 66#include <netinet6/nd6.h> 67#include <netinet6/in6_ifattach.h> 68#endif 69 70#ifdef IPX 71#include <netipx/ipx.h> 72#include <netipx/ipx_if.h> 73#endif 74 75#ifdef NS 76#include <netns/ns.h> 77#include <netns/ns_if.h> 78ushort ns_nettype; 79int ether_outputdebug = 0; 80int ether_inputdebug = 0; 81#endif 82 83#ifdef ISO 84#include <netiso/argo_debug.h> 85#include <netiso/iso.h> 86#include <netiso/iso_var.h> 87#include <netiso/iso_snpac.h> 88#endif 89 90/*#ifdef LLC 91#include <netccitt/dll.h> 92#include <netccitt/llc_var.h> 93#endif*/ 94 95#if defined(LLC) && defined(CCITT) 96extern struct ifqueue pkintrq; 97#endif 98 99#ifdef NETATALK 100#include <netatalk/at.h> 101#include <netatalk/at_var.h> 102#include <netatalk/at_extern.h> 103 104#define llc_snap_org_code llc_un.type_snap.org_code 105#define llc_snap_ether_type llc_un.type_snap.ether_type 106 107extern u_char at_org_code[3]; 108extern u_char aarp_org_code[3]; 109#endif /* NETATALK */ 110 111#ifdef BRIDGE 112#include <net/bridge.h> 113#endif 114 115#include "vlan.h" 116#if NVLAN > 0 117#include <net/if_vlan_var.h> 118#endif /* NVLAN > 0 */ 119 120static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **, 121 struct sockaddr *)); 122u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 123#define senderr(e) do { error = (e); goto bad;} while (0) 124#define IFP2AC(IFP) ((struct arpcom *)IFP) 125 126#ifdef NETGRAPH 127#include <netgraph/ng_ether.h> 128#include <netgraph/ng_message.h> 129#include <netgraph/netgraph.h> 130 131static void ngether_init(void* ignored); 132static void ngether_send(struct arpcom *ac, 133 struct ether_header *eh, struct mbuf *m); 134static ng_constructor_t ngether_constructor; 135static ng_rcvmsg_t ngether_rcvmsg; 136static ng_shutdown_t ngether_rmnode; 137static ng_newhook_t ngether_newhook; 138static ng_connect_t ngether_connect; 139static ng_rcvdata_t ngether_rcvdata; 140static ng_disconnect_t ngether_disconnect; 141 142static struct ng_type typestruct = { 143 NG_VERSION, 144 NG_ETHER_NODE_TYPE, 145 NULL, 146 ngether_constructor, 147 ngether_rcvmsg, 148 ngether_rmnode, 149 ngether_newhook, 150 NULL, 151 ngether_connect, 152 ngether_rcvdata, 153 ngether_rcvdata, 154 ngether_disconnect, 155 NULL 156}; 157 158#define AC2NG(AC) ((node_p)((AC)->ac_ng)) 159#define NGEF_DIVERT NGF_TYPE1 /* all packets sent to netgraph */ 160#endif /* NETGRAPH */ 161 162/* 163 * Ethernet output routine. 164 * Encapsulate a packet of type family for the local net. 165 * Use trailer local net encapsulation if enough data in first 166 * packet leaves a multiple of 512 bytes of data in remainder. 167 * Assumes that ifp is actually pointer to arpcom structure. 168 */ 169int 170ether_output(ifp, m0, dst, rt0) 171 register struct ifnet *ifp; 172 struct mbuf *m0; 173 struct sockaddr *dst; 174 struct rtentry *rt0; 175{ 176 short type; 177 int s, error = 0, hdrcmplt = 0; 178 u_char esrc[6], edst[6]; 179 register struct mbuf *m = m0; 180 register struct rtentry *rt; 181 register struct ether_header *eh; 182 int off, len = m->m_pkthdr.len, loop_copy = 0; 183 int hlen; /* link layer header lenght */ 184 struct arpcom *ac = IFP2AC(ifp); 185 186 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 187 senderr(ENETDOWN); 188 rt = rt0; 189 if (rt) { 190 if ((rt->rt_flags & RTF_UP) == 0) { 191 rt0 = rt = rtalloc1(dst, 1, 0UL); 192 if (rt0) 193 rt->rt_refcnt--; 194 else 195 senderr(EHOSTUNREACH); 196 } 197 if (rt->rt_flags & RTF_GATEWAY) { 198 if (rt->rt_gwroute == 0) 199 goto lookup; 200 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 201 rtfree(rt); rt = rt0; 202 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 203 0UL); 204 if ((rt = rt->rt_gwroute) == 0) 205 senderr(EHOSTUNREACH); 206 } 207 } 208 if (rt->rt_flags & RTF_REJECT) 209 if (rt->rt_rmx.rmx_expire == 0 || 210 time_second < rt->rt_rmx.rmx_expire) 211 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 212 } 213 hlen = ETHER_HDR_LEN; 214 switch (dst->sa_family) { 215#ifdef INET 216 case AF_INET: 217 if (!arpresolve(ac, rt, m, dst, edst, rt0)) 218 return (0); /* if not yet resolved */ 219 off = m->m_pkthdr.len - m->m_len; 220 type = htons(ETHERTYPE_IP); 221 break; 222#endif 223#ifdef INET6 224 case AF_INET6: 225 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) { 226 /* this must be impossible, so we bark */ 227 printf("nd6_storelladdr failed\n"); 228 return(0); 229 } 230 off = m->m_pkthdr.len - m->m_len; 231 type = htons(ETHERTYPE_IPV6); 232 break; 233#endif 234#ifdef IPX 235 case AF_IPX: 236 type = htons(ETHERTYPE_IPX); 237 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 238 (caddr_t)edst, sizeof (edst)); 239 break; 240#endif 241#ifdef NETATALK 242 case AF_APPLETALK: 243 { 244 struct at_ifaddr *aa; 245 246 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) { 247 goto bad; 248 } 249 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 250 return (0); 251 /* 252 * In the phase 2 case, need to prepend an mbuf for the llc header. 253 * Since we must preserve the value of m, which is passed to us by 254 * value, we m_copy() the first mbuf, and use it for our llc header. 255 */ 256 if ( aa->aa_flags & AFA_PHASE2 ) { 257 struct llc llc; 258 259 M_PREPEND(m, sizeof(struct llc), M_WAIT); 260 len += sizeof(struct llc); 261 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 262 llc.llc_control = LLC_UI; 263 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 264 llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); 265 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 266 type = htons(m->m_pkthdr.len); 267 hlen = sizeof(struct llc) + ETHER_HDR_LEN; 268 } else { 269 type = htons(ETHERTYPE_AT); 270 } 271 break; 272 } 273#endif NETATALK 274#ifdef NS 275 case AF_NS: 276 switch(ns_nettype){ 277 default: 278 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 279 type = 0x8137; 280 break; 281 case 0x0: /* Novell 802.3 */ 282 type = htons( m->m_pkthdr.len); 283 break; 284 case 0xe0e0: /* Novell 802.2 and Token-Ring */ 285 M_PREPEND(m, 3, M_WAIT); 286 type = htons( m->m_pkthdr.len); 287 cp = mtod(m, u_char *); 288 *cp++ = 0xE0; 289 *cp++ = 0xE0; 290 *cp++ = 0x03; 291 break; 292 } 293 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 294 (caddr_t)edst, sizeof (edst)); 295 /* 296 * XXX if ns_thishost is the same as the node's ethernet 297 * address then just the default code will catch this anyhow. 298 * So I'm not sure if this next clause should be here at all? 299 * [JRE] 300 */ 301 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ 302 m->m_pkthdr.rcvif = ifp; 303 schednetisr(NETISR_NS); 304 inq = &nsintrq; 305 s = splimp(); 306 if (IF_QFULL(inq)) { 307 IF_DROP(inq); 308 m_freem(m); 309 } else 310 IF_ENQUEUE(inq, m); 311 splx(s); 312 return (error); 313 } 314 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ 315 m->m_flags |= M_BCAST; 316 } 317 break; 318#endif /* NS */ 319#ifdef ISO 320 case AF_ISO: { 321 int snpalen; 322 struct llc *l; 323 register struct sockaddr_dl *sdl; 324 325 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && 326 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { 327 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); 328 } else if (error = 329 iso_snparesolve(ifp, (struct sockaddr_iso *)dst, 330 (char *)edst, &snpalen)) 331 goto bad; /* Not Resolved */ 332 /* If broadcasting on a simplex interface, loopback a copy */ 333 if (*edst & 1) 334 m->m_flags |= (M_BCAST|M_MCAST); 335 M_PREPEND(m, 3, M_DONTWAIT); 336 if (m == NULL) 337 return (0); 338 type = htons(m->m_pkthdr.len); 339 l = mtod(m, struct llc *); 340 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; 341 l->llc_control = LLC_UI; 342 len += 3; 343 IFDEBUG(D_ETHER) 344 int i; 345 printf("unoutput: sending pkt to: "); 346 for (i=0; i<6; i++) 347 printf("%x ", edst[i] & 0xff); 348 printf("\n"); 349 ENDDEBUG 350 } break; 351#endif /* ISO */ 352#ifdef LLC 353/* case AF_NSAP: */ 354 case AF_CCITT: { 355 register struct sockaddr_dl *sdl = 356 (struct sockaddr_dl *) rt -> rt_gateway; 357 358 if (sdl && sdl->sdl_family == AF_LINK 359 && sdl->sdl_alen > 0) { 360 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst)); 361 } else goto bad; /* Not a link interface ? Funny ... */ 362 if (*edst & 1) 363 loop_copy = 1; 364 type = htons(m->m_pkthdr.len); 365#ifdef LLC_DEBUG 366 { 367 int i; 368 register struct llc *l = mtod(m, struct llc *); 369 370 printf("ether_output: sending LLC2 pkt to: "); 371 for (i=0; i<6; i++) 372 printf("%x ", edst[i] & 0xff); 373 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", 374 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, 375 l->llc_control & 0xff); 376 377 } 378#endif /* LLC_DEBUG */ 379 } break; 380#endif /* LLC */ 381 382 case pseudo_AF_HDRCMPLT: 383 hdrcmplt = 1; 384 eh = (struct ether_header *)dst->sa_data; 385 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc)); 386 /* FALLTHROUGH */ 387 388 case AF_UNSPEC: 389 loop_copy = -1; /* if this is for us, don't do it */ 390 eh = (struct ether_header *)dst->sa_data; 391 (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); 392 type = eh->ether_type; 393 break; 394 395 default: 396 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 397 dst->sa_family); 398 senderr(EAFNOSUPPORT); 399 } 400 401 /* 402 * Add local net header. If no space in first mbuf, 403 * allocate another. 404 */ 405 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); 406 if (m == 0) 407 senderr(ENOBUFS); 408 eh = mtod(m, struct ether_header *); 409 (void)memcpy(&eh->ether_type, &type, 410 sizeof(eh->ether_type)); 411 (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); 412 if (hdrcmplt) 413 (void)memcpy(eh->ether_shost, esrc, 414 sizeof(eh->ether_shost)); 415 else 416 (void)memcpy(eh->ether_shost, ac->ac_enaddr, 417 sizeof(eh->ether_shost)); 418 419 /* 420 * If a simplex interface, and the packet is being sent to our 421 * Ethernet address or a broadcast address, loopback a copy. 422 * XXX To make a simplex device behave exactly like a duplex 423 * device, we should copy in the case of sending to our own 424 * ethernet address (thus letting the original actually appear 425 * on the wire). However, we don't do that here for security 426 * reasons and compatibility with the original behavior. 427 */ 428 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 429 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 430 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 431 432 (void) if_simloop(ifp, n, dst, hlen); 433 } else if (bcmp(eh->ether_dhost, 434 eh->ether_shost, ETHER_ADDR_LEN) == 0) { 435 (void) if_simloop(ifp, m, dst, hlen); 436 return (0); /* XXX */ 437 } 438 } 439#ifdef BRIDGE 440 if (do_bridge) { 441 struct mbuf *m0 = m ; 442 443 if (m->m_pkthdr.rcvif) 444 m->m_pkthdr.rcvif = NULL ; 445 ifp = bridge_dst_lookup(m); 446 bdg_forward(&m0, ifp); 447 if (m0) 448 m_freem(m0); 449 return (0); 450 } 451#endif 452 s = splimp(); 453 /* 454 * Queue message on interface, and start output if interface 455 * not yet active. 456 */ 457 if (IF_QFULL(&ifp->if_snd)) { 458 IF_DROP(&ifp->if_snd); 459 splx(s); 460 senderr(ENOBUFS); 461 } 462 IF_ENQUEUE(&ifp->if_snd, m); 463 if ((ifp->if_flags & IFF_OACTIVE) == 0) 464 (*ifp->if_start)(ifp); 465 splx(s); 466 ifp->if_obytes += len + sizeof (struct ether_header); 467 if (m->m_flags & M_MCAST) 468 ifp->if_omcasts++; 469 return (error); 470 471bad: 472 if (m) 473 m_freem(m); 474 return (error); 475} 476 477/* 478 * Process a received Ethernet packet; 479 * the packet is in the mbuf chain m without 480 * the ether header, which is provided separately. 481 */ 482void 483ether_input(ifp, eh, m) 484 struct ifnet *ifp; 485 register struct ether_header *eh; 486 struct mbuf *m; 487{ 488 register struct ifqueue *inq; 489 u_short ether_type; 490 int s; 491#if defined (ISO) || defined (LLC) || defined(NETATALK) 492 register struct llc *l; 493#endif 494 495 if ((ifp->if_flags & IFF_UP) == 0) { 496 m_freem(m); 497 return; 498 } 499 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 500 if (eh->ether_dhost[0] & 1) { 501 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 502 sizeof(etherbroadcastaddr)) == 0) 503 m->m_flags |= M_BCAST; 504 else 505 m->m_flags |= M_MCAST; 506 } 507 if (m->m_flags & (M_BCAST|M_MCAST)) 508 ifp->if_imcasts++; 509 510 ether_type = ntohs(eh->ether_type); 511 512#ifdef NETGRAPH 513 { 514 struct arpcom *ac = IFP2AC(ifp); 515 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) { 516 ngether_send(ac, eh, m); 517 return; 518 } 519 } 520#endif /* NETGRAPH */ 521 522#if NVLAN > 0 523 if (ether_type == vlan_proto) { 524 if (vlan_input(eh, m) < 0) 525 ifp->if_data.ifi_noproto++; 526 return; 527 } 528#endif /* NVLAN > 0 */ 529 530 switch (ether_type) { 531#ifdef INET 532 case ETHERTYPE_IP: 533 if (ipflow_fastforward(m)) 534 return; 535 schednetisr(NETISR_IP); 536 inq = &ipintrq; 537 break; 538 539 case ETHERTYPE_ARP: 540 schednetisr(NETISR_ARP); 541 inq = &arpintrq; 542 break; 543#endif 544#ifdef IPX 545 case ETHERTYPE_IPX: 546 schednetisr(NETISR_IPX); 547 inq = &ipxintrq; 548 break; 549#endif 550#ifdef INET6 551 case ETHERTYPE_IPV6: 552 schednetisr(NETISR_IPV6); 553 inq = &ip6intrq; 554 break; 555#endif 556#ifdef NS 557 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ 558 schednetisr(NETISR_NS); 559 inq = &nsintrq; 560 break; 561 562#endif /* NS */ 563#ifdef NETATALK 564 case ETHERTYPE_AT: 565 schednetisr(NETISR_ATALK); 566 inq = &atintrq1; 567 break; 568 case ETHERTYPE_AARP: 569 /* probably this should be done with a NETISR as well */ 570 aarpinput(IFP2AC(ifp), m); /* XXX */ 571 return; 572#endif NETATALK 573 default: 574#ifdef NS 575 checksum = mtod(m, ushort *); 576 /* Novell 802.3 */ 577 if ((ether_type <= ETHERMTU) && 578 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ 579 if(*checksum == 0xE0E0) { 580 m->m_pkthdr.len -= 3; 581 m->m_len -= 3; 582 m->m_data += 3; 583 } 584 schednetisr(NETISR_NS); 585 inq = &nsintrq; 586 break; 587 } 588#endif /* NS */ 589#if defined (ISO) || defined (LLC) || defined(NETATALK) 590 if (ether_type > ETHERMTU) 591 goto dropanyway; 592 l = mtod(m, struct llc *); 593 switch (l->llc_dsap) { 594#ifdef NETATALK 595 case LLC_SNAP_LSAP: 596 switch (l->llc_control) { 597 case LLC_UI: 598 if (l->llc_ssap != LLC_SNAP_LSAP) 599 goto dropanyway; 600 601 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 602 sizeof(at_org_code)) == 0 && 603 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 604 inq = &atintrq2; 605 m_adj( m, sizeof( struct llc )); 606 schednetisr(NETISR_ATALK); 607 break; 608 } 609 610 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 611 sizeof(aarp_org_code)) == 0 && 612 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 613 m_adj( m, sizeof( struct llc )); 614 aarpinput(IFP2AC(ifp), m); /* XXX */ 615 return; 616 } 617 618 default: 619 goto dropanyway; 620 } 621 break; 622#endif NETATALK 623#ifdef ISO 624 case LLC_ISO_LSAP: 625 switch (l->llc_control) { 626 case LLC_UI: 627 /* LLC_UI_P forbidden in class 1 service */ 628 if ((l->llc_dsap == LLC_ISO_LSAP) && 629 (l->llc_ssap == LLC_ISO_LSAP)) { 630 /* LSAP for ISO */ 631 if (m->m_pkthdr.len > ether_type) 632 m_adj(m, ether_type - m->m_pkthdr.len); 633 m->m_data += 3; /* XXX */ 634 m->m_len -= 3; /* XXX */ 635 m->m_pkthdr.len -= 3; /* XXX */ 636 M_PREPEND(m, sizeof *eh, M_DONTWAIT); 637 if (m == 0) 638 return; 639 *mtod(m, struct ether_header *) = *eh; 640 IFDEBUG(D_ETHER) 641 printf("clnp packet"); 642 ENDDEBUG 643 schednetisr(NETISR_ISO); 644 inq = &clnlintrq; 645 break; 646 } 647 goto dropanyway; 648 649 case LLC_XID: 650 case LLC_XID_P: 651 if(m->m_len < 6) 652 goto dropanyway; 653 l->llc_window = 0; 654 l->llc_fid = 9; 655 l->llc_class = 1; 656 l->llc_dsap = l->llc_ssap = 0; 657 /* Fall through to */ 658 case LLC_TEST: 659 case LLC_TEST_P: 660 { 661 struct sockaddr sa; 662 register struct ether_header *eh2; 663 int i; 664 u_char c = l->llc_dsap; 665 666 l->llc_dsap = l->llc_ssap; 667 l->llc_ssap = c; 668 if (m->m_flags & (M_BCAST | M_MCAST)) 669 bcopy((caddr_t)ac->ac_enaddr, 670 (caddr_t)eh->ether_dhost, 6); 671 sa.sa_family = AF_UNSPEC; 672 sa.sa_len = sizeof(sa); 673 eh2 = (struct ether_header *)sa.sa_data; 674 for (i = 0; i < 6; i++) { 675 eh2->ether_shost[i] = c = eh->ether_dhost[i]; 676 eh2->ether_dhost[i] = 677 eh->ether_dhost[i] = eh->ether_shost[i]; 678 eh->ether_shost[i] = c; 679 } 680 ifp->if_output(ifp, m, &sa, NULL); 681 return; 682 } 683 default: 684 m_freem(m); 685 return; 686 } 687 break; 688#endif /* ISO */ 689#ifdef LLC 690 case LLC_X25_LSAP: 691 { 692 if (m->m_pkthdr.len > ether_type) 693 m_adj(m, ether_type - m->m_pkthdr.len); 694 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); 695 if (m == 0) 696 return; 697 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, 698 eh->ether_dhost, LLC_X25_LSAP, 6, 699 mtod(m, struct sdl_hdr *))) 700 panic("ETHER cons addr failure"); 701 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type; 702#ifdef LLC_DEBUG 703 printf("llc packet\n"); 704#endif /* LLC_DEBUG */ 705 schednetisr(NETISR_CCITT); 706 inq = &llcintrq; 707 break; 708 } 709#endif /* LLC */ 710 dropanyway: 711 default: 712#ifdef NETGRAPH 713 ngether_send(IFP2AC(ifp), eh, m); 714#else /* NETGRAPH */ 715 m_freem(m); 716#endif /* NETGRAPH */ 717 return; 718 } 719#else /* ISO || LLC || NETATALK */ 720#ifdef NETGRAPH 721 ngether_send(IFP2AC(ifp), eh, m); 722#else /* NETGRAPH */ 723 m_freem(m); 724#endif /* NETGRAPH */ 725 return; 726#endif /* ISO || LLC || NETATALK */ 727 } 728 729 s = splimp(); 730 if (IF_QFULL(inq)) { 731 IF_DROP(inq); 732 m_freem(m); 733 } else 734 IF_ENQUEUE(inq, m); 735 splx(s); 736} 737 738/* 739 * Perform common duties while attaching to interface list 740 */ 741void 742ether_ifattach(ifp) 743 register struct ifnet *ifp; 744{ 745 register struct ifaddr *ifa; 746 register struct sockaddr_dl *sdl; 747 748 ifp->if_type = IFT_ETHER; 749 ifp->if_addrlen = 6; 750 ifp->if_hdrlen = 14; 751 ifp->if_mtu = ETHERMTU; 752 ifp->if_resolvemulti = ether_resolvemulti; 753 if (ifp->if_baudrate == 0) 754 ifp->if_baudrate = 10000000; 755 ifa = ifnet_addrs[ifp->if_index - 1]; 756 if (ifa == 0) { 757 printf("ether_ifattach: no lladdr!\n"); 758 return; 759 } 760 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 761 sdl->sdl_type = IFT_ETHER; 762 sdl->sdl_alen = ifp->if_addrlen; 763 bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 764#ifdef NETGRAPH 765 ngether_init(ifp); 766#endif /* NETGRAPH */ 767#ifdef INET6 768 in6_ifattach_getifid(ifp); 769#endif 770} 771 772SYSCTL_DECL(_net_link); 773SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); 774 775int 776ether_ioctl(ifp, command, data) 777 struct ifnet *ifp; 778 int command; 779 caddr_t data; 780{ 781 struct ifaddr *ifa = (struct ifaddr *) data; 782 struct ifreq *ifr = (struct ifreq *) data; 783 int error = 0; 784 785 switch (command) { 786 case SIOCSIFADDR: 787 ifp->if_flags |= IFF_UP; 788 789 switch (ifa->ifa_addr->sa_family) { 790#ifdef INET 791 case AF_INET: 792 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 793 arp_ifinit(IFP2AC(ifp), ifa); 794 break; 795#endif 796#ifdef IPX 797 /* 798 * XXX - This code is probably wrong 799 */ 800 case AF_IPX: 801 { 802 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 803 struct arpcom *ac = IFP2AC(ifp); 804 805 if (ipx_nullhost(*ina)) 806 ina->x_host = 807 *(union ipx_host *) 808 ac->ac_enaddr; 809 else { 810 bcopy((caddr_t) ina->x_host.c_host, 811 (caddr_t) ac->ac_enaddr, 812 sizeof(ac->ac_enaddr)); 813 } 814 815 /* 816 * Set new address 817 */ 818 ifp->if_init(ifp->if_softc); 819 break; 820 } 821#endif 822#ifdef NS 823 /* 824 * XXX - This code is probably wrong 825 */ 826 case AF_NS: 827 { 828 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 829 struct arpcom *ac = IFP2AC(ifp); 830 831 if (ns_nullhost(*ina)) 832 ina->x_host = 833 *(union ns_host *) (ac->ac_enaddr); 834 else { 835 bcopy((caddr_t) ina->x_host.c_host, 836 (caddr_t) ac->ac_enaddr, 837 sizeof(ac->ac_enaddr)); 838 } 839 840 /* 841 * Set new address 842 */ 843 ifp->if_init(ifp->if_softc); 844 break; 845 } 846#endif 847 default: 848 ifp->if_init(ifp->if_softc); 849 break; 850 } 851 break; 852 853 case SIOCGIFADDR: 854 { 855 struct sockaddr *sa; 856 857 sa = (struct sockaddr *) & ifr->ifr_data; 858 bcopy(IFP2AC(ifp)->ac_enaddr, 859 (caddr_t) sa->sa_data, ETHER_ADDR_LEN); 860 } 861 break; 862 863 case SIOCSIFMTU: 864 /* 865 * Set the interface MTU. 866 */ 867 if (ifr->ifr_mtu > ETHERMTU) { 868 error = EINVAL; 869 } else { 870 ifp->if_mtu = ifr->ifr_mtu; 871 } 872 break; 873 } 874 return (error); 875} 876 877int 878ether_resolvemulti(ifp, llsa, sa) 879 struct ifnet *ifp; 880 struct sockaddr **llsa; 881 struct sockaddr *sa; 882{ 883 struct sockaddr_dl *sdl; 884 struct sockaddr_in *sin; 885#ifdef INET6 886 struct sockaddr_in6 *sin6; 887#endif 888 u_char *e_addr; 889 890 switch(sa->sa_family) { 891 case AF_LINK: 892 /* 893 * No mapping needed. Just check that it's a valid MC address. 894 */ 895 sdl = (struct sockaddr_dl *)sa; 896 e_addr = LLADDR(sdl); 897 if ((e_addr[0] & 1) != 1) 898 return EADDRNOTAVAIL; 899 *llsa = 0; 900 return 0; 901 902#ifdef INET 903 case AF_INET: 904 sin = (struct sockaddr_in *)sa; 905 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 906 return EADDRNOTAVAIL; 907 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 908 M_WAITOK); 909 sdl->sdl_len = sizeof *sdl; 910 sdl->sdl_family = AF_LINK; 911 sdl->sdl_index = ifp->if_index; 912 sdl->sdl_type = IFT_ETHER; 913 sdl->sdl_nlen = 0; 914 sdl->sdl_alen = ETHER_ADDR_LEN; 915 sdl->sdl_slen = 0; 916 e_addr = LLADDR(sdl); 917 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); 918 *llsa = (struct sockaddr *)sdl; 919 return 0; 920#endif 921#ifdef INET6 922 case AF_INET6: 923 sin6 = (struct sockaddr_in6 *)sa; 924 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 925 return EADDRNOTAVAIL; 926 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 927 M_WAITOK); 928 sdl->sdl_len = sizeof *sdl; 929 sdl->sdl_family = AF_LINK; 930 sdl->sdl_index = ifp->if_index; 931 sdl->sdl_type = IFT_ETHER; 932 sdl->sdl_nlen = 0; 933 sdl->sdl_alen = ETHER_ADDR_LEN; 934 sdl->sdl_slen = 0; 935 e_addr = LLADDR(sdl); 936 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); 937 *llsa = (struct sockaddr *)sdl; 938 return 0; 939#endif 940 941 default: 942 /* 943 * Well, the text isn't quite right, but it's the name 944 * that counts... 945 */ 946 return EAFNOSUPPORT; 947 } 948} 949 950#ifdef NETGRAPH 951 952/*********************************************************************** 953 * This section contains the methods for the Netgraph interface 954 ***********************************************************************/ 955/* It's Ascii-art time! 956 * The ifnet is the first part of the arpcom which must be 957 * the first part of the device's softc.. yuk. 958 * 959 * +--------------------------+-----+---------+ 960 * | struct ifnet (*ifp) | | | 961 * | | | | 962 * +--------------------------+ | | 963 * +--|[ac_ng] struct arpcom (*ac) | | 964 * | +--------------------------------+ | 965 * | | struct softc (*ifp->if_softc) (device) | 966 * | +------------------------------------------+ 967 * | ^ 968 * AC2NG() | 969 * | v 970 * | +----------------------+ 971 * | | [private] [flags] | 972 * +------>| struct ng_node | 973 * | [hooks] | ** we only allow one hook 974 * +----------------------+ 975 * ^ 976 * | 977 * v 978 * +-------------+ 979 * | [node] | 980 * | hook | 981 * | [private]|-- *unused* 982 * +-------------+ 983 */ 984 985/* 986 * called during interface attaching 987 */ 988static void 989ngether_init(void *ifpvoid) 990{ 991 struct ifnet *ifp = ifpvoid; 992 struct arpcom *ac = IFP2AC(ifp); 993 static int ngether_done_init; 994 char namebuf[32]; 995 node_p node; 996 997 /* 998 * we have found a node, make sure our 'type' is availabe. 999 */ 1000 if (ngether_done_init == 0) { 1001 if (ng_newtype(&typestruct)) { 1002 printf("ngether install failed\n"); 1003 return; 1004 } 1005 ngether_done_init = 1; 1006 } 1007 if (ng_make_node_common(&typestruct, &node) != 0) 1008 return; 1009 ac->ac_ng = node; 1010 node->private = ifp; 1011 sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit); 1012 ng_name_node(AC2NG(ac), namebuf); 1013} 1014 1015/* 1016 * It is not possible or allowable to create a node of this type. 1017 * If the hardware exists, it will already have created it. 1018 */ 1019static int 1020ngether_constructor(node_p *nodep) 1021{ 1022 return (EINVAL); 1023} 1024 1025/* 1026 * Give our ok for a hook to be added... 1027 * 1028 * Allow one hook at a time (rawdata). 1029 * It can eiteh rdivert everything or only unclaimed packets. 1030 */ 1031static int 1032ngether_newhook(node_p node, hook_p hook, const char *name) 1033{ 1034 1035 /* check if there is already a hook */ 1036 if (LIST_FIRST(&(node->hooks))) 1037 return(EISCONN); 1038 /* 1039 * Check for which mode hook we want. 1040 */ 1041 if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) { 1042 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) { 1043 return (EINVAL); 1044 } 1045 node->flags |= NGEF_DIVERT; 1046 } else { 1047 node->flags &= ~NGEF_DIVERT; 1048 } 1049 return (0); 1050} 1051 1052/* 1053 * incoming messages. 1054 * Just respond to the generic TEXT_STATUS message 1055 */ 1056static int 1057ngether_rcvmsg(node_p node, 1058 struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp) 1059{ 1060 struct ifnet *ifp; 1061 int error = 0; 1062 1063 ifp = node->private; 1064 switch (msg->header.typecookie) { 1065 case NGM_ETHER_COOKIE: 1066 error = EINVAL; 1067 break; 1068 case NGM_GENERIC_COOKIE: 1069 switch(msg->header.cmd) { 1070 case NGM_TEXT_STATUS: { 1071 char *arg; 1072 int pos = 0; 1073 int resplen = sizeof(struct ng_mesg) + 512; 1074 MALLOC(*resp, struct ng_mesg *, resplen, 1075 M_NETGRAPH, M_NOWAIT); 1076 if (*resp == NULL) { 1077 error = ENOMEM; 1078 break; 1079 } 1080 bzero(*resp, resplen); 1081 arg = (*resp)->data; 1082 1083 /* 1084 * Put in the throughput information. 1085 */ 1086 pos = sprintf(arg, "%ld bytes in, %ld bytes out\n", 1087 ifp->if_ibytes, ifp->if_obytes); 1088 pos += sprintf(arg + pos, 1089 "%ld output errors\n", 1090 ifp->if_oerrors); 1091 pos += sprintf(arg + pos, 1092 "ierrors = %ld\n", 1093 ifp->if_ierrors); 1094 1095 (*resp)->header.version = NG_VERSION; 1096 (*resp)->header.arglen = strlen(arg) + 1; 1097 (*resp)->header.token = msg->header.token; 1098 (*resp)->header.typecookie = NGM_ETHER_COOKIE; 1099 (*resp)->header.cmd = msg->header.cmd; 1100 strncpy((*resp)->header.cmdstr, "status", 1101 NG_CMDSTRLEN); 1102 } 1103 break; 1104 default: 1105 error = EINVAL; 1106 break; 1107 } 1108 break; 1109 default: 1110 error = EINVAL; 1111 break; 1112 } 1113 free(msg, M_NETGRAPH); 1114 return (error); 1115} 1116 1117/* 1118 * Receive a completed ethernet packet. 1119 * Queue it for output. 1120 */ 1121static int 1122ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 1123{ 1124 struct ifnet *ifp; 1125 int error = 0; 1126 int s; 1127 struct ether_header *eh; 1128 1129 ifp = hook->node->private; 1130 1131 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1132 senderr(ENETDOWN); 1133 /* drop in the MAC address */ 1134 eh = mtod(m, struct ether_header *); 1135 bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6); 1136 /* 1137 * If a simplex interface, and the packet is being sent to our 1138 * Ethernet address or a broadcast address, loopback a copy. 1139 * XXX To make a simplex device behave exactly like a duplex 1140 * device, we should copy in the case of sending to our own 1141 * ethernet address (thus letting the original actually appear 1142 * on the wire). However, we don't do that here for security 1143 * reasons and compatibility with the original behavior. 1144 */ 1145 if (ifp->if_flags & IFF_SIMPLEX) { 1146 if (m->m_flags & M_BCAST) { 1147 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 1148 1149 ng_queue_data(hook, n, meta); 1150 } else if (bcmp(eh->ether_dhost, 1151 eh->ether_shost, ETHER_ADDR_LEN) == 0) { 1152 ng_queue_data(hook, m, meta); 1153 return (0); /* XXX */ 1154 } 1155 } 1156 s = splimp(); 1157 /* 1158 * Queue message on interface, and start output if interface 1159 * not yet active. 1160 * XXX if we lookead at the priority in the meta data we could 1161 * queue high priority items at the head. 1162 */ 1163 if (IF_QFULL(&ifp->if_snd)) { 1164 IF_DROP(&ifp->if_snd); 1165 splx(s); 1166 senderr(ENOBUFS); 1167 } 1168 IF_ENQUEUE(&ifp->if_snd, m); 1169 if ((ifp->if_flags & IFF_OACTIVE) == 0) 1170 (*ifp->if_start)(ifp); 1171 splx(s); 1172 ifp->if_obytes += m->m_pkthdr.len; 1173 if (m->m_flags & M_MCAST) 1174 ifp->if_omcasts++; 1175 return (error); 1176 1177bad: 1178 NG_FREE_DATA(m, meta); 1179 return (error); 1180} 1181 1182/* 1183 * pass an mbuf out to the connected hook 1184 * More complicated than just an m_prepend, as it tries to save later nodes 1185 * from needing to do lots of m_pullups. 1186 */ 1187static void 1188ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m) 1189{ 1190 int room; 1191 node_p node = AC2NG(ac); 1192 struct ether_header *eh2; 1193 1194 if (node && LIST_FIRST(&(node->hooks))) { 1195 /* 1196 * Possibly the header is already on the front, 1197 */ 1198 eh2 = mtod(m, struct ether_header *) - 1; 1199 if ( eh == eh2) { 1200 /* 1201 * This is the case so just move the markers back to 1202 * re-include it. We lucked out. 1203 * This allows us to avoid a yucky m_pullup 1204 * in later nodes if it works. 1205 */ 1206 m->m_len += sizeof(*eh); 1207 m->m_data -= sizeof(*eh); 1208 m->m_pkthdr.len += sizeof(*eh); 1209 } else { 1210 /* 1211 * Alternatively there may be room even though 1212 * it is stored somewhere else. If so, copy it in. 1213 * This only safe because we KNOW that this packet has 1214 * just been generated by an ethernet card, so there 1215 * are no aliases to the buffer. (unlike in outgoing 1216 * packets). 1217 * Nearly all ethernet cards will end up producing mbufs 1218 * that fall into these cases. So we are not optimising 1219 * contorted cases. 1220 */ 1221 1222 if (m->m_flags & M_EXT) { 1223 room = (mtod(m, caddr_t) - m->m_ext.ext_buf); 1224 if (room > m->m_ext.ext_size) /* garbage */ 1225 room = 0; /* fail immediatly */ 1226 } else { 1227 room = (mtod(m, caddr_t) - m->m_pktdat); 1228 } 1229 if (room > sizeof (*eh)) { 1230 /* we have room, just copy it and adjust */ 1231 m->m_len += sizeof(*eh); 1232 m->m_data -= sizeof(*eh); 1233 m->m_pkthdr.len += sizeof(*eh); 1234 } else { 1235 /* 1236 * Doing anything more is likely to get more 1237 * expensive than it's worth.. 1238 * it's probable that everything else is in one 1239 * big lump. The next node will do an m_pullup() 1240 * for exactly the amount of data it needs and 1241 * hopefully everything after that will not 1242 * need one. So let's just use M_PREPEND. 1243 */ 1244 M_PREPEND(m, sizeof (*eh), M_DONTWAIT); 1245 if (m == NULL) 1246 return; 1247 } 1248 bcopy ((caddr_t)eh, mtod(m, struct ether_header *), 1249 sizeof(*eh)); 1250 } 1251 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL); 1252 } else { 1253 m_freem(m); 1254 } 1255} 1256 1257/* 1258 * do local shutdown processing.. 1259 * This node will refuse to go away, unless the hardware says to.. 1260 * don't unref the node, or remove our name. just clear our links up. 1261 */ 1262static int 1263ngether_rmnode(node_p node) 1264{ 1265 ng_cutlinks(node); 1266 node->flags &= ~NG_INVALID; /* bounce back to life */ 1267 return (0); 1268} 1269 1270/* already linked */ 1271static int 1272ngether_connect(hook_p hook) 1273{ 1274 /* be really amiable and just say "YUP that's OK by me! " */ 1275 return (0); 1276} 1277 1278/* 1279 * notify on hook disconnection (destruction) 1280 * 1281 * For this type, removal of the last lins no effect. The interface can run 1282 * independently. 1283 * Since we have no per-hook information, this is rather simple. 1284 */ 1285static int 1286ngether_disconnect(hook_p hook) 1287{ 1288 hook->node->flags &= ~NGEF_DIVERT; 1289 return (0); 1290} 1291#endif /* NETGRAPH */ 1292 1293/********************************** END *************************************/
|