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