#include <libvarpd_impl.h>
#include <errno.h>
#include <strings.h>
#include <sys/mac.h>
#include <umem.h>
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;
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;
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) {
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);
}