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