npf_params.c revision 1.2 1 1.1 rmind /*-
2 1.1 rmind * Copyright (c) 2019 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.2 rmind __KERNEL_RCSID(0, "$NetBSD: npf_params.c,v 1.2 2019/08/11 20:26:34 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.1 rmind void
53 1.1 rmind npf_param_init(npf_t *npf)
54 1.1 rmind {
55 1.1 rmind npf_paraminfo_t *paraminfo;
56 1.1 rmind
57 1.1 rmind paraminfo = kmem_zalloc(sizeof(npf_paraminfo_t), KM_SLEEP);
58 1.1 rmind paraminfo->map = thmap_create(0, NULL, THMAP_NOCOPY);
59 1.1 rmind npf->paraminfo = paraminfo;
60 1.1 rmind }
61 1.1 rmind
62 1.1 rmind void
63 1.1 rmind npf_param_fini(npf_t *npf)
64 1.1 rmind {
65 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
66 1.1 rmind npf_paramreg_t *paramreg = pinfo->list;
67 1.1 rmind
68 1.1 rmind while (paramreg) {
69 1.1 rmind npf_param_t *plist = paramreg->params;
70 1.1 rmind npf_paramreg_t *next = paramreg->next;
71 1.1 rmind size_t len;
72 1.1 rmind
73 1.1 rmind /* Remove the parameters from the map. */
74 1.1 rmind for (unsigned i = 0; i < paramreg->count; i++) {
75 1.1 rmind npf_param_t *param = &plist[i];
76 1.1 rmind const char *name = param->name;
77 1.1 rmind void *ret __diagused;
78 1.1 rmind
79 1.1 rmind ret = thmap_del(pinfo->map, name, strlen(name));
80 1.1 rmind KASSERT(ret != NULL);
81 1.1 rmind }
82 1.1 rmind
83 1.1 rmind /* Destroy this registry. */
84 1.1 rmind len = offsetof(npf_paramreg_t, params[paramreg->count]);
85 1.1 rmind kmem_free(paramreg, len);
86 1.1 rmind
87 1.1 rmind /* Next .. */
88 1.1 rmind paramreg = next;
89 1.1 rmind }
90 1.1 rmind thmap_destroy(pinfo->map);
91 1.1 rmind kmem_free(pinfo, sizeof(npf_paraminfo_t));
92 1.1 rmind }
93 1.1 rmind
94 1.1 rmind void *
95 1.1 rmind npf_param_allocgroup(npf_t *npf, npf_paramgroup_t group, size_t len)
96 1.1 rmind {
97 1.1 rmind void *params = kmem_zalloc(len, KM_SLEEP);
98 1.1 rmind npf->params[group] = params;
99 1.1 rmind return params;
100 1.1 rmind }
101 1.1 rmind
102 1.1 rmind void
103 1.1 rmind npf_param_freegroup(npf_t *npf, npf_paramgroup_t group, size_t len)
104 1.1 rmind {
105 1.1 rmind kmem_free(npf->params[group], len);
106 1.1 rmind npf->params[group] = NULL; // diagnostic
107 1.1 rmind }
108 1.1 rmind
109 1.1 rmind /*
110 1.1 rmind * npf_param_register: register an array of named parameters.
111 1.1 rmind */
112 1.1 rmind void
113 1.1 rmind npf_param_register(npf_t *npf, npf_param_t *params, unsigned count)
114 1.1 rmind {
115 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
116 1.1 rmind npf_paramreg_t *paramreg;
117 1.1 rmind size_t len;
118 1.1 rmind
119 1.1 rmind /*
120 1.1 rmind * Copy over the parameters.
121 1.1 rmind */
122 1.1 rmind len = offsetof(npf_paramreg_t, params[count]);
123 1.1 rmind paramreg = kmem_zalloc(len, KM_SLEEP);
124 1.1 rmind memcpy(paramreg->params, params, sizeof(npf_param_t) * count);
125 1.1 rmind paramreg->count = count;
126 1.1 rmind params = NULL; // dead
127 1.1 rmind
128 1.1 rmind /*
129 1.1 rmind * Map the parameter names to the variables.
130 1.1 rmind * Assign the default values.
131 1.1 rmind */
132 1.1 rmind for (unsigned i = 0; i < count; i++) {
133 1.1 rmind npf_param_t *param = ¶mreg->params[i];
134 1.1 rmind const char *name = param->name;
135 1.1 rmind void *ret __diagused;
136 1.1 rmind
137 1.1 rmind ret = thmap_put(pinfo->map, name, strlen(name), param);
138 1.1 rmind KASSERT(ret == param);
139 1.1 rmind
140 1.1 rmind /* Assign the default value. */
141 1.1 rmind KASSERT(param->default_val >= param->min);
142 1.1 rmind KASSERT(param->default_val <= param->max);
143 1.1 rmind *param->valp = param->default_val;
144 1.1 rmind }
145 1.1 rmind
146 1.1 rmind /* Insert the registry of params into the list. */
147 1.1 rmind paramreg->next = pinfo->list;
148 1.1 rmind pinfo->list = paramreg;
149 1.1 rmind }
150 1.1 rmind
151 1.1 rmind /*
152 1.1 rmind * NPF param API.
153 1.1 rmind */
154 1.1 rmind
155 1.1 rmind static npf_param_t *
156 1.1 rmind npf_param_lookup(npf_t *npf, const char *name)
157 1.1 rmind {
158 1.1 rmind npf_paraminfo_t *pinfo = npf->paraminfo;
159 1.1 rmind const size_t namelen = strlen(name);
160 1.1 rmind return thmap_get(pinfo->map, name, namelen);
161 1.1 rmind }
162 1.1 rmind
163 1.1 rmind int
164 1.1 rmind npf_param_check(npf_t *npf, const char *name, int val)
165 1.1 rmind {
166 1.1 rmind npf_param_t *param;
167 1.1 rmind
168 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
169 1.1 rmind return ENOENT;
170 1.1 rmind }
171 1.1 rmind if (val < param->min || val > param->max) {
172 1.1 rmind return EINVAL;
173 1.1 rmind }
174 1.1 rmind return 0;
175 1.1 rmind }
176 1.1 rmind
177 1.1 rmind __dso_public int
178 1.2 rmind npfk_param_get(npf_t *npf, const char *name, int *val)
179 1.1 rmind {
180 1.1 rmind npf_param_t *param;
181 1.1 rmind
182 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
183 1.1 rmind return ENOENT;
184 1.1 rmind }
185 1.1 rmind *val = *param->valp;
186 1.1 rmind return 0;
187 1.1 rmind }
188 1.1 rmind
189 1.1 rmind __dso_public int
190 1.2 rmind npfk_param_set(npf_t *npf, const char *name, int val)
191 1.1 rmind {
192 1.1 rmind npf_param_t *param;
193 1.1 rmind
194 1.1 rmind if ((param = npf_param_lookup(npf, name)) == NULL) {
195 1.1 rmind return ENOENT;
196 1.1 rmind }
197 1.1 rmind if (val < param->min || val > param->max) {
198 1.1 rmind return EINVAL;
199 1.1 rmind }
200 1.1 rmind *param->valp = val;
201 1.1 rmind return 0;
202 1.1 rmind }
203