1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Joyent, Inc. 14 */ 15 16 /* 17 * varpd property management 18 */ 19 20 #include <libvarpd_impl.h> 21 #include <errno.h> 22 #include <strings.h> 23 #include <sys/mac.h> 24 #include <umem.h> 25 26 typedef struct varpd_prop_info { 27 varpd_impl_t *vprop_vip; 28 varpd_instance_t *vprop_instance; 29 uint_t vprop_type; 30 uint_t vprop_prot; 31 uint32_t vprop_defsize; 32 uint32_t vprop_psize; 33 char vprop_name[LIBVARPD_PROP_NAMELEN]; 34 uint8_t vprop_default[LIBVARPD_PROP_SIZEMAX]; 35 uint8_t vprop_poss[LIBVARPD_PROP_SIZEMAX]; 36 } varpd_prop_info_t; 37 38 /* Internal Properties */ 39 static int varpd_nintprops = 1; 40 static const char *varpd_intprops[] = { 41 "search" 42 }; 43 44 static int 45 libvarpd_prop_get_search(varpd_prop_info_t *infop, void *buf, uint32_t *sizep) 46 { 47 varpd_plugin_t *vpp = infop->vprop_instance->vri_plugin; 48 size_t nlen; 49 50 nlen = strlen(vpp->vpp_name) + 1; 51 if (nlen > *sizep) 52 return (EOVERFLOW); 53 *sizep = nlen; 54 (void) strlcpy(buf, vpp->vpp_name, *sizep); 55 return (0); 56 } 57 58 void 59 libvarpd_prop_set_name(varpd_prop_handle_t *phdl, const char *name) 60 { 61 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 62 (void) strlcpy(infop->vprop_name, name, OVERLAY_PROP_NAMELEN); 63 } 64 65 void 66 libvarpd_prop_set_prot(varpd_prop_handle_t *phdl, overlay_prop_prot_t perm) 67 { 68 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 69 infop->vprop_prot = perm; 70 } 71 72 void 73 libvarpd_prop_set_type(varpd_prop_handle_t *phdl, overlay_prop_type_t type) 74 { 75 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 76 infop->vprop_type = type; 77 } 78 79 int 80 libvarpd_prop_set_default(varpd_prop_handle_t *phdl, void *buf, ssize_t len) 81 { 82 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 83 84 if (len > LIBVARPD_PROP_SIZEMAX) 85 return (E2BIG); 86 87 if (len < 0) 88 return (EOVERFLOW); 89 90 bcopy(buf, infop->vprop_default, len); 91 infop->vprop_defsize = len; 92 return (0); 93 } 94 95 void 96 libvarpd_prop_set_nodefault(varpd_prop_handle_t *phdl) 97 { 98 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 99 100 infop->vprop_default[0] = '\0'; 101 infop->vprop_defsize = 0; 102 } 103 104 void 105 libvarpd_prop_set_range_uint32(varpd_prop_handle_t *phdl, uint32_t min, 106 uint32_t max) 107 { 108 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 109 mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; 110 111 if (rangep->mpr_count != 0 && rangep->mpr_type != MAC_PROPVAL_UINT32) 112 return; 113 114 if (infop->vprop_psize + sizeof (mac_propval_uint32_range_t) > 115 sizeof (infop->vprop_poss)) 116 return; 117 118 infop->vprop_psize += sizeof (mac_propval_uint32_range_t); 119 rangep->mpr_count++; 120 rangep->mpr_type = MAC_PROPVAL_UINT32; 121 rangep->u.mpr_uint32[rangep->mpr_count-1].mpur_min = min; 122 rangep->u.mpr_uint32[rangep->mpr_count-1].mpur_max = max; 123 } 124 125 void 126 libvarpd_prop_set_range_str(varpd_prop_handle_t *phdl, const char *str) 127 { 128 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 129 size_t len = strlen(str) + 1; /* Account for a null terminator */ 130 mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; 131 mac_propval_str_range_t *pstr = &rangep->u.mpr_str; 132 133 if (rangep->mpr_count != 0 && rangep->mpr_type != MAC_PROPVAL_STR) 134 return; 135 136 if (infop->vprop_psize + len > sizeof (infop->vprop_poss)) 137 return; 138 139 rangep->mpr_count++; 140 rangep->mpr_type = MAC_PROPVAL_STR; 141 (void) strlcpy((char *)&pstr->mpur_data[pstr->mpur_nextbyte], str, 142 sizeof (infop->vprop_poss) - infop->vprop_psize); 143 pstr->mpur_nextbyte += len; 144 infop->vprop_psize += len; 145 } 146 147 int 148 libvarpd_prop_handle_alloc(varpd_handle_t *vph, varpd_instance_handle_t *inst, 149 varpd_prop_handle_t **phdlp) 150 { 151 varpd_prop_info_t *infop; 152 153 infop = umem_alloc(sizeof (varpd_prop_info_t), UMEM_DEFAULT); 154 if (infop == NULL) 155 return (ENOMEM); 156 157 bzero(infop, sizeof (varpd_prop_info_t)); 158 infop->vprop_vip = (varpd_impl_t *)vph; 159 infop->vprop_instance = (varpd_instance_t *)inst; 160 161 *phdlp = (varpd_prop_handle_t *)infop; 162 return (0); 163 } 164 165 void 166 libvarpd_prop_handle_free(varpd_prop_handle_t *phdl) 167 { 168 umem_free(phdl, sizeof (varpd_prop_info_t)); 169 } 170 171 int 172 libvarpd_prop_nprops(varpd_instance_handle_t *ihdl, uint_t *np) 173 { 174 int ret; 175 varpd_instance_t *instp = (varpd_instance_t *)ihdl; 176 177 ret = instp->vri_plugin->vpp_ops->vpo_nprops(instp->vri_private, np); 178 if (ret != 0) 179 return (ret); 180 *np += varpd_nintprops; 181 return (0); 182 } 183 184 static int 185 libvarpd_prop_info_fill_int_cb(varpd_handle_t *handle, const char *name, 186 void *arg) 187 { 188 varpd_prop_handle_t *vph = arg; 189 libvarpd_prop_set_range_str(vph, name); 190 return (0); 191 } 192 193 static int 194 libvarpd_prop_info_fill_int(varpd_prop_handle_t *vph, uint_t propid) 195 { 196 varpd_prop_info_t *infop = (varpd_prop_info_t *)vph; 197 if (propid >= varpd_nintprops) 198 abort(); 199 libvarpd_prop_set_name(vph, varpd_intprops[0]); 200 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_READ); 201 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_STRING); 202 libvarpd_prop_set_nodefault(vph); 203 (void) libvarpd_plugin_walk( 204 (varpd_handle_t *)infop->vprop_instance->vri_impl, 205 libvarpd_prop_info_fill_int_cb, vph); 206 return (0); 207 } 208 209 int 210 libvarpd_prop_info_fill(varpd_prop_handle_t *phdl, uint_t propid) 211 { 212 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 213 varpd_instance_t *instp = infop->vprop_instance; 214 mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; 215 216 infop->vprop_psize = sizeof (mac_propval_range_t); 217 218 bzero(rangep, sizeof (mac_propval_range_t)); 219 if (propid < varpd_nintprops) { 220 return (libvarpd_prop_info_fill_int(phdl, propid)); 221 } else { 222 varpd_plugin_t *vpp = instp->vri_plugin; 223 return (vpp->vpp_ops->vpo_propinfo(instp->vri_private, 224 propid - varpd_nintprops, phdl)); 225 } 226 } 227 228 int 229 libvarpd_prop_info(varpd_prop_handle_t *phdl, const char **namep, 230 uint_t *typep, uint_t *protp, const void **defp, uint32_t *sizep, 231 const mac_propval_range_t **possp) 232 { 233 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 234 if (namep != NULL) 235 *namep = infop->vprop_name; 236 if (typep != NULL) 237 *typep = infop->vprop_type; 238 if (protp != NULL) 239 *protp = infop->vprop_prot; 240 if (defp != NULL) 241 *defp = infop->vprop_default; 242 if (sizep != NULL) 243 *sizep = infop->vprop_psize; 244 if (possp != NULL) 245 *possp = (mac_propval_range_t *)infop->vprop_poss; 246 return (0); 247 } 248 249 int 250 libvarpd_prop_get(varpd_prop_handle_t *phdl, void *buf, uint32_t *sizep) 251 { 252 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 253 varpd_instance_t *instp = infop->vprop_instance; 254 255 if (infop->vprop_name[0] == '\0') 256 return (EINVAL); 257 258 if (strcmp(varpd_intprops[0], infop->vprop_name) == 0) { 259 /* search property */ 260 return (libvarpd_prop_get_search(infop, buf, sizep)); 261 } 262 263 return (instp->vri_plugin->vpp_ops->vpo_getprop(instp->vri_private, 264 infop->vprop_name, buf, sizep)); 265 } 266 267 int 268 libvarpd_prop_set(varpd_prop_handle_t *phdl, const void *buf, uint32_t size) 269 { 270 int i; 271 varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; 272 varpd_instance_t *instp = infop->vprop_instance; 273 274 if (infop->vprop_name[0] == '\0') 275 return (EINVAL); 276 277 for (i = 0; i < varpd_nintprops; i++) { 278 if (strcmp(infop->vprop_name, varpd_intprops[i]) == 0) { 279 return (EPERM); 280 } 281 } 282 283 return (instp->vri_plugin->vpp_ops->vpo_setprop(instp->vri_private, 284 infop->vprop_name, buf, size)); 285 } 286 287 void 288 libvarpd_prop_door_convert(const varpd_prop_handle_t *phdl, 289 varpd_client_propinfo_arg_t *vcfap) 290 { 291 const varpd_prop_info_t *infop = (const varpd_prop_info_t *)phdl; 292 293 vcfap->vcfa_type = infop->vprop_type; 294 vcfap->vcfa_prot = infop->vprop_prot; 295 vcfap->vcfa_defsize = infop->vprop_defsize; 296 vcfap->vcfa_psize = infop->vprop_psize; 297 bcopy(infop->vprop_name, vcfap->vcfa_name, LIBVARPD_PROP_NAMELEN); 298 bcopy(infop->vprop_default, vcfap->vcfa_default, LIBVARPD_PROP_SIZEMAX); 299 bcopy(infop->vprop_poss, vcfap->vcfa_poss, LIBVARPD_PROP_SIZEMAX); 300 } 301