if_vlan.c revision 152139
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: head/sys/net/if_vlan.c 152139 2005-11-06 19:43:04Z glebius $ 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 73struct vlan_mc_entry { 74 struct ether_addr mc_addr; 75 SLIST_ENTRY(vlan_mc_entry) mc_entries; 76}; 77 78struct 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 */ 99static 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 108SYSCTL_DECL(_net_link); 109SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN"); 110SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency"); 111 112static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface"); 113static 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 */ 120static 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 127static void vlan_start(struct ifnet *ifp); 128static void vlan_ifinit(void *foo); 129static void vlan_input(struct ifnet *ifp, struct mbuf *m); 130static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); 131static int vlan_setflag(struct ifnet *ifp, int flag, int status, 132 int (*func)(struct ifnet *, int)); 133static int vlan_setflags(struct ifnet *ifp, int status); 134static int vlan_setmulti(struct ifnet *ifp); 135static int vlan_unconfig(struct ifnet *ifp); 136static int vlan_config(struct ifvlan *ifv, struct ifnet *p); 137static void vlan_link_state(struct ifnet *ifp, int link); 138 139static struct ifnet *vlan_clone_match_ethertag(struct if_clone *, 140 const char *, int *); 141static int vlan_clone_match(struct if_clone *, const char *); 142static int vlan_clone_create(struct if_clone *, char *, size_t); 143static int vlan_clone_destroy(struct if_clone *, struct ifnet *); 144 145static 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 */ 159static int 160vlan_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 */ 233extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); 234 235/* For if_link_state_change() eyes only... */ 236extern void (*vlan_link_state_p)(struct ifnet *, int); 237 238static int 239vlan_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 265static moduledata_t vlan_mod = { 266 "if_vlan", 267 vlan_modevent, 268 0 269}; 270 271DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 272MODULE_DEPEND(if_vlan, miibus, 1, 1, 1); 273 274static struct ifnet * 275vlan_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 305static int 306vlan_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 323static int 324vlan_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 436static int 437vlan_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 */ 462static void 463vlan_ifinit(void *foo) 464{ 465 466} 467 468/* 469 * The if_start method for vlan(4) interface. It doesn't 470 * raises the IFF_DRV_OACTIVE flag, since it is called 471 * only from IFQ_HANDOFF() macro in ether_output_frame(). 472 * If the interface queue is full, and vlan_start() is 473 * not called, the queue would never get emptied and 474 * interface would stall forever. 475 */ 476static void 477vlan_start(struct ifnet *ifp) 478{ 479 struct ifvlan *ifv; 480 struct ifnet *p; 481 struct ether_vlan_header *evl; 482 struct mbuf *m; 483 int error; 484 485 ifv = ifp->if_softc; 486 p = ifv->ifv_p; 487 488 for (;;) { 489 IF_DEQUEUE(&ifp->if_snd, m); 490 if (m == 0) 491 break; 492 BPF_MTAP(ifp, m); 493 494 /* 495 * Do not run parent's if_start() if the parent is not up, 496 * or parent's driver will cause a system crash. 497 */ 498 if (!((p->if_flags & IFF_UP) && 499 (p->if_drv_flags & IFF_DRV_RUNNING))) { 500 m_freem(m); 501 ifp->if_collisions++; 502 continue; 503 } 504 505 /* 506 * If underlying interface can do VLAN tag insertion itself, 507 * just pass the packet along. However, we need some way to 508 * tell the interface where the packet came from so that it 509 * knows how to find the VLAN tag to use, so we attach a 510 * packet tag that holds it. 511 */ 512 if (p->if_capenable & IFCAP_VLAN_HWTAGGING) { 513 struct m_tag *mtag = m_tag_alloc(MTAG_VLAN, 514 MTAG_VLAN_TAG, 515 sizeof(u_int), 516 M_NOWAIT); 517 if (mtag == NULL) { 518 ifp->if_oerrors++; 519 m_freem(m); 520 continue; 521 } 522 VLAN_TAG_VALUE(mtag) = ifv->ifv_tag; 523 m_tag_prepend(m, mtag); 524 m->m_flags |= M_VLANTAG; 525 } else { 526 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 527 if (m == NULL) { 528 if_printf(ifp, 529 "unable to prepend VLAN header\n"); 530 ifp->if_oerrors++; 531 continue; 532 } 533 /* M_PREPEND takes care of m_len, m_pkthdr.len for us */ 534 535 if (m->m_len < sizeof(*evl)) { 536 m = m_pullup(m, sizeof(*evl)); 537 if (m == NULL) { 538 if_printf(ifp, 539 "cannot pullup VLAN header\n"); 540 ifp->if_oerrors++; 541 continue; 542 } 543 } 544 545 /* 546 * Transform the Ethernet header into an Ethernet header 547 * with 802.1Q encapsulation. 548 */ 549 bcopy(mtod(m, char *) + ifv->ifv_encaplen, 550 mtod(m, char *), ETHER_HDR_LEN); 551 evl = mtod(m, struct ether_vlan_header *); 552 evl->evl_proto = evl->evl_encap_proto; 553 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 554 evl->evl_tag = htons(ifv->ifv_tag); 555#ifdef DEBUG 556 printf("%s: %*D\n", __func__, (int)sizeof(*evl), 557 (unsigned char *)evl, ":"); 558#endif 559 } 560 561 /* 562 * Send it, precisely as ether_output() would have. 563 * We are already running at splimp. 564 */ 565 IFQ_HANDOFF(p, m, error); 566 if (!error) 567 ifp->if_opackets++; 568 else 569 ifp->if_oerrors++; 570 } 571} 572 573static void 574vlan_input(struct ifnet *ifp, struct mbuf *m) 575{ 576 struct ether_vlan_header *evl; 577 struct ifvlan *ifv; 578 struct m_tag *mtag; 579 u_int tag; 580 581 if (m->m_flags & M_VLANTAG) { 582 /* 583 * Packet is tagged, but m contains a normal 584 * Ethernet frame; the tag is stored out-of-band. 585 */ 586 mtag = m_tag_locate(m, MTAG_VLAN, MTAG_VLAN_TAG, NULL); 587 KASSERT(mtag != NULL, 588 ("%s: M_VLANTAG without m_tag", __func__)); 589 tag = EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag)); 590 m_tag_delete(m, mtag); 591 m->m_flags &= ~M_VLANTAG; 592 } else { 593 /* 594 * Packet is tagged in-band as specified by 802.1q. 595 */ 596 mtag = NULL; 597 switch (ifp->if_type) { 598 case IFT_ETHER: 599 if (m->m_len < sizeof(*evl) && 600 (m = m_pullup(m, sizeof(*evl))) == NULL) { 601 if_printf(ifp, "cannot pullup VLAN header\n"); 602 return; 603 } 604 evl = mtod(m, struct ether_vlan_header *); 605 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN, 606 ("%s: bad encapsulation protocol (%u)", 607 __func__, ntohs(evl->evl_encap_proto))); 608 609 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag)); 610 611 /* 612 * Restore the original ethertype. We'll remove 613 * the encapsulation after we've found the vlan 614 * interface corresponding to the tag. 615 */ 616 evl->evl_encap_proto = evl->evl_proto; 617 break; 618 default: 619 tag = (u_int) -1; 620#ifdef INVARIANTS 621 panic("%s: unsupported if_type (%u)", 622 __func__, ifp->if_type); 623#endif 624 break; 625 } 626 } 627 628 VLAN_LOCK(); 629 LIST_FOREACH(ifv, &ifv_list, ifv_list) 630 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 631 break; 632 633 if (ifv == NULL || (ifv->ifv_ifp->if_flags & IFF_UP) == 0) { 634 VLAN_UNLOCK(); 635 m_freem(m); 636 ifp->if_noproto++; 637#ifdef DEBUG 638 printf("%s: tag %d, no interface\n", __func__, tag); 639#endif 640 return; 641 } 642 VLAN_UNLOCK(); /* XXX extend below? */ 643#ifdef DEBUG 644 printf("%s: tag %d, parent %s\n", __func__, tag, ifv->ifv_p->if_xname); 645#endif 646 647 if (mtag == NULL) { 648 /* 649 * Packet had an in-line encapsulation header; 650 * remove it. The original header has already 651 * been fixed up above. 652 */ 653 bcopy(mtod(m, caddr_t), 654 mtod(m, caddr_t) + ETHER_VLAN_ENCAP_LEN, 655 ETHER_HDR_LEN); 656 m_adj(m, ETHER_VLAN_ENCAP_LEN); 657 } 658 659 m->m_pkthdr.rcvif = ifv->ifv_ifp; 660 ifv->ifv_ifp->if_ipackets++; 661 662 /* Pass it back through the parent's input routine. */ 663 (*ifp->if_input)(ifv->ifv_ifp, m); 664} 665 666static int 667vlan_config(struct ifvlan *ifv, struct ifnet *p) 668{ 669 struct ifaddr *ifa1, *ifa2; 670 struct ifnet *ifp; 671 struct sockaddr_dl *sdl1, *sdl2; 672 673 VLAN_LOCK_ASSERT(); 674 675 if (p->if_type != IFT_ETHER) 676 return (EPROTONOSUPPORT); 677 if (ifv->ifv_p) 678 return (EBUSY); 679 680 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 681 ifv->ifv_mintu = ETHERMIN; 682 ifv->ifv_pflags = 0; 683 684 /* 685 * The active VLAN counter on the parent is used 686 * at various places to see if there is a vlan(4) 687 * attached to this physical interface. 688 */ 689 p->if_nvlans++; 690 691 /* 692 * If the parent supports the VLAN_MTU capability, 693 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, 694 * use it. 695 */ 696 if (p->if_capenable & IFCAP_VLAN_MTU) { 697 /* 698 * No need to fudge the MTU since the parent can 699 * handle extended frames. 700 */ 701 ifv->ifv_mtufudge = 0; 702 } else { 703 /* 704 * Fudge the MTU by the encapsulation size. This 705 * makes us incompatible with strictly compliant 706 * 802.1Q implementations, but allows us to use 707 * the feature with other NetBSD implementations, 708 * which might still be useful. 709 */ 710 ifv->ifv_mtufudge = ifv->ifv_encaplen; 711 } 712 713 ifv->ifv_p = p; 714 ifp = ifv->ifv_ifp; 715 ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge; 716 /* 717 * Copy only a selected subset of flags from the parent. 718 * Other flags are none of our business. 719 */ 720#define VLAN_COPY_FLAGS \ 721 (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT) 722 ifp->if_flags &= ~VLAN_COPY_FLAGS; 723 ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS; 724#undef VLAN_COPY_FLAGS 725 726 ifp->if_link_state = p->if_link_state; 727 728#if 0 729 /* 730 * Not ready yet. We need notification from the parent 731 * when hw checksumming flags in its if_capenable change. 732 * Flags set in if_capabilities only are useless. 733 */ 734 /* 735 * If the parent interface can do hardware-assisted 736 * VLAN encapsulation, then propagate its hardware- 737 * assisted checksumming flags. 738 */ 739 if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) 740 ifp->if_capabilities |= p->if_capabilities & IFCAP_HWCSUM; 741#endif 742 743 /* 744 * Set up our ``Ethernet address'' to reflect the underlying 745 * physical interface's. 746 */ 747 ifa1 = ifaddr_byindex(ifp->if_index); 748 ifa2 = ifaddr_byindex(p->if_index); 749 sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr; 750 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr; 751 sdl1->sdl_type = IFT_ETHER; 752 sdl1->sdl_alen = ETHER_ADDR_LEN; 753 bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN); 754 bcopy(LLADDR(sdl2), IFP2ENADDR(ifp), ETHER_ADDR_LEN); 755 756 /* 757 * Configure multicast addresses that may already be 758 * joined on the vlan device. 759 */ 760 (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */ 761 762 return (0); 763} 764 765static int 766vlan_unconfig(struct ifnet *ifp) 767{ 768 struct ifaddr *ifa; 769 struct sockaddr_dl *sdl; 770 struct vlan_mc_entry *mc; 771 struct ifvlan *ifv; 772 struct ifnet *p; 773 int error; 774 775 VLAN_LOCK_ASSERT(); 776 777 ifv = ifp->if_softc; 778 p = ifv->ifv_p; 779 780 if (p) { 781 struct sockaddr_dl sdl; 782 783 /* 784 * Since the interface is being unconfigured, we need to 785 * empty the list of multicast groups that we may have joined 786 * while we were alive from the parent's list. 787 */ 788 bzero((char *)&sdl, sizeof(sdl)); 789 sdl.sdl_len = sizeof(sdl); 790 sdl.sdl_family = AF_LINK; 791 sdl.sdl_index = p->if_index; 792 sdl.sdl_type = IFT_ETHER; 793 sdl.sdl_alen = ETHER_ADDR_LEN; 794 795 while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) { 796 mc = SLIST_FIRST(&ifv->vlan_mc_listhead); 797 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), 798 ETHER_ADDR_LEN); 799 error = if_delmulti(p, (struct sockaddr *)&sdl); 800 if (error) 801 return (error); 802 SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); 803 free(mc, M_VLAN); 804 } 805 806 vlan_setflags(ifp, 0); /* clear special flags on parent */ 807 p->if_nvlans--; 808 } 809 810 /* Disconnect from parent. */ 811 if (ifv->ifv_pflags) 812 if_printf(ifp, "%s: ifv_pflags unclean\n", __func__); 813 ifv->ifv_p = NULL; 814 ifv->ifv_ifp->if_mtu = ETHERMTU; /* XXX why not 0? */ 815 ifv->ifv_ifp->if_link_state = LINK_STATE_UNKNOWN; 816 817 /* Clear our MAC address. */ 818 ifa = ifaddr_byindex(ifv->ifv_ifp->if_index); 819 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 820 sdl->sdl_type = IFT_ETHER; 821 sdl->sdl_alen = ETHER_ADDR_LEN; 822 bzero(LLADDR(sdl), ETHER_ADDR_LEN); 823 bzero(IFP2ENADDR(ifv->ifv_ifp), ETHER_ADDR_LEN); 824 825 return (0); 826} 827 828/* Handle a reference counted flag that should be set on the parent as well */ 829static int 830vlan_setflag(struct ifnet *ifp, int flag, int status, 831 int (*func)(struct ifnet *, int)) 832{ 833 struct ifvlan *ifv; 834 int error; 835 836 /* XXX VLAN_LOCK_ASSERT(); */ 837 838 ifv = ifp->if_softc; 839 status = status ? (ifp->if_flags & flag) : 0; 840 /* Now "status" contains the flag value or 0 */ 841 842 /* 843 * See if recorded parent's status is different from what 844 * we want it to be. If it is, flip it. We record parent's 845 * status in ifv_pflags so that we won't clear parent's flag 846 * we haven't set. In fact, we don't clear or set parent's 847 * flags directly, but get or release references to them. 848 * That's why we can be sure that recorded flags still are 849 * in accord with actual parent's flags. 850 */ 851 if (status != (ifv->ifv_pflags & flag)) { 852 error = (*func)(ifv->ifv_p, status); 853 if (error) 854 return (error); 855 ifv->ifv_pflags &= ~flag; 856 ifv->ifv_pflags |= status; 857 } 858 return (0); 859} 860 861/* 862 * Handle IFF_* flags that require certain changes on the parent: 863 * if "status" is true, update parent's flags respective to our if_flags; 864 * if "status" is false, forcedly clear the flags set on parent. 865 */ 866static int 867vlan_setflags(struct ifnet *ifp, int status) 868{ 869 int error, i; 870 871 for (i = 0; vlan_pflags[i].flag; i++) { 872 error = vlan_setflag(ifp, vlan_pflags[i].flag, 873 status, vlan_pflags[i].func); 874 if (error) 875 return (error); 876 } 877 return (0); 878} 879 880/* Inform all vlans that their parent has changed link state */ 881static void 882vlan_link_state(struct ifnet *ifp, int link) 883{ 884 struct ifvlan *ifv; 885 886 VLAN_LOCK(); 887 LIST_FOREACH(ifv, &ifv_list, ifv_list) { 888 if (ifv->ifv_p == ifp) 889 if_link_state_change(ifv->ifv_ifp, 890 ifv->ifv_p->if_link_state); 891 } 892 VLAN_UNLOCK(); 893} 894 895static int 896vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 897{ 898 struct ifaddr *ifa; 899 struct ifnet *p; 900 struct ifreq *ifr; 901 struct ifvlan *ifv; 902 struct vlanreq vlr; 903 int error = 0; 904 905 ifr = (struct ifreq *)data; 906 ifa = (struct ifaddr *)data; 907 ifv = ifp->if_softc; 908 909 switch (cmd) { 910 case SIOCSIFADDR: 911 ifp->if_flags |= IFF_UP; 912 913 switch (ifa->ifa_addr->sa_family) { 914#ifdef INET 915 case AF_INET: 916 arp_ifinit(ifv->ifv_ifp, ifa); 917 break; 918#endif 919 default: 920 break; 921 } 922 break; 923 924 case SIOCGIFADDR: 925 { 926 struct sockaddr *sa; 927 928 sa = (struct sockaddr *) &ifr->ifr_data; 929 bcopy(IFP2ENADDR(ifp), (caddr_t)sa->sa_data, 930 ETHER_ADDR_LEN); 931 } 932 break; 933 934 case SIOCGIFMEDIA: 935 VLAN_LOCK(); 936 if (ifv->ifv_p != NULL) { 937 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, 938 SIOCGIFMEDIA, data); 939 VLAN_UNLOCK(); 940 /* Limit the result to the parent's current config. */ 941 if (error == 0) { 942 struct ifmediareq *ifmr; 943 944 ifmr = (struct ifmediareq *)data; 945 if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) { 946 ifmr->ifm_count = 1; 947 error = copyout(&ifmr->ifm_current, 948 ifmr->ifm_ulist, 949 sizeof(int)); 950 } 951 } 952 } else { 953 VLAN_UNLOCK(); 954 error = EINVAL; 955 } 956 break; 957 958 case SIOCSIFMEDIA: 959 error = EINVAL; 960 break; 961 962 case SIOCSIFMTU: 963 /* 964 * Set the interface MTU. 965 */ 966 VLAN_LOCK(); 967 if (ifv->ifv_p != NULL) { 968 if (ifr->ifr_mtu > 969 (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) || 970 ifr->ifr_mtu < 971 (ifv->ifv_mintu - ifv->ifv_mtufudge)) 972 error = EINVAL; 973 else 974 ifp->if_mtu = ifr->ifr_mtu; 975 } else 976 error = EINVAL; 977 VLAN_UNLOCK(); 978 break; 979 980 case SIOCSETVLAN: 981 error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); 982 if (error) 983 break; 984 if (vlr.vlr_parent[0] == '\0') { 985 VLAN_LOCK(); 986 vlan_unconfig(ifp); 987 if (ifp->if_flags & IFF_UP) 988 if_down(ifp); 989 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 990 VLAN_UNLOCK(); 991 break; 992 } 993 p = ifunit(vlr.vlr_parent); 994 if (p == 0) { 995 error = ENOENT; 996 break; 997 } 998 /* 999 * Don't let the caller set up a VLAN tag with 1000 * anything except VLID bits. 1001 */ 1002 if (vlr.vlr_tag & ~EVL_VLID_MASK) { 1003 error = EINVAL; 1004 break; 1005 } 1006 VLAN_LOCK(); 1007 error = vlan_config(ifv, p); 1008 if (error) { 1009 VLAN_UNLOCK(); 1010 break; 1011 } 1012 ifv->ifv_tag = vlr.vlr_tag; 1013 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1014 VLAN_UNLOCK(); 1015 1016 /* Update flags on the parent, if necessary. */ 1017 vlan_setflags(ifp, 1); 1018 break; 1019 1020 case SIOCGETVLAN: 1021 bzero(&vlr, sizeof(vlr)); 1022 VLAN_LOCK(); 1023 if (ifv->ifv_p) { 1024 strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname, 1025 sizeof(vlr.vlr_parent)); 1026 vlr.vlr_tag = ifv->ifv_tag; 1027 } 1028 VLAN_UNLOCK(); 1029 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr)); 1030 break; 1031 1032 case SIOCSIFFLAGS: 1033 /* 1034 * We should propagate selected flags to the parent, 1035 * e.g., promiscuous mode. 1036 */ 1037 if (ifv->ifv_p != NULL) 1038 error = vlan_setflags(ifp, 1); 1039 break; 1040 1041 case SIOCADDMULTI: 1042 case SIOCDELMULTI: 1043 /*VLAN_LOCK();*/ 1044 error = vlan_setmulti(ifp); 1045 /*VLAN_UNLOCK();*/ 1046 break; 1047 default: 1048 error = EINVAL; 1049 } 1050 1051 return (error); 1052} 1053