/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2019 Joyent, Inc. */ /* * varpd property management */ #include #include #include #include #include typedef struct varpd_prop_info { varpd_impl_t *vprop_vip; varpd_instance_t *vprop_instance; uint_t vprop_type; uint_t vprop_prot; uint32_t vprop_defsize; uint32_t vprop_psize; char vprop_name[LIBVARPD_PROP_NAMELEN]; uint8_t vprop_default[LIBVARPD_PROP_SIZEMAX]; uint8_t vprop_poss[LIBVARPD_PROP_SIZEMAX]; } varpd_prop_info_t; /* Internal Properties */ static int varpd_nintprops = 1; static const char *varpd_intprops[] = { "search" }; static int libvarpd_prop_get_search(varpd_prop_info_t *infop, void *buf, uint32_t *sizep) { varpd_plugin_t *vpp = infop->vprop_instance->vri_plugin; size_t nlen; nlen = strlen(vpp->vpp_name) + 1; if (nlen > *sizep) return (EOVERFLOW); *sizep = nlen; (void) strlcpy(buf, vpp->vpp_name, *sizep); return (0); } void libvarpd_prop_set_name(varpd_prop_handle_t *phdl, const char *name) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; (void) strlcpy(infop->vprop_name, name, OVERLAY_PROP_NAMELEN); } void libvarpd_prop_set_prot(varpd_prop_handle_t *phdl, overlay_prop_prot_t perm) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; infop->vprop_prot = perm; } void libvarpd_prop_set_type(varpd_prop_handle_t *phdl, overlay_prop_type_t type) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; infop->vprop_type = type; } int libvarpd_prop_set_default(varpd_prop_handle_t *phdl, void *buf, ssize_t len) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; if (len > LIBVARPD_PROP_SIZEMAX) return (E2BIG); if (len < 0) return (EOVERFLOW); bcopy(buf, infop->vprop_default, len); infop->vprop_defsize = len; return (0); } void libvarpd_prop_set_nodefault(varpd_prop_handle_t *phdl) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; infop->vprop_default[0] = '\0'; infop->vprop_defsize = 0; } void libvarpd_prop_set_range_uint32(varpd_prop_handle_t *phdl, uint32_t min, uint32_t max) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; if (rangep->mpr_count != 0 && rangep->mpr_type != MAC_PROPVAL_UINT32) return; if (infop->vprop_psize + sizeof (mac_propval_uint32_range_t) > sizeof (infop->vprop_poss)) return; infop->vprop_psize += sizeof (mac_propval_uint32_range_t); rangep->mpr_count++; rangep->mpr_type = MAC_PROPVAL_UINT32; rangep->u.mpr_uint32[rangep->mpr_count-1].mpur_min = min; rangep->u.mpr_uint32[rangep->mpr_count-1].mpur_max = max; } void libvarpd_prop_set_range_str(varpd_prop_handle_t *phdl, const char *str) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; size_t len = strlen(str) + 1; /* Account for a null terminator */ mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; mac_propval_str_range_t *pstr = &rangep->u.mpr_str; if (rangep->mpr_count != 0 && rangep->mpr_type != MAC_PROPVAL_STR) return; if (infop->vprop_psize + len > sizeof (infop->vprop_poss)) return; rangep->mpr_count++; rangep->mpr_type = MAC_PROPVAL_STR; (void) strlcpy((char *)&pstr->mpur_data[pstr->mpur_nextbyte], str, sizeof (infop->vprop_poss) - infop->vprop_psize); pstr->mpur_nextbyte += len; infop->vprop_psize += len; } int libvarpd_prop_handle_alloc(varpd_handle_t *vph, varpd_instance_handle_t *inst, varpd_prop_handle_t **phdlp) { varpd_prop_info_t *infop; infop = umem_alloc(sizeof (varpd_prop_info_t), UMEM_DEFAULT); if (infop == NULL) return (ENOMEM); bzero(infop, sizeof (varpd_prop_info_t)); infop->vprop_vip = (varpd_impl_t *)vph; infop->vprop_instance = (varpd_instance_t *)inst; *phdlp = (varpd_prop_handle_t *)infop; return (0); } void libvarpd_prop_handle_free(varpd_prop_handle_t *phdl) { umem_free(phdl, sizeof (varpd_prop_info_t)); } int libvarpd_prop_nprops(varpd_instance_handle_t *ihdl, uint_t *np) { int ret; varpd_instance_t *instp = (varpd_instance_t *)ihdl; ret = instp->vri_plugin->vpp_ops->vpo_nprops(instp->vri_private, np); if (ret != 0) return (ret); *np += varpd_nintprops; return (0); } static int libvarpd_prop_info_fill_int_cb(varpd_handle_t *handle, const char *name, void *arg) { varpd_prop_handle_t *vph = arg; libvarpd_prop_set_range_str(vph, name); return (0); } static int libvarpd_prop_info_fill_int(varpd_prop_handle_t *vph, uint_t propid) { varpd_prop_info_t *infop = (varpd_prop_info_t *)vph; if (propid >= varpd_nintprops) abort(); libvarpd_prop_set_name(vph, varpd_intprops[0]); libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_READ); libvarpd_prop_set_type(vph, OVERLAY_PROP_T_STRING); libvarpd_prop_set_nodefault(vph); (void) libvarpd_plugin_walk( (varpd_handle_t *)infop->vprop_instance->vri_impl, libvarpd_prop_info_fill_int_cb, vph); return (0); } int libvarpd_prop_info_fill(varpd_prop_handle_t *phdl, uint_t propid) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; varpd_instance_t *instp = infop->vprop_instance; mac_propval_range_t *rangep = (mac_propval_range_t *)infop->vprop_poss; infop->vprop_psize = sizeof (mac_propval_range_t); bzero(rangep, sizeof (mac_propval_range_t)); if (propid < varpd_nintprops) { return (libvarpd_prop_info_fill_int(phdl, propid)); } else { varpd_plugin_t *vpp = instp->vri_plugin; return (vpp->vpp_ops->vpo_propinfo(instp->vri_private, propid - varpd_nintprops, phdl)); } } int libvarpd_prop_info(varpd_prop_handle_t *phdl, const char **namep, uint_t *typep, uint_t *protp, const void **defp, uint32_t *sizep, const mac_propval_range_t **possp) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; if (namep != NULL) *namep = infop->vprop_name; if (typep != NULL) *typep = infop->vprop_type; if (protp != NULL) *protp = infop->vprop_prot; if (defp != NULL) *defp = infop->vprop_default; if (sizep != NULL) *sizep = infop->vprop_psize; if (possp != NULL) *possp = (mac_propval_range_t *)infop->vprop_poss; return (0); } int libvarpd_prop_get(varpd_prop_handle_t *phdl, void *buf, uint32_t *sizep) { varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; varpd_instance_t *instp = infop->vprop_instance; if (infop->vprop_name[0] == '\0') return (EINVAL); if (strcmp(varpd_intprops[0], infop->vprop_name) == 0) { /* search property */ return (libvarpd_prop_get_search(infop, buf, sizep)); } return (instp->vri_plugin->vpp_ops->vpo_getprop(instp->vri_private, infop->vprop_name, buf, sizep)); } int libvarpd_prop_set(varpd_prop_handle_t *phdl, const void *buf, uint32_t size) { int i; varpd_prop_info_t *infop = (varpd_prop_info_t *)phdl; varpd_instance_t *instp = infop->vprop_instance; if (infop->vprop_name[0] == '\0') return (EINVAL); for (i = 0; i < varpd_nintprops; i++) { if (strcmp(infop->vprop_name, varpd_intprops[i]) == 0) { return (EPERM); } } return (instp->vri_plugin->vpp_ops->vpo_setprop(instp->vri_private, infop->vprop_name, buf, size)); } void libvarpd_prop_door_convert(const varpd_prop_handle_t *phdl, varpd_client_propinfo_arg_t *vcfap) { const varpd_prop_info_t *infop = (const varpd_prop_info_t *)phdl; vcfap->vcfa_type = infop->vprop_type; vcfap->vcfa_prot = infop->vprop_prot; vcfap->vcfa_defsize = infop->vprop_defsize; vcfap->vcfa_psize = infop->vprop_psize; bcopy(infop->vprop_name, vcfap->vcfa_name, LIBVARPD_PROP_NAMELEN); bcopy(infop->vprop_default, vcfap->vcfa_default, LIBVARPD_PROP_SIZEMAX); bcopy(infop->vprop_poss, vcfap->vcfa_poss, LIBVARPD_PROP_SIZEMAX); }