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