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
libvarpd_prop_get_search(varpd_prop_info_t * infop,void * buf,uint32_t * sizep)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
libvarpd_prop_set_name(varpd_prop_handle_t * phdl,const char * name)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
libvarpd_prop_set_prot(varpd_prop_handle_t * phdl,overlay_prop_prot_t perm)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
libvarpd_prop_set_type(varpd_prop_handle_t * phdl,overlay_prop_type_t type)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
libvarpd_prop_set_default(varpd_prop_handle_t * phdl,void * buf,ssize_t len)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
libvarpd_prop_set_nodefault(varpd_prop_handle_t * phdl)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
libvarpd_prop_set_range_uint32(varpd_prop_handle_t * phdl,uint32_t min,uint32_t max)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
libvarpd_prop_set_range_str(varpd_prop_handle_t * phdl,const char * str)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
libvarpd_prop_handle_alloc(varpd_handle_t * vph,varpd_instance_handle_t * inst,varpd_prop_handle_t ** phdlp)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
libvarpd_prop_handle_free(varpd_prop_handle_t * phdl)166 libvarpd_prop_handle_free(varpd_prop_handle_t *phdl)
167 {
168 umem_free(phdl, sizeof (varpd_prop_info_t));
169 }
170
171 int
libvarpd_prop_nprops(varpd_instance_handle_t * ihdl,uint_t * np)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
libvarpd_prop_info_fill_int_cb(varpd_handle_t * handle,const char * name,void * arg)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
libvarpd_prop_info_fill_int(varpd_prop_handle_t * vph,uint_t propid)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
libvarpd_prop_info_fill(varpd_prop_handle_t * phdl,uint_t propid)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
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)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
libvarpd_prop_get(varpd_prop_handle_t * phdl,void * buf,uint32_t * sizep)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
libvarpd_prop_set(varpd_prop_handle_t * phdl,const void * buf,uint32_t size)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
libvarpd_prop_door_convert(const varpd_prop_handle_t * phdl,varpd_client_propinfo_arg_t * vcfap)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