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