npf_params.c revision 1.3 1 1.1 rmind /*-
2 1.3 rmind * Copyright (c) 2019-2020 The NetBSD Foundation, Inc.
3 1.1 rmind * All rights reserved.
4 1.1 rmind *
5 1.1 rmind * Redistribution and use in source and binary forms, with or without
6 1.1 rmind * modification, are permitted provided that the following conditions
7 1.1 rmind * are met:
8 1.1 rmind * 1. Redistributions of source code must retain the above copyright
9 1.1 rmind * notice, this list of conditions and the following disclaimer.
10 1.1 rmind * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 rmind * notice, this list of conditions and the following disclaimer in the
12 1.1 rmind * documentation and/or other materials provided with the distribution.
13 1.1 rmind *
14 1.1 rmind * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
15 1.1 rmind * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 1.1 rmind * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 1.1 rmind * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
18 1.1 rmind * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 1.1 rmind * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 1.1 rmind * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 1.1 rmind * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 1.1 rmind * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 1.1 rmind * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 1.1 rmind * POSSIBILITY OF SUCH DAMAGE.
25 1.1 rmind */
26 1.1 rmind
27 1.1 rmind #ifdef _KERNEL
28 1.1 rmind #include <sys/cdefs.h>
29 1.3 rmind __KERNEL_RCSID(0, "$NetBSD: npf_params.c,v 1.3 2020/05/30 14:16:56 rmind Exp $");
30 1.1 rmind
31 1.1 rmind #include <sys/param.h>
32 1.1 rmind #include <sys/types.h>
33 1.1 rmind
34 1.1 rmind #include <sys/kmem.h>
35 1.1 rmind #include <sys/queue.h>
36 1.1 rmind #include <sys/thmap.h>
37 1.1 rmind #endif
38 1.1 rmind
39 1.1 rmind #include "npf_impl.h"
40 1.1 rmind
41 1.1 rmind typedef struct npf_paramreg {
42 1.1 rmind struct npf_paramreg * next;
43 1.1 rmind unsigned count;
44 1.1 rmind npf_param_t params[];
45 1.1 rmind } npf_paramreg_t;
46 1.1 rmind
47 1.1 rmind struct npf_paraminfo {
48 1.1 rmind npf_paramreg_t * list;
49 1.1 rmind thmap_t * map;
50 1.1 rmind };
51 1.1 rmind
52 1.3 rmind static inline void
53 1.3 rmind npf_param_general_register(npf_t *npf)
54 1.3 rmind {
55 1.3 rmind npf_param_t param_map[] = {
56 1.3 rmind {
57 1.3 rmind "ip4.reassembly",
58 1.3 rmind &npf->ip4_reassembly,
59 1.3 rmind .default_val = 0, // false
60 1.3 rmind .min = 0, .max = 1
61 1.3 rmind },
62 1.3 rmind {
63 1.3 rmind "ip6.reassembly",
64 1.3 rmind &npf->ip6_reassembly,
65 1.3 rmind .default_val = 0, // false
66 1.3 rmind .min = 0, .max = 1
67 1.3 rmind },
68 1.3 rmind };
69 1.3 rmind npf_param_register(npf, param_map, __arraycount(param_map));
70 1.3 rmind }
71 1.3 rmind
72 1.1 rmind void
73 1.1 rmind npf_param_init(npf_t *npf)
74 1.1 rmind {
75 1.1 rmind npf_paraminfo_t *paraminfo;
76 1.1 rmind
77 1.1 rmind paraminfo = kmem_zalloc(sizeof(npf_paraminfo_t), KM_SLEEP);
78 1.1 rmind paraminfo->map = thmap_create(0, NULL, THMAP_NOCOPY);
79 1.1 rmind npf->paraminfo = paraminfo;
80 1.3 rmind
81 1.3 rmind /* Register some general parameters. */
82 1.3 rmind npf_param_general_register(npf);
83 1.1 rmind }
84 1.1 rmind
85 1.1 rmind void
86 1.1 rmind npf_param_fini(npf_t *npf)
87 1.1 rmind {
88 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
89 1.1 rmind npf_paramreg_t *paramreg = pinfo->list;
90 1.1 rmind
91 1.1 rmind while (paramreg) {
92 1.1 rmind npf_param_t *plist = paramreg->params;
93 1.1 rmind npf_paramreg_t *next = paramreg->next;
94 1.1 rmind size_t len;
95 1.1 rmind
96 1.1 rmind /* Remove the parameters from the map. */
97 1.1 rmind for (unsigned i = 0; i < paramreg->count; i++) {
98 1.1 rmind npf_param_t *param = &plist[i];
99 1.1 rmind const char *name = param->name;
100 1.1 rmind void *ret __diagused;
101 1.1 rmind
102 1.1 rmind ret = thmap_del(pinfo->map, name, strlen(name));
103 1.1 rmind KASSERT(ret != NULL);
104 1.1 rmind }
105 1.1 rmind
106 1.1 rmind /* Destroy this registry. */
107 1.1 rmind len = offsetof(npf_paramreg_t, params[paramreg->count]);
108 1.1 rmind kmem_free(paramreg, len);
109 1.1 rmind
110 1.1 rmind /* Next .. */
111 1.1 rmind paramreg = next;
112 1.1 rmind }
113 1.1 rmind thmap_destroy(pinfo->map);
114 1.1 rmind kmem_free(pinfo, sizeof(npf_paraminfo_t));
115 1.1 rmind }
116 1.1 rmind
117 1.3 rmind int
118 1.3 rmind npf_params_export(const npf_t *npf, nvlist_t *nv)
119 1.3 rmind {
120 1.3 rmind nvlist_t *params, *dparams;
121 1.3 rmind
122 1.3 rmind /*
123 1.3 rmind * Export both the active and default values. The latter are to
124 1.3 rmind * accommodate npfctl so it could distinguish what has been set.
125 1.3 rmind */
126 1.3 rmind params = nvlist_create(0);
127 1.3 rmind dparams = nvlist_create(0);
128 1.3 rmind for (npf_paramreg_t *pr = npf->paraminfo->list; pr; pr = pr->next) {
129 1.3 rmind for (unsigned i = 0; i < pr->count; i++) {
130 1.3 rmind const npf_param_t *param = &pr->params[i];
131 1.3 rmind const uint64_t val = *param->valp;
132 1.3 rmind const uint64_t defval = param->default_val;
133 1.3 rmind
134 1.3 rmind nvlist_add_number(params, param->name, val);
135 1.3 rmind nvlist_add_number(dparams, param->name, defval);
136 1.3 rmind }
137 1.3 rmind }
138 1.3 rmind nvlist_add_nvlist(nv, "params", params);
139 1.3 rmind nvlist_add_nvlist(nv, "params-defaults", dparams);
140 1.3 rmind return 0;
141 1.3 rmind }
142 1.3 rmind
143 1.1 rmind void *
144 1.1 rmind npf_param_allocgroup(npf_t *npf, npf_paramgroup_t group, size_t len)
145 1.1 rmind {
146 1.1 rmind void *params = kmem_zalloc(len, KM_SLEEP);
147 1.1 rmind npf->params[group] = params;
148 1.1 rmind return params;
149 1.1 rmind }
150 1.1 rmind
151 1.1 rmind void
152 1.1 rmind npf_param_freegroup(npf_t *npf, npf_paramgroup_t group, size_t len)
153 1.1 rmind {
154 1.1 rmind kmem_free(npf->params[group], len);
155 1.1 rmind npf->params[group] = NULL; // diagnostic
156 1.1 rmind }
157 1.1 rmind
158 1.1 rmind /*
159 1.1 rmind * npf_param_register: register an array of named parameters.
160 1.1 rmind */
161 1.1 rmind void
162 1.1 rmind npf_param_register(npf_t *npf, npf_param_t *params, unsigned count)
163 1.1 rmind {
164 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
165 1.1 rmind npf_paramreg_t *paramreg;
166 1.1 rmind size_t len;
167 1.1 rmind
168 1.1 rmind /*
169 1.1 rmind * Copy over the parameters.
170 1.1 rmind */
171 1.1 rmind len = offsetof(npf_paramreg_t, params[count]);
172 1.1 rmind paramreg = kmem_zalloc(len, KM_SLEEP);
173 1.1 rmind memcpy(paramreg->params, params, sizeof(npf_param_t) * count);
174 1.1 rmind paramreg->count = count;
175 1.1 rmind params = NULL; // dead
176 1.1 rmind
177 1.1 rmind /*
178 1.1 rmind * Map the parameter names to the variables.
179 1.1 rmind * Assign the default values.
180 1.1 rmind */
181 1.1 rmind for (unsigned i = 0; i < count; i++) {
182 1.1 rmind npf_param_t *param = ¶mreg->params[i];
183 1.1 rmind const char *name = param->name;
184 1.1 rmind void *ret __diagused;
185 1.1 rmind
186 1.1 rmind ret = thmap_put(pinfo->map, name, strlen(name), param);
187 1.1 rmind KASSERT(ret == param);
188 1.1 rmind
189 1.1 rmind /* Assign the default value. */
190 1.1 rmind KASSERT(param->default_val >= param->min);
191 1.1 rmind KASSERT(param->default_val <= param->max);
192 1.1 rmind *param->valp = param->default_val;
193 1.1 rmind }
194 1.1 rmind
195 1.1 rmind /* Insert the registry of params into the list. */
196 1.1 rmind paramreg->next = pinfo->list;
197 1.1 rmind pinfo->list = paramreg;
198 1.1 rmind }
199 1.1 rmind
200 1.1 rmind /*
201 1.1 rmind * NPF param API.
202 1.1 rmind */
203 1.1 rmind
204 1.1 rmind static npf_param_t *
205 1.1 rmind npf_param_lookup(npf_t *npf, const char *name)
206 1.1 rmind {
207 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
208 1.1 rmind const size_t namelen = strlen(name);
209 1.1 rmind return thmap_get(pinfo->map, name, namelen);
210 1.1 rmind }
211 1.1 rmind
212 1.1 rmind int
213 1.1 rmind npf_param_check(npf_t *npf, const char *name, int val)
214 1.1 rmind {
215 1.1 rmind npf_param_t *param;
216 1.1 rmind
217 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
218 1.1 rmind return ENOENT;
219 1.1 rmind }
220 1.1 rmind if (val < param->min || val > param->max) {
221 1.1 rmind return EINVAL;
222 1.1 rmind }
223 1.1 rmind return 0;
224 1.1 rmind }
225 1.1 rmind
226 1.1 rmind __dso_public int
227 1.2 rmind npfk_param_get(npf_t *npf, const char *name, int *val)
228 1.1 rmind {
229 1.1 rmind npf_param_t *param;
230 1.1 rmind
231 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
232 1.1 rmind return ENOENT;
233 1.1 rmind }
234 1.1 rmind *val = *param->valp;
235 1.1 rmind return 0;
236 1.1 rmind }
237 1.1 rmind
238 1.1 rmind __dso_public int
239 1.2 rmind npfk_param_set(npf_t *npf, const char *name, int val)
240 1.1 rmind {
241 1.1 rmind npf_param_t *param;
242 1.1 rmind
243 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
244 1.1 rmind return ENOENT;
245 1.1 rmind }
246 1.1 rmind if (val < param->min || val > param->max) {
247 1.1 rmind return EINVAL;
248 1.1 rmind }
249 1.1 rmind *param->valp = val;
250 1.1 rmind return 0;
251 1.1 rmind }
252