1 /*- 2 * Copyright 1998 Massachusetts Institute of Technology 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose and without fee is hereby 6 * granted, provided that both the above copyright notice and this 7 * permission notice appear in all copies, that both the above 8 * copyright notice and this permission notice appear in all 9 * supporting documentation, and that the name of M.I.T. not be used 10 * in advertising or publicity pertaining to distribution of the 11 * software without specific, written prior permission. M.I.T. makes 12 * no representations about the suitability of this software for any 13 * purpose. It is provided "as is" without express or implied 14 * warranty. 15 * 16 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 17 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 20 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs. 34 * Might be extended some day to also handle IEEE 802.1p priority 35 * tagging. This is sort of sneaky in the implementation, since 36 * we need to pretend to be enough of an Ethernet implementation 37 * to make arp work. The way we do this is by telling everyone 38 * that we are an Ethernet, and then catch the packets that 39 * ether_output() left on our output queue when it calls 40 * if_start(), rewrite them for use by the real outgoing interface, 41 * and ask it to send them. 42 */ 43 44 #include "opt_inet.h" 45 46 #include <sys/param.h> 47 #include <sys/kernel.h> 48 #include <sys/malloc.h> 49 #include <sys/mbuf.h> 50 #include <sys/module.h> 51 #include <sys/queue.h> 52 #include <sys/socket.h> 53 #include <sys/sockio.h> 54 #include <sys/sysctl.h> 55 #include <sys/systm.h> 56 57 #include <net/bpf.h> 58 #include <net/ethernet.h> 59 #include <net/if.h> 60 #include <net/if_clone.h> 61 #include <net/if_arp.h> 62 #include <net/if_dl.h> 63 #include <net/if_types.h> 64 #include <net/if_vlan_var.h> 65 66 #ifdef INET 67 #include <netinet/in.h> 68 #include <netinet/if_ether.h> 69 #endif 70 71 #define VLANNAME "vlan" 72 73 struct vlan_mc_entry { 74 struct ether_addr mc_addr; 75 SLIST_ENTRY(vlan_mc_entry) mc_entries; 76 }; 77 78 struct ifvlan { 79 struct ifnet *ifv_ifp; 80 struct ifnet *ifv_p; /* parent inteface of this vlan */ 81 int ifv_pflags; /* special flags we have set on parent */ 82 struct ifv_linkmib { 83 int ifvm_parent; 84 int ifvm_encaplen; /* encapsulation length */ 85 int ifvm_mtufudge; /* MTU fudged by this much */ 86 int ifvm_mintu; /* min transmission unit */ 87 u_int16_t ifvm_proto; /* encapsulation ethertype */ 88 u_int16_t ifvm_tag; /* tag to apply on packets leaving if */ 89 } ifv_mib; 90 SLIST_HEAD(__vlan_mchead, vlan_mc_entry) vlan_mc_listhead; 91 LIST_ENTRY(ifvlan) ifv_list; 92 }; 93 #define ifv_tag ifv_mib.ifvm_tag 94 #define ifv_encaplen ifv_mib.ifvm_encaplen 95 #define ifv_mtufudge ifv_mib.ifvm_mtufudge 96 #define ifv_mintu ifv_mib.ifvm_mintu 97 98 /* Special flags we should propagate to parent */ 99 static struct { 100 int flag; 101 int (*func)(struct ifnet *, int); 102 } vlan_pflags[] = { 103 {IFF_PROMISC, ifpromisc}, 104 {IFF_ALLMULTI, if_allmulti}, 105 {0, NULL} 106 }; 107 108 SYSCTL_DECL(_net_link); 109 SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN"); 110 SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency"); 111 112 static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface"); 113 static LIST_HEAD(, ifvlan) ifv_list; 114 115 /* 116 * Locking: one lock is used to guard both the ifv_list and modification 117 * to vlan data structures. We are rather conservative here; probably 118 * more than necessary. 119 */ 120 static struct mtx ifv_mtx; 121 #define VLAN_LOCK_INIT() mtx_init(&ifv_mtx, VLANNAME, NULL, MTX_DEF) 122 #define VLAN_LOCK_DESTROY() mtx_destroy(&ifv_mtx) 123 #define VLAN_LOCK_ASSERT() mtx_assert(&ifv_mtx, MA_OWNED) 124 #define VLAN_LOCK() mtx_lock(&ifv_mtx) 125 #define VLAN_UNLOCK() mtx_unlock(&ifv_mtx) 126 127 static void vlan_start(struct ifnet *ifp); 128 static void vlan_ifinit(void *foo); 129 static void vlan_input(struct ifnet *ifp, struct mbuf *m); 130 static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); 131 static int vlan_setflag(struct ifnet *ifp, int flag, int status, 132 int (*func)(struct ifnet *, int)); 133 static int vlan_setflags(struct ifnet *ifp, int status); 134 static int vlan_setmulti(struct ifnet *ifp); 135 static int vlan_unconfig(struct ifnet *ifp); 136 static int vlan_config(struct ifvlan *ifv, struct ifnet *p); 137 static void vlan_link_state(struct ifnet *ifp, int link); 138 139 static struct ifnet *vlan_clone_match_ethertag(struct if_clone *, 140 const char *, int *); 141 static int vlan_clone_match(struct if_clone *, const char *); 142 static int vlan_clone_create(struct if_clone *, char *, size_t); 143 static int vlan_clone_destroy(struct if_clone *, struct ifnet *); 144 145 static struct if_clone vlan_cloner = IFC_CLONE_INITIALIZER(VLANNAME, NULL, 146 IF_MAXUNIT, NULL, vlan_clone_match, vlan_clone_create, vlan_clone_destroy); 147 148 /* 149 * Program our multicast filter. What we're actually doing is 150 * programming the multicast filter of the parent. This has the 151 * side effect of causing the parent interface to receive multicast 152 * traffic that it doesn't really want, which ends up being discarded 153 * later by the upper protocol layers. Unfortunately, there's no way 154 * to avoid this: there really is only one physical interface. 155 * 156 * XXX: There is a possible race here if more than one thread is 157 * modifying the multicast state of the vlan interface at the same time. 158 */ 159 static int 160 vlan_setmulti(struct ifnet *ifp) 161 { 162 struct ifnet *ifp_p; 163 struct ifmultiaddr *ifma, *rifma = NULL; 164 struct ifvlan *sc; 165 struct vlan_mc_entry *mc = NULL; 166 struct sockaddr_dl sdl; 167 int error; 168 169 /*VLAN_LOCK_ASSERT();*/ 170 171 /* Find the parent. */ 172 sc = ifp->if_softc; 173 ifp_p = sc->ifv_p; 174 175 /* 176 * If we don't have a parent, just remember the membership for 177 * when we do. 178 */ 179 if (ifp_p == NULL) 180 return (0); 181 182 bzero((char *)&sdl, sizeof(sdl)); 183 sdl.sdl_len = sizeof(sdl); 184 sdl.sdl_family = AF_LINK; 185 sdl.sdl_index = ifp_p->if_index; 186 sdl.sdl_type = IFT_ETHER; 187 sdl.sdl_alen = ETHER_ADDR_LEN; 188 189 /* First, remove any existing filter entries. */ 190 while (SLIST_FIRST(&sc->vlan_mc_listhead) != NULL) { 191 mc = SLIST_FIRST(&sc->vlan_mc_listhead); 192 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN); 193 error = if_delmulti(ifp_p, (struct sockaddr *)&sdl); 194 if (error) 195 return (error); 196 SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); 197 free(mc, M_VLAN); 198 } 199 200 /* Now program new ones. */ 201 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 202 if (ifma->ifma_addr->sa_family != AF_LINK) 203 continue; 204 mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); 205 if (mc == NULL) 206 return (ENOMEM); 207 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 208 (char *)&mc->mc_addr, ETHER_ADDR_LEN); 209 SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); 210 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 211 LLADDR(&sdl), ETHER_ADDR_LEN); 212 error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma); 213 if (error) 214 return (error); 215 } 216 217 return (0); 218 } 219 220 /* 221 * VLAN support can be loaded as a module. The only place in the 222 * system that's intimately aware of this is ether_input. We hook 223 * into this code through vlan_input_p which is defined there and 224 * set here. Noone else in the system should be aware of this so 225 * we use an explicit reference here. 226 * 227 * NB: Noone should ever need to check if vlan_input_p is null or 228 * not. This is because interfaces have a count of the number 229 * of active vlans (if_nvlans) and this should never be bumped 230 * except by vlan_config--which is in this module so therefore 231 * the module must be loaded and vlan_input_p must be non-NULL. 232 */ 233 extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); 234 235 /* For if_link_state_change() eyes only... */ 236 extern void (*vlan_link_state_p)(struct ifnet *, int); 237 238 static int 239 vlan_modevent(module_t mod, int type, void *data) 240 { 241 242 switch (type) { 243 case MOD_LOAD: 244 LIST_INIT(&ifv_list); 245 VLAN_LOCK_INIT(); 246 vlan_input_p = vlan_input; 247 vlan_link_state_p = vlan_link_state; 248 if_clone_attach(&vlan_cloner); 249 break; 250 case MOD_UNLOAD: 251 if_clone_detach(&vlan_cloner); 252 vlan_input_p = NULL; 253 vlan_link_state_p = NULL; 254 while (!LIST_EMPTY(&ifv_list)) 255 vlan_clone_destroy(&vlan_cloner, 256 LIST_FIRST(&ifv_list)->ifv_ifp); 257 VLAN_LOCK_DESTROY(); 258 break; 259 default: 260 return (EOPNOTSUPP); 261 } 262 return (0); 263 } 264 265 static moduledata_t vlan_mod = { 266 "if_vlan", 267 vlan_modevent, 268 0 269 }; 270 271 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 272 MODULE_DEPEND(if_vlan, miibus, 1, 1, 1); 273 274 static struct ifnet * 275 vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag) 276 { 277 const char *cp; 278 struct ifnet *ifp; 279 int t = 0; 280 281 /* Check for <etherif>.<vlan> style interface names. */ 282 IFNET_RLOCK(); 283 TAILQ_FOREACH(ifp, &ifnet, if_link) { 284 if (ifp->if_type != IFT_ETHER) 285 continue; 286 if (strncmp(ifp->if_xname, name, strlen(ifp->if_xname)) != 0) 287 continue; 288 cp = name + strlen(ifp->if_xname); 289 if (*cp != '.') 290 continue; 291 for(; *cp != '\0'; cp++) { 292 if (*cp < '0' || *cp > '9') 293 continue; 294 t = (t * 10) + (*cp - '0'); 295 } 296 if (tag != NULL) 297 *tag = t; 298 break; 299 } 300 IFNET_RUNLOCK(); 301 302 return (ifp); 303 } 304 305 static int 306 vlan_clone_match(struct if_clone *ifc, const char *name) 307 { 308 const char *cp; 309 310 if (vlan_clone_match_ethertag(ifc, name, NULL) != NULL) 311 return (1); 312 313 if (strncmp(VLANNAME, name, strlen(VLANNAME)) != 0) 314 return (0); 315 for (cp = name + 4; *cp != '\0'; cp++) { 316 if (*cp < '0' || *cp > '9') 317 return (0); 318 } 319 320 return (1); 321 } 322 323 static int 324 vlan_clone_create(struct if_clone *ifc, char *name, size_t len) 325 { 326 char *dp; 327 int wildcard; 328 int unit; 329 int error; 330 int tag; 331 int ethertag; 332 struct ifvlan *ifv; 333 struct ifnet *ifp; 334 struct ifnet *p; 335 u_char eaddr[6] = {0,0,0,0,0,0}; 336 337 if ((p = vlan_clone_match_ethertag(ifc, name, &tag)) != NULL) { 338 ethertag = 1; 339 unit = -1; 340 wildcard = 0; 341 342 /* 343 * Don't let the caller set up a VLAN tag with 344 * anything except VLID bits. 345 */ 346 if (tag & ~EVL_VLID_MASK) 347 return (EINVAL); 348 } else { 349 ethertag = 0; 350 351 error = ifc_name2unit(name, &unit); 352 if (error != 0) 353 return (error); 354 355 wildcard = (unit < 0); 356 } 357 358 error = ifc_alloc_unit(ifc, &unit); 359 if (error != 0) 360 return (error); 361 362 /* In the wildcard case, we need to update the name. */ 363 if (wildcard) { 364 for (dp = name; *dp != '\0'; dp++); 365 if (snprintf(dp, len - (dp-name), "%d", unit) > 366 len - (dp-name) - 1) { 367 panic("%s: interface name too long", __func__); 368 } 369 } 370 371 ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO); 372 ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER); 373 if (ifp == NULL) { 374 ifc_free_unit(ifc, unit); 375 free(ifv, M_VLAN); 376 return (ENOSPC); 377 } 378 SLIST_INIT(&ifv->vlan_mc_listhead); 379 380 ifp->if_softc = ifv; 381 /* 382 * Set the name manually rather than using if_initname because 383 * we don't conform to the default naming convention for interfaces. 384 */ 385 strlcpy(ifp->if_xname, name, IFNAMSIZ); 386 ifp->if_dname = ifc->ifc_name; 387 ifp->if_dunit = unit; 388 /* NB: flags are not set here */ 389 ifp->if_linkmib = &ifv->ifv_mib; 390 ifp->if_linkmiblen = sizeof(ifv->ifv_mib); 391 /* NB: mtu is not set here */ 392 393 ifp->if_init = vlan_ifinit; 394 ifp->if_start = vlan_start; 395 ifp->if_ioctl = vlan_ioctl; 396 ifp->if_snd.ifq_maxlen = ifqmaxlen; 397 ether_ifattach(ifp, eaddr); 398 /* Now undo some of the damage... */ 399 ifp->if_baudrate = 0; 400 ifp->if_type = IFT_L2VLAN; 401 ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN; 402 403 VLAN_LOCK(); 404 LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list); 405 VLAN_UNLOCK(); 406 407 if (ethertag) { 408 VLAN_LOCK(); 409 error = vlan_config(ifv, p); 410 if (error != 0) { 411 /* 412 * Since we've partialy failed, we need to back 413 * out all the way, otherwise userland could get 414 * confused. Thus, we destroy the interface. 415 */ 416 LIST_REMOVE(ifv, ifv_list); 417 vlan_unconfig(ifp); 418 VLAN_UNLOCK(); 419 ether_ifdetach(ifp); 420 if_free_type(ifp, IFT_ETHER); 421 free(ifv, M_VLAN); 422 423 return (error); 424 } 425 ifv->ifv_tag = tag; 426 ifp->if_drv_flags |= IFF_DRV_RUNNING; 427 VLAN_UNLOCK(); 428 429 /* Update flags on the parent, if necessary. */ 430 vlan_setflags(ifp, 1); 431 } 432 433 return (0); 434 } 435 436 static int 437 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 438 { 439 int unit; 440 struct ifvlan *ifv = ifp->if_softc; 441 442 unit = ifp->if_dunit; 443 444 VLAN_LOCK(); 445 LIST_REMOVE(ifv, ifv_list); 446 vlan_unconfig(ifp); 447 VLAN_UNLOCK(); 448 449 ether_ifdetach(ifp); 450 if_free_type(ifp, IFT_ETHER); 451 452 free(ifv, M_VLAN); 453 454 ifc_free_unit(ifc, unit); 455 456 return (0); 457 } 458 459 /* 460 * The ifp->if_init entry point for vlan(4) is a no-op. 461 */ 462 static void 463 vlan_ifinit(void *foo) 464 { 465 466 } 467 468 static void 469 vlan_start(struct ifnet *ifp) 470 { 471 struct ifvlan *ifv; 472 struct ifnet *p; 473 struct ether_vlan_header *evl; 474 struct mbuf *m; 475 int error; 476 477 ifv = ifp->if_softc; 478 p = ifv->ifv_p; 479 480 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 481 for (;;) { 482 IF_DEQUEUE(&ifp->if_snd, m); 483 if (m == 0) 484 break; 485 BPF_MTAP(ifp, m); 486 487 /* 488 * Do not run parent's if_start() if the parent is not up, 489 * or parent's driver will cause a system crash. 490 */ 491 if (!((p->if_flags & IFF_UP) && 492 (p->if_drv_flags & IFF_DRV_RUNNING))) { 493 m_freem(m); 494 ifp->if_collisions++; 495 continue; 496 } 497 498 /* 499 * If underlying interface can do VLAN tag insertion itself, 500 * just pass the packet along. However, we need some way to 501 * tell the interface where the packet came from so that it 502 * knows how to find the VLAN tag to use, so we attach a 503 * packet tag that holds it. 504 */ 505 if (p->if_capenable & IFCAP_VLAN_HWTAGGING) { 506 struct m_tag *mtag = m_tag_alloc(MTAG_VLAN, 507 MTAG_VLAN_TAG, 508 sizeof(u_int), 509 M_NOWAIT); 510 if (mtag == NULL) { 511 ifp->if_oerrors++; 512 m_freem(m); 513 continue; 514 } 515 VLAN_TAG_VALUE(mtag) = ifv->ifv_tag; 516 m_tag_prepend(m, mtag); 517 m->m_flags |= M_VLANTAG; 518 } else { 519 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 520 if (m == NULL) { 521 if_printf(ifp, 522 "unable to prepend VLAN header\n"); 523 ifp->if_oerrors++; 524 continue; 525 } 526 /* M_PREPEND takes care of m_len, m_pkthdr.len for us */ 527 528 if (m->m_len < sizeof(*evl)) { 529 m = m_pullup(m, sizeof(*evl)); 530 if (m == NULL) { 531 if_printf(ifp, 532 "cannot pullup VLAN header\n"); 533 ifp->if_oerrors++; 534 continue; 535 } 536 } 537 538 /* 539 * Transform the Ethernet header into an Ethernet header 540 * with 802.1Q encapsulation. 541 */ 542 bcopy(mtod(m, char *) + ifv->ifv_encaplen, 543 mtod(m, char *), ETHER_HDR_LEN); 544 evl = mtod(m, struct ether_vlan_header *); 545 evl->evl_proto = evl->evl_encap_proto; 546 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 547 evl->evl_tag = htons(ifv->ifv_tag); 548 #ifdef DEBUG 549 printf("%s: %*D\n", __func__, (int)sizeof(*evl), 550 (unsigned char *)evl, ":"); 551 #endif 552 } 553 554 /* 555 * Send it, precisely as ether_output() would have. 556 * We are already running at splimp. 557 */ 558 IFQ_HANDOFF(p, m, error); 559 if (!error) 560 ifp->if_opackets++; 561 else 562 ifp->if_oerrors++; 563 } 564 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 565 } 566 567 static void 568 vlan_input(struct ifnet *ifp, struct mbuf *m) 569 { 570 struct ether_vlan_header *evl; 571 struct ifvlan *ifv; 572 struct m_tag *mtag; 573 u_int tag; 574 575 if (m->m_flags & M_VLANTAG) { 576 /* 577 * Packet is tagged, but m contains a normal 578 * Ethernet frame; the tag is stored out-of-band. 579 */ 580 mtag = m_tag_locate(m, MTAG_VLAN, MTAG_VLAN_TAG, NULL); 581 KASSERT(mtag != NULL, 582 ("%s: M_VLANTAG without m_tag", __func__)); 583 tag = EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag)); 584 m_tag_delete(m, mtag); 585 m->m_flags &= ~M_VLANTAG; 586 } else { 587 /* 588 * Packet is tagged in-band as specified by 802.1q. 589 */ 590 mtag = NULL; 591 switch (ifp->if_type) { 592 case IFT_ETHER: 593 if (m->m_len < sizeof(*evl) && 594 (m = m_pullup(m, sizeof(*evl))) == NULL) { 595 if_printf(ifp, "cannot pullup VLAN header\n"); 596 return; 597 } 598 evl = mtod(m, struct ether_vlan_header *); 599 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN, 600 ("%s: bad encapsulation protocol (%u)", 601 __func__, ntohs(evl->evl_encap_proto))); 602 603 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag)); 604 605 /* 606 * Restore the original ethertype. We'll remove 607 * the encapsulation after we've found the vlan 608 * interface corresponding to the tag. 609 */ 610 evl->evl_encap_proto = evl->evl_proto; 611 break; 612 default: 613 tag = (u_int) -1; 614 #ifdef INVARIANTS 615 panic("%s: unsupported if_type (%u)", 616 __func__, ifp->if_type); 617 #endif 618 break; 619 } 620 } 621 622 VLAN_LOCK(); 623 LIST_FOREACH(ifv, &ifv_list, ifv_list) 624 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 625 break; 626 627 if (ifv == NULL || (ifv->ifv_ifp->if_flags & IFF_UP) == 0) { 628 VLAN_UNLOCK(); 629 m_freem(m); 630 ifp->if_noproto++; 631 #ifdef DEBUG 632 printf("%s: tag %d, no interface\n", __func__, tag); 633 #endif 634 return; 635 } 636 VLAN_UNLOCK(); /* XXX extend below? */ 637 #ifdef DEBUG 638 printf("%s: tag %d, parent %s\n", __func__, tag, ifv->ifv_p->if_xname); 639 #endif 640 641 if (mtag == NULL) { 642 /* 643 * Packet had an in-line encapsulation header; 644 * remove it. The original header has already 645 * been fixed up above. 646 */ 647 bcopy(mtod(m, caddr_t), 648 mtod(m, caddr_t) + ETHER_VLAN_ENCAP_LEN, 649 ETHER_HDR_LEN); 650 m_adj(m, ETHER_VLAN_ENCAP_LEN); 651 } 652 653 m->m_pkthdr.rcvif = ifv->ifv_ifp; 654 ifv->ifv_ifp->if_ipackets++; 655 656 /* Pass it back through the parent's input routine. */ 657 (*ifp->if_input)(ifv->ifv_ifp, m); 658 } 659 660 static int 661 vlan_config(struct ifvlan *ifv, struct ifnet *p) 662 { 663 struct ifaddr *ifa1, *ifa2; 664 struct ifnet *ifp; 665 struct sockaddr_dl *sdl1, *sdl2; 666 667 VLAN_LOCK_ASSERT(); 668 669 if (p->if_type != IFT_ETHER) 670 return (EPROTONOSUPPORT); 671 if (ifv->ifv_p) 672 return (EBUSY); 673 674 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 675 ifv->ifv_mintu = ETHERMIN; 676 ifv->ifv_pflags = 0; 677 678 /* 679 * The active VLAN counter on the parent is used 680 * at various places to see if there is a vlan(4) 681 * attached to this physical interface. 682 */ 683 p->if_nvlans++; 684 685 /* 686 * If the parent supports the VLAN_MTU capability, 687 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, 688 * use it. 689 */ 690 if (p->if_capenable & IFCAP_VLAN_MTU) { 691 /* 692 * No need to fudge the MTU since the parent can 693 * handle extended frames. 694 */ 695 ifv->ifv_mtufudge = 0; 696 } else { 697 /* 698 * Fudge the MTU by the encapsulation size. This 699 * makes us incompatible with strictly compliant 700 * 802.1Q implementations, but allows us to use 701 * the feature with other NetBSD implementations, 702 * which might still be useful. 703 */ 704 ifv->ifv_mtufudge = ifv->ifv_encaplen; 705 } 706 707 ifv->ifv_p = p; 708 ifp = ifv->ifv_ifp; 709 ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge; 710 /* 711 * Copy only a selected subset of flags from the parent. 712 * Other flags are none of our business. 713 */ 714 #define VLAN_COPY_FLAGS \ 715 (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT) 716 ifp->if_flags &= ~VLAN_COPY_FLAGS; 717 ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS; 718 #undef VLAN_COPY_FLAGS 719 720 ifp->if_link_state = p->if_link_state; 721 722 #if 0 723 /* 724 * Not ready yet. We need notification from the parent 725 * when hw checksumming flags in its if_capenable change. 726 * Flags set in if_capabilities only are useless. 727 */ 728 /* 729 * If the parent interface can do hardware-assisted 730 * VLAN encapsulation, then propagate its hardware- 731 * assisted checksumming flags. 732 */ 733 if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) 734 ifp->if_capabilities |= p->if_capabilities & IFCAP_HWCSUM; 735 #endif 736 737 /* 738 * Set up our ``Ethernet address'' to reflect the underlying 739 * physical interface's. 740 */ 741 ifa1 = ifaddr_byindex(ifp->if_index); 742 ifa2 = ifaddr_byindex(p->if_index); 743 sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr; 744 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr; 745 sdl1->sdl_type = IFT_ETHER; 746 sdl1->sdl_alen = ETHER_ADDR_LEN; 747 bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN); 748 bcopy(LLADDR(sdl2), IFP2ENADDR(ifp), ETHER_ADDR_LEN); 749 750 /* 751 * Configure multicast addresses that may already be 752 * joined on the vlan device. 753 */ 754 (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */ 755 756 return (0); 757 } 758 759 static int 760 vlan_unconfig(struct ifnet *ifp) 761 { 762 struct ifaddr *ifa; 763 struct sockaddr_dl *sdl; 764 struct vlan_mc_entry *mc; 765 struct ifvlan *ifv; 766 struct ifnet *p; 767 int error; 768 769 VLAN_LOCK_ASSERT(); 770 771 ifv = ifp->if_softc; 772 p = ifv->ifv_p; 773 774 if (p) { 775 struct sockaddr_dl sdl; 776 777 /* 778 * Since the interface is being unconfigured, we need to 779 * empty the list of multicast groups that we may have joined 780 * while we were alive from the parent's list. 781 */ 782 bzero((char *)&sdl, sizeof(sdl)); 783 sdl.sdl_len = sizeof(sdl); 784 sdl.sdl_family = AF_LINK; 785 sdl.sdl_index = p->if_index; 786 sdl.sdl_type = IFT_ETHER; 787 sdl.sdl_alen = ETHER_ADDR_LEN; 788 789 while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) { 790 mc = SLIST_FIRST(&ifv->vlan_mc_listhead); 791 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), 792 ETHER_ADDR_LEN); 793 error = if_delmulti(p, (struct sockaddr *)&sdl); 794 if (error) 795 return (error); 796 SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); 797 free(mc, M_VLAN); 798 } 799 800 vlan_setflags(ifp, 0); /* clear special flags on parent */ 801 p->if_nvlans--; 802 } 803 804 /* Disconnect from parent. */ 805 if (ifv->ifv_pflags) 806 if_printf(ifp, "%s: ifv_pflags unclean\n", __func__); 807 ifv->ifv_p = NULL; 808 ifv->ifv_ifp->if_mtu = ETHERMTU; /* XXX why not 0? */ 809 ifv->ifv_ifp->if_link_state = LINK_STATE_UNKNOWN; 810 811 /* Clear our MAC address. */ 812 ifa = ifaddr_byindex(ifv->ifv_ifp->if_index); 813 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 814 sdl->sdl_type = IFT_ETHER; 815 sdl->sdl_alen = ETHER_ADDR_LEN; 816 bzero(LLADDR(sdl), ETHER_ADDR_LEN); 817 bzero(IFP2ENADDR(ifv->ifv_ifp), ETHER_ADDR_LEN); 818 819 return (0); 820 } 821 822 /* Handle a reference counted flag that should be set on the parent as well */ 823 static int 824 vlan_setflag(struct ifnet *ifp, int flag, int status, 825 int (*func)(struct ifnet *, int)) 826 { 827 struct ifvlan *ifv; 828 int error; 829 830 /* XXX VLAN_LOCK_ASSERT(); */ 831 832 ifv = ifp->if_softc; 833 status = status ? (ifp->if_flags & flag) : 0; 834 /* Now "status" contains the flag value or 0 */ 835 836 /* 837 * See if recorded parent's status is different from what 838 * we want it to be. If it is, flip it. We record parent's 839 * status in ifv_pflags so that we won't clear parent's flag 840 * we haven't set. In fact, we don't clear or set parent's 841 * flags directly, but get or release references to them. 842 * That's why we can be sure that recorded flags still are 843 * in accord with actual parent's flags. 844 */ 845 if (status != (ifv->ifv_pflags & flag)) { 846 error = (*func)(ifv->ifv_p, status); 847 if (error) 848 return (error); 849 ifv->ifv_pflags &= ~flag; 850 ifv->ifv_pflags |= status; 851 } 852 return (0); 853 } 854 855 /* 856 * Handle IFF_* flags that require certain changes on the parent: 857 * if "status" is true, update parent's flags respective to our if_flags; 858 * if "status" is false, forcedly clear the flags set on parent. 859 */ 860 static int 861 vlan_setflags(struct ifnet *ifp, int status) 862 { 863 int error, i; 864 865 for (i = 0; vlan_pflags[i].flag; i++) { 866 error = vlan_setflag(ifp, vlan_pflags[i].flag, 867 status, vlan_pflags[i].func); 868 if (error) 869 return (error); 870 } 871 return (0); 872 } 873 874 /* Inform all vlans that their parent has changed link state */ 875 static void 876 vlan_link_state(struct ifnet *ifp, int link) 877 { 878 struct ifvlan *ifv; 879 880 VLAN_LOCK(); 881 LIST_FOREACH(ifv, &ifv_list, ifv_list) { 882 if (ifv->ifv_p == ifp) 883 if_link_state_change(ifv->ifv_ifp, 884 ifv->ifv_p->if_link_state); 885 } 886 VLAN_UNLOCK(); 887 } 888 889 static int 890 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 891 { 892 struct ifaddr *ifa; 893 struct ifnet *p; 894 struct ifreq *ifr; 895 struct ifvlan *ifv; 896 struct vlanreq vlr; 897 int error = 0; 898 899 ifr = (struct ifreq *)data; 900 ifa = (struct ifaddr *)data; 901 ifv = ifp->if_softc; 902 903 switch (cmd) { 904 case SIOCSIFADDR: 905 ifp->if_flags |= IFF_UP; 906 907 switch (ifa->ifa_addr->sa_family) { 908 #ifdef INET 909 case AF_INET: 910 arp_ifinit(ifv->ifv_ifp, ifa); 911 break; 912 #endif 913 default: 914 break; 915 } 916 break; 917 918 case SIOCGIFADDR: 919 { 920 struct sockaddr *sa; 921 922 sa = (struct sockaddr *) &ifr->ifr_data; 923 bcopy(IFP2ENADDR(ifp), (caddr_t)sa->sa_data, 924 ETHER_ADDR_LEN); 925 } 926 break; 927 928 case SIOCGIFMEDIA: 929 VLAN_LOCK(); 930 if (ifv->ifv_p != NULL) { 931 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, 932 SIOCGIFMEDIA, data); 933 VLAN_UNLOCK(); 934 /* Limit the result to the parent's current config. */ 935 if (error == 0) { 936 struct ifmediareq *ifmr; 937 938 ifmr = (struct ifmediareq *)data; 939 if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) { 940 ifmr->ifm_count = 1; 941 error = copyout(&ifmr->ifm_current, 942 ifmr->ifm_ulist, 943 sizeof(int)); 944 } 945 } 946 } else { 947 VLAN_UNLOCK(); 948 error = EINVAL; 949 } 950 break; 951 952 case SIOCSIFMEDIA: 953 error = EINVAL; 954 break; 955 956 case SIOCSIFMTU: 957 /* 958 * Set the interface MTU. 959 */ 960 VLAN_LOCK(); 961 if (ifv->ifv_p != NULL) { 962 if (ifr->ifr_mtu > 963 (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) || 964 ifr->ifr_mtu < 965 (ifv->ifv_mintu - ifv->ifv_mtufudge)) 966 error = EINVAL; 967 else 968 ifp->if_mtu = ifr->ifr_mtu; 969 } else 970 error = EINVAL; 971 VLAN_UNLOCK(); 972 break; 973 974 case SIOCSETVLAN: 975 error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); 976 if (error) 977 break; 978 if (vlr.vlr_parent[0] == '\0') { 979 VLAN_LOCK(); 980 vlan_unconfig(ifp); 981 if (ifp->if_flags & IFF_UP) 982 if_down(ifp); 983 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 984 VLAN_UNLOCK(); 985 break; 986 } 987 p = ifunit(vlr.vlr_parent); 988 if (p == 0) { 989 error = ENOENT; 990 break; 991 } 992 /* 993 * Don't let the caller set up a VLAN tag with 994 * anything except VLID bits. 995 */ 996 if (vlr.vlr_tag & ~EVL_VLID_MASK) { 997 error = EINVAL; 998 break; 999 } 1000 VLAN_LOCK(); 1001 error = vlan_config(ifv, p); 1002 if (error) { 1003 VLAN_UNLOCK(); 1004 break; 1005 } 1006 ifv->ifv_tag = vlr.vlr_tag; 1007 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1008 VLAN_UNLOCK(); 1009 1010 /* Update flags on the parent, if necessary. */ 1011 vlan_setflags(ifp, 1); 1012 break; 1013 1014 case SIOCGETVLAN: 1015 bzero(&vlr, sizeof(vlr)); 1016 VLAN_LOCK(); 1017 if (ifv->ifv_p) { 1018 strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname, 1019 sizeof(vlr.vlr_parent)); 1020 vlr.vlr_tag = ifv->ifv_tag; 1021 } 1022 VLAN_UNLOCK(); 1023 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr)); 1024 break; 1025 1026 case SIOCSIFFLAGS: 1027 /* 1028 * We should propagate selected flags to the parent, 1029 * e.g., promiscuous mode. 1030 */ 1031 if (ifv->ifv_p != NULL) 1032 error = vlan_setflags(ifp, 1); 1033 break; 1034 1035 case SIOCADDMULTI: 1036 case SIOCDELMULTI: 1037 /*VLAN_LOCK();*/ 1038 error = vlan_setmulti(ifp); 1039 /*VLAN_UNLOCK();*/ 1040 break; 1041 default: 1042 error = EINVAL; 1043 } 1044 1045 return (error); 1046 } 1047