xref: /netbsd-src/sys/net/npf/npf_params.c (revision e6c7e151de239c49d2e38720a061ed9d1fa99309)
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 = &paramreg->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