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 VLAN_LOCK_DESTROY(); 255 break; 256 default: 257 return (EOPNOTSUPP); 258 } 259 return (0); 260 } 261 262 static moduledata_t vlan_mod = { 263 "if_vlan", 264 vlan_modevent, 265 0 266 }; 267 268 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 269 MODULE_DEPEND(if_vlan, miibus, 1, 1, 1); 270 271 static struct ifnet * 272 vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag) 273 { 274 const char *cp; 275 struct ifnet *ifp; 276 int t = 0; 277 278 /* Check for <etherif>.<vlan> style interface names. */ 279 IFNET_RLOCK(); 280 TAILQ_FOREACH(ifp, &ifnet, if_link) { 281 if (ifp->if_type != IFT_ETHER) 282 continue; 283 if (strncmp(ifp->if_xname, name, strlen(ifp->if_xname)) != 0) 284 continue; 285 cp = name + strlen(ifp->if_xname); 286 if (*cp != '.') 287 continue; 288 for(; *cp != '\0'; cp++) { 289 if (*cp < '0' || *cp > '9') 290 continue; 291 t = (t * 10) + (*cp - '0'); 292 } 293 if (tag != NULL) 294 *tag = t; 295 break; 296 } 297 IFNET_RUNLOCK(); 298 299 return (ifp); 300 } 301 302 static int 303 vlan_clone_match(struct if_clone *ifc, const char *name) 304 { 305 const char *cp; 306 307 if (vlan_clone_match_ethertag(ifc, name, NULL) != NULL) 308 return (1); 309 310 if (strncmp(VLANNAME, name, strlen(VLANNAME)) != 0) 311 return (0); 312 for (cp = name + 4; *cp != '\0'; cp++) { 313 if (*cp < '0' || *cp > '9') 314 return (0); 315 } 316 317 return (1); 318 } 319 320 static int 321 vlan_clone_create(struct if_clone *ifc, char *name, size_t len) 322 { 323 char *dp; 324 int wildcard; 325 int unit; 326 int error; 327 int tag; 328 int ethertag; 329 struct ifvlan *ifv; 330 struct ifnet *ifp; 331 struct ifnet *p; 332 u_char eaddr[6] = {0,0,0,0,0,0}; 333 334 if ((p = vlan_clone_match_ethertag(ifc, name, &tag)) != NULL) { 335 ethertag = 1; 336 unit = -1; 337 wildcard = 0; 338 339 /* 340 * Don't let the caller set up a VLAN tag with 341 * anything except VLID bits. 342 */ 343 if (tag & ~EVL_VLID_MASK) 344 return (EINVAL); 345 } else { 346 ethertag = 0; 347 348 error = ifc_name2unit(name, &unit); 349 if (error != 0) 350 return (error); 351 352 wildcard = (unit < 0); 353 } 354 355 error = ifc_alloc_unit(ifc, &unit); 356 if (error != 0) 357 return (error); 358 359 /* In the wildcard case, we need to update the name. */ 360 if (wildcard) { 361 for (dp = name; *dp != '\0'; dp++); 362 if (snprintf(dp, len - (dp-name), "%d", unit) > 363 len - (dp-name) - 1) { 364 panic("%s: interface name too long", __func__); 365 } 366 } 367 368 ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO); 369 ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER); 370 if (ifp == NULL) { 371 ifc_free_unit(ifc, unit); 372 free(ifv, M_VLAN); 373 return (ENOSPC); 374 } 375 SLIST_INIT(&ifv->vlan_mc_listhead); 376 377 ifp->if_softc = ifv; 378 /* 379 * Set the name manually rather than using if_initname because 380 * we don't conform to the default naming convention for interfaces. 381 */ 382 strlcpy(ifp->if_xname, name, IFNAMSIZ); 383 ifp->if_dname = ifc->ifc_name; 384 ifp->if_dunit = unit; 385 /* NB: flags are not set here */ 386 ifp->if_linkmib = &ifv->ifv_mib; 387 ifp->if_linkmiblen = sizeof(ifv->ifv_mib); 388 /* NB: mtu is not set here */ 389 390 ifp->if_init = vlan_ifinit; 391 ifp->if_start = vlan_start; 392 ifp->if_ioctl = vlan_ioctl; 393 ifp->if_snd.ifq_maxlen = ifqmaxlen; 394 ether_ifattach(ifp, eaddr); 395 /* Now undo some of the damage... */ 396 ifp->if_baudrate = 0; 397 ifp->if_type = IFT_L2VLAN; 398 ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN; 399 400 VLAN_LOCK(); 401 LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list); 402 VLAN_UNLOCK(); 403 404 if (ethertag) { 405 VLAN_LOCK(); 406 error = vlan_config(ifv, p); 407 if (error != 0) { 408 /* 409 * Since we've partialy failed, we need to back 410 * out all the way, otherwise userland could get 411 * confused. Thus, we destroy the interface. 412 */ 413 LIST_REMOVE(ifv, ifv_list); 414 vlan_unconfig(ifp); 415 VLAN_UNLOCK(); 416 ether_ifdetach(ifp); 417 if_free_type(ifp, IFT_ETHER); 418 free(ifv, M_VLAN); 419 420 return (error); 421 } 422 ifv->ifv_tag = tag; 423 ifp->if_drv_flags |= IFF_DRV_RUNNING; 424 VLAN_UNLOCK(); 425 426 /* Update flags on the parent, if necessary. */ 427 vlan_setflags(ifp, 1); 428 } 429 430 return (0); 431 } 432 433 static int 434 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 435 { 436 int unit; 437 struct ifvlan *ifv = ifp->if_softc; 438 439 unit = ifp->if_dunit; 440 441 VLAN_LOCK(); 442 LIST_REMOVE(ifv, ifv_list); 443 vlan_unconfig(ifp); 444 VLAN_UNLOCK(); 445 446 ether_ifdetach(ifp); 447 if_free_type(ifp, IFT_ETHER); 448 449 free(ifv, M_VLAN); 450 451 ifc_free_unit(ifc, unit); 452 453 return (0); 454 } 455 456 /* 457 * The ifp->if_init entry point for vlan(4) is a no-op. 458 */ 459 static void 460 vlan_ifinit(void *foo) 461 { 462 463 } 464 465 /* 466 * The if_start method for vlan(4) interface. It doesn't 467 * raises the IFF_DRV_OACTIVE flag, since it is called 468 * only from IFQ_HANDOFF() macro in ether_output_frame(). 469 * If the interface queue is full, and vlan_start() is 470 * not called, the queue would never get emptied and 471 * interface would stall forever. 472 */ 473 static void 474 vlan_start(struct ifnet *ifp) 475 { 476 struct ifvlan *ifv; 477 struct ifnet *p; 478 struct ether_vlan_header *evl; 479 struct mbuf *m; 480 int error; 481 482 ifv = ifp->if_softc; 483 p = ifv->ifv_p; 484 485 for (;;) { 486 IF_DEQUEUE(&ifp->if_snd, m); 487 if (m == 0) 488 break; 489 BPF_MTAP(ifp, m); 490 491 /* 492 * Do not run parent's if_start() if the parent is not up, 493 * or parent's driver will cause a system crash. 494 */ 495 if (!((p->if_flags & IFF_UP) && 496 (p->if_drv_flags & IFF_DRV_RUNNING))) { 497 m_freem(m); 498 ifp->if_collisions++; 499 continue; 500 } 501 502 /* 503 * If underlying interface can do VLAN tag insertion itself, 504 * just pass the packet along. However, we need some way to 505 * tell the interface where the packet came from so that it 506 * knows how to find the VLAN tag to use, so we attach a 507 * packet tag that holds it. 508 */ 509 if (p->if_capenable & IFCAP_VLAN_HWTAGGING) { 510 struct m_tag *mtag = m_tag_alloc(MTAG_VLAN, 511 MTAG_VLAN_TAG, 512 sizeof(u_int), 513 M_NOWAIT); 514 if (mtag == NULL) { 515 ifp->if_oerrors++; 516 m_freem(m); 517 continue; 518 } 519 VLAN_TAG_VALUE(mtag) = ifv->ifv_tag; 520 m_tag_prepend(m, mtag); 521 m->m_flags |= M_VLANTAG; 522 } else { 523 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 524 if (m == NULL) { 525 if_printf(ifp, 526 "unable to prepend VLAN header\n"); 527 ifp->if_oerrors++; 528 continue; 529 } 530 /* M_PREPEND takes care of m_len, m_pkthdr.len for us */ 531 532 if (m->m_len < sizeof(*evl)) { 533 m = m_pullup(m, sizeof(*evl)); 534 if (m == NULL) { 535 if_printf(ifp, 536 "cannot pullup VLAN header\n"); 537 ifp->if_oerrors++; 538 continue; 539 } 540 } 541 542 /* 543 * Transform the Ethernet header into an Ethernet header 544 * with 802.1Q encapsulation. 545 */ 546 bcopy(mtod(m, char *) + ifv->ifv_encaplen, 547 mtod(m, char *), ETHER_HDR_LEN); 548 evl = mtod(m, struct ether_vlan_header *); 549 evl->evl_proto = evl->evl_encap_proto; 550 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 551 evl->evl_tag = htons(ifv->ifv_tag); 552 #ifdef DEBUG 553 printf("%s: %*D\n", __func__, (int)sizeof(*evl), 554 (unsigned char *)evl, ":"); 555 #endif 556 } 557 558 /* 559 * Send it, precisely as ether_output() would have. 560 * We are already running at splimp. 561 */ 562 IFQ_HANDOFF(p, m, error); 563 if (!error) 564 ifp->if_opackets++; 565 else 566 ifp->if_oerrors++; 567 } 568 } 569 570 static void 571 vlan_input(struct ifnet *ifp, struct mbuf *m) 572 { 573 struct ether_vlan_header *evl; 574 struct ifvlan *ifv; 575 struct m_tag *mtag; 576 u_int tag; 577 578 if (m->m_flags & M_VLANTAG) { 579 /* 580 * Packet is tagged, but m contains a normal 581 * Ethernet frame; the tag is stored out-of-band. 582 */ 583 mtag = m_tag_locate(m, MTAG_VLAN, MTAG_VLAN_TAG, NULL); 584 KASSERT(mtag != NULL, 585 ("%s: M_VLANTAG without m_tag", __func__)); 586 tag = EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag)); 587 m_tag_delete(m, mtag); 588 m->m_flags &= ~M_VLANTAG; 589 } else { 590 /* 591 * Packet is tagged in-band as specified by 802.1q. 592 */ 593 mtag = NULL; 594 switch (ifp->if_type) { 595 case IFT_ETHER: 596 if (m->m_len < sizeof(*evl) && 597 (m = m_pullup(m, sizeof(*evl))) == NULL) { 598 if_printf(ifp, "cannot pullup VLAN header\n"); 599 return; 600 } 601 evl = mtod(m, struct ether_vlan_header *); 602 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN, 603 ("%s: bad encapsulation protocol (%u)", 604 __func__, ntohs(evl->evl_encap_proto))); 605 606 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag)); 607 608 /* 609 * Restore the original ethertype. We'll remove 610 * the encapsulation after we've found the vlan 611 * interface corresponding to the tag. 612 */ 613 evl->evl_encap_proto = evl->evl_proto; 614 break; 615 default: 616 tag = (u_int) -1; 617 #ifdef INVARIANTS 618 panic("%s: unsupported if_type (%u)", 619 __func__, ifp->if_type); 620 #endif 621 break; 622 } 623 } 624 625 VLAN_LOCK(); 626 LIST_FOREACH(ifv, &ifv_list, ifv_list) 627 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 628 break; 629 630 if (ifv == NULL || (ifv->ifv_ifp->if_flags & IFF_UP) == 0) { 631 VLAN_UNLOCK(); 632 m_freem(m); 633 ifp->if_noproto++; 634 #ifdef DEBUG 635 printf("%s: tag %d, no interface\n", __func__, tag); 636 #endif 637 return; 638 } 639 VLAN_UNLOCK(); /* XXX extend below? */ 640 #ifdef DEBUG 641 printf("%s: tag %d, parent %s\n", __func__, tag, ifv->ifv_p->if_xname); 642 #endif 643 644 if (mtag == NULL) { 645 /* 646 * Packet had an in-line encapsulation header; 647 * remove it. The original header has already 648 * been fixed up above. 649 */ 650 bcopy(mtod(m, caddr_t), 651 mtod(m, caddr_t) + ETHER_VLAN_ENCAP_LEN, 652 ETHER_HDR_LEN); 653 m_adj(m, ETHER_VLAN_ENCAP_LEN); 654 } 655 656 m->m_pkthdr.rcvif = ifv->ifv_ifp; 657 ifv->ifv_ifp->if_ipackets++; 658 659 /* Pass it back through the parent's input routine. */ 660 (*ifp->if_input)(ifv->ifv_ifp, m); 661 } 662 663 static int 664 vlan_config(struct ifvlan *ifv, struct ifnet *p) 665 { 666 struct ifnet *ifp; 667 668 VLAN_LOCK_ASSERT(); 669 670 if (p->if_type != IFT_ETHER) 671 return (EPROTONOSUPPORT); 672 if (ifv->ifv_p) 673 return (EBUSY); 674 675 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 676 ifv->ifv_mintu = ETHERMIN; 677 ifv->ifv_pflags = 0; 678 679 /* 680 * The active VLAN counter on the parent is used 681 * at various places to see if there is a vlan(4) 682 * attached to this physical interface. 683 */ 684 p->if_nvlans++; 685 686 /* 687 * If the parent supports the VLAN_MTU capability, 688 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, 689 * use it. 690 */ 691 if (p->if_capenable & IFCAP_VLAN_MTU) { 692 /* 693 * No need to fudge the MTU since the parent can 694 * handle extended frames. 695 */ 696 ifv->ifv_mtufudge = 0; 697 } else { 698 /* 699 * Fudge the MTU by the encapsulation size. This 700 * makes us incompatible with strictly compliant 701 * 802.1Q implementations, but allows us to use 702 * the feature with other NetBSD implementations, 703 * which might still be useful. 704 */ 705 ifv->ifv_mtufudge = ifv->ifv_encaplen; 706 } 707 708 ifv->ifv_p = p; 709 ifp = ifv->ifv_ifp; 710 ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge; 711 ifv->ifv_ifp->if_baudrate = p->if_baudrate; 712 /* 713 * Copy only a selected subset of flags from the parent. 714 * Other flags are none of our business. 715 */ 716 #define VLAN_COPY_FLAGS \ 717 (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT) 718 ifp->if_flags &= ~VLAN_COPY_FLAGS; 719 ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS; 720 #undef VLAN_COPY_FLAGS 721 722 ifp->if_link_state = p->if_link_state; 723 724 #if 0 725 /* 726 * Not ready yet. We need notification from the parent 727 * when hw checksumming flags in its if_capenable change. 728 * Flags set in if_capabilities only are useless. 729 */ 730 /* 731 * If the parent interface can do hardware-assisted 732 * VLAN encapsulation, then propagate its hardware- 733 * assisted checksumming flags. 734 */ 735 if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) 736 ifp->if_capabilities |= p->if_capabilities & IFCAP_HWCSUM; 737 #endif 738 739 /* 740 * Set up our ``Ethernet address'' to reflect the underlying 741 * physical interface's. 742 */ 743 bcopy(IF_LLADDR(p), IF_LLADDR(ifp), ETHER_ADDR_LEN); 744 745 /* 746 * Configure multicast addresses that may already be 747 * joined on the vlan device. 748 */ 749 (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */ 750 751 return (0); 752 } 753 754 static int 755 vlan_unconfig(struct ifnet *ifp) 756 { 757 struct vlan_mc_entry *mc; 758 struct ifvlan *ifv; 759 struct ifnet *p; 760 int error; 761 762 VLAN_LOCK_ASSERT(); 763 764 ifv = ifp->if_softc; 765 p = ifv->ifv_p; 766 767 if (p) { 768 struct sockaddr_dl sdl; 769 770 /* 771 * Since the interface is being unconfigured, we need to 772 * empty the list of multicast groups that we may have joined 773 * while we were alive from the parent's list. 774 */ 775 bzero((char *)&sdl, sizeof(sdl)); 776 sdl.sdl_len = sizeof(sdl); 777 sdl.sdl_family = AF_LINK; 778 sdl.sdl_index = p->if_index; 779 sdl.sdl_type = IFT_ETHER; 780 sdl.sdl_alen = ETHER_ADDR_LEN; 781 782 while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) { 783 mc = SLIST_FIRST(&ifv->vlan_mc_listhead); 784 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), 785 ETHER_ADDR_LEN); 786 error = if_delmulti(p, (struct sockaddr *)&sdl); 787 if (error) 788 return (error); 789 SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); 790 free(mc, M_VLAN); 791 } 792 793 vlan_setflags(ifp, 0); /* clear special flags on parent */ 794 p->if_nvlans--; 795 } 796 797 /* Disconnect from parent. */ 798 if (ifv->ifv_pflags) 799 if_printf(ifp, "%s: ifv_pflags unclean\n", __func__); 800 ifv->ifv_p = NULL; 801 ifv->ifv_ifp->if_mtu = ETHERMTU; /* XXX why not 0? */ 802 ifv->ifv_ifp->if_link_state = LINK_STATE_UNKNOWN; 803 804 /* Clear our MAC address. */ 805 bzero(IF_LLADDR(ifv->ifv_ifp), ETHER_ADDR_LEN); 806 807 return (0); 808 } 809 810 /* Handle a reference counted flag that should be set on the parent as well */ 811 static int 812 vlan_setflag(struct ifnet *ifp, int flag, int status, 813 int (*func)(struct ifnet *, int)) 814 { 815 struct ifvlan *ifv; 816 int error; 817 818 /* XXX VLAN_LOCK_ASSERT(); */ 819 820 ifv = ifp->if_softc; 821 status = status ? (ifp->if_flags & flag) : 0; 822 /* Now "status" contains the flag value or 0 */ 823 824 /* 825 * See if recorded parent's status is different from what 826 * we want it to be. If it is, flip it. We record parent's 827 * status in ifv_pflags so that we won't clear parent's flag 828 * we haven't set. In fact, we don't clear or set parent's 829 * flags directly, but get or release references to them. 830 * That's why we can be sure that recorded flags still are 831 * in accord with actual parent's flags. 832 */ 833 if (status != (ifv->ifv_pflags & flag)) { 834 error = (*func)(ifv->ifv_p, status); 835 if (error) 836 return (error); 837 ifv->ifv_pflags &= ~flag; 838 ifv->ifv_pflags |= status; 839 } 840 return (0); 841 } 842 843 /* 844 * Handle IFF_* flags that require certain changes on the parent: 845 * if "status" is true, update parent's flags respective to our if_flags; 846 * if "status" is false, forcedly clear the flags set on parent. 847 */ 848 static int 849 vlan_setflags(struct ifnet *ifp, int status) 850 { 851 int error, i; 852 853 for (i = 0; vlan_pflags[i].flag; i++) { 854 error = vlan_setflag(ifp, vlan_pflags[i].flag, 855 status, vlan_pflags[i].func); 856 if (error) 857 return (error); 858 } 859 return (0); 860 } 861 862 /* Inform all vlans that their parent has changed link state */ 863 static void 864 vlan_link_state(struct ifnet *ifp, int link) 865 { 866 struct ifvlan *ifv; 867 868 VLAN_LOCK(); 869 LIST_FOREACH(ifv, &ifv_list, ifv_list) { 870 if (ifv->ifv_p == ifp) 871 if_link_state_change(ifv->ifv_ifp, 872 ifv->ifv_p->if_link_state); 873 } 874 VLAN_UNLOCK(); 875 } 876 877 static int 878 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 879 { 880 struct ifaddr *ifa; 881 struct ifnet *p; 882 struct ifreq *ifr; 883 struct ifvlan *ifv; 884 struct vlanreq vlr; 885 int error = 0; 886 887 ifr = (struct ifreq *)data; 888 ifa = (struct ifaddr *)data; 889 ifv = ifp->if_softc; 890 891 switch (cmd) { 892 case SIOCSIFADDR: 893 ifp->if_flags |= IFF_UP; 894 895 switch (ifa->ifa_addr->sa_family) { 896 #ifdef INET 897 case AF_INET: 898 arp_ifinit(ifv->ifv_ifp, ifa); 899 break; 900 #endif 901 default: 902 break; 903 } 904 break; 905 906 case SIOCGIFADDR: 907 { 908 struct sockaddr *sa; 909 910 sa = (struct sockaddr *) &ifr->ifr_data; 911 bcopy(IF_LLADDR(ifp), (caddr_t)sa->sa_data, 912 ETHER_ADDR_LEN); 913 } 914 break; 915 916 case SIOCGIFMEDIA: 917 VLAN_LOCK(); 918 if (ifv->ifv_p != NULL) { 919 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, 920 SIOCGIFMEDIA, data); 921 VLAN_UNLOCK(); 922 /* Limit the result to the parent's current config. */ 923 if (error == 0) { 924 struct ifmediareq *ifmr; 925 926 ifmr = (struct ifmediareq *)data; 927 if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) { 928 ifmr->ifm_count = 1; 929 error = copyout(&ifmr->ifm_current, 930 ifmr->ifm_ulist, 931 sizeof(int)); 932 } 933 } 934 } else { 935 VLAN_UNLOCK(); 936 error = EINVAL; 937 } 938 break; 939 940 case SIOCSIFMEDIA: 941 error = EINVAL; 942 break; 943 944 case SIOCSIFMTU: 945 /* 946 * Set the interface MTU. 947 */ 948 VLAN_LOCK(); 949 if (ifv->ifv_p != NULL) { 950 if (ifr->ifr_mtu > 951 (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) || 952 ifr->ifr_mtu < 953 (ifv->ifv_mintu - ifv->ifv_mtufudge)) 954 error = EINVAL; 955 else 956 ifp->if_mtu = ifr->ifr_mtu; 957 } else 958 error = EINVAL; 959 VLAN_UNLOCK(); 960 break; 961 962 case SIOCSETVLAN: 963 error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); 964 if (error) 965 break; 966 if (vlr.vlr_parent[0] == '\0') { 967 VLAN_LOCK(); 968 vlan_unconfig(ifp); 969 if (ifp->if_flags & IFF_UP) 970 if_down(ifp); 971 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 972 VLAN_UNLOCK(); 973 break; 974 } 975 p = ifunit(vlr.vlr_parent); 976 if (p == 0) { 977 error = ENOENT; 978 break; 979 } 980 /* 981 * Don't let the caller set up a VLAN tag with 982 * anything except VLID bits. 983 */ 984 if (vlr.vlr_tag & ~EVL_VLID_MASK) { 985 error = EINVAL; 986 break; 987 } 988 VLAN_LOCK(); 989 error = vlan_config(ifv, p); 990 if (error) { 991 VLAN_UNLOCK(); 992 break; 993 } 994 ifv->ifv_tag = vlr.vlr_tag; 995 ifp->if_drv_flags |= IFF_DRV_RUNNING; 996 VLAN_UNLOCK(); 997 998 /* Update flags on the parent, if necessary. */ 999 vlan_setflags(ifp, 1); 1000 break; 1001 1002 case SIOCGETVLAN: 1003 bzero(&vlr, sizeof(vlr)); 1004 VLAN_LOCK(); 1005 if (ifv->ifv_p) { 1006 strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname, 1007 sizeof(vlr.vlr_parent)); 1008 vlr.vlr_tag = ifv->ifv_tag; 1009 } 1010 VLAN_UNLOCK(); 1011 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr)); 1012 break; 1013 1014 case SIOCSIFFLAGS: 1015 /* 1016 * We should propagate selected flags to the parent, 1017 * e.g., promiscuous mode. 1018 */ 1019 if (ifv->ifv_p != NULL) 1020 error = vlan_setflags(ifp, 1); 1021 break; 1022 1023 case SIOCADDMULTI: 1024 case SIOCDELMULTI: 1025 /*VLAN_LOCK();*/ 1026 error = vlan_setmulti(ifp); 1027 /*VLAN_UNLOCK();*/ 1028 break; 1029 default: 1030 error = EINVAL; 1031 } 1032 1033 return (error); 1034 } 1035