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