Home | History | Annotate | Line # | Download | only in npf
npf_params.c revision 1.4
      1 /*-
      2  * Copyright (c) 2019-2020 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.4 2022/04/28 15:43:51 martin 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 static inline void
     53 npf_param_general_register(npf_t *npf)
     54 {
     55 	npf_param_t param_map[] = {
     56 		{
     57 			"ip4.reassembly",
     58 			&npf->ip4_reassembly,
     59 			.default_val = 0, // false
     60 			.min = 0, .max = 1
     61 		},
     62 		{
     63 			"ip6.reassembly",
     64 			&npf->ip6_reassembly,
     65 			.default_val = 0, // false
     66 			.min = 0, .max = 1
     67 		},
     68 	};
     69 	npf_param_register(npf, param_map, __arraycount(param_map));
     70 }
     71 
     72 void
     73 npf_param_init(npf_t *npf)
     74 {
     75 	npf_paraminfo_t *paraminfo;
     76 
     77 	paraminfo = kmem_zalloc(sizeof(npf_paraminfo_t), KM_SLEEP);
     78 	paraminfo->map = thmap_create(0, NULL, THMAP_NOCOPY);
     79 	npf->paraminfo = paraminfo;
     80 
     81 	/* Register some general parameters. */
     82 	npf_param_general_register(npf);
     83 }
     84 
     85 void
     86 npf_param_fini(npf_t *npf)
     87 {
     88 	npf_paraminfo_t *pinfo = npf->paraminfo;
     89 	npf_paramreg_t *paramreg = pinfo->list;
     90 
     91 	while (paramreg) {
     92 		npf_param_t *plist = paramreg->params;
     93 		npf_paramreg_t *next = paramreg->next;
     94 		size_t len;
     95 
     96 		/* Remove the parameters from the map. */
     97 		for (unsigned i = 0; i < paramreg->count; i++) {
     98 			npf_param_t *param = &plist[i];
     99 			const char *name = param->name;
    100 			void *ret __diagused;
    101 
    102 			ret = thmap_del(pinfo->map, name, strlen(name));
    103 			KASSERT(ret != NULL);
    104 		}
    105 
    106 		/* Destroy this registry. */
    107 		len = offsetof(npf_paramreg_t, params[paramreg->count]);
    108 		kmem_free(paramreg, len);
    109 
    110 		/* Next .. */
    111 		paramreg = next;
    112 	}
    113 	thmap_destroy(pinfo->map);
    114 	kmem_free(pinfo, sizeof(npf_paraminfo_t));
    115 }
    116 
    117 int
    118 npf_params_export(const npf_t *npf, nvlist_t *nv)
    119 {
    120 	nvlist_t *params, *dparams;
    121 
    122 	/*
    123 	 * Export both the active and default values.  The latter are to
    124 	 * accommodate npfctl so it could distinguish what has been set.
    125 	 */
    126 	params = nvlist_create(0);
    127 	dparams = nvlist_create(0);
    128 	for (npf_paramreg_t *pr = npf->paraminfo->list; pr; pr = pr->next) {
    129 		for (unsigned i = 0; i < pr->count; i++) {
    130 			const npf_param_t *param = &pr->params[i];
    131 			const uint64_t val = *param->valp;
    132 			const uint64_t defval = param->default_val;
    133 
    134 			nvlist_add_number(params, param->name, val);
    135 			nvlist_add_number(dparams, param->name, defval);
    136 		}
    137 	}
    138 	nvlist_add_nvlist(nv, "params", params);
    139 	nvlist_add_nvlist(nv, "params-defaults", dparams);
    140 	return 0;
    141 }
    142 
    143 void *
    144 npf_param_allocgroup(npf_t *npf, npf_paramgroup_t group, size_t len)
    145 {
    146 	void *params = kmem_zalloc(len, KM_SLEEP);
    147 	npf->params[group] = params;
    148 	return params;
    149 }
    150 
    151 void
    152 npf_param_freegroup(npf_t *npf, npf_paramgroup_t group, size_t len)
    153 {
    154 	kmem_free(npf->params[group], len);
    155 	npf->params[group] = NULL; // diagnostic
    156 }
    157 
    158 /*
    159  * npf_param_register: register an array of named parameters.
    160  */
    161 void
    162 npf_param_register(npf_t *npf, npf_param_t *params, unsigned count)
    163 {
    164 	npf_paraminfo_t *pinfo = npf->paraminfo;
    165 	npf_paramreg_t *paramreg;
    166 	size_t len;
    167 
    168 	/*
    169 	 * Copy over the parameters.
    170 	 */
    171 	len = offsetof(npf_paramreg_t, params[count]);
    172 	paramreg = kmem_zalloc(len, KM_SLEEP);
    173 	memcpy(paramreg->params, params, sizeof(npf_param_t) * count);
    174 	paramreg->count = count;
    175 	params = NULL; // dead
    176 
    177 	/*
    178 	 * Map the parameter names to the variables.
    179 	 * Assign the default values.
    180 	 */
    181 	for (unsigned i = 0; i < count; i++) {
    182 		npf_param_t *param = &paramreg->params[i];
    183 		const char *name = param->name;
    184 		void *ret __diagused;
    185 
    186 		ret = thmap_put(pinfo->map, name, strlen(name), param);
    187 		KASSERTMSG(ret == param,
    188 		    "parameter insertion failed: ret=%p, param=%p",
    189 		    ret, param);
    190 
    191 		/* Assign the default value. */
    192 		KASSERT(param->default_val >= param->min);
    193 		KASSERT(param->default_val <= param->max);
    194 		*param->valp = param->default_val;
    195 	}
    196 
    197 	/* Insert the registry of params into the list. */
    198 	paramreg->next = pinfo->list;
    199 	pinfo->list = paramreg;
    200 }
    201 
    202 /*
    203  * NPF param API.
    204  */
    205 
    206 static npf_param_t *
    207 npf_param_lookup(npf_t *npf, const char *name)
    208 {
    209 	npf_paraminfo_t *pinfo = npf->paraminfo;
    210 	const size_t namelen = strlen(name);
    211 	return thmap_get(pinfo->map, name, namelen);
    212 }
    213 
    214 int
    215 npf_param_check(npf_t *npf, const char *name, int val)
    216 {
    217 	npf_param_t *param;
    218 
    219 	if ((param = npf_param_lookup(npf, name)) == NULL) {
    220 		return ENOENT;
    221 	}
    222 	if (val < param->min || val > param->max) {
    223 		return EINVAL;
    224 	}
    225 	return 0;
    226 }
    227 
    228 __dso_public int
    229 npfk_param_get(npf_t *npf, const char *name, int *val)
    230 {
    231 	npf_param_t *param;
    232 
    233 	if ((param = npf_param_lookup(npf, name)) == NULL) {
    234 		return ENOENT;
    235 	}
    236 	*val = *param->valp;
    237 	return 0;
    238 }
    239 
    240 __dso_public int
    241 npfk_param_set(npf_t *npf, const char *name, int val)
    242 {
    243 	npf_param_t *param;
    244 
    245 	if ((param = npf_param_lookup(npf, name)) == NULL) {
    246 		return ENOENT;
    247 	}
    248 	if (val < param->min || val > param->max) {
    249 		return EINVAL;
    250 	}
    251 	*param->valp = val;
    252 	return 0;
    253 }
    254