1 /* $NetBSD: if_vlan.c,v 1.38 2003/12/05 19:35:43 scw 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright 1998 Massachusetts Institute of Technology 41 * 42 * Permission to use, copy, modify, and distribute this software and 43 * its documentation for any purpose and without fee is hereby 44 * granted, provided that both the above copyright notice and this 45 * permission notice appear in all copies, that both the above 46 * copyright notice and this permission notice appear in all 47 * supporting documentation, and that the name of M.I.T. not be used 48 * in advertising or publicity pertaining to distribution of the 49 * software without specific, written prior permission. M.I.T. makes 50 * no representations about the suitability of this software for any 51 * purpose. It is provided "as is" without express or implied 52 * warranty. 53 * 54 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 55 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 56 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 57 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 58 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 60 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 61 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 62 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 63 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 64 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 * 67 * from FreeBSD: if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp 68 * via OpenBSD: if_vlan.c,v 1.4 2000/05/15 19:15:00 chris Exp 69 */ 70 71 /* 72 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs. Might be 73 * extended some day to also handle IEEE 802.1P priority tagging. This is 74 * sort of sneaky in the implementation, since we need to pretend to be 75 * enough of an Ethernet implementation to make ARP work. The way we do 76 * this is by telling everyone that we are an Ethernet interface, and then 77 * catch the packets that ether_output() left on our output queue when it 78 * calls if_start(), rewrite them for use by the real outgoing interface, 79 * and ask it to send them. 80 * 81 * TODO: 82 * 83 * - Need some way to notify vlan interfaces when the parent 84 * interface changes MTU. 85 */ 86 87 #include <sys/cdefs.h> 88 __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.38 2003/12/05 19:35:43 scw Exp $"); 89 90 #include "opt_inet.h" 91 #include "bpfilter.h" 92 93 #include <sys/param.h> 94 #include <sys/kernel.h> 95 #include <sys/mbuf.h> 96 #include <sys/queue.h> 97 #include <sys/socket.h> 98 #include <sys/sockio.h> 99 #include <sys/systm.h> 100 #include <sys/proc.h> 101 102 #if NBPFILTER > 0 103 #include <net/bpf.h> 104 #endif 105 #include <net/if.h> 106 #include <net/if_dl.h> 107 #include <net/if_types.h> 108 #include <net/if_ether.h> 109 #include <net/if_vlanvar.h> 110 111 #ifdef INET 112 #include <netinet/in.h> 113 #include <netinet/if_inarp.h> 114 #endif 115 116 struct vlan_mc_entry { 117 LIST_ENTRY(vlan_mc_entry) mc_entries; 118 /* 119 * A key to identify this entry. The mc_addr below can't be 120 * used since multiple sockaddr may mapped into the same 121 * ether_multi (e.g., AF_UNSPEC). 122 */ 123 union { 124 struct ether_multi *mcu_enm; 125 } mc_u; 126 struct sockaddr_storage mc_addr; 127 }; 128 129 #define mc_enm mc_u.mcu_enm 130 131 struct ifvlan { 132 union { 133 struct ethercom ifvu_ec; 134 } ifv_u; 135 struct ifnet *ifv_p; /* parent interface of this vlan */ 136 struct ifv_linkmib { 137 const struct vlan_multisw *ifvm_msw; 138 int ifvm_encaplen; /* encapsulation length */ 139 int ifvm_mtufudge; /* MTU fudged by this much */ 140 int ifvm_mintu; /* min transmission unit */ 141 u_int16_t ifvm_proto; /* encapsulation ethertype */ 142 u_int16_t ifvm_tag; /* tag to apply on packets */ 143 } ifv_mib; 144 LIST_HEAD(__vlan_mchead, vlan_mc_entry) ifv_mc_listhead; 145 LIST_ENTRY(ifvlan) ifv_list; 146 int ifv_flags; 147 }; 148 149 #define IFVF_PROMISC 0x01 /* promiscuous mode enabled */ 150 151 #define ifv_ec ifv_u.ifvu_ec 152 153 #define ifv_if ifv_ec.ec_if 154 155 #define ifv_msw ifv_mib.ifvm_msw 156 #define ifv_encaplen ifv_mib.ifvm_encaplen 157 #define ifv_mtufudge ifv_mib.ifvm_mtufudge 158 #define ifv_mintu ifv_mib.ifvm_mintu 159 #define ifv_tag ifv_mib.ifvm_tag 160 161 struct vlan_multisw { 162 int (*vmsw_addmulti)(struct ifvlan *, struct ifreq *); 163 int (*vmsw_delmulti)(struct ifvlan *, struct ifreq *); 164 void (*vmsw_purgemulti)(struct ifvlan *); 165 }; 166 167 static int vlan_ether_addmulti(struct ifvlan *, struct ifreq *); 168 static int vlan_ether_delmulti(struct ifvlan *, struct ifreq *); 169 static void vlan_ether_purgemulti(struct ifvlan *); 170 171 const struct vlan_multisw vlan_ether_multisw = { 172 vlan_ether_addmulti, 173 vlan_ether_delmulti, 174 vlan_ether_purgemulti, 175 }; 176 177 static int vlan_clone_create(struct if_clone *, int); 178 static void vlan_clone_destroy(struct ifnet *); 179 static int vlan_config(struct ifvlan *, struct ifnet *); 180 static int vlan_ioctl(struct ifnet *, u_long, caddr_t); 181 static void vlan_start(struct ifnet *); 182 static void vlan_unconfig(struct ifnet *); 183 184 void vlanattach(int); 185 186 /* XXX This should be a hash table with the tag as the basis of the key. */ 187 static LIST_HEAD(, ifvlan) ifv_list; 188 189 struct if_clone vlan_cloner = 190 IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy); 191 192 /* Used to pad ethernet frames with < ETHER_MIN_LEN bytes */ 193 static char vlan_zero_pad_buff[ETHER_MIN_LEN]; 194 195 void 196 vlanattach(int n) 197 { 198 199 LIST_INIT(&ifv_list); 200 if_clone_attach(&vlan_cloner); 201 } 202 203 static void 204 vlan_reset_linkname(struct ifnet *ifp) 205 { 206 207 /* 208 * We start out with a "802.1Q VLAN" type and zero-length 209 * addresses. When we attach to a parent interface, we 210 * inherit its type, address length, address, and data link 211 * type. 212 */ 213 214 ifp->if_type = IFT_L2VLAN; 215 ifp->if_addrlen = 0; 216 ifp->if_dlt = DLT_NULL; 217 if_alloc_sadl(ifp); 218 } 219 220 static int 221 vlan_clone_create(struct if_clone *ifc, int unit) 222 { 223 struct ifvlan *ifv; 224 struct ifnet *ifp; 225 int s; 226 227 ifv = malloc(sizeof(struct ifvlan), M_DEVBUF, M_WAITOK); 228 memset(ifv, 0, sizeof(struct ifvlan)); 229 ifp = &ifv->ifv_if; 230 LIST_INIT(&ifv->ifv_mc_listhead); 231 232 s = splnet(); 233 LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list); 234 splx(s); 235 236 sprintf(ifp->if_xname, "%s%d", ifc->ifc_name, unit); 237 ifp->if_softc = ifv; 238 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 239 ifp->if_start = vlan_start; 240 ifp->if_ioctl = vlan_ioctl; 241 IFQ_SET_READY(&ifp->if_snd); 242 243 if_attach(ifp); 244 vlan_reset_linkname(ifp); 245 246 return (0); 247 } 248 249 static void 250 vlan_clone_destroy(struct ifnet *ifp) 251 { 252 struct ifvlan *ifv = ifp->if_softc; 253 int s; 254 255 s = splnet(); 256 LIST_REMOVE(ifv, ifv_list); 257 vlan_unconfig(ifp); 258 splx(s); 259 260 if_detach(ifp); 261 free(ifv, M_DEVBUF); 262 } 263 264 /* 265 * Configure a VLAN interface. Must be called at splnet(). 266 */ 267 static int 268 vlan_config(struct ifvlan *ifv, struct ifnet *p) 269 { 270 struct ifnet *ifp = &ifv->ifv_if; 271 int error; 272 273 if (ifv->ifv_p != NULL) 274 return (EBUSY); 275 276 switch (p->if_type) { 277 case IFT_ETHER: 278 { 279 struct ethercom *ec = (void *) p; 280 281 ifv->ifv_msw = &vlan_ether_multisw; 282 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 283 ifv->ifv_mintu = ETHERMIN; 284 285 /* 286 * If the parent supports the VLAN_MTU capability, 287 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, 288 * enable it. 289 */ 290 if (ec->ec_nvlans++ == 0 && 291 (ec->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) { 292 /* 293 * Enable Tx/Rx of VLAN-sized frames. 294 */ 295 ec->ec_capenable |= ETHERCAP_VLAN_MTU; 296 if (p->if_flags & IFF_UP) { 297 struct ifreq ifr; 298 299 ifr.ifr_flags = p->if_flags; 300 error = (*p->if_ioctl)(p, SIOCSIFFLAGS, 301 (caddr_t) &ifr); 302 if (error) { 303 if (ec->ec_nvlans-- == 1) 304 ec->ec_capenable &= 305 ~ETHERCAP_VLAN_MTU; 306 return (error); 307 } 308 } 309 ifv->ifv_mtufudge = 0; 310 } else if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) { 311 /* 312 * Fudge the MTU by the encapsulation size. This 313 * makes us incompatible with strictly compliant 314 * 802.1Q implementations, but allows us to use 315 * the feature with other NetBSD implementations, 316 * which might still be useful. 317 */ 318 ifv->ifv_mtufudge = ifv->ifv_encaplen; 319 } 320 321 /* 322 * If the parent interface can do hardware-assisted 323 * VLAN encapsulation, then propagate its hardware- 324 * assisted checksumming flags. 325 */ 326 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) 327 ifp->if_capabilities = p->if_capabilities & 328 (IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4| 329 IFCAP_CSUM_UDPv4|IFCAP_CSUM_TCPv6| 330 IFCAP_CSUM_UDPv6); 331 332 /* 333 * We inherit the parent's Ethernet address. 334 */ 335 ether_ifattach(ifp, LLADDR(p->if_sadl)); 336 ifp->if_hdrlen = sizeof(struct ether_vlan_header); /* XXX? */ 337 break; 338 } 339 340 default: 341 return (EPROTONOSUPPORT); 342 } 343 344 ifv->ifv_p = p; 345 ifv->ifv_if.if_mtu = p->if_mtu - ifv->ifv_mtufudge; 346 ifv->ifv_if.if_flags = p->if_flags & 347 (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 348 349 /* 350 * Inherit the if_type from the parent. This allows us 351 * to participate in bridges of that type. 352 */ 353 ifv->ifv_if.if_type = p->if_type; 354 355 return (0); 356 } 357 358 /* 359 * Unconfigure a VLAN interface. Must be called at splnet(). 360 */ 361 static void 362 vlan_unconfig(struct ifnet *ifp) 363 { 364 struct ifvlan *ifv = ifp->if_softc; 365 366 if (ifv->ifv_p == NULL) 367 return; 368 369 /* 370 * Since the interface is being unconfigured, we need to empty the 371 * list of multicast groups that we may have joined while we were 372 * alive and remove them from the parent's list also. 373 */ 374 (*ifv->ifv_msw->vmsw_purgemulti)(ifv); 375 376 /* Disconnect from parent. */ 377 switch (ifv->ifv_p->if_type) { 378 case IFT_ETHER: 379 { 380 struct ethercom *ec = (void *) ifv->ifv_p; 381 382 if (ec->ec_nvlans-- == 1) { 383 /* 384 * Disable Tx/Rx of VLAN-sized frames. 385 */ 386 ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; 387 if (ifv->ifv_p->if_flags & IFF_UP) { 388 struct ifreq ifr; 389 390 ifr.ifr_flags = ifv->ifv_p->if_flags; 391 (void) (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, 392 SIOCSIFFLAGS, (caddr_t) &ifr); 393 } 394 } 395 396 ether_ifdetach(ifp); 397 vlan_reset_linkname(ifp); 398 break; 399 } 400 401 #ifdef DIAGNOSTIC 402 default: 403 panic("vlan_unconfig: impossible"); 404 #endif 405 } 406 407 ifv->ifv_p = NULL; 408 ifv->ifv_if.if_mtu = 0; 409 ifv->ifv_flags = 0; 410 411 if_down(ifp); 412 ifp->if_flags &= ~(IFF_UP|IFF_RUNNING); 413 ifp->if_capabilities = 0; 414 } 415 416 /* 417 * Called when a parent interface is detaching; destroy any VLAN 418 * configuration for the parent interface. 419 */ 420 void 421 vlan_ifdetach(struct ifnet *p) 422 { 423 struct ifvlan *ifv; 424 int s; 425 426 s = splnet(); 427 428 for (ifv = LIST_FIRST(&ifv_list); ifv != NULL; 429 ifv = LIST_NEXT(ifv, ifv_list)) { 430 if (ifv->ifv_p == p) 431 vlan_unconfig(&ifv->ifv_if); 432 } 433 434 splx(s); 435 } 436 437 static int 438 vlan_set_promisc(struct ifnet *ifp) 439 { 440 struct ifvlan *ifv = ifp->if_softc; 441 int error = 0; 442 443 if ((ifp->if_flags & IFF_PROMISC) != 0) { 444 if ((ifv->ifv_flags & IFVF_PROMISC) == 0) { 445 error = ifpromisc(ifv->ifv_p, 1); 446 if (error == 0) 447 ifv->ifv_flags |= IFVF_PROMISC; 448 } 449 } else { 450 if ((ifv->ifv_flags & IFVF_PROMISC) != 0) { 451 error = ifpromisc(ifv->ifv_p, 0); 452 if (error == 0) 453 ifv->ifv_flags &= ~IFVF_PROMISC; 454 } 455 } 456 457 return (error); 458 } 459 460 static int 461 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 462 { 463 struct proc *p = curproc; /* XXX */ 464 struct ifvlan *ifv = ifp->if_softc; 465 struct ifaddr *ifa = (struct ifaddr *) data; 466 struct ifreq *ifr = (struct ifreq *) data; 467 struct ifnet *pr; 468 struct vlanreq vlr; 469 struct sockaddr *sa; 470 int s, error = 0; 471 472 s = splnet(); 473 474 switch (cmd) { 475 case SIOCSIFADDR: 476 if (ifv->ifv_p != NULL) { 477 ifp->if_flags |= IFF_UP; 478 479 switch (ifa->ifa_addr->sa_family) { 480 #ifdef INET 481 case AF_INET: 482 arp_ifinit(ifp, ifa); 483 break; 484 #endif 485 default: 486 break; 487 } 488 } else { 489 error = EINVAL; 490 } 491 break; 492 493 case SIOCGIFADDR: 494 sa = (struct sockaddr *)&ifr->ifr_data; 495 memcpy(sa->sa_data, LLADDR(ifp->if_sadl), ifp->if_addrlen); 496 break; 497 498 case SIOCSIFMTU: 499 if (ifv->ifv_p != NULL) { 500 if (ifr->ifr_mtu > 501 (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) || 502 ifr->ifr_mtu < 503 (ifv->ifv_mintu - ifv->ifv_mtufudge)) 504 error = EINVAL; 505 else 506 ifp->if_mtu = ifr->ifr_mtu; 507 } else 508 error = EINVAL; 509 break; 510 511 case SIOCSETVLAN: 512 if ((error = suser(p->p_ucred, &p->p_acflag)) != 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 struct vlan_mc_entry *mc; 579 u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 580 int error; 581 582 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr_storage)) 583 return (EINVAL); 584 585 error = ether_addmulti(ifr, &ifv->ifv_ec); 586 if (error != ENETRESET) 587 return (error); 588 589 /* 590 * This is new multicast address. We have to tell parent 591 * about it. Also, remember this multicast address so that 592 * we can delete them on unconfigure. 593 */ 594 MALLOC(mc, struct vlan_mc_entry *, sizeof(struct vlan_mc_entry), 595 M_DEVBUF, M_NOWAIT); 596 if (mc == NULL) { 597 error = ENOMEM; 598 goto alloc_failed; 599 } 600 601 /* 602 * As ether_addmulti() returns ENETRESET, following two 603 * statement shouldn't fail. 604 */ 605 (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 606 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, mc->mc_enm); 607 memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len); 608 LIST_INSERT_HEAD(&ifv->ifv_mc_listhead, mc, mc_entries); 609 610 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, SIOCADDMULTI, 611 (caddr_t)ifr); 612 if (error != 0) 613 goto ioctl_failed; 614 return (error); 615 616 ioctl_failed: 617 LIST_REMOVE(mc, mc_entries); 618 FREE(mc, M_DEVBUF); 619 alloc_failed: 620 (void)ether_delmulti(ifr, &ifv->ifv_ec); 621 return (error); 622 } 623 624 static int 625 vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr) 626 { 627 struct ether_multi *enm; 628 struct vlan_mc_entry *mc; 629 u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 630 int error; 631 632 /* 633 * Find a key to lookup vlan_mc_entry. We have to do this 634 * before calling ether_delmulti for obvious reason. 635 */ 636 if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0) 637 return (error); 638 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, enm); 639 640 error = ether_delmulti(ifr, &ifv->ifv_ec); 641 if (error != ENETRESET) 642 return (error); 643 644 /* We no longer use this multicast address. Tell parent so. */ 645 error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p, SIOCDELMULTI, 646 (caddr_t)ifr); 647 if (error == 0) { 648 /* And forget about this address. */ 649 for (mc = LIST_FIRST(&ifv->ifv_mc_listhead); mc != NULL; 650 mc = LIST_NEXT(mc, mc_entries)) { 651 if (mc->mc_enm == enm) { 652 LIST_REMOVE(mc, mc_entries); 653 FREE(mc, M_DEVBUF); 654 break; 655 } 656 } 657 KASSERT(mc != NULL); 658 } else 659 (void)ether_addmulti(ifr, &ifv->ifv_ec); 660 return (error); 661 } 662 663 /* 664 * Delete any multicast address we have asked to add from parent 665 * interface. Called when the vlan is being unconfigured. 666 */ 667 static void 668 vlan_ether_purgemulti(struct ifvlan *ifv) 669 { 670 struct ifnet *ifp = ifv->ifv_p; /* Parent. */ 671 struct vlan_mc_entry *mc; 672 union { 673 struct ifreq ifreq; 674 struct { 675 char ifr_name[IFNAMSIZ]; 676 struct sockaddr_storage ifr_ss; 677 } ifreq_storage; 678 } ifreq; 679 struct ifreq *ifr = &ifreq.ifreq; 680 681 memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ); 682 while ((mc = LIST_FIRST(&ifv->ifv_mc_listhead)) != NULL) { 683 memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len); 684 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr); 685 LIST_REMOVE(mc, mc_entries); 686 FREE(mc, M_DEVBUF); 687 } 688 } 689 690 static void 691 vlan_start(struct ifnet *ifp) 692 { 693 struct ifvlan *ifv = ifp->if_softc; 694 struct ifnet *p = ifv->ifv_p; 695 struct ethercom *ec = (void *) ifv->ifv_p; 696 struct mbuf *m; 697 int error; 698 ALTQ_DECL(struct altq_pktattr pktattr;) 699 700 ifp->if_flags |= IFF_OACTIVE; 701 702 for (;;) { 703 IFQ_DEQUEUE(&ifp->if_snd, m); 704 if (m == NULL) 705 break; 706 707 #ifdef ALTQ 708 /* 709 * If ALTQ is enabled on the parent interface, do 710 * classification; the queueing discipline might 711 * not require classification, but might require 712 * the address family/header pointer in the pktattr. 713 */ 714 if (ALTQ_IS_ENABLED(&p->if_snd)) { 715 switch (p->if_type) { 716 case IFT_ETHER: 717 altq_etherclassify(&p->if_snd, m, &pktattr); 718 break; 719 #ifdef DIAGNOSTIC 720 default: 721 panic("vlan_start: impossible (altq)"); 722 #endif 723 } 724 } 725 #endif /* ALTQ */ 726 727 #if NBPFILTER > 0 728 if (ifp->if_bpf) 729 bpf_mtap(ifp->if_bpf, m); 730 #endif 731 /* 732 * If the parent can insert the tag itself, just mark 733 * the tag in the mbuf header. 734 */ 735 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { 736 struct m_tag *mtag; 737 738 mtag = m_tag_get(PACKET_TAG_VLAN, sizeof(u_int), 739 M_NOWAIT); 740 if (mtag == NULL) { 741 ifp->if_oerrors++; 742 m_freem(m); 743 continue; 744 } 745 *(u_int *)(mtag + 1) = ifv->ifv_tag; 746 m_tag_prepend(m, mtag); 747 } else { 748 /* 749 * insert the tag ourselves 750 */ 751 M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT); 752 if (m == NULL) { 753 printf("%s: unable to prepend encap header", 754 ifv->ifv_p->if_xname); 755 ifp->if_oerrors++; 756 continue; 757 } 758 759 switch (p->if_type) { 760 case IFT_ETHER: 761 { 762 struct ether_vlan_header *evl; 763 764 if (m->m_len < sizeof(struct ether_vlan_header)) 765 m = m_pullup(m, 766 sizeof(struct ether_vlan_header)); 767 if (m == NULL) { 768 printf("%s: unable to pullup encap " 769 "header", ifv->ifv_p->if_xname); 770 ifp->if_oerrors++; 771 continue; 772 } 773 774 /* 775 * Transform the Ethernet header into an 776 * Ethernet header with 802.1Q encapsulation. 777 */ 778 memmove(mtod(m, caddr_t), 779 mtod(m, caddr_t) + ifv->ifv_encaplen, 780 sizeof(struct ether_header)); 781 evl = mtod(m, struct ether_vlan_header *); 782 evl->evl_proto = evl->evl_encap_proto; 783 evl->evl_encap_proto = htons(ETHERTYPE_VLAN); 784 evl->evl_tag = htons(ifv->ifv_tag); 785 786 /* 787 * To cater for VLAN-aware layer 2 ethernet 788 * switches which may need to strip the tag 789 * before forwarding the packet, make sure 790 * the packet+tag is at least 68 bytes long. 791 * This is necessary because our parent will 792 * only pad to 64 bytes (ETHER_MIN_LEN) and 793 * some switches will not pad by themselves 794 * after deleting a tag. 795 */ 796 if (m->m_pkthdr.len < 797 (ETHER_MIN_LEN + ETHER_VLAN_ENCAP_LEN)) { 798 m_copyback(m, m->m_pkthdr.len, 799 (ETHER_MIN_LEN + 800 ETHER_VLAN_ENCAP_LEN) - 801 m->m_pkthdr.len, 802 vlan_zero_pad_buff); 803 } 804 break; 805 } 806 807 #ifdef DIAGNOSTIC 808 default: 809 panic("vlan_start: impossible"); 810 #endif 811 } 812 } 813 814 /* 815 * Send it, precisely as the parent's output routine 816 * would have. We are already running at splnet. 817 */ 818 IFQ_ENQUEUE(&p->if_snd, m, &pktattr, error); 819 if (error) { 820 /* mbuf is already freed */ 821 ifp->if_oerrors++; 822 continue; 823 } 824 825 ifp->if_opackets++; 826 if ((p->if_flags & IFF_OACTIVE) == 0) 827 (*p->if_start)(p); 828 } 829 830 ifp->if_flags &= ~IFF_OACTIVE; 831 } 832 833 /* 834 * Given an Ethernet frame, find a valid vlan interface corresponding to the 835 * given source interface and tag, then run the the real packet through 836 * the parent's input routine. 837 */ 838 void 839 vlan_input(struct ifnet *ifp, struct mbuf *m) 840 { 841 struct ifvlan *ifv; 842 u_int tag; 843 struct m_tag *mtag; 844 845 mtag = m_tag_find(m, PACKET_TAG_VLAN, NULL); 846 if (mtag != NULL) { 847 /* m contains a normal ethernet frame, the tag is in mtag */ 848 tag = *(u_int *)(mtag + 1); 849 m_tag_delete(m, mtag); 850 for (ifv = LIST_FIRST(&ifv_list); ifv != NULL; 851 ifv = LIST_NEXT(ifv, ifv_list)) 852 if (ifp == ifv->ifv_p && tag == ifv->ifv_tag) 853 break; 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 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 894 /* 895 * Now, remove the encapsulation header. The original 896 * header has already been fixed up above. 897 */ 898 if (ifv) { 899 memmove(mtod(m, caddr_t) + ifv->ifv_encaplen, 900 mtod(m, caddr_t), sizeof(struct ether_header)); 901 m_adj(m, ifv->ifv_encaplen); 902 } 903 } 904 905 if (ifv == NULL || 906 (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != 907 (IFF_UP|IFF_RUNNING)) { 908 m_freem(m); 909 ifp->if_noproto++; 910 return; 911 } 912 m->m_pkthdr.rcvif = &ifv->ifv_if; 913 ifv->ifv_if.if_ipackets++; 914 915 #if NBPFILTER > 0 916 if (ifv->ifv_if.if_bpf) 917 bpf_mtap(ifv->ifv_if.if_bpf, m); 918 #endif 919 920 /* Pass it back through the parent's input routine. */ 921 (*ifp->if_input)(&ifv->ifv_if, m); 922 } 923