1 /* $NetBSD: if_vlan.c,v 1.67 2011/04/08 13:56:51 sborrill 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.67 2011/04/08 13:56:51 sborrill 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 struct ifreq ifr; 290 291 ifr.ifr_flags = p->if_flags; 292 error = (*p->if_ioctl)(p, SIOCSIFFLAGS, 293 (void *) &ifr); 294 if (error) { 295 if (ec->ec_nvlans-- == 1) 296 ec->ec_capenable &= 297 ~ETHERCAP_VLAN_MTU; 298 return (error); 299 } 300 } 301 ifv->ifv_mtufudge = 0; 302 } else if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) { 303 /* 304 * Fudge the MTU by the encapsulation size. This 305 * makes us incompatible with strictly compliant 306 * 802.1Q implementations, but allows us to use 307 * the feature with other NetBSD implementations, 308 * which might still be useful. 309 */ 310 ifv->ifv_mtufudge = ifv->ifv_encaplen; 311 } 312 313 /* 314 * If the parent interface can do hardware-assisted 315 * VLAN encapsulation, then propagate its hardware- 316 * assisted checksumming flags and tcp segmentation 317 * offload. 318 */ 319 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { 320 ec->ec_capenable |= ETHERCAP_VLAN_HWTAGGING; 321 ifp->if_capabilities = p->if_capabilities & 322 (IFCAP_TSOv4 | IFCAP_TSOv6 | 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 bpf_mtap(ifp, m); 736 /* 737 * If the parent can insert the tag itself, just mark 738 * the tag in the mbuf header. 739 */ 740 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { 741 struct m_tag *mtag; 742 743 mtag = m_tag_get(PACKET_TAG_VLAN, sizeof(u_int), 744 M_NOWAIT); 745 if (mtag == NULL) { 746 ifp->if_oerrors++; 747 m_freem(m); 748 continue; 749 } 750 *(u_int *)(mtag + 1) = ifv->ifv_tag; 751 m_tag_prepend(m, mtag); 752 } else { 753 /* 754 * insert the tag ourselves 755 */ 756 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 757 if (m == NULL) { 758 printf("%s: unable to prepend encap header", 759 ifv->ifv_p->if_xname); 760 ifp->if_oerrors++; 761 continue; 762 } 763 764 switch (p->if_type) { 765 case IFT_ETHER: 766 { 767 struct ether_vlan_header *evl; 768 769 if (m->m_len < sizeof(struct ether_vlan_header)) 770 m = m_pullup(m, 771 sizeof(struct ether_vlan_header)); 772 if (m == NULL) { 773 printf("%s: unable to pullup encap " 774 "header", ifv->ifv_p->if_xname); 775 ifp->if_oerrors++; 776 continue; 777 } 778 779 /* 780 * Transform the Ethernet header into an 781 * Ethernet header with 802.1Q encapsulation. 782 */ 783 memmove(mtod(m, void *), 784 mtod(m, char *) + ifv->ifv_encaplen, 785 sizeof(struct ether_header)); 786 evl = mtod(m, struct ether_vlan_header *); 787 evl->evl_proto = evl->evl_encap_proto; 788 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 789 evl->evl_tag = htons(ifv->ifv_tag); 790 791 /* 792 * To cater for VLAN-aware layer 2 ethernet 793 * switches which may need to strip the tag 794 * before forwarding the packet, make sure 795 * the packet+tag is at least 68 bytes long. 796 * This is necessary because our parent will 797 * only pad to 64 bytes (ETHER_MIN_LEN) and 798 * some switches will not pad by themselves 799 * after deleting a tag. 800 */ 801 if (m->m_pkthdr.len < 802 (ETHER_MIN_LEN + ETHER_VLAN_ENCAP_LEN)) { 803 m_copyback(m, m->m_pkthdr.len, 804 (ETHER_MIN_LEN + 805 ETHER_VLAN_ENCAP_LEN) - 806 m->m_pkthdr.len, 807 vlan_zero_pad_buff); 808 } 809 break; 810 } 811 812 #ifdef DIAGNOSTIC 813 default: 814 panic("vlan_start: impossible"); 815 #endif 816 } 817 } 818 819 /* 820 * Send it, precisely as the parent's output routine 821 * would have. We are already running at splnet. 822 */ 823 IFQ_ENQUEUE(&p->if_snd, m, &pktattr, error); 824 if (error) { 825 /* mbuf is already freed */ 826 ifp->if_oerrors++; 827 continue; 828 } 829 830 ifp->if_opackets++; 831 if ((p->if_flags & (IFF_RUNNING|IFF_OACTIVE)) == IFF_RUNNING) 832 (*p->if_start)(p); 833 } 834 835 ifp->if_flags &= ~IFF_OACTIVE; 836 } 837 838 /* 839 * Given an Ethernet frame, find a valid vlan interface corresponding to the 840 * given source interface and tag, then run the real packet through the 841 * parent's input routine. 842 */ 843 void 844 vlan_input(struct ifnet *ifp, struct mbuf *m) 845 { 846 struct ifvlan *ifv; 847 u_int tag; 848 struct m_tag *mtag; 849 850 mtag = m_tag_find(m, PACKET_TAG_VLAN, NULL); 851 if (mtag != NULL) { 852 /* m contains a normal ethernet frame, the tag is in mtag */ 853 tag = EVL_VLANOFTAG(*(u_int *)(mtag + 1)); 854 m_tag_delete(m, mtag); 855 } else { 856 switch (ifp->if_type) { 857 case IFT_ETHER: 858 { 859 struct ether_vlan_header *evl; 860 861 if (m->m_len < sizeof(struct ether_vlan_header) && 862 (m = m_pullup(m, 863 sizeof(struct ether_vlan_header))) == NULL) { 864 printf("%s: no memory for VLAN header, " 865 "dropping packet.\n", ifp->if_xname); 866 return; 867 } 868 evl = mtod(m, struct ether_vlan_header *); 869 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN); 870 871 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag)); 872 873 /* 874 * Restore the original ethertype. We'll remove 875 * the encapsulation after we've found the vlan 876 * interface corresponding to the tag. 877 */ 878 evl->evl_encap_proto = evl->evl_proto; 879 break; 880 } 881 882 default: 883 tag = (u_int) -1; /* XXX GCC */ 884 #ifdef DIAGNOSTIC 885 panic("vlan_input: impossible"); 886 #endif 887 } 888 } 889 890 for (ifv = LIST_FIRST(&ifv_list); ifv != NULL; 891 ifv = LIST_NEXT(ifv, ifv_list)) 892 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 893 break; 894 895 if (ifv == NULL || 896 (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != 897 (IFF_UP|IFF_RUNNING)) { 898 m_freem(m); 899 ifp->if_noproto++; 900 return; 901 } 902 903 /* 904 * Now, remove the encapsulation header. The original 905 * header has already been fixed up above. 906 */ 907 if (mtag == NULL) { 908 memmove(mtod(m, char *) + ifv->ifv_encaplen, 909 mtod(m, void *), sizeof(struct ether_header)); 910 m_adj(m, ifv->ifv_encaplen); 911 } 912 913 m->m_pkthdr.rcvif = &ifv->ifv_if; 914 ifv->ifv_if.if_ipackets++; 915 916 bpf_mtap(&ifv->ifv_if, m); 917 918 /* Pass it back through the parent's input routine. */ 919 (*ifp->if_input)(&ifv->ifv_if, m); 920 } 921