| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_tap.c,v 1.128 2023/01/06 01:54:22 ozaki-r Exp $ */ | | 1 | /* $NetBSD: if_tap.c,v 1.129 2024/04/17 18:32:13 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.128 2023/01/06 01:54:22 ozaki-r Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.129 2024/04/17 18:32:13 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> |
| @@ -107,27 +107,27 @@ struct tap_softc { | | | @@ -107,27 +107,27 @@ struct tap_softc { |
107 | }; | | 107 | }; |
108 | | | 108 | |
109 | /* autoconf(9) glue */ | | 109 | /* autoconf(9) glue */ |
110 | | | 110 | |
111 | static int tap_match(device_t, cfdata_t, void *); | | 111 | static int tap_match(device_t, cfdata_t, void *); |
112 | static void tap_attach(device_t, device_t, void *); | | 112 | static void tap_attach(device_t, device_t, void *); |
113 | static int tap_detach(device_t, int); | | 113 | static int tap_detach(device_t, int); |
114 | | | 114 | |
115 | CFATTACH_DECL_NEW(tap, sizeof(struct tap_softc), | | 115 | CFATTACH_DECL_NEW(tap, sizeof(struct tap_softc), |
116 | tap_match, tap_attach, tap_detach, NULL); | | 116 | tap_match, tap_attach, tap_detach, NULL); |
117 | extern struct cfdriver tap_cd; | | 117 | extern struct cfdriver tap_cd; |
118 | | | 118 | |
119 | /* Real device access routines */ | | 119 | /* Real device access routines */ |
120 | static int tap_dev_close(struct tap_softc *); | | 120 | static void tap_dev_close(struct tap_softc *); |
121 | static int tap_dev_read(int, struct uio *, int); | | 121 | static int tap_dev_read(int, struct uio *, int); |
122 | static int tap_dev_write(int, struct uio *, int); | | 122 | static int tap_dev_write(int, struct uio *, int); |
123 | static int tap_dev_ioctl(int, u_long, void *, struct lwp *); | | 123 | static int tap_dev_ioctl(int, u_long, void *, struct lwp *); |
124 | static int tap_dev_poll(int, int, struct lwp *); | | 124 | static int tap_dev_poll(int, int, struct lwp *); |
125 | static int tap_dev_kqfilter(int, struct knote *); | | 125 | static int tap_dev_kqfilter(int, struct knote *); |
126 | | | 126 | |
127 | /* Fileops access routines */ | | 127 | /* Fileops access routines */ |
128 | static int tap_fops_close(file_t *); | | 128 | static int tap_fops_close(file_t *); |
129 | static int tap_fops_read(file_t *, off_t *, struct uio *, | | 129 | static int tap_fops_read(file_t *, off_t *, struct uio *, |
130 | kauth_cred_t, int); | | 130 | kauth_cred_t, int); |
131 | static int tap_fops_write(file_t *, off_t *, struct uio *, | | 131 | static int tap_fops_write(file_t *, off_t *, struct uio *, |
132 | kauth_cred_t, int); | | 132 | kauth_cred_t, int); |
133 | static int tap_fops_ioctl(file_t *, u_long, void *); | | 133 | static int tap_fops_ioctl(file_t *, u_long, void *); |
| @@ -749,67 +749,63 @@ tap_dev_cloner(struct lwp *l) | | | @@ -749,67 +749,63 @@ tap_dev_cloner(struct lwp *l) |
749 | * As for the other, the core of it is shared in tap_dev_close. What | | 749 | * As for the other, the core of it is shared in tap_dev_close. What |
750 | * it does is sufficient for the cdevsw interface, but the cloning interface | | 750 | * it does is sufficient for the cdevsw interface, but the cloning interface |
751 | * needs another thing: the interface is destroyed when the processes that | | 751 | * needs another thing: the interface is destroyed when the processes that |
752 | * created it closes it. | | 752 | * created it closes it. |
753 | */ | | 753 | */ |
754 | static int | | 754 | static int |
755 | tap_cdev_close(dev_t dev, int flags, int fmt, struct lwp *l) | | 755 | tap_cdev_close(dev_t dev, int flags, int fmt, struct lwp *l) |
756 | { | | 756 | { |
757 | struct tap_softc *sc = device_lookup_private(&tap_cd, minor(dev)); | | 757 | struct tap_softc *sc = device_lookup_private(&tap_cd, minor(dev)); |
758 | | | 758 | |
759 | if (sc == NULL) | | 759 | if (sc == NULL) |
760 | return ENXIO; | | 760 | return ENXIO; |
761 | | | 761 | |
762 | return tap_dev_close(sc); | | 762 | tap_dev_close(sc); |
| | | 763 | return 0; |
763 | } | | 764 | } |
764 | | | 765 | |
765 | /* | | 766 | /* |
766 | * It might happen that the administrator used ifconfig to externally destroy | | 767 | * It might happen that the administrator used ifconfig to externally destroy |
767 | * the interface. In that case, tap_fops_close will be called while | | 768 | * the interface. In that case, tap_fops_close will be called while |
768 | * tap_detach is already happening. If we called it again from here, we | | 769 | * tap_detach is already happening. If we called it again from here, we |
769 | * would dead lock. TAP_GOING ensures that this situation doesn't happen. | | 770 | * would dead lock. TAP_GOING ensures that this situation doesn't happen. |
770 | */ | | 771 | */ |
771 | static int | | 772 | static int |
772 | tap_fops_close(file_t *fp) | | 773 | tap_fops_close(file_t *fp) |
773 | { | | 774 | { |
774 | struct tap_softc *sc; | | 775 | struct tap_softc *sc; |
775 | int unit = fp->f_devunit; | | 776 | int unit = fp->f_devunit; |
776 | int error; | | 777 | int error; |
777 | | | 778 | |
778 | sc = device_lookup_private(&tap_cd, unit); | | 779 | sc = device_lookup_private(&tap_cd, unit); |
779 | if (sc == NULL) | | 780 | if (sc == NULL) |
780 | return ENXIO; | | 781 | return ENXIO; |
781 | | | 782 | |
782 | /* tap_dev_close currently always succeeds, but it might not | | | |
783 | * always be the case. */ | | | |
784 | KERNEL_LOCK(1, NULL); | | 783 | KERNEL_LOCK(1, NULL); |
785 | if ((error = tap_dev_close(sc)) != 0) { | | 784 | tap_dev_close(sc); |
786 | KERNEL_UNLOCK_ONE(NULL); | | | |
787 | return error; | | | |
788 | } | | | |
789 | | | 785 | |
790 | /* Destroy the device now that it is no longer useful, | | 786 | /* Destroy the device now that it is no longer useful, |
791 | * unless it's already being destroyed. */ | | 787 | * unless it's already being destroyed. */ |
792 | if ((sc->sc_flags & TAP_GOING) != 0) { | | 788 | if ((sc->sc_flags & TAP_GOING) != 0) { |
793 | KERNEL_UNLOCK_ONE(NULL); | | 789 | KERNEL_UNLOCK_ONE(NULL); |
794 | return 0; | | 790 | return 0; |
795 | } | | 791 | } |
796 | | | 792 | |
797 | error = tap_clone_destroyer(sc->sc_dev); | | 793 | error = tap_clone_destroyer(sc->sc_dev); |
798 | KERNEL_UNLOCK_ONE(NULL); | | 794 | KERNEL_UNLOCK_ONE(NULL); |
799 | return error; | | 795 | return error; |
800 | } | | 796 | } |
801 | | | 797 | |
802 | static int | | 798 | static void |
803 | tap_dev_close(struct tap_softc *sc) | | 799 | tap_dev_close(struct tap_softc *sc) |
804 | { | | 800 | { |
805 | struct ifnet *ifp; | | 801 | struct ifnet *ifp; |
806 | int s; | | 802 | int s; |
807 | | | 803 | |
808 | s = splnet(); | | 804 | s = splnet(); |
809 | /* Let tap_start handle packets again */ | | 805 | /* Let tap_start handle packets again */ |
810 | ifp = &sc->sc_ec.ec_if; | | 806 | ifp = &sc->sc_ec.ec_if; |
811 | ifp->if_flags &= ~IFF_OACTIVE; | | 807 | ifp->if_flags &= ~IFF_OACTIVE; |
812 | | | 808 | |
813 | /* Purge output queue */ | | 809 | /* Purge output queue */ |
814 | if (!(IFQ_IS_EMPTY(&ifp->if_snd))) { | | 810 | if (!(IFQ_IS_EMPTY(&ifp->if_snd))) { |
815 | struct mbuf *m; | | 811 | struct mbuf *m; |
| @@ -822,28 +818,26 @@ tap_dev_close(struct tap_softc *sc) | | | @@ -822,28 +818,26 @@ tap_dev_close(struct tap_softc *sc) |
822 | if_statadd2(ifp, if_opackets, 1, if_obytes, m->m_len); | | 818 | if_statadd2(ifp, if_opackets, 1, if_obytes, m->m_len); |
823 | bpf_mtap(ifp, m, BPF_D_OUT); | | 819 | bpf_mtap(ifp, m, BPF_D_OUT); |
824 | m_freem(m); | | 820 | m_freem(m); |
825 | } | | 821 | } |
826 | } | | 822 | } |
827 | splx(s); | | 823 | splx(s); |
828 | | | 824 | |
829 | if (sc->sc_sih != NULL) { | | 825 | if (sc->sc_sih != NULL) { |
830 | softint_disestablish(sc->sc_sih); | | 826 | softint_disestablish(sc->sc_sih); |
831 | sc->sc_sih = NULL; | | 827 | sc->sc_sih = NULL; |
832 | } | | 828 | } |
833 | sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO); | | 829 | sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO); |
834 | if_link_state_change(ifp, LINK_STATE_DOWN); | | 830 | if_link_state_change(ifp, LINK_STATE_DOWN); |
835 | | | | |
836 | return 0; | | | |
837 | } | | 831 | } |
838 | | | 832 | |
839 | static int | | 833 | static int |
840 | tap_cdev_read(dev_t dev, struct uio *uio, int flags) | | 834 | tap_cdev_read(dev_t dev, struct uio *uio, int flags) |
841 | { | | 835 | { |
842 | | | 836 | |
843 | return tap_dev_read(minor(dev), uio, flags); | | 837 | return tap_dev_read(minor(dev), uio, flags); |
844 | } | | 838 | } |
845 | | | 839 | |
846 | static int | | 840 | static int |
847 | tap_fops_read(file_t *fp, off_t *offp, struct uio *uio, | | 841 | tap_fops_read(file_t *fp, off_t *offp, struct uio *uio, |
848 | kauth_cred_t cred, int flags) | | 842 | kauth_cred_t cred, int flags) |
849 | { | | 843 | { |