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