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 = ¶mreg->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