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.3 2020/05/30 14:16:56 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 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 = ¶mreg->params[i]; 183 const char *name = param->name; 184 void *ret __diagused; 185 186 ret = thmap_put(pinfo->map, name, strlen(name), param); 187 KASSERT(ret == param); 188 189 /* Assign the default value. */ 190 KASSERT(param->default_val >= param->min); 191 KASSERT(param->default_val <= param->max); 192 *param->valp = param->default_val; 193 } 194 195 /* Insert the registry of params into the list. */ 196 paramreg->next = pinfo->list; 197 pinfo->list = paramreg; 198 } 199 200 /* 201 * NPF param API. 202 */ 203 204 static npf_param_t * 205 npf_param_lookup(npf_t *npf, const char *name) 206 { 207 npf_paraminfo_t *pinfo = npf->paraminfo; 208 const size_t namelen = strlen(name); 209 return thmap_get(pinfo->map, name, namelen); 210 } 211 212 int 213 npf_param_check(npf_t *npf, const char *name, int val) 214 { 215 npf_param_t *param; 216 217 if ((param = npf_param_lookup(npf, name)) == NULL) { 218 return ENOENT; 219 } 220 if (val < param->min || val > param->max) { 221 return EINVAL; 222 } 223 return 0; 224 } 225 226 __dso_public int 227 npfk_param_get(npf_t *npf, const char *name, int *val) 228 { 229 npf_param_t *param; 230 231 if ((param = npf_param_lookup(npf, name)) == NULL) { 232 return ENOENT; 233 } 234 *val = *param->valp; 235 return 0; 236 } 237 238 __dso_public int 239 npfk_param_set(npf_t *npf, const char *name, int val) 240 { 241 npf_param_t *param; 242 243 if ((param = npf_param_lookup(npf, name)) == NULL) { 244 return ENOENT; 245 } 246 if (val < param->min || val > param->max) { 247 return EINVAL; 248 } 249 *param->valp = val; 250 return 0; 251 } 252