npf: Make sure to initialize portmap_lock only once. PR kern/55586diff -r1.43 -r1.44 src/sys/net/npf/npf.c
(riastradh)
--- src/sys/net/npf/npf.c 2020/05/30 14:16:56 1.43
+++ src/sys/net/npf/npf.c 2020/08/27 18:50:25 1.44
@@ -23,55 +23,59 @@ | @@ -23,55 +23,59 @@ | |||
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
27 | * POSSIBILITY OF SUCH DAMAGE. | 27 | * POSSIBILITY OF SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | /* | 30 | /* | |
31 | * NPF main: dynamic load/initialisation and unload routines. | 31 | * NPF main: dynamic load/initialisation and unload routines. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #ifdef _KERNEL | 34 | #ifdef _KERNEL | |
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.43 2020/05/30 14:16:56 rmind Exp $"); | 36 | __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.44 2020/08/27 18:50:25 riastradh Exp $"); | |
37 | 37 | |||
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | #include <sys/types.h> | 39 | #include <sys/types.h> | |
40 | 40 | |||
41 | #include <sys/conf.h> | 41 | #include <sys/conf.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/percpu.h> | 43 | #include <sys/percpu.h> | |
44 | #include <sys/xcall.h> | 44 | #include <sys/xcall.h> | |
45 | #endif | 45 | #endif | |
46 | 46 | |||
47 | #include "npf_impl.h" | 47 | #include "npf_impl.h" | |
48 | #include "npf_conn.h" | 48 | #include "npf_conn.h" | |
49 | 49 | |||
50 | static __read_mostly npf_t * npf_kernel_ctx = NULL; | 50 | static __read_mostly npf_t * npf_kernel_ctx = NULL; | |
51 | 51 | |||
52 | __dso_public int | 52 | __dso_public int | |
53 | npfk_sysinit(unsigned nworkers) | 53 | npfk_sysinit(unsigned nworkers) | |
54 | { | 54 | { | |
55 | ||||
55 | npf_bpf_sysinit(); | 56 | npf_bpf_sysinit(); | |
56 | npf_tableset_sysinit(); | 57 | npf_tableset_sysinit(); | |
57 | npf_nat_sysinit(); | 58 | npf_nat_sysinit(); | |
59 | npf_portmap_sysinit(); | |||
58 | return npf_worker_sysinit(nworkers); | 60 | return npf_worker_sysinit(nworkers); | |
59 | } | 61 | } | |
60 | 62 | |||
61 | __dso_public void | 63 | __dso_public void | |
62 | npfk_sysfini(void) | 64 | npfk_sysfini(void) | |
63 | { | 65 | { | |
66 | ||||
64 | npf_worker_sysfini(); | 67 | npf_worker_sysfini(); | |
68 | npf_portmap_sysfini(); | |||
65 | npf_nat_sysfini(); | 69 | npf_nat_sysfini(); | |
66 | npf_tableset_sysfini(); | 70 | npf_tableset_sysfini(); | |
67 | npf_bpf_sysfini(); | 71 | npf_bpf_sysfini(); | |
68 | } | 72 | } | |
69 | 73 | |||
70 | __dso_public npf_t * | 74 | __dso_public npf_t * | |
71 | npfk_create(int flags, const npf_mbufops_t *mbufops, | 75 | npfk_create(int flags, const npf_mbufops_t *mbufops, | |
72 | const npf_ifops_t *ifops, void *arg) | 76 | const npf_ifops_t *ifops, void *arg) | |
73 | { | 77 | { | |
74 | npf_t *npf; | 78 | npf_t *npf; | |
75 | 79 | |||
76 | npf = kmem_zalloc(sizeof(npf_t), KM_SLEEP); | 80 | npf = kmem_zalloc(sizeof(npf_t), KM_SLEEP); | |
77 | npf->ebr = npf_ebr_create(); | 81 | npf->ebr = npf_ebr_create(); |
--- src/sys/net/npf/npf_impl.h 2020/05/30 14:16:56 1.81
+++ src/sys/net/npf/npf_impl.h 2020/08/27 18:50:25 1.82
@@ -462,26 +462,29 @@ void npf_state_sysinit(npf_t *); | @@ -462,26 +462,29 @@ void npf_state_sysinit(npf_t *); | |||
462 | void npf_state_sysfini(npf_t *); | 462 | void npf_state_sysfini(npf_t *); | |
463 | 463 | |||
464 | bool npf_state_init(npf_cache_t *, npf_state_t *); | 464 | bool npf_state_init(npf_cache_t *, npf_state_t *); | |
465 | bool npf_state_inspect(npf_cache_t *, npf_state_t *, npf_flow_t); | 465 | bool npf_state_inspect(npf_cache_t *, npf_state_t *, npf_flow_t); | |
466 | int npf_state_etime(npf_t *, const npf_state_t *, const int); | 466 | int npf_state_etime(npf_t *, const npf_state_t *, const int); | |
467 | void npf_state_destroy(npf_state_t *); | 467 | void npf_state_destroy(npf_state_t *); | |
468 | 468 | |||
469 | void npf_state_tcp_sysinit(npf_t *); | 469 | void npf_state_tcp_sysinit(npf_t *); | |
470 | void npf_state_tcp_sysfini(npf_t *); | 470 | void npf_state_tcp_sysfini(npf_t *); | |
471 | bool npf_state_tcp(npf_cache_t *, npf_state_t *, npf_flow_t); | 471 | bool npf_state_tcp(npf_cache_t *, npf_state_t *, npf_flow_t); | |
472 | int npf_state_tcp_timeout(npf_t *, const npf_state_t *); | 472 | int npf_state_tcp_timeout(npf_t *, const npf_state_t *); | |
473 | 473 | |||
474 | /* Portmap. */ | 474 | /* Portmap. */ | |
475 | void npf_portmap_sysinit(void); | |||
476 | void npf_portmap_sysfini(void); | |||
477 | ||||
475 | void npf_portmap_init(npf_t *); | 478 | void npf_portmap_init(npf_t *); | |
476 | void npf_portmap_fini(npf_t *); | 479 | void npf_portmap_fini(npf_t *); | |
477 | 480 | |||
478 | npf_portmap_t * npf_portmap_create(int, int); | 481 | npf_portmap_t * npf_portmap_create(int, int); | |
479 | void npf_portmap_destroy(npf_portmap_t *); | 482 | void npf_portmap_destroy(npf_portmap_t *); | |
480 | 483 | |||
481 | in_port_t npf_portmap_get(npf_portmap_t *, int, const npf_addr_t *); | 484 | in_port_t npf_portmap_get(npf_portmap_t *, int, const npf_addr_t *); | |
482 | bool npf_portmap_take(npf_portmap_t *, int, const npf_addr_t *, in_port_t); | 485 | bool npf_portmap_take(npf_portmap_t *, int, const npf_addr_t *, in_port_t); | |
483 | void npf_portmap_put(npf_portmap_t *, int, const npf_addr_t *, in_port_t); | 486 | void npf_portmap_put(npf_portmap_t *, int, const npf_addr_t *, in_port_t); | |
484 | void npf_portmap_flush(npf_portmap_t *); | 487 | void npf_portmap_flush(npf_portmap_t *); | |
485 | 488 | |||
486 | /* NAT. */ | 489 | /* NAT. */ | |
487 | void npf_nat_sysinit(void); | 490 | void npf_nat_sysinit(void); |
--- src/sys/net/npf/npf_portmap.c 2020/05/30 14:16:56 1.5
+++ src/sys/net/npf/npf_portmap.c 2020/08/27 18:50:25 1.6
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | */ | 25 | */ | |
26 | 26 | |||
27 | /* | 27 | /* | |
28 | * NPF port map mechanism. | 28 | * NPF port map mechanism. | |
29 | * | 29 | * | |
30 | * The port map is a bitmap used to track TCP/UDP ports used for | 30 | * The port map is a bitmap used to track TCP/UDP ports used for | |
31 | * translation. Port maps are per IP addresses, therefore multiple | 31 | * translation. Port maps are per IP addresses, therefore multiple | |
32 | * NAT policies operating on the same IP address will share the | 32 | * NAT policies operating on the same IP address will share the | |
33 | * same port map. | 33 | * same port map. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #ifdef _KERNEL | 36 | #ifdef _KERNEL | |
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.5 2020/05/30 14:16:56 rmind Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.6 2020/08/27 18:50:25 riastradh Exp $"); | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/types.h> | 41 | #include <sys/types.h> | |
42 | 42 | |||
43 | #include <sys/atomic.h> | 43 | #include <sys/atomic.h> | |
44 | #include <sys/bitops.h> | 44 | #include <sys/bitops.h> | |
45 | #include <sys/kmem.h> | 45 | #include <sys/kmem.h> | |
46 | #include <sys/mutex.h> | 46 | #include <sys/mutex.h> | |
47 | #include <sys/cprng.h> | 47 | #include <sys/cprng.h> | |
48 | #include <sys/thmap.h> | 48 | #include <sys/thmap.h> | |
49 | #endif | 49 | #endif | |
50 | 50 | |||
51 | #include "npf_impl.h" | 51 | #include "npf_impl.h" | |
@@ -99,54 +99,70 @@ typedef struct bitmap { | @@ -99,54 +99,70 @@ typedef struct bitmap { | |||
99 | #define NPF_PORTMAP_MAXPORT 65535 | 99 | #define NPF_PORTMAP_MAXPORT 65535 | |
100 | 100 | |||
101 | struct npf_portmap { | 101 | struct npf_portmap { | |
102 | thmap_t * addr_map; | 102 | thmap_t * addr_map; | |
103 | LIST_HEAD(, bitmap) bitmap_list; | 103 | LIST_HEAD(, bitmap) bitmap_list; | |
104 | kmutex_t list_lock; | 104 | kmutex_t list_lock; | |
105 | int min_port; | 105 | int min_port; | |
106 | int max_port; | 106 | int max_port; | |
107 | }; | 107 | }; | |
108 | 108 | |||
109 | static kmutex_t portmap_lock; | 109 | static kmutex_t portmap_lock; | |
110 | 110 | |||
111 | void | 111 | void | |
112 | npf_portmap_sysinit(void) | |||
113 | { | |||
114 | ||||
115 | mutex_init(&portmap_lock, MUTEX_DEFAULT, IPL_SOFTNET); | |||
116 | __insn_barrier(); | |||
117 | } | |||
118 | ||||
119 | void | |||
120 | npf_portmap_sysfini(void) | |||
121 | { | |||
122 | ||||
123 | mutex_destroy(&portmap_lock); | |||
124 | __insn_barrier(); | |||
125 | } | |||
126 | ||||
127 | void | |||
112 | npf_portmap_init(npf_t *npf) | 128 | npf_portmap_init(npf_t *npf) | |
113 | { | 129 | { | |
114 | npf_portmap_t *pm = npf_portmap_create( | 130 | npf_portmap_t *pm = npf_portmap_create( | |
115 | NPF_PORTMAP_MINPORT, NPF_PORTMAP_MAXPORT); | 131 | NPF_PORTMAP_MINPORT, NPF_PORTMAP_MAXPORT); | |
116 | npf_param_t param_map[] = { | 132 | npf_param_t param_map[] = { | |
117 | { | 133 | { | |
118 | "portmap.min_port", | 134 | "portmap.min_port", | |
119 | &pm->min_port, | 135 | &pm->min_port, | |
120 | .default_val = NPF_PORTMAP_MINPORT, | 136 | .default_val = NPF_PORTMAP_MINPORT, | |
121 | .min = 1024, .max = 65535 | 137 | .min = 1024, .max = 65535 | |
122 | }, | 138 | }, | |
123 | { | 139 | { | |
124 | "portmap.max_port", | 140 | "portmap.max_port", | |
125 | &pm->max_port, | 141 | &pm->max_port, | |
126 | .default_val = 49151, // RFC 6335 | 142 | .default_val = 49151, // RFC 6335 | |
127 | .min = 1024, .max = 65535 | 143 | .min = 1024, .max = 65535 | |
128 | } | 144 | } | |
129 | }; | 145 | }; | |
146 | ||||
130 | npf_param_register(npf, param_map, __arraycount(param_map)); | 147 | npf_param_register(npf, param_map, __arraycount(param_map)); | |
131 | mutex_init(&portmap_lock, MUTEX_DEFAULT, IPL_SOFTNET); | |||
132 | npf->portmap = pm; | 148 | npf->portmap = pm; | |
133 | } | 149 | } | |
134 | 150 | |||
135 | void | 151 | void | |
136 | npf_portmap_fini(npf_t *npf) | 152 | npf_portmap_fini(npf_t *npf) | |
137 | { | 153 | { | |
154 | ||||
138 | npf_portmap_destroy(npf->portmap); | 155 | npf_portmap_destroy(npf->portmap); | |
139 | mutex_destroy(&portmap_lock); | |||
140 | npf->portmap = NULL; // diagnostic | 156 | npf->portmap = NULL; // diagnostic | |
141 | } | 157 | } | |
142 | 158 | |||
143 | npf_portmap_t * | 159 | npf_portmap_t * | |
144 | npf_portmap_create(int min_port, int max_port) | 160 | npf_portmap_create(int min_port, int max_port) | |
145 | { | 161 | { | |
146 | npf_portmap_t *pm; | 162 | npf_portmap_t *pm; | |
147 | 163 | |||
148 | pm = kmem_zalloc(sizeof(npf_portmap_t), KM_SLEEP); | 164 | pm = kmem_zalloc(sizeof(npf_portmap_t), KM_SLEEP); | |
149 | mutex_init(&pm->list_lock, MUTEX_DEFAULT, IPL_SOFTNET); | 165 | mutex_init(&pm->list_lock, MUTEX_DEFAULT, IPL_SOFTNET); | |
150 | pm->addr_map = thmap_create(0, NULL, THMAP_NOCOPY); | 166 | pm->addr_map = thmap_create(0, NULL, THMAP_NOCOPY); | |
151 | pm->min_port = min_port; | 167 | pm->min_port = min_port; | |
152 | pm->max_port = max_port; | 168 | pm->max_port = max_port; |
--- src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c 2020/05/30 21:00:31 1.18
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c 2020/08/27 18:50:25 1.19
@@ -61,46 +61,45 @@ void | @@ -61,46 +61,45 @@ void | |||
61 | npf_test_init(int (*pton_func)(int, const char *, void *), | 61 | npf_test_init(int (*pton_func)(int, const char *, void *), | |
62 | const char *(*ntop_func)(int, const void *, char *, socklen_t), | 62 | const char *(*ntop_func)(int, const void *, char *, socklen_t), | |
63 | long (*rndfunc)(void)) | 63 | long (*rndfunc)(void)) | |
64 | { | 64 | { | |
65 | npf_t *npf; | 65 | npf_t *npf; | |
66 | 66 | |||
67 | #ifdef __NetBSD__ | 67 | #ifdef __NetBSD__ | |
68 | // XXX: Workaround for npf_init() | 68 | // XXX: Workaround for npf_init() | |
69 | if ((npf = npf_getkernctx()) != NULL) { | 69 | if ((npf = npf_getkernctx()) != NULL) { | |
70 | npf_worker_discharge(npf); | 70 | npf_worker_discharge(npf); | |
71 | npf_worker_sysfini(); | 71 | npf_worker_sysfini(); | |
72 | } | 72 | } | |
73 | #endif | 73 | #endif | |
74 | npfk_sysinit(0); | |||
75 | npf = npfk_create(0, &npftest_mbufops, &npftest_ifops, NULL); | 74 | npf = npfk_create(0, &npftest_mbufops, &npftest_ifops, NULL); | |
76 | npfk_thread_register(npf); | 75 | npfk_thread_register(npf); | |
77 | npf_setkernctx(npf); | 76 | npf_setkernctx(npf); | |
78 | 77 | |||
79 | npf_state_setsampler(npf_state_sample); | 78 | npf_state_setsampler(npf_state_sample); | |
80 | _pton_func = pton_func; | 79 | _pton_func = pton_func; | |
81 | _ntop_func = ntop_func; | 80 | _ntop_func = ntop_func; | |
82 | _random_func = rndfunc; | 81 | _random_func = rndfunc; | |
83 | 82 | |||
84 | (void)npf_test_addif(IFNAME_DUMMY, false, false); | 83 | (void)npf_test_addif(IFNAME_DUMMY, false, false); | |
85 | } | 84 | } | |
86 | 85 | |||
87 | void | 86 | void | |
88 | npf_test_fini(void) | 87 | npf_test_fini(void) | |
89 | { | 88 | { | |
90 | npf_t *npf = npf_getkernctx(); | 89 | npf_t *npf = npf_getkernctx(); | |
90 | ||||
91 | npfk_thread_unregister(npf); | 91 | npfk_thread_unregister(npf); | |
92 | npfk_destroy(npf); | 92 | npfk_destroy(npf); | |
93 | npfk_sysfini(); | |||
94 | } | 93 | } | |
95 | 94 | |||
96 | int | 95 | int | |
97 | npf_test_load(const void *buf, size_t len, bool verbose) | 96 | npf_test_load(const void *buf, size_t len, bool verbose) | |
98 | { | 97 | { | |
99 | nvlist_t *npf_dict; | 98 | nvlist_t *npf_dict; | |
100 | npf_error_t error; | 99 | npf_error_t error; | |
101 | int ret; | 100 | int ret; | |
102 | 101 | |||
103 | npf_dict = nvlist_unpack(buf, len, 0); | 102 | npf_dict = nvlist_unpack(buf, len, 0); | |
104 | if (!npf_dict) { | 103 | if (!npf_dict) { | |
105 | printf("%s: could not unpack the nvlist\n", __func__); | 104 | printf("%s: could not unpack the nvlist\n", __func__); | |
106 | return EINVAL; | 105 | return EINVAL; |