| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_tap.c,v 1.129 2024/04/17 18:32:13 riastradh Exp $ */ | | 1 | /* $NetBSD: if_tap.c,v 1.130 2024/04/17 18:52:25 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation. | | 4 | * Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -23,27 +23,27 @@ | | | @@ -23,27 +23,27 @@ |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. | | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | /* | | 29 | /* |
30 | * tap(4) is a virtual Ethernet interface. It appears as a real Ethernet | | 30 | * tap(4) is a virtual Ethernet interface. It appears as a real Ethernet |
31 | * device to the system, but can also be accessed by userland through a | | 31 | * device to the system, but can also be accessed by userland through a |
32 | * character device interface, which allows reading and injecting frames. | | 32 | * character device interface, which allows reading and injecting frames. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | __KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.129 2024/04/17 18:32:13 riastradh Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.130 2024/04/17 18:52:25 riastradh Exp $"); |
37 | | | 37 | |
38 | #if defined(_KERNEL_OPT) | | 38 | #if defined(_KERNEL_OPT) |
39 | | | 39 | |
40 | #include "opt_modular.h" | | 40 | #include "opt_modular.h" |
41 | #endif | | 41 | #endif |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/atomic.h> | | 44 | #include <sys/atomic.h> |
45 | #include <sys/conf.h> | | 45 | #include <sys/conf.h> |
46 | #include <sys/cprng.h> | | 46 | #include <sys/cprng.h> |
47 | #include <sys/device.h> | | 47 | #include <sys/device.h> |
48 | #include <sys/file.h> | | 48 | #include <sys/file.h> |
49 | #include <sys/filedesc.h> | | 49 | #include <sys/filedesc.h> |
| @@ -200,27 +200,27 @@ static void tap_softintr(void *); | | | @@ -200,27 +200,27 @@ static void tap_softintr(void *); |
200 | * an Ethernet device. | | 200 | * an Ethernet device. |
201 | * | | 201 | * |
202 | * Here are the bits needed for a clonable interface. | | 202 | * Here are the bits needed for a clonable interface. |
203 | */ | | 203 | */ |
204 | static int tap_clone_create(struct if_clone *, int); | | 204 | static int tap_clone_create(struct if_clone *, int); |
205 | static int tap_clone_destroy(struct ifnet *); | | 205 | static int tap_clone_destroy(struct ifnet *); |
206 | | | 206 | |
207 | struct if_clone tap_cloners = IF_CLONE_INITIALIZER("tap", | | 207 | struct if_clone tap_cloners = IF_CLONE_INITIALIZER("tap", |
208 | tap_clone_create, | | 208 | tap_clone_create, |
209 | tap_clone_destroy); | | 209 | tap_clone_destroy); |
210 | | | 210 | |
211 | /* Helper functions shared by the two cloning code paths */ | | 211 | /* Helper functions shared by the two cloning code paths */ |
212 | static struct tap_softc * tap_clone_creator(int); | | 212 | static struct tap_softc * tap_clone_creator(int); |
213 | int tap_clone_destroyer(device_t); | | 213 | static void tap_clone_destroyer(device_t); |
214 | | | 214 | |
215 | static struct sysctllog *tap_sysctl_clog; | | 215 | static struct sysctllog *tap_sysctl_clog; |
216 | | | 216 | |
217 | #ifdef _MODULE | | 217 | #ifdef _MODULE |
218 | devmajor_t tap_bmajor = -1, tap_cmajor = -1; | | 218 | devmajor_t tap_bmajor = -1, tap_cmajor = -1; |
219 | #endif | | 219 | #endif |
220 | | | 220 | |
221 | static u_int tap_count; | | 221 | static u_int tap_count; |
222 | | | 222 | |
223 | void | | 223 | void |
224 | tapattach(int n) | | 224 | tapattach(int n) |
225 | { | | 225 | { |
226 | | | 226 | |
| @@ -615,53 +615,45 @@ tap_clone_creator(int unit) | | | @@ -615,53 +615,45 @@ tap_clone_creator(int unit) |
615 | cf->cf_atname = tap_ca.ca_name; | | 615 | cf->cf_atname = tap_ca.ca_name; |
616 | if (unit == -1) { | | 616 | if (unit == -1) { |
617 | /* let autoconf find the first free one */ | | 617 | /* let autoconf find the first free one */ |
618 | cf->cf_unit = 0; | | 618 | cf->cf_unit = 0; |
619 | cf->cf_fstate = FSTATE_STAR; | | 619 | cf->cf_fstate = FSTATE_STAR; |
620 | } else { | | 620 | } else { |
621 | cf->cf_unit = unit; | | 621 | cf->cf_unit = unit; |
622 | cf->cf_fstate = FSTATE_NOTFOUND; | | 622 | cf->cf_fstate = FSTATE_NOTFOUND; |
623 | } | | 623 | } |
624 | | | 624 | |
625 | return device_private(config_attach_pseudo(cf)); | | 625 | return device_private(config_attach_pseudo(cf)); |
626 | } | | 626 | } |
627 | | | 627 | |
628 | /* | | | |
629 | * The clean design of if_clone and autoconf(9) makes that part | | | |
630 | * really straightforward. The second argument of config_detach | | | |
631 | * means neither QUIET nor FORCED. | | | |
632 | */ | | | |
633 | static int | | 628 | static int |
634 | tap_clone_destroy(struct ifnet *ifp) | | 629 | tap_clone_destroy(struct ifnet *ifp) |
635 | { | | 630 | { |
636 | struct tap_softc *sc = ifp->if_softc; | | 631 | struct tap_softc *sc = ifp->if_softc; |
637 | int error = tap_clone_destroyer(sc->sc_dev); | | | |
638 | | | 632 | |
639 | if (error == 0) | | 633 | tap_clone_destroyer(sc->sc_dev); |
640 | atomic_dec_uint(&tap_count); | | 634 | atomic_dec_uint(&tap_count); |
641 | return error; | | 635 | return 0; |
642 | } | | 636 | } |
643 | | | 637 | |
644 | int | | 638 | static void |
645 | tap_clone_destroyer(device_t dev) | | 639 | tap_clone_destroyer(device_t dev) |
646 | { | | 640 | { |
647 | cfdata_t cf = device_cfdata(dev); | | 641 | cfdata_t cf = device_cfdata(dev); |
648 | int error; | | 642 | int error; |
649 | | | 643 | |
650 | if ((error = config_detach(dev, 0)) != 0) | | 644 | error = config_detach(dev, 0); |
651 | aprint_error_dev(dev, "unable to detach instance\n"); | | 645 | KASSERTMSG(error == 0, "error=%d", error); |
652 | kmem_free(cf, sizeof(*cf)); | | 646 | kmem_free(cf, sizeof(*cf)); |
653 | | | | |
654 | return error; | | | |
655 | } | | 647 | } |
656 | | | 648 | |
657 | /* | | 649 | /* |
658 | * tap(4) is a bit of an hybrid device. It can be used in two different | | 650 | * tap(4) is a bit of an hybrid device. It can be used in two different |
659 | * ways: | | 651 | * ways: |
660 | * 1. ifconfig tapN create, then use /dev/tapN to read/write off it. | | 652 | * 1. ifconfig tapN create, then use /dev/tapN to read/write off it. |
661 | * 2. open /dev/tap, get a new interface created and read/write off it. | | 653 | * 2. open /dev/tap, get a new interface created and read/write off it. |
662 | * That interface is destroyed when the process that had it created exits. | | 654 | * That interface is destroyed when the process that had it created exits. |
663 | * | | 655 | * |
664 | * The first way is managed by the cdevsw structure, and you access interfaces | | 656 | * The first way is managed by the cdevsw structure, and you access interfaces |
665 | * through a (major, minor) mapping: tap4 is obtained by the minor number | | 657 | * through a (major, minor) mapping: tap4 is obtained by the minor number |
666 | * 4. The entry points for the cdevsw interface are prefixed by tap_cdev_. | | 658 | * 4. The entry points for the cdevsw interface are prefixed by tap_cdev_. |
667 | * | | 659 | * |
| @@ -764,45 +756,44 @@ tap_cdev_close(dev_t dev, int flags, int | | | @@ -764,45 +756,44 @@ tap_cdev_close(dev_t dev, int flags, int |
764 | } | | 756 | } |
765 | | | 757 | |
766 | /* | | 758 | /* |
767 | * It might happen that the administrator used ifconfig to externally destroy | | 759 | * It might happen that the administrator used ifconfig to externally destroy |
768 | * the interface. In that case, tap_fops_close will be called while | | 760 | * the interface. In that case, tap_fops_close will be called while |
769 | * tap_detach is already happening. If we called it again from here, we | | 761 | * tap_detach is already happening. If we called it again from here, we |
770 | * would dead lock. TAP_GOING ensures that this situation doesn't happen. | | 762 | * would dead lock. TAP_GOING ensures that this situation doesn't happen. |
771 | */ | | 763 | */ |
772 | static int | | 764 | static int |
773 | tap_fops_close(file_t *fp) | | 765 | tap_fops_close(file_t *fp) |
774 | { | | 766 | { |
775 | struct tap_softc *sc; | | 767 | struct tap_softc *sc; |
776 | int unit = fp->f_devunit; | | 768 | int unit = fp->f_devunit; |
777 | int error; | | | |
778 | | | 769 | |
779 | sc = device_lookup_private(&tap_cd, unit); | | 770 | sc = device_lookup_private(&tap_cd, unit); |
780 | if (sc == NULL) | | 771 | if (sc == NULL) |
781 | return ENXIO; | | 772 | return ENXIO; |
782 | | | 773 | |
783 | KERNEL_LOCK(1, NULL); | | 774 | KERNEL_LOCK(1, NULL); |
784 | tap_dev_close(sc); | | 775 | tap_dev_close(sc); |
785 | | | 776 | |
786 | /* Destroy the device now that it is no longer useful, | | 777 | /* |
787 | * unless it's already being destroyed. */ | | 778 | * Destroy the device now that it is no longer useful, unless |
788 | if ((sc->sc_flags & TAP_GOING) != 0) { | | 779 | * it's already being destroyed. |
789 | KERNEL_UNLOCK_ONE(NULL); | | 780 | */ |
790 | return 0; | | 781 | if ((sc->sc_flags & TAP_GOING) != 0) |
791 | } | | 782 | goto out; |
| | | 783 | tap_clone_destroyer(sc->sc_dev); |
792 | | | 784 | |
793 | error = tap_clone_destroyer(sc->sc_dev); | | 785 | out: KERNEL_UNLOCK_ONE(NULL); |
794 | KERNEL_UNLOCK_ONE(NULL); | | 786 | return 0; |
795 | return error; | | | |
796 | } | | 787 | } |
797 | | | 788 | |
798 | static void | | 789 | static void |
799 | tap_dev_close(struct tap_softc *sc) | | 790 | tap_dev_close(struct tap_softc *sc) |
800 | { | | 791 | { |
801 | struct ifnet *ifp; | | 792 | struct ifnet *ifp; |
802 | int s; | | 793 | int s; |
803 | | | 794 | |
804 | s = splnet(); | | 795 | s = splnet(); |
805 | /* Let tap_start handle packets again */ | | 796 | /* Let tap_start handle packets again */ |
806 | ifp = &sc->sc_ec.ec_if; | | 797 | ifp = &sc->sc_ec.ec_if; |
807 | ifp->if_flags &= ~IFF_OACTIVE; | | 798 | ifp->if_flags &= ~IFF_OACTIVE; |
808 | | | 799 | |