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