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