1 /* $NetBSD: if_vlan.c,v 1.59 2008/06/15 16:37:21 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright 1998 Massachusetts Institute of Technology 34 * 35 * Permission to use, copy, modify, and distribute this software and 36 * its documentation for any purpose and without fee is hereby 37 * granted, provided that both the above copyright notice and this 38 * permission notice appear in all copies, that both the above 39 * copyright notice and this permission notice appear in all 40 * supporting documentation, and that the name of M.I.T. not be used 41 * in advertising or publicity pertaining to distribution of the 42 * software without specific, written prior permission. M.I.T. makes 43 * no representations about the suitability of this software for any 44 * purpose. It is provided "as is" without express or implied 45 * warranty. 46 * 47 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 48 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 49 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 50 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 51 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 54 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * from FreeBSD: if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp 61 * via OpenBSD: if_vlan.c,v 1.4 2000/05/15 19:15:00 chris Exp 62 */ 63 64 /* 65 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs. Might be 66 * extended some day to also handle IEEE 802.1P priority tagging. This is 67 * sort of sneaky in the implementation, since we need to pretend to be 68 * enough of an Ethernet implementation to make ARP work. The way we do 69 * this is by telling everyone that we are an Ethernet interface, and then 70 * catch the packets that ether_output() left on our output queue when it 71 * calls if_start(), rewrite them for use by the real outgoing interface, 72 * and ask it to send them. 73 * 74 * TODO: 75 * 76 * - Need some way to notify vlan interfaces when the parent 77 * interface changes MTU. 78 */ 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.59 2008/06/15 16:37:21 christos Exp $"); 82 83 #include "opt_inet.h" 84 #include "bpfilter.h" 85 86 #include <sys/param.h> 87 #include <sys/kernel.h> 88 #include <sys/mbuf.h> 89 #include <sys/queue.h> 90 #include <sys/socket.h> 91 #include <sys/sockio.h> 92 #include <sys/systm.h> 93 #include <sys/proc.h> 94 #include <sys/kauth.h> 95 96 #if NBPFILTER > 0 97 #include <net/bpf.h> 98 #endif 99 #include <net/if.h> 100 #include <net/if_dl.h> 101 #include <net/if_types.h> 102 #include <net/if_ether.h> 103 #include <net/if_vlanvar.h> 104 105 #ifdef INET 106 #include <netinet/in.h> 107 #include <netinet/if_inarp.h> 108 #endif 109 110 struct vlan_mc_entry { 111 LIST_ENTRY(vlan_mc_entry) mc_entries; 112 /* 113 * A key to identify this entry. The mc_addr below can't be 114 * used since multiple sockaddr may mapped into the same 115 * ether_multi (e.g., AF_UNSPEC). 116 */ 117 union { 118 struct ether_multi *mcu_enm; 119 } mc_u; 120 struct sockaddr_storage mc_addr; 121 }; 122 123 #define mc_enm mc_u.mcu_enm 124 125 struct ifvlan { 126 union { 127 struct ethercom ifvu_ec; 128 } ifv_u; 129 struct ifnet *ifv_p; /* parent interface of this vlan */ 130 struct ifv_linkmib { 131 const struct vlan_multisw *ifvm_msw; 132 int ifvm_encaplen; /* encapsulation length */ 133 int ifvm_mtufudge; /* MTU fudged by this much */ 134 int ifvm_mintu; /* min transmission unit */ 135 uint16_t ifvm_proto; /* encapsulation ethertype */ 136 uint16_t ifvm_tag; /* tag to apply on packets */ 137 } ifv_mib; 138 LIST_HEAD(__vlan_mchead, vlan_mc_entry) ifv_mc_listhead; 139 LIST_ENTRY(ifvlan) ifv_list; 140 int ifv_flags; 141 }; 142 143 #define IFVF_PROMISC 0x01 /* promiscuous mode enabled */ 144 145 #define ifv_ec ifv_u.ifvu_ec 146 147 #define ifv_if ifv_ec.ec_if 148 149 #define ifv_msw ifv_mib.ifvm_msw 150 #define ifv_encaplen ifv_mib.ifvm_encaplen 151 #define ifv_mtufudge ifv_mib.ifvm_mtufudge 152 #define ifv_mintu ifv_mib.ifvm_mintu 153 #define ifv_tag ifv_mib.ifvm_tag 154 155 struct vlan_multisw { 156 int (*vmsw_addmulti)(struct ifvlan *, struct ifreq *); 157 int (*vmsw_delmulti)(struct ifvlan *, struct ifreq *); 158 void (*vmsw_purgemulti)(struct ifvlan *); 159 }; 160 161 static int vlan_ether_addmulti(struct ifvlan *, struct ifreq *); 162 static int vlan_ether_delmulti(struct ifvlan *, struct ifreq *); 163 static void vlan_ether_purgemulti(struct ifvlan *); 164 165 const struct vlan_multisw vlan_ether_multisw = { 166 vlan_ether_addmulti, 167 vlan_ether_delmulti, 168 vlan_ether_purgemulti, 169 }; 170 171 static int vlan_clone_create(struct if_clone *, int); 172 static int vlan_clone_destroy(struct ifnet *); 173 static int vlan_config(struct ifvlan *, struct ifnet *); 174 static int vlan_ioctl(struct ifnet *, u_long, void *); 175 static void vlan_start(struct ifnet *); 176 static void vlan_unconfig(struct ifnet *); 177 178 void vlanattach(int); 179 180 /* XXX This should be a hash table with the tag as the basis of the key. */ 181 static LIST_HEAD(, ifvlan) ifv_list; 182 183 struct if_clone vlan_cloner = 184 IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy); 185 186 /* Used to pad ethernet frames with < ETHER_MIN_LEN bytes */ 187 static char vlan_zero_pad_buff[ETHER_MIN_LEN]; 188 189 void 190 vlanattach(int n) 191 { 192 193 LIST_INIT(&ifv_list); 194 if_clone_attach(&vlan_cloner); 195 } 196 197 static void 198 vlan_reset_linkname(struct ifnet *ifp) 199 { 200 201 /* 202 * We start out with a "802.1Q VLAN" type and zero-length 203 * addresses. When we attach to a parent interface, we 204 * inherit its type, address length, address, and data link 205 * type. 206 */ 207 208 ifp->if_type = IFT_L2VLAN; 209 ifp->if_addrlen = 0; 210 ifp->if_dlt = DLT_NULL; 211 if_alloc_sadl(ifp); 212 } 213 214 static int 215 vlan_clone_create(struct if_clone *ifc, int unit) 216 { 217 struct ifvlan *ifv; 218 struct ifnet *ifp; 219 int s; 220 221 ifv = malloc(sizeof(struct ifvlan), M_DEVBUF, M_WAITOK|M_ZERO); 222 ifp = &ifv->ifv_if; 223 LIST_INIT(&ifv->ifv_mc_listhead); 224 225 s = splnet(); 226 LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list); 227 splx(s); 228 229 if_initname(ifp, ifc->ifc_name, unit); 230 ifp->if_softc = ifv; 231 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 232 ifp->if_start = vlan_start; 233 ifp->if_ioctl = vlan_ioctl; 234 IFQ_SET_READY(&ifp->if_snd); 235 236 if_attach(ifp); 237 vlan_reset_linkname(ifp); 238 239 return (0); 240 } 241 242 static int 243 vlan_clone_destroy(struct ifnet *ifp) 244 { 245 struct ifvlan *ifv = ifp->if_softc; 246 int s; 247 248 s = splnet(); 249 LIST_REMOVE(ifv, ifv_list); 250 vlan_unconfig(ifp); 251 splx(s); 252 253 if_detach(ifp); 254 free(ifv, M_DEVBUF); 255 256 return (0); 257 } 258 259 /* 260 * Configure a VLAN interface. Must be called at splnet(). 261 */ 262 static int 263 vlan_config(struct ifvlan *ifv, struct ifnet *p) 264 { 265 struct ifnet *ifp = &ifv->ifv_if; 266 int error; 267 268 if (ifv->ifv_p != NULL) 269 return (EBUSY); 270 271 switch (p->if_type) { 272 case IFT_ETHER: 273 { 274 struct ethercom *ec = (void *) p; 275 276 ifv->ifv_msw = &vlan_ether_multisw; 277 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 278 ifv->ifv_mintu = ETHERMIN; 279 280 /* 281 * If the parent supports the VLAN_MTU capability, 282 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, 283 * enable it. 284 */ 285 if (ec->ec_nvlans++ == 0 && 286 (ec->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) { 287 /* 288 * Enable Tx/Rx of VLAN-sized frames. 289 */ 290 ec->ec_capenable |= ETHERCAP_VLAN_MTU; 291 if (p->if_flags & IFF_UP) { 292 struct ifreq ifr; 293 294 ifr.ifr_flags = p->if_flags; 295 error = (*p->if_ioctl)(p, SIOCSIFFLAGS, 296 (void *) &ifr); 297 if (error) { 298 if (ec->ec_nvlans-- == 1) 299 ec->ec_capenable &= 300 ~ETHERCAP_VLAN_MTU; 301 return (error); 302 } 303 } 304 ifv->ifv_mtufudge = 0; 305 } else if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) { 306 /* 307 * Fudge the MTU by the encapsulation size. This 308 * makes us incompatible with strictly compliant 309 * 802.1Q implementations, but allows us to use 310 * the feature with other NetBSD implementations, 311 * which might still be useful. 312 */ 313 ifv->ifv_mtufudge = ifv->ifv_encaplen; 314 } 315 316 /* 317 * If the parent interface can do hardware-assisted 318 * VLAN encapsulation, then propagate its hardware- 319 * assisted checksumming flags. 320 */ 321 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) 322 ifp->if_capabilities = p->if_capabilities & 323 (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx| 324 IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx| 325 IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx| 326 IFCAP_CSUM_TCPv6_Tx|IFCAP_CSUM_TCPv6_Rx| 327 IFCAP_CSUM_UDPv6_Tx|IFCAP_CSUM_UDPv6_Rx); 328 329 /* 330 * We inherit the parent's Ethernet address. 331 */ 332 ether_ifattach(ifp, CLLADDR(p->if_sadl)); 333 ifp->if_hdrlen = sizeof(struct ether_vlan_header); /* XXX? */ 334 break; 335 } 336 337 default: 338 return (EPROTONOSUPPORT); 339 } 340 341 ifv->ifv_p = p; 342 ifv->ifv_if.if_mtu = p->if_mtu - ifv->ifv_mtufudge; 343 ifv->ifv_if.if_flags = p->if_flags & 344 (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 345 346 /* 347 * Inherit the if_type from the parent. This allows us 348 * to participate in bridges of that type. 349 */ 350 ifv->ifv_if.if_type = p->if_type; 351 352 return (0); 353 } 354 355 /* 356 * Unconfigure a VLAN interface. Must be called at splnet(). 357 */ 358 static void 359 vlan_unconfig(struct ifnet *ifp) 360 { 361 struct ifvlan *ifv = ifp->if_softc; 362 363 if (ifv->ifv_p == NULL) 364 return; 365 366 /* 367 * Since the interface is being unconfigured, we need to empty the 368 * list of multicast groups that we may have joined while we were 369 * alive and remove them from the parent's list also. 370 */ 371 (*ifv->ifv_msw->vmsw_purgemulti)(ifv); 372 373 /* Disconnect from parent. */ 374 switch (ifv->ifv_p->if_type) { 375 case IFT_ETHER: 376 { 377 struct ethercom *ec = (void *) ifv->ifv_p; 378 379 if (ec->ec_nvlans-- == 1) { 380 /* 381 * Disable Tx/Rx of VLAN-sized frames. 382 */ 383 ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; 384 if (ifv->ifv_p->if_flags & IFF_UP) { 385 struct ifreq ifr; 386 387 ifr.ifr_flags = ifv->ifv_p->if_flags; 388 (void) (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, 389 SIOCSIFFLAGS, (void *) &ifr); 390 } 391 } 392 393 ether_ifdetach(ifp); 394 vlan_reset_linkname(ifp); 395 break; 396 } 397 398 #ifdef DIAGNOSTIC 399 default: 400 panic("vlan_unconfig: impossible"); 401 #endif 402 } 403 404 ifv->ifv_p = NULL; 405 ifv->ifv_if.if_mtu = 0; 406 ifv->ifv_flags = 0; 407 408 if_down(ifp); 409 ifp->if_flags &= ~(IFF_UP|IFF_RUNNING); 410 ifp->if_capabilities = 0; 411 } 412 413 /* 414 * Called when a parent interface is detaching; destroy any VLAN 415 * configuration for the parent interface. 416 */ 417 void 418 vlan_ifdetach(struct ifnet *p) 419 { 420 struct ifvlan *ifv; 421 int s; 422 423 s = splnet(); 424 425 for (ifv = LIST_FIRST(&ifv_list); ifv != NULL; 426 ifv = LIST_NEXT(ifv, ifv_list)) { 427 if (ifv->ifv_p == p) 428 vlan_unconfig(&ifv->ifv_if); 429 } 430 431 splx(s); 432 } 433 434 static int 435 vlan_set_promisc(struct ifnet *ifp) 436 { 437 struct ifvlan *ifv = ifp->if_softc; 438 int error = 0; 439 440 if ((ifp->if_flags & IFF_PROMISC) != 0) { 441 if ((ifv->ifv_flags & IFVF_PROMISC) == 0) { 442 error = ifpromisc(ifv->ifv_p, 1); 443 if (error == 0) 444 ifv->ifv_flags |= IFVF_PROMISC; 445 } 446 } else { 447 if ((ifv->ifv_flags & IFVF_PROMISC) != 0) { 448 error = ifpromisc(ifv->ifv_p, 0); 449 if (error == 0) 450 ifv->ifv_flags &= ~IFVF_PROMISC; 451 } 452 } 453 454 return (error); 455 } 456 457 static int 458 vlan_ioctl(struct ifnet *ifp, u_long cmd, void *data) 459 { 460 struct lwp *l = curlwp; /* XXX */ 461 struct ifvlan *ifv = ifp->if_softc; 462 struct ifaddr *ifa = (struct ifaddr *) data; 463 struct ifreq *ifr = (struct ifreq *) data; 464 struct ifnet *pr; 465 struct vlanreq vlr; 466 struct sockaddr *sa; 467 int s, error = 0; 468 469 s = splnet(); 470 471 switch (cmd) { 472 case SIOCSIFADDR: 473 if (ifv->ifv_p != NULL) { 474 ifp->if_flags |= IFF_UP; 475 476 switch (ifa->ifa_addr->sa_family) { 477 #ifdef INET 478 case AF_INET: 479 arp_ifinit(ifp, ifa); 480 break; 481 #endif 482 default: 483 break; 484 } 485 } else { 486 error = EINVAL; 487 } 488 break; 489 490 case SIOCGIFADDR: 491 sa = (struct sockaddr *)&ifr->ifr_data; 492 memcpy(sa->sa_data, CLLADDR(ifp->if_sadl), ifp->if_addrlen); 493 break; 494 495 case SIOCSIFMTU: 496 if (ifv->ifv_p == NULL) 497 error = EINVAL; 498 else if ( 499 ifr->ifr_mtu > (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) || 500 ifr->ifr_mtu < (ifv->ifv_mintu - ifv->ifv_mtufudge)) 501 error = EINVAL; 502 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 503 error = 0; 504 break; 505 506 case SIOCSETVLAN: 507 if ((error = kauth_authorize_network(l->l_cred, 508 KAUTH_NETWORK_INTERFACE, 509 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd, 510 NULL)) != 0) 511 break; 512 if ((error = copyin(ifr->ifr_data, &vlr, sizeof(vlr))) != 0) 513 break; 514 if (vlr.vlr_parent[0] == '\0') { 515 vlan_unconfig(ifp); 516 break; 517 } 518 if (vlr.vlr_tag != EVL_VLANOFTAG(vlr.vlr_tag)) { 519 error = EINVAL; /* check for valid tag */ 520 break; 521 } 522 if ((pr = ifunit(vlr.vlr_parent)) == 0) { 523 error = ENOENT; 524 break; 525 } 526 if ((error = vlan_config(ifv, pr)) != 0) 527 break; 528 ifv->ifv_tag = vlr.vlr_tag; 529 ifp->if_flags |= IFF_RUNNING; 530 531 /* Update promiscuous mode, if necessary. */ 532 vlan_set_promisc(ifp); 533 break; 534 535 case SIOCGETVLAN: 536 memset(&vlr, 0, sizeof(vlr)); 537 if (ifv->ifv_p != NULL) { 538 snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent), "%s", 539 ifv->ifv_p->if_xname); 540 vlr.vlr_tag = ifv->ifv_tag; 541 } 542 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr)); 543 break; 544 545 case SIOCSIFFLAGS: 546 /* 547 * For promiscuous mode, we enable promiscuous mode on 548 * the parent if we need promiscuous on the VLAN interface. 549 */ 550 if (ifv->ifv_p != NULL) 551 error = vlan_set_promisc(ifp); 552 break; 553 554 case SIOCADDMULTI: 555 error = (ifv->ifv_p != NULL) ? 556 (*ifv->ifv_msw->vmsw_addmulti)(ifv, ifr) : EINVAL; 557 break; 558 559 case SIOCDELMULTI: 560 error = (ifv->ifv_p != NULL) ? 561 (*ifv->ifv_msw->vmsw_delmulti)(ifv, ifr) : EINVAL; 562 break; 563 564 default: 565 error = EINVAL; 566 } 567 568 splx(s); 569 570 return (error); 571 } 572 573 static int 574 vlan_ether_addmulti(struct ifvlan *ifv, struct ifreq *ifr) 575 { 576 const struct sockaddr *sa = ifreq_getaddr(SIOCADDMULTI, ifr); 577 struct vlan_mc_entry *mc; 578 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 579 int error; 580 581 if (sa->sa_len > sizeof(struct sockaddr_storage)) 582 return (EINVAL); 583 584 error = ether_addmulti(sa, &ifv->ifv_ec); 585 if (error != ENETRESET) 586 return (error); 587 588 /* 589 * This is new multicast address. We have to tell parent 590 * about it. Also, remember this multicast address so that 591 * we can delete them on unconfigure. 592 */ 593 MALLOC(mc, struct vlan_mc_entry *, sizeof(struct vlan_mc_entry), 594 M_DEVBUF, M_NOWAIT); 595 if (mc == NULL) { 596 error = ENOMEM; 597 goto alloc_failed; 598 } 599 600 /* 601 * As ether_addmulti() returns ENETRESET, following two 602 * statement shouldn't fail. 603 */ 604 (void)ether_multiaddr(sa, addrlo, addrhi); 605 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, mc->mc_enm); 606 memcpy(&mc->mc_addr, sa, sa->sa_len); 607 LIST_INSERT_HEAD(&ifv->ifv_mc_listhead, mc, mc_entries); 608 609 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, SIOCADDMULTI, 610 (void *)ifr); 611 if (error != 0) 612 goto ioctl_failed; 613 return (error); 614 615 ioctl_failed: 616 LIST_REMOVE(mc, mc_entries); 617 FREE(mc, M_DEVBUF); 618 alloc_failed: 619 (void)ether_delmulti(sa, &ifv->ifv_ec); 620 return (error); 621 } 622 623 static int 624 vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr) 625 { 626 const struct sockaddr *sa = ifreq_getaddr(SIOCDELMULTI, ifr); 627 struct ether_multi *enm; 628 struct vlan_mc_entry *mc; 629 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 630 int error; 631 632 /* 633 * Find a key to lookup vlan_mc_entry. We have to do this 634 * before calling ether_delmulti for obvious reason. 635 */ 636 if ((error = ether_multiaddr(sa, addrlo, addrhi)) != 0) 637 return (error); 638 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, enm); 639 640 error = ether_delmulti(sa, &ifv->ifv_ec); 641 if (error != ENETRESET) 642 return (error); 643 644 /* We no longer use this multicast address. Tell parent so. */ 645 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, SIOCDELMULTI, 646 (void *)ifr); 647 if (error == 0) { 648 /* And forget about this address. */ 649 for (mc = LIST_FIRST(&ifv->ifv_mc_listhead); mc != NULL; 650 mc = LIST_NEXT(mc, mc_entries)) { 651 if (mc->mc_enm == enm) { 652 LIST_REMOVE(mc, mc_entries); 653 FREE(mc, M_DEVBUF); 654 break; 655 } 656 } 657 KASSERT(mc != NULL); 658 } else 659 (void)ether_addmulti(sa, &ifv->ifv_ec); 660 return (error); 661 } 662 663 /* 664 * Delete any multicast address we have asked to add from parent 665 * interface. Called when the vlan is being unconfigured. 666 */ 667 static void 668 vlan_ether_purgemulti(struct ifvlan *ifv) 669 { 670 struct ifnet *ifp = ifv->ifv_p; /* Parent. */ 671 struct vlan_mc_entry *mc; 672 union { 673 struct ifreq ifreq; 674 struct { 675 char ifr_name[IFNAMSIZ]; 676 struct sockaddr_storage ifr_ss; 677 } ifreq_storage; 678 } ifreq; 679 struct ifreq *ifr = &ifreq.ifreq; 680 681 memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ); 682 while ((mc = LIST_FIRST(&ifv->ifv_mc_listhead)) != NULL) { 683 ifreq_setaddr(SIOCDELMULTI, ifr, 684 (const struct sockaddr *)&mc->mc_addr); 685 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (void *)ifr); 686 LIST_REMOVE(mc, mc_entries); 687 FREE(mc, M_DEVBUF); 688 } 689 } 690 691 static void 692 vlan_start(struct ifnet *ifp) 693 { 694 struct ifvlan *ifv = ifp->if_softc; 695 struct ifnet *p = ifv->ifv_p; 696 struct ethercom *ec = (void *) ifv->ifv_p; 697 struct mbuf *m; 698 int error; 699 ALTQ_DECL(struct altq_pktattr pktattr;) 700 701 ifp->if_flags |= IFF_OACTIVE; 702 703 for (;;) { 704 IFQ_DEQUEUE(&ifp->if_snd, m); 705 if (m == NULL) 706 break; 707 708 #ifdef ALTQ 709 /* 710 * If ALTQ is enabled on the parent interface, do 711 * classification; the queueing discipline might 712 * not require classification, but might require 713 * the address family/header pointer in the pktattr. 714 */ 715 if (ALTQ_IS_ENABLED(&p->if_snd)) { 716 switch (p->if_type) { 717 case IFT_ETHER: 718 altq_etherclassify(&p->if_snd, m, &pktattr); 719 break; 720 #ifdef DIAGNOSTIC 721 default: 722 panic("vlan_start: impossible (altq)"); 723 #endif 724 } 725 } 726 #endif /* ALTQ */ 727 728 #if NBPFILTER > 0 729 if (ifp->if_bpf) 730 bpf_mtap(ifp->if_bpf, m); 731 #endif 732 /* 733 * If the parent can insert the tag itself, just mark 734 * the tag in the mbuf header. 735 */ 736 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { 737 struct m_tag *mtag; 738 739 mtag = m_tag_get(PACKET_TAG_VLAN, sizeof(u_int), 740 M_NOWAIT); 741 if (mtag == NULL) { 742 ifp->if_oerrors++; 743 m_freem(m); 744 continue; 745 } 746 *(u_int *)(mtag + 1) = ifv->ifv_tag; 747 m_tag_prepend(m, mtag); 748 } else { 749 /* 750 * insert the tag ourselves 751 */ 752 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 753 if (m == NULL) { 754 printf("%s: unable to prepend encap header", 755 ifv->ifv_p->if_xname); 756 ifp->if_oerrors++; 757 continue; 758 } 759 760 switch (p->if_type) { 761 case IFT_ETHER: 762 { 763 struct ether_vlan_header *evl; 764 765 if (m->m_len < sizeof(struct ether_vlan_header)) 766 m = m_pullup(m, 767 sizeof(struct ether_vlan_header)); 768 if (m == NULL) { 769 printf("%s: unable to pullup encap " 770 "header", ifv->ifv_p->if_xname); 771 ifp->if_oerrors++; 772 continue; 773 } 774 775 /* 776 * Transform the Ethernet header into an 777 * Ethernet header with 802.1Q encapsulation. 778 */ 779 memmove(mtod(m, void *), 780 mtod(m, char *) + ifv->ifv_encaplen, 781 sizeof(struct ether_header)); 782 evl = mtod(m, struct ether_vlan_header *); 783 evl->evl_proto = evl->evl_encap_proto; 784 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 785 evl->evl_tag = htons(ifv->ifv_tag); 786 787 /* 788 * To cater for VLAN-aware layer 2 ethernet 789 * switches which may need to strip the tag 790 * before forwarding the packet, make sure 791 * the packet+tag is at least 68 bytes long. 792 * This is necessary because our parent will 793 * only pad to 64 bytes (ETHER_MIN_LEN) and 794 * some switches will not pad by themselves 795 * after deleting a tag. 796 */ 797 if (m->m_pkthdr.len < 798 (ETHER_MIN_LEN + ETHER_VLAN_ENCAP_LEN)) { 799 m_copyback(m, m->m_pkthdr.len, 800 (ETHER_MIN_LEN + 801 ETHER_VLAN_ENCAP_LEN) - 802 m->m_pkthdr.len, 803 vlan_zero_pad_buff); 804 } 805 break; 806 } 807 808 #ifdef DIAGNOSTIC 809 default: 810 panic("vlan_start: impossible"); 811 #endif 812 } 813 } 814 815 /* 816 * Send it, precisely as the parent's output routine 817 * would have. We are already running at splnet. 818 */ 819 IFQ_ENQUEUE(&p->if_snd, m, &pktattr, error); 820 if (error) { 821 /* mbuf is already freed */ 822 ifp->if_oerrors++; 823 continue; 824 } 825 826 ifp->if_opackets++; 827 if ((p->if_flags & (IFF_RUNNING|IFF_OACTIVE)) == IFF_RUNNING) 828 (*p->if_start)(p); 829 } 830 831 ifp->if_flags &= ~IFF_OACTIVE; 832 } 833 834 /* 835 * Given an Ethernet frame, find a valid vlan interface corresponding to the 836 * given source interface and tag, then run the real packet through the 837 * parent's input routine. 838 */ 839 void 840 vlan_input(struct ifnet *ifp, struct mbuf *m) 841 { 842 struct ifvlan *ifv; 843 u_int tag; 844 struct m_tag *mtag; 845 846 mtag = m_tag_find(m, PACKET_TAG_VLAN, NULL); 847 if (mtag != NULL) { 848 /* m contains a normal ethernet frame, the tag is in mtag */ 849 tag = EVL_VLANOFTAG(*(u_int *)(mtag + 1)); 850 m_tag_delete(m, mtag); 851 } else { 852 switch (ifp->if_type) { 853 case IFT_ETHER: 854 { 855 struct ether_vlan_header *evl; 856 857 if (m->m_len < sizeof(struct ether_vlan_header) && 858 (m = m_pullup(m, 859 sizeof(struct ether_vlan_header))) == NULL) { 860 printf("%s: no memory for VLAN header, " 861 "dropping packet.\n", ifp->if_xname); 862 return; 863 } 864 evl = mtod(m, struct ether_vlan_header *); 865 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN); 866 867 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag)); 868 869 /* 870 * Restore the original ethertype. We'll remove 871 * the encapsulation after we've found the vlan 872 * interface corresponding to the tag. 873 */ 874 evl->evl_encap_proto = evl->evl_proto; 875 break; 876 } 877 878 default: 879 tag = (u_int) -1; /* XXX GCC */ 880 #ifdef DIAGNOSTIC 881 panic("vlan_input: impossible"); 882 #endif 883 } 884 } 885 886 for (ifv = LIST_FIRST(&ifv_list); ifv != NULL; 887 ifv = LIST_NEXT(ifv, ifv_list)) 888 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 889 break; 890 891 if (ifv == NULL || 892 (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != 893 (IFF_UP|IFF_RUNNING)) { 894 m_freem(m); 895 ifp->if_noproto++; 896 return; 897 } 898 899 /* 900 * Now, remove the encapsulation header. The original 901 * header has already been fixed up above. 902 */ 903 if (mtag == NULL) { 904 memmove(mtod(m, char *) + ifv->ifv_encaplen, 905 mtod(m, void *), sizeof(struct ether_header)); 906 m_adj(m, ifv->ifv_encaplen); 907 } 908 909 m->m_pkthdr.rcvif = &ifv->ifv_if; 910 ifv->ifv_if.if_ipackets++; 911 912 #if NBPFILTER > 0 913 if (ifv->ifv_if.if_bpf) 914 bpf_mtap(ifv->ifv_if.if_bpf, m); 915 #endif 916 917 /* Pass it back through the parent's input routine. */ 918 (*ifp->if_input)(&ifv->ifv_if, m); 919 } 920