Home | History | Annotate | Line # | Download | only in npf
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 = &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