1*36589d6bSRobert Mustacchi /*
2*36589d6bSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*36589d6bSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*36589d6bSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*36589d6bSRobert Mustacchi  * 1.0 of the CDDL.
6*36589d6bSRobert Mustacchi  *
7*36589d6bSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*36589d6bSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*36589d6bSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*36589d6bSRobert Mustacchi  */
11*36589d6bSRobert Mustacchi 
12*36589d6bSRobert Mustacchi /*
13*36589d6bSRobert Mustacchi  * Copyright 2019 Joyent, Inc.
14*36589d6bSRobert Mustacchi  */
15*36589d6bSRobert Mustacchi 
16*36589d6bSRobert Mustacchi /*
17*36589d6bSRobert Mustacchi  * varpd client interfaces
18*36589d6bSRobert Mustacchi  */
19*36589d6bSRobert Mustacchi 
20*36589d6bSRobert Mustacchi #include <sys/types.h>
21*36589d6bSRobert Mustacchi #include <sys/stat.h>
22*36589d6bSRobert Mustacchi #include <fcntl.h>
23*36589d6bSRobert Mustacchi #include <errno.h>
24*36589d6bSRobert Mustacchi #include <umem.h>
25*36589d6bSRobert Mustacchi #include <unistd.h>
26*36589d6bSRobert Mustacchi #include <string.h>
27*36589d6bSRobert Mustacchi #include <strings.h>
28*36589d6bSRobert Mustacchi #include <door.h>
29*36589d6bSRobert Mustacchi 
30*36589d6bSRobert Mustacchi #include <libvarpd_impl.h>
31*36589d6bSRobert Mustacchi 
32*36589d6bSRobert Mustacchi typedef struct varpd_client {
33*36589d6bSRobert Mustacchi 	int vcl_doorfd;
34*36589d6bSRobert Mustacchi } varpd_client_t;
35*36589d6bSRobert Mustacchi 
36*36589d6bSRobert Mustacchi typedef struct varpd_client_prop_info {
37*36589d6bSRobert Mustacchi 	varpd_client_t		*vcprop_client;
38*36589d6bSRobert Mustacchi 	uint64_t		vcprop_instance;
39*36589d6bSRobert Mustacchi 	uint_t			vcprop_propid;
40*36589d6bSRobert Mustacchi 	uint_t			vcprop_type;
41*36589d6bSRobert Mustacchi 	uint_t			vcprop_prot;
42*36589d6bSRobert Mustacchi 	uint32_t		vcprop_defsize;
43*36589d6bSRobert Mustacchi 	uint32_t		vcprop_psize;
44*36589d6bSRobert Mustacchi 	char			vcprop_name[LIBVARPD_PROP_NAMELEN];
45*36589d6bSRobert Mustacchi 	uint8_t			vcprop_default[LIBVARPD_PROP_SIZEMAX];
46*36589d6bSRobert Mustacchi 	uint8_t			vcprop_poss[LIBVARPD_PROP_SIZEMAX];
47*36589d6bSRobert Mustacchi } varpd_client_prop_info_t;
48*36589d6bSRobert Mustacchi 
49*36589d6bSRobert Mustacchi static int
libvarpd_c_door_call(varpd_client_t * client,varpd_client_arg_t * argp,size_t altsize)50*36589d6bSRobert Mustacchi libvarpd_c_door_call(varpd_client_t *client, varpd_client_arg_t *argp,
51*36589d6bSRobert Mustacchi     size_t altsize)
52*36589d6bSRobert Mustacchi {
53*36589d6bSRobert Mustacchi 	int ret;
54*36589d6bSRobert Mustacchi 	door_arg_t darg;
55*36589d6bSRobert Mustacchi 
56*36589d6bSRobert Mustacchi 	darg.data_ptr = (char *)argp;
57*36589d6bSRobert Mustacchi 	darg.desc_ptr = NULL;
58*36589d6bSRobert Mustacchi 	darg.desc_num = 0;
59*36589d6bSRobert Mustacchi 	darg.rbuf = (char *)argp;
60*36589d6bSRobert Mustacchi 	if (altsize != 0) {
61*36589d6bSRobert Mustacchi 		darg.data_size = altsize;
62*36589d6bSRobert Mustacchi 		darg.rsize = altsize;
63*36589d6bSRobert Mustacchi 	} else {
64*36589d6bSRobert Mustacchi 		darg.data_size = sizeof (varpd_client_arg_t);
65*36589d6bSRobert Mustacchi 		darg.rsize = sizeof (varpd_client_arg_t);
66*36589d6bSRobert Mustacchi 	}
67*36589d6bSRobert Mustacchi 
68*36589d6bSRobert Mustacchi 	do {
69*36589d6bSRobert Mustacchi 		ret = door_call(client->vcl_doorfd, &darg);
70*36589d6bSRobert Mustacchi 	} while (ret != 0 && errno == EINTR);
71*36589d6bSRobert Mustacchi 	if (ret != 0) {
72*36589d6bSRobert Mustacchi 		switch (errno) {
73*36589d6bSRobert Mustacchi 		case E2BIG:
74*36589d6bSRobert Mustacchi 		case EFAULT:
75*36589d6bSRobert Mustacchi 		case EINVAL:
76*36589d6bSRobert Mustacchi 		case ENOTSUP:
77*36589d6bSRobert Mustacchi 		case EOVERFLOW:
78*36589d6bSRobert Mustacchi 		case ENFILE:
79*36589d6bSRobert Mustacchi 			libvarpd_panic("unhandleable errno from door_call: %d",
80*36589d6bSRobert Mustacchi 			    errno);
81*36589d6bSRobert Mustacchi 		}
82*36589d6bSRobert Mustacchi 		ret = errno;
83*36589d6bSRobert Mustacchi 	}
84*36589d6bSRobert Mustacchi 
85*36589d6bSRobert Mustacchi 	return (ret);
86*36589d6bSRobert Mustacchi }
87*36589d6bSRobert Mustacchi 
88*36589d6bSRobert Mustacchi int
libvarpd_c_create(varpd_client_handle_t ** chpp,const char * doorname)89*36589d6bSRobert Mustacchi libvarpd_c_create(varpd_client_handle_t **chpp, const char *doorname)
90*36589d6bSRobert Mustacchi {
91*36589d6bSRobert Mustacchi 	varpd_client_t *client;
92*36589d6bSRobert Mustacchi 
93*36589d6bSRobert Mustacchi 	client = umem_alloc(sizeof (varpd_client_t), UMEM_DEFAULT);
94*36589d6bSRobert Mustacchi 	if (client == NULL)
95*36589d6bSRobert Mustacchi 		return (ENOMEM);
96*36589d6bSRobert Mustacchi 
97*36589d6bSRobert Mustacchi 	client->vcl_doorfd = open(doorname, O_RDWR);
98*36589d6bSRobert Mustacchi 	if (client->vcl_doorfd < 0) {
99*36589d6bSRobert Mustacchi 		int ret = errno;
100*36589d6bSRobert Mustacchi 		umem_free(client, sizeof (varpd_client_t));
101*36589d6bSRobert Mustacchi 		return (ret);
102*36589d6bSRobert Mustacchi 	}
103*36589d6bSRobert Mustacchi 
104*36589d6bSRobert Mustacchi 	*chpp = (varpd_client_handle_t *)client;
105*36589d6bSRobert Mustacchi 	return (0);
106*36589d6bSRobert Mustacchi }
107*36589d6bSRobert Mustacchi 
108*36589d6bSRobert Mustacchi void
libvarpd_c_destroy(varpd_client_handle_t * chp)109*36589d6bSRobert Mustacchi libvarpd_c_destroy(varpd_client_handle_t *chp)
110*36589d6bSRobert Mustacchi {
111*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
112*36589d6bSRobert Mustacchi 	if (close(client->vcl_doorfd) != 0)
113*36589d6bSRobert Mustacchi 		libvarpd_panic("failed to close door fd %d: %d",
114*36589d6bSRobert Mustacchi 		    client->vcl_doorfd, errno);
115*36589d6bSRobert Mustacchi 
116*36589d6bSRobert Mustacchi 	umem_free(chp, sizeof (varpd_client_t));
117*36589d6bSRobert Mustacchi }
118*36589d6bSRobert Mustacchi 
119*36589d6bSRobert Mustacchi int
libvarpd_c_instance_create(varpd_client_handle_t * chp,datalink_id_t linkid,const char * search,uint64_t * cidp)120*36589d6bSRobert Mustacchi libvarpd_c_instance_create(varpd_client_handle_t *chp, datalink_id_t linkid,
121*36589d6bSRobert Mustacchi     const char *search, uint64_t *cidp)
122*36589d6bSRobert Mustacchi {
123*36589d6bSRobert Mustacchi 	int ret;
124*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
125*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
126*36589d6bSRobert Mustacchi 	varpd_client_create_arg_t *cap = &carg.vca_un.vca_create;
127*36589d6bSRobert Mustacchi 
128*36589d6bSRobert Mustacchi 	if (strlen(search) >= LIBVARPD_PROP_NAMELEN)
129*36589d6bSRobert Mustacchi 		return (EINVAL);
130*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_CREATE;
131*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
132*36589d6bSRobert Mustacchi 	cap->vcca_linkid = linkid;
133*36589d6bSRobert Mustacchi 	(void) strlcpy(cap->vcca_plugin, search, LIBVARPD_PROP_NAMELEN);
134*36589d6bSRobert Mustacchi 
135*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
136*36589d6bSRobert Mustacchi 	if (ret != 0)
137*36589d6bSRobert Mustacchi 		return (ret);
138*36589d6bSRobert Mustacchi 
139*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
140*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
141*36589d6bSRobert Mustacchi 
142*36589d6bSRobert Mustacchi 	*cidp = cap->vcca_id;
143*36589d6bSRobert Mustacchi 
144*36589d6bSRobert Mustacchi 	return (0);
145*36589d6bSRobert Mustacchi }
146*36589d6bSRobert Mustacchi 
147*36589d6bSRobert Mustacchi int
libvarpd_c_instance_activate(varpd_client_handle_t * chp,uint64_t cid)148*36589d6bSRobert Mustacchi libvarpd_c_instance_activate(varpd_client_handle_t *chp, uint64_t cid)
149*36589d6bSRobert Mustacchi {
150*36589d6bSRobert Mustacchi 	int ret;
151*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
152*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
153*36589d6bSRobert Mustacchi 	varpd_client_instance_arg_t *vciap = &carg.vca_un.vca_instance;
154*36589d6bSRobert Mustacchi 
155*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_ACTIVATE;
156*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
157*36589d6bSRobert Mustacchi 	vciap->vcia_id = cid;
158*36589d6bSRobert Mustacchi 
159*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
160*36589d6bSRobert Mustacchi 	if (ret != 0)
161*36589d6bSRobert Mustacchi 		return (ret);
162*36589d6bSRobert Mustacchi 
163*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
164*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
165*36589d6bSRobert Mustacchi 
166*36589d6bSRobert Mustacchi 	return (0);
167*36589d6bSRobert Mustacchi }
168*36589d6bSRobert Mustacchi 
169*36589d6bSRobert Mustacchi int
libvarpd_c_instance_destroy(varpd_client_handle_t * chp,uint64_t cid)170*36589d6bSRobert Mustacchi libvarpd_c_instance_destroy(varpd_client_handle_t *chp, uint64_t cid)
171*36589d6bSRobert Mustacchi {
172*36589d6bSRobert Mustacchi 	int ret;
173*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
174*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
175*36589d6bSRobert Mustacchi 	varpd_client_instance_arg_t *vciap = &carg.vca_un.vca_instance;
176*36589d6bSRobert Mustacchi 
177*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_DESTROY;
178*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
179*36589d6bSRobert Mustacchi 	vciap->vcia_id = cid;
180*36589d6bSRobert Mustacchi 
181*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
182*36589d6bSRobert Mustacchi 	if (ret != 0)
183*36589d6bSRobert Mustacchi 		return (ret);
184*36589d6bSRobert Mustacchi 
185*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
186*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
187*36589d6bSRobert Mustacchi 
188*36589d6bSRobert Mustacchi 	return (0);
189*36589d6bSRobert Mustacchi }
190*36589d6bSRobert Mustacchi 
191*36589d6bSRobert Mustacchi int
libvarpd_c_prop_nprops(varpd_client_handle_t * chp,uint64_t cid,uint_t * nprops)192*36589d6bSRobert Mustacchi libvarpd_c_prop_nprops(varpd_client_handle_t *chp, uint64_t cid, uint_t *nprops)
193*36589d6bSRobert Mustacchi {
194*36589d6bSRobert Mustacchi 	int ret;
195*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
196*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
197*36589d6bSRobert Mustacchi 	varpd_client_nprops_arg_t *vcnap = &carg.vca_un.vca_nprops;
198*36589d6bSRobert Mustacchi 
199*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_NPROPS;
200*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
201*36589d6bSRobert Mustacchi 	vcnap->vcna_id = cid;
202*36589d6bSRobert Mustacchi 	vcnap->vcna_nprops = 0;
203*36589d6bSRobert Mustacchi 
204*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
205*36589d6bSRobert Mustacchi 	if (ret != 0)
206*36589d6bSRobert Mustacchi 		return (ret);
207*36589d6bSRobert Mustacchi 
208*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
209*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
210*36589d6bSRobert Mustacchi 	*nprops = vcnap->vcna_nprops;
211*36589d6bSRobert Mustacchi 	return (0);
212*36589d6bSRobert Mustacchi }
213*36589d6bSRobert Mustacchi 
214*36589d6bSRobert Mustacchi int
libvarpd_c_prop_handle_alloc(varpd_client_handle_t * chp,uint64_t cid,varpd_client_prop_handle_t ** phdlp)215*36589d6bSRobert Mustacchi libvarpd_c_prop_handle_alloc(varpd_client_handle_t *chp, uint64_t cid,
216*36589d6bSRobert Mustacchi     varpd_client_prop_handle_t **phdlp)
217*36589d6bSRobert Mustacchi {
218*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop;
219*36589d6bSRobert Mustacchi 
220*36589d6bSRobert Mustacchi 	infop = umem_alloc(sizeof (varpd_client_prop_info_t), UMEM_DEFAULT);
221*36589d6bSRobert Mustacchi 	if (infop == NULL)
222*36589d6bSRobert Mustacchi 		return (ENOMEM);
223*36589d6bSRobert Mustacchi 
224*36589d6bSRobert Mustacchi 	bzero(infop, sizeof (varpd_client_prop_info_t));
225*36589d6bSRobert Mustacchi 	infop->vcprop_client = (varpd_client_t *)chp;
226*36589d6bSRobert Mustacchi 	infop->vcprop_instance = cid;
227*36589d6bSRobert Mustacchi 	infop->vcprop_propid = UINT_MAX;
228*36589d6bSRobert Mustacchi 	*phdlp = (varpd_client_prop_handle_t *)infop;
229*36589d6bSRobert Mustacchi 	return (0);
230*36589d6bSRobert Mustacchi }
231*36589d6bSRobert Mustacchi 
232*36589d6bSRobert Mustacchi void
libvarpd_c_prop_handle_free(varpd_client_prop_handle_t * phdl)233*36589d6bSRobert Mustacchi libvarpd_c_prop_handle_free(varpd_client_prop_handle_t *phdl)
234*36589d6bSRobert Mustacchi {
235*36589d6bSRobert Mustacchi 	umem_free(phdl, sizeof (varpd_client_prop_info_t));
236*36589d6bSRobert Mustacchi 	phdl = NULL;
237*36589d6bSRobert Mustacchi }
238*36589d6bSRobert Mustacchi 
239*36589d6bSRobert Mustacchi static void
libvarpd_c_prop_info_from_door(varpd_client_prop_info_t * infop,const varpd_client_propinfo_arg_t * vcfap)240*36589d6bSRobert Mustacchi libvarpd_c_prop_info_from_door(varpd_client_prop_info_t *infop,
241*36589d6bSRobert Mustacchi     const varpd_client_propinfo_arg_t *vcfap)
242*36589d6bSRobert Mustacchi {
243*36589d6bSRobert Mustacchi 	infop->vcprop_propid = vcfap->vcfa_propid;
244*36589d6bSRobert Mustacchi 	infop->vcprop_type = vcfap->vcfa_type;
245*36589d6bSRobert Mustacchi 	infop->vcprop_prot = vcfap->vcfa_prot;
246*36589d6bSRobert Mustacchi 	infop->vcprop_defsize = vcfap->vcfa_defsize;
247*36589d6bSRobert Mustacchi 	infop->vcprop_psize = vcfap->vcfa_psize;
248*36589d6bSRobert Mustacchi 	bcopy(vcfap->vcfa_name, infop->vcprop_name, LIBVARPD_PROP_NAMELEN);
249*36589d6bSRobert Mustacchi 	bcopy(vcfap->vcfa_default, infop->vcprop_default,
250*36589d6bSRobert Mustacchi 	    LIBVARPD_PROP_SIZEMAX);
251*36589d6bSRobert Mustacchi 	bcopy(vcfap->vcfa_poss, infop->vcprop_poss, LIBVARPD_PROP_SIZEMAX);
252*36589d6bSRobert Mustacchi }
253*36589d6bSRobert Mustacchi 
254*36589d6bSRobert Mustacchi int
libvarpd_c_prop_info_fill_by_name(varpd_client_prop_handle_t * phdl,const char * name)255*36589d6bSRobert Mustacchi libvarpd_c_prop_info_fill_by_name(varpd_client_prop_handle_t *phdl,
256*36589d6bSRobert Mustacchi     const char *name)
257*36589d6bSRobert Mustacchi {
258*36589d6bSRobert Mustacchi 	int ret;
259*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
260*36589d6bSRobert Mustacchi 	varpd_client_propinfo_arg_t *vcfap = &carg.vca_un.vca_info;
261*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop = (varpd_client_prop_info_t *)phdl;
262*36589d6bSRobert Mustacchi 
263*36589d6bSRobert Mustacchi 	if (strlen(name) >= LIBVARPD_PROP_NAMELEN)
264*36589d6bSRobert Mustacchi 		return (EINVAL);
265*36589d6bSRobert Mustacchi 	bzero(&carg, sizeof (varpd_client_arg_t));
266*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_PROPINFO;
267*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
268*36589d6bSRobert Mustacchi 	vcfap->vcfa_id = infop->vcprop_instance;
269*36589d6bSRobert Mustacchi 	vcfap->vcfa_propid = UINT_MAX;
270*36589d6bSRobert Mustacchi 	(void) strlcpy(vcfap->vcfa_name, name, LIBVARPD_PROP_NAMELEN);
271*36589d6bSRobert Mustacchi 
272*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(infop->vcprop_client, &carg, 0);
273*36589d6bSRobert Mustacchi 	if (ret != 0)
274*36589d6bSRobert Mustacchi 		return (ret);
275*36589d6bSRobert Mustacchi 
276*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
277*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
278*36589d6bSRobert Mustacchi 
279*36589d6bSRobert Mustacchi 	libvarpd_c_prop_info_from_door(infop, vcfap);
280*36589d6bSRobert Mustacchi 	return (0);
281*36589d6bSRobert Mustacchi }
282*36589d6bSRobert Mustacchi 
283*36589d6bSRobert Mustacchi int
libvarpd_c_prop_info_fill(varpd_client_prop_handle_t * phdl,uint_t propid)284*36589d6bSRobert Mustacchi libvarpd_c_prop_info_fill(varpd_client_prop_handle_t *phdl, uint_t propid)
285*36589d6bSRobert Mustacchi {
286*36589d6bSRobert Mustacchi 	int ret;
287*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
288*36589d6bSRobert Mustacchi 	varpd_client_propinfo_arg_t *vcfap = &carg.vca_un.vca_info;
289*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop = (varpd_client_prop_info_t *)phdl;
290*36589d6bSRobert Mustacchi 
291*36589d6bSRobert Mustacchi 	bzero(&carg, sizeof (varpd_client_arg_t));
292*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_PROPINFO;
293*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
294*36589d6bSRobert Mustacchi 	vcfap->vcfa_id = infop->vcprop_instance;
295*36589d6bSRobert Mustacchi 	vcfap->vcfa_propid = propid;
296*36589d6bSRobert Mustacchi 
297*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(infop->vcprop_client, &carg, 0);
298*36589d6bSRobert Mustacchi 	if (ret != 0)
299*36589d6bSRobert Mustacchi 		return (ret);
300*36589d6bSRobert Mustacchi 
301*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
302*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
303*36589d6bSRobert Mustacchi 
304*36589d6bSRobert Mustacchi 	libvarpd_c_prop_info_from_door(infop, vcfap);
305*36589d6bSRobert Mustacchi 	return (0);
306*36589d6bSRobert Mustacchi }
307*36589d6bSRobert Mustacchi 
308*36589d6bSRobert Mustacchi int
libvarpd_c_prop_info(varpd_client_prop_handle_t * phdl,const char ** namep,uint_t * typep,uint_t * protp,const void ** defp,uint32_t * defsizep,const mac_propval_range_t ** possp)309*36589d6bSRobert Mustacchi libvarpd_c_prop_info(varpd_client_prop_handle_t *phdl, const char **namep,
310*36589d6bSRobert Mustacchi     uint_t *typep, uint_t *protp, const void **defp, uint32_t *defsizep,
311*36589d6bSRobert Mustacchi     const mac_propval_range_t **possp)
312*36589d6bSRobert Mustacchi {
313*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop = (varpd_client_prop_info_t *)phdl;
314*36589d6bSRobert Mustacchi 	if (infop->vcprop_propid == UINT_MAX)
315*36589d6bSRobert Mustacchi 		return (EINVAL);
316*36589d6bSRobert Mustacchi 
317*36589d6bSRobert Mustacchi 	if (namep != NULL)
318*36589d6bSRobert Mustacchi 		*namep = infop->vcprop_name;
319*36589d6bSRobert Mustacchi 	if (typep != NULL)
320*36589d6bSRobert Mustacchi 		*typep = infop->vcprop_type;
321*36589d6bSRobert Mustacchi 	if (protp != NULL)
322*36589d6bSRobert Mustacchi 		*protp = infop->vcprop_prot;
323*36589d6bSRobert Mustacchi 	if (defp != NULL)
324*36589d6bSRobert Mustacchi 		*defp = infop->vcprop_default;
325*36589d6bSRobert Mustacchi 	if (defsizep != NULL)
326*36589d6bSRobert Mustacchi 		*defsizep = infop->vcprop_defsize;
327*36589d6bSRobert Mustacchi 	if (possp != NULL)
328*36589d6bSRobert Mustacchi 		*possp = (const mac_propval_range_t *)infop->vcprop_poss;
329*36589d6bSRobert Mustacchi 	return (0);
330*36589d6bSRobert Mustacchi }
331*36589d6bSRobert Mustacchi 
332*36589d6bSRobert Mustacchi int
libvarpd_c_prop_get(varpd_client_prop_handle_t * phdl,void * buf,uint32_t * len)333*36589d6bSRobert Mustacchi libvarpd_c_prop_get(varpd_client_prop_handle_t *phdl, void *buf, uint32_t *len)
334*36589d6bSRobert Mustacchi {
335*36589d6bSRobert Mustacchi 	int ret;
336*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
337*36589d6bSRobert Mustacchi 	varpd_client_prop_arg_t *vcpap = &carg.vca_un.vca_prop;
338*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop = (varpd_client_prop_info_t *)phdl;
339*36589d6bSRobert Mustacchi 
340*36589d6bSRobert Mustacchi 	if (len == NULL || buf == NULL || infop->vcprop_propid == UINT_MAX)
341*36589d6bSRobert Mustacchi 		return (EINVAL);
342*36589d6bSRobert Mustacchi 	if (*len < LIBVARPD_PROP_SIZEMAX)
343*36589d6bSRobert Mustacchi 		return (EOVERFLOW);
344*36589d6bSRobert Mustacchi 
345*36589d6bSRobert Mustacchi 	bzero(&carg, sizeof (varpd_client_arg_t));
346*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_GETPROP;
347*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
348*36589d6bSRobert Mustacchi 	vcpap->vcpa_id = infop->vcprop_instance;
349*36589d6bSRobert Mustacchi 	vcpap->vcpa_propid = infop->vcprop_propid;
350*36589d6bSRobert Mustacchi 
351*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(infop->vcprop_client, &carg, 0);
352*36589d6bSRobert Mustacchi 	if (ret != 0)
353*36589d6bSRobert Mustacchi 		return (ret);
354*36589d6bSRobert Mustacchi 
355*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
356*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
357*36589d6bSRobert Mustacchi 
358*36589d6bSRobert Mustacchi 	/*
359*36589d6bSRobert Mustacchi 	 * If the buffer size is too large then something odd has certainly
360*36589d6bSRobert Mustacchi 	 * happened here, it means that varpd has gone rogue. In such a case we
361*36589d6bSRobert Mustacchi 	 * return a rather odd errror, though we don't believe that this should
362*36589d6bSRobert Mustacchi 	 * generally happen.
363*36589d6bSRobert Mustacchi 	 */
364*36589d6bSRobert Mustacchi 	if (vcpap->vcpa_bufsize > LIBVARPD_PROP_SIZEMAX)
365*36589d6bSRobert Mustacchi 		return (E2BIG);
366*36589d6bSRobert Mustacchi 
367*36589d6bSRobert Mustacchi 	bcopy(vcpap->vcpa_buf, buf, vcpap->vcpa_bufsize);
368*36589d6bSRobert Mustacchi 	*len = vcpap->vcpa_bufsize;
369*36589d6bSRobert Mustacchi 	return (0);
370*36589d6bSRobert Mustacchi }
371*36589d6bSRobert Mustacchi 
372*36589d6bSRobert Mustacchi int
libvarpd_c_prop_set(varpd_client_prop_handle_t * phdl,const void * buf,uint32_t len)373*36589d6bSRobert Mustacchi libvarpd_c_prop_set(varpd_client_prop_handle_t *phdl, const void *buf,
374*36589d6bSRobert Mustacchi     uint32_t len)
375*36589d6bSRobert Mustacchi {
376*36589d6bSRobert Mustacchi 	int ret;
377*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
378*36589d6bSRobert Mustacchi 	varpd_client_prop_arg_t *vcpap = &carg.vca_un.vca_prop;
379*36589d6bSRobert Mustacchi 	varpd_client_prop_info_t *infop = (varpd_client_prop_info_t *)phdl;
380*36589d6bSRobert Mustacchi 
381*36589d6bSRobert Mustacchi 	if (len == 0 || buf == NULL || infop->vcprop_propid == UINT_MAX)
382*36589d6bSRobert Mustacchi 		return (EINVAL);
383*36589d6bSRobert Mustacchi 	if (len > LIBVARPD_PROP_SIZEMAX)
384*36589d6bSRobert Mustacchi 		return (EOVERFLOW);
385*36589d6bSRobert Mustacchi 
386*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_SETPROP;
387*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
388*36589d6bSRobert Mustacchi 	vcpap->vcpa_id = infop->vcprop_instance;
389*36589d6bSRobert Mustacchi 	vcpap->vcpa_propid = infop->vcprop_propid;
390*36589d6bSRobert Mustacchi 	vcpap->vcpa_bufsize = len;
391*36589d6bSRobert Mustacchi 	bcopy(buf, vcpap->vcpa_buf, len);
392*36589d6bSRobert Mustacchi 
393*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(infop->vcprop_client, &carg, 0);
394*36589d6bSRobert Mustacchi 	if (ret != 0)
395*36589d6bSRobert Mustacchi 		return (ret);
396*36589d6bSRobert Mustacchi 
397*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
398*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
399*36589d6bSRobert Mustacchi 
400*36589d6bSRobert Mustacchi 	return (0);
401*36589d6bSRobert Mustacchi }
402*36589d6bSRobert Mustacchi 
403*36589d6bSRobert Mustacchi int
libvarpd_c_instance_lookup(varpd_client_handle_t * chp,datalink_id_t linkid,uint64_t * instp)404*36589d6bSRobert Mustacchi libvarpd_c_instance_lookup(varpd_client_handle_t *chp, datalink_id_t linkid,
405*36589d6bSRobert Mustacchi     uint64_t *instp)
406*36589d6bSRobert Mustacchi {
407*36589d6bSRobert Mustacchi 	int ret;
408*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
409*36589d6bSRobert Mustacchi 	varpd_client_lookup_arg_t *vclap = &carg.vca_un.vca_lookup;
410*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
411*36589d6bSRobert Mustacchi 
412*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_LOOKUP;
413*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
414*36589d6bSRobert Mustacchi 	vclap->vcla_linkid = linkid;
415*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
416*36589d6bSRobert Mustacchi 	if (ret != 0)
417*36589d6bSRobert Mustacchi 		return (ret);
418*36589d6bSRobert Mustacchi 
419*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
420*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
421*36589d6bSRobert Mustacchi 	if (instp != NULL)
422*36589d6bSRobert Mustacchi 		*instp = vclap->vcla_id;
423*36589d6bSRobert Mustacchi 
424*36589d6bSRobert Mustacchi 	return (0);
425*36589d6bSRobert Mustacchi }
426*36589d6bSRobert Mustacchi 
427*36589d6bSRobert Mustacchi int
libvarpd_c_instance_target_mode(varpd_client_handle_t * chp,uint64_t cid,uint_t * dtype,uint_t * mtype)428*36589d6bSRobert Mustacchi libvarpd_c_instance_target_mode(varpd_client_handle_t *chp, uint64_t cid,
429*36589d6bSRobert Mustacchi     uint_t *dtype, uint_t *mtype)
430*36589d6bSRobert Mustacchi {
431*36589d6bSRobert Mustacchi 	int ret;
432*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
433*36589d6bSRobert Mustacchi 	varpd_client_target_mode_arg_t *vctmap = &carg.vca_un.vca_mode;
434*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
435*36589d6bSRobert Mustacchi 
436*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_TARGET_MODE;
437*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
438*36589d6bSRobert Mustacchi 	vctmap->vtma_id = cid;
439*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
440*36589d6bSRobert Mustacchi 	if (ret != 0)
441*36589d6bSRobert Mustacchi 		return (ret);
442*36589d6bSRobert Mustacchi 
443*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
444*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
445*36589d6bSRobert Mustacchi 	if (ret == 0) {
446*36589d6bSRobert Mustacchi 		if (mtype != NULL)
447*36589d6bSRobert Mustacchi 			*mtype = vctmap->vtma_mode;
448*36589d6bSRobert Mustacchi 		if (dtype != NULL)
449*36589d6bSRobert Mustacchi 			*dtype = vctmap->vtma_dest;
450*36589d6bSRobert Mustacchi 	}
451*36589d6bSRobert Mustacchi 
452*36589d6bSRobert Mustacchi 	return (ret);
453*36589d6bSRobert Mustacchi }
454*36589d6bSRobert Mustacchi 
455*36589d6bSRobert Mustacchi int
libvarpd_c_instance_cache_flush(varpd_client_handle_t * chp,uint64_t cid)456*36589d6bSRobert Mustacchi libvarpd_c_instance_cache_flush(varpd_client_handle_t *chp, uint64_t cid)
457*36589d6bSRobert Mustacchi {
458*36589d6bSRobert Mustacchi 	int ret;
459*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
460*36589d6bSRobert Mustacchi 	varpd_client_target_cache_arg_t *vctcap = &carg.vca_un.vca_cache;
461*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
462*36589d6bSRobert Mustacchi 
463*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_CACHE_FLUSH;
464*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
465*36589d6bSRobert Mustacchi 
466*36589d6bSRobert Mustacchi 	vctcap->vtca_id = cid;
467*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
468*36589d6bSRobert Mustacchi 	if (ret != 0)
469*36589d6bSRobert Mustacchi 		return (ret);
470*36589d6bSRobert Mustacchi 
471*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
472*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
473*36589d6bSRobert Mustacchi 
474*36589d6bSRobert Mustacchi 	return (0);
475*36589d6bSRobert Mustacchi }
476*36589d6bSRobert Mustacchi 
477*36589d6bSRobert Mustacchi int
libvarpd_c_instance_cache_delete(varpd_client_handle_t * chp,uint64_t cid,const struct ether_addr * key)478*36589d6bSRobert Mustacchi libvarpd_c_instance_cache_delete(varpd_client_handle_t *chp, uint64_t cid,
479*36589d6bSRobert Mustacchi     const struct ether_addr *key)
480*36589d6bSRobert Mustacchi {
481*36589d6bSRobert Mustacchi 	int ret;
482*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
483*36589d6bSRobert Mustacchi 	varpd_client_target_cache_arg_t *vctcap = &carg.vca_un.vca_cache;
484*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
485*36589d6bSRobert Mustacchi 
486*36589d6bSRobert Mustacchi 	if (key == NULL)
487*36589d6bSRobert Mustacchi 		return (EINVAL);
488*36589d6bSRobert Mustacchi 
489*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_CACHE_DELETE;
490*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
491*36589d6bSRobert Mustacchi 	vctcap->vtca_id = cid;
492*36589d6bSRobert Mustacchi 	bcopy(key, vctcap->vtca_key, ETHERADDRL);
493*36589d6bSRobert Mustacchi 
494*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
495*36589d6bSRobert Mustacchi 	if (ret != 0)
496*36589d6bSRobert Mustacchi 		return (ret);
497*36589d6bSRobert Mustacchi 
498*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
499*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
500*36589d6bSRobert Mustacchi 
501*36589d6bSRobert Mustacchi 	return (0);
502*36589d6bSRobert Mustacchi }
503*36589d6bSRobert Mustacchi 
504*36589d6bSRobert Mustacchi int
libvarpd_c_instance_cache_get(varpd_client_handle_t * chp,uint64_t cid,const struct ether_addr * key,varpd_client_cache_entry_t * entry)505*36589d6bSRobert Mustacchi libvarpd_c_instance_cache_get(varpd_client_handle_t *chp, uint64_t cid,
506*36589d6bSRobert Mustacchi     const struct ether_addr *key, varpd_client_cache_entry_t *entry)
507*36589d6bSRobert Mustacchi {
508*36589d6bSRobert Mustacchi 	int ret;
509*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
510*36589d6bSRobert Mustacchi 	varpd_client_target_cache_arg_t *vctcap = &carg.vca_un.vca_cache;
511*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
512*36589d6bSRobert Mustacchi 
513*36589d6bSRobert Mustacchi 	if (key == NULL || entry == NULL)
514*36589d6bSRobert Mustacchi 		return (EINVAL);
515*36589d6bSRobert Mustacchi 
516*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_CACHE_GET;
517*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
518*36589d6bSRobert Mustacchi 	vctcap->vtca_id = cid;
519*36589d6bSRobert Mustacchi 	bcopy(key, vctcap->vtca_key, ETHERADDRL);
520*36589d6bSRobert Mustacchi 	bzero(&vctcap->vtca_entry, sizeof (varpd_client_cache_entry_t));
521*36589d6bSRobert Mustacchi 
522*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
523*36589d6bSRobert Mustacchi 	if (ret != 0)
524*36589d6bSRobert Mustacchi 		return (ret);
525*36589d6bSRobert Mustacchi 
526*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
527*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
528*36589d6bSRobert Mustacchi 
529*36589d6bSRobert Mustacchi 	bcopy(&vctcap->vtca_entry, entry, sizeof (varpd_client_cache_entry_t));
530*36589d6bSRobert Mustacchi 	return (0);
531*36589d6bSRobert Mustacchi }
532*36589d6bSRobert Mustacchi 
533*36589d6bSRobert Mustacchi int
libvarpd_c_instance_cache_set(varpd_client_handle_t * chp,uint64_t cid,const struct ether_addr * key,const varpd_client_cache_entry_t * entry)534*36589d6bSRobert Mustacchi libvarpd_c_instance_cache_set(varpd_client_handle_t *chp, uint64_t cid,
535*36589d6bSRobert Mustacchi     const struct ether_addr *key, const varpd_client_cache_entry_t *entry)
536*36589d6bSRobert Mustacchi {
537*36589d6bSRobert Mustacchi 	int ret;
538*36589d6bSRobert Mustacchi 	varpd_client_arg_t carg;
539*36589d6bSRobert Mustacchi 	varpd_client_target_cache_arg_t *vctcap = &carg.vca_un.vca_cache;
540*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
541*36589d6bSRobert Mustacchi 
542*36589d6bSRobert Mustacchi 	if (key == NULL || entry == NULL)
543*36589d6bSRobert Mustacchi 		return (EINVAL);
544*36589d6bSRobert Mustacchi 
545*36589d6bSRobert Mustacchi 	carg.vca_command = VARPD_CLIENT_CACHE_SET;
546*36589d6bSRobert Mustacchi 	carg.vca_errno = 0;
547*36589d6bSRobert Mustacchi 	vctcap->vtca_id = cid;
548*36589d6bSRobert Mustacchi 	bcopy(key, vctcap->vtca_key, ETHERADDRL);
549*36589d6bSRobert Mustacchi 	bcopy(entry, &vctcap->vtca_entry, sizeof (varpd_client_cache_entry_t));
550*36589d6bSRobert Mustacchi 
551*36589d6bSRobert Mustacchi 	ret = libvarpd_c_door_call(client, &carg, 0);
552*36589d6bSRobert Mustacchi 	if (ret != 0)
553*36589d6bSRobert Mustacchi 		return (ret);
554*36589d6bSRobert Mustacchi 
555*36589d6bSRobert Mustacchi 	if (carg.vca_errno != 0)
556*36589d6bSRobert Mustacchi 		return (carg.vca_errno);
557*36589d6bSRobert Mustacchi 
558*36589d6bSRobert Mustacchi 	return (0);
559*36589d6bSRobert Mustacchi }
560*36589d6bSRobert Mustacchi 
561*36589d6bSRobert Mustacchi int
libvarpd_c_instance_cache_walk(varpd_client_handle_t * chp,uint64_t cid,varpd_client_cache_f func,void * arg)562*36589d6bSRobert Mustacchi libvarpd_c_instance_cache_walk(varpd_client_handle_t *chp, uint64_t cid,
563*36589d6bSRobert Mustacchi     varpd_client_cache_f func, void *arg)
564*36589d6bSRobert Mustacchi {
565*36589d6bSRobert Mustacchi 	int ret = 0;
566*36589d6bSRobert Mustacchi 	size_t bufsize = sizeof (varpd_client_arg_t) +
567*36589d6bSRobert Mustacchi 	    100 * sizeof (varpd_client_cache_entry_t);
568*36589d6bSRobert Mustacchi 	varpd_client_t *client = (varpd_client_t *)chp;
569*36589d6bSRobert Mustacchi 	varpd_client_arg_t *cargp;
570*36589d6bSRobert Mustacchi 	varpd_client_target_walk_arg_t *vctwap;
571*36589d6bSRobert Mustacchi 
572*36589d6bSRobert Mustacchi 	/*
573*36589d6bSRobert Mustacchi 	 * Because the number of entries involved in a walk may be large, we
574*36589d6bSRobert Mustacchi 	 * dynamically allocate a number of queries to make at a single time.
575*36589d6bSRobert Mustacchi 	 * This also means that the average door request doesn't inflate by the
576*36589d6bSRobert Mustacchi 	 * number of entries we want. For now, let's always grab 100 entries in
577*36589d6bSRobert Mustacchi 	 * a request.
578*36589d6bSRobert Mustacchi 	 */
579*36589d6bSRobert Mustacchi 	cargp = umem_zalloc(bufsize, UMEM_DEFAULT);
580*36589d6bSRobert Mustacchi 	if (cargp == NULL)
581*36589d6bSRobert Mustacchi 		return (errno);
582*36589d6bSRobert Mustacchi 	vctwap = &cargp->vca_un.vca_walk;
583*36589d6bSRobert Mustacchi 	for (;;) {
584*36589d6bSRobert Mustacchi 		int i;
585*36589d6bSRobert Mustacchi 
586*36589d6bSRobert Mustacchi 		cargp->vca_command = VARPD_CLIENT_CACHE_WALK;
587*36589d6bSRobert Mustacchi 		cargp->vca_errno = 0;
588*36589d6bSRobert Mustacchi 		vctwap->vtcw_id = cid;
589*36589d6bSRobert Mustacchi 		vctwap->vtcw_count = 100;
590*36589d6bSRobert Mustacchi 
591*36589d6bSRobert Mustacchi 		ret = libvarpd_c_door_call(client, cargp, bufsize);
592*36589d6bSRobert Mustacchi 		if (ret != 0)
593*36589d6bSRobert Mustacchi 			break;
594*36589d6bSRobert Mustacchi 
595*36589d6bSRobert Mustacchi 		if (cargp->vca_errno != 0) {
596*36589d6bSRobert Mustacchi 			ret = cargp->vca_errno;
597*36589d6bSRobert Mustacchi 			break;
598*36589d6bSRobert Mustacchi 		}
599*36589d6bSRobert Mustacchi 
600*36589d6bSRobert Mustacchi 		if (vctwap->vtcw_count == 0) {
601*36589d6bSRobert Mustacchi 			ret = 0;
602*36589d6bSRobert Mustacchi 			break;
603*36589d6bSRobert Mustacchi 		}
604*36589d6bSRobert Mustacchi 
605*36589d6bSRobert Mustacchi 		for (i = 0; i < vctwap->vtcw_count; i++) {
606*36589d6bSRobert Mustacchi 			varpd_client_cache_entry_t ent;
607*36589d6bSRobert Mustacchi 
608*36589d6bSRobert Mustacchi 			ent.vcp_flags = vctwap->vtcw_ents[i].otce_flags;
609*36589d6bSRobert Mustacchi 			bcopy(vctwap->vtcw_ents[i].otce_dest.otp_mac,
610*36589d6bSRobert Mustacchi 			    &ent.vcp_mac, ETHERADDRL);
611*36589d6bSRobert Mustacchi 			ent.vcp_ip = vctwap->vtcw_ents[i].otce_dest.otp_ip;
612*36589d6bSRobert Mustacchi 			ent.vcp_port = vctwap->vtcw_ents[i].otce_dest.otp_port;
613*36589d6bSRobert Mustacchi 			ret = func(chp, cid,
614*36589d6bSRobert Mustacchi 			    (struct ether_addr *)vctwap->vtcw_ents[i].otce_mac,
615*36589d6bSRobert Mustacchi 			    &ent, arg);
616*36589d6bSRobert Mustacchi 			if (ret != 0) {
617*36589d6bSRobert Mustacchi 				ret = 0;
618*36589d6bSRobert Mustacchi 				goto done;
619*36589d6bSRobert Mustacchi 			}
620*36589d6bSRobert Mustacchi 		}
621*36589d6bSRobert Mustacchi 	}
622*36589d6bSRobert Mustacchi 
623*36589d6bSRobert Mustacchi done:
624*36589d6bSRobert Mustacchi 	umem_free(cargp, bufsize);
625*36589d6bSRobert Mustacchi 	return (ret);
626*36589d6bSRobert Mustacchi }
627