xref: /titanic_51/usr/src/cmd/cmd-inet/usr.lib/ilbd/ilbd_scf.c (revision 3ae6a67df7e14eea9c865af54a90bb0347cbd31a)
1dbed73cbSSangeeta Misra /*
2dbed73cbSSangeeta Misra  * CDDL HEADER START
3dbed73cbSSangeeta Misra  *
4dbed73cbSSangeeta Misra  * The contents of this file are subject to the terms of the
5dbed73cbSSangeeta Misra  * Common Development and Distribution License (the "License").
6dbed73cbSSangeeta Misra  * You may not use this file except in compliance with the License.
7dbed73cbSSangeeta Misra  *
8dbed73cbSSangeeta Misra  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9dbed73cbSSangeeta Misra  * or http://www.opensolaris.org/os/licensing.
10dbed73cbSSangeeta Misra  * See the License for the specific language governing permissions
11dbed73cbSSangeeta Misra  * and limitations under the License.
12dbed73cbSSangeeta Misra  *
13dbed73cbSSangeeta Misra  * When distributing Covered Code, include this CDDL HEADER in each
14dbed73cbSSangeeta Misra  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15dbed73cbSSangeeta Misra  * If applicable, add the following below this CDDL HEADER, with the
16dbed73cbSSangeeta Misra  * fields enclosed by brackets "[]" replaced with your own identifying
17dbed73cbSSangeeta Misra  * information: Portions Copyright [yyyy] [name of copyright owner]
18dbed73cbSSangeeta Misra  *
19dbed73cbSSangeeta Misra  * CDDL HEADER END
20dbed73cbSSangeeta Misra  */
21dbed73cbSSangeeta Misra 
22dbed73cbSSangeeta Misra /*
23*3ae6a67dSSangeeta Misra  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24dbed73cbSSangeeta Misra  */
25dbed73cbSSangeeta Misra 
26dbed73cbSSangeeta Misra #include <stdlib.h>
27dbed73cbSSangeeta Misra #include <stdio.h>
28dbed73cbSSangeeta Misra #include <strings.h>
29dbed73cbSSangeeta Misra #include <sys/types.h>
30dbed73cbSSangeeta Misra #include <sys/socket.h>
31dbed73cbSSangeeta Misra #include <netinet/in.h>
32dbed73cbSSangeeta Misra #include <arpa/inet.h>
33dbed73cbSSangeeta Misra #include <sys/list.h>
34dbed73cbSSangeeta Misra #include <libilb.h>
35dbed73cbSSangeeta Misra #include <assert.h>
36dbed73cbSSangeeta Misra #include <libscf.h>
37dbed73cbSSangeeta Misra #include "libilb_impl.h"
38dbed73cbSSangeeta Misra #include "ilbd.h"
39dbed73cbSSangeeta Misra 
40dbed73cbSSangeeta Misra #define	ILBD_PG_NAME_RULE "rule_"
41dbed73cbSSangeeta Misra #define	ILBD_PG_NAME_SG "sg_"
42dbed73cbSSangeeta Misra #define	ILBD_PG_NAME_HC "hc_"
43dbed73cbSSangeeta Misra #define	ILBD_SVC_FMRI "svc:/network/loadbalancer/ilb"
44dbed73cbSSangeeta Misra #define	ILBD_INST_NAME "default"
45dbed73cbSSangeeta Misra 
46dbed73cbSSangeeta Misra typedef enum {
47dbed73cbSSangeeta Misra 	ILBD_RULE_STATUS,
48dbed73cbSSangeeta Misra 	ILBD_RULE_VIP,
49dbed73cbSSangeeta Misra 	ILBD_RULE_PROTO,
50dbed73cbSSangeeta Misra 	ILBD_RULE_PORT,
51dbed73cbSSangeeta Misra 	ILBD_RULE_ALGO,
52dbed73cbSSangeeta Misra 	ILBD_RULE_TOPO,
53dbed73cbSSangeeta Misra 	ILBD_RULE_NAT_STR,
54dbed73cbSSangeeta Misra 	ILBD_RULE_NAT_END,
55dbed73cbSSangeeta Misra 	ILBD_RULE_STI_MASK,
56dbed73cbSSangeeta Misra 	ILBD_RULE_SGNAME,
57dbed73cbSSangeeta Misra 	ILBD_RULE_HCNAME,
58dbed73cbSSangeeta Misra 	ILBD_RULE_HCPORT,
59dbed73cbSSangeeta Misra 	ILBD_RULE_HCPFLAG,
60dbed73cbSSangeeta Misra 	ILBD_RULE_DRAINTIME,
61dbed73cbSSangeeta Misra 	ILBD_RULE_NAT_TO,
62dbed73cbSSangeeta Misra 	ILBD_RULE_PERS_TO,
63dbed73cbSSangeeta Misra 
64dbed73cbSSangeeta Misra 	ILBD_SG_SERVER,
65dbed73cbSSangeeta Misra 
66dbed73cbSSangeeta Misra 	ILBD_HC_TEST,
67dbed73cbSSangeeta Misra 	ILBD_HC_TIMEOUT,
68dbed73cbSSangeeta Misra 	ILBD_HC_INTERVAL,
69dbed73cbSSangeeta Misra 	ILBD_HC_DEF_PING,
70dbed73cbSSangeeta Misra 	ILBD_HC_COUNT,
71dbed73cbSSangeeta Misra 
72dbed73cbSSangeeta Misra 	ILBD_VAR_INVALID
73dbed73cbSSangeeta Misra } ilbd_var_type_t;
74dbed73cbSSangeeta Misra 
75dbed73cbSSangeeta Misra typedef struct prop_tbl_entry {
76dbed73cbSSangeeta Misra 	ilbd_var_type_t val_type;
77dbed73cbSSangeeta Misra 	const char *scf_propname;
78dbed73cbSSangeeta Misra 	scf_type_t scf_proptype;
79dbed73cbSSangeeta Misra } prop_tbl_entry_t;
80dbed73cbSSangeeta Misra 
81dbed73cbSSangeeta Misra /*
82dbed73cbSSangeeta Misra  * this table contains a map of all SCF properties, including rules,
83dbed73cbSSangeeta Misra  * servergroups and health checks. The place to add new property needs to be
84dbed73cbSSangeeta Misra  * watched carefully. When new properties are added, corresponding *VAR_NUM
85dbed73cbSSangeeta Misra  * needs to be adjusted to reflect the correct index of the table
86dbed73cbSSangeeta Misra  */
87dbed73cbSSangeeta Misra prop_tbl_entry_t prop_tbl[] = {
88dbed73cbSSangeeta Misra 	/* entried for rule */
89dbed73cbSSangeeta Misra 	{ILBD_RULE_STATUS, "status", SCF_TYPE_BOOLEAN},
90dbed73cbSSangeeta Misra 	/* SCF_TYPE_NET_ADDR_V4 or SCF_TYPE_NET_ADDR_V6 */
91dbed73cbSSangeeta Misra 	{ILBD_RULE_VIP, "vip", SCF_TYPE_INVALID},
92dbed73cbSSangeeta Misra 	{ILBD_RULE_PROTO, "protocol", SCF_TYPE_ASTRING},
93dbed73cbSSangeeta Misra 	{ILBD_RULE_PORT, "port", SCF_TYPE_ASTRING},
94dbed73cbSSangeeta Misra 	{ILBD_RULE_ALGO, "ilb-algo", SCF_TYPE_ASTRING},
95dbed73cbSSangeeta Misra 	{ILBD_RULE_TOPO, "ilb-type", SCF_TYPE_ASTRING},
96dbed73cbSSangeeta Misra 	{ILBD_RULE_NAT_STR, "ilb-nat-start", SCF_TYPE_INVALID},
97dbed73cbSSangeeta Misra 	{ILBD_RULE_NAT_END, "ilb-nat-end", SCF_TYPE_INVALID},
98dbed73cbSSangeeta Misra 	{ILBD_RULE_STI_MASK, "ilb-sti-mask", SCF_TYPE_INVALID},
99dbed73cbSSangeeta Misra 	{ILBD_RULE_SGNAME, "servergroup", SCF_TYPE_ASTRING},
100dbed73cbSSangeeta Misra 	{ILBD_RULE_HCNAME, "healthcheck", SCF_TYPE_ASTRING},
101dbed73cbSSangeeta Misra 	{ILBD_RULE_HCPORT, "hc-port", SCF_TYPE_INTEGER},
102dbed73cbSSangeeta Misra 	{ILBD_RULE_HCPFLAG, "hcp-flag", SCF_TYPE_INTEGER},
103dbed73cbSSangeeta Misra 	{ILBD_RULE_DRAINTIME, "drain-time", SCF_TYPE_INTEGER},
104dbed73cbSSangeeta Misra 	{ILBD_RULE_NAT_TO, "nat-timeout", SCF_TYPE_INTEGER},
105dbed73cbSSangeeta Misra 	{ILBD_RULE_PERS_TO, "pers-timeout", SCF_TYPE_INTEGER},
106dbed73cbSSangeeta Misra 	/* add new rule related prop here */
107dbed73cbSSangeeta Misra 	/* entries for sg */
108dbed73cbSSangeeta Misra 	{ILBD_SG_SERVER, "server", SCF_TYPE_ASTRING},
109dbed73cbSSangeeta Misra 	/* add new sg related prop here */
110dbed73cbSSangeeta Misra 	/* entries for hc */
111dbed73cbSSangeeta Misra 	{ILBD_HC_TEST, "test", SCF_TYPE_ASTRING},
112dbed73cbSSangeeta Misra 	{ILBD_HC_TIMEOUT, "timeout", SCF_TYPE_INTEGER},
113dbed73cbSSangeeta Misra 	{ILBD_HC_INTERVAL, "interval", SCF_TYPE_INTEGER},
114dbed73cbSSangeeta Misra 	{ILBD_HC_DEF_PING, "ping", SCF_TYPE_BOOLEAN},
115dbed73cbSSangeeta Misra 	/* add new hc related prop here */
116dbed73cbSSangeeta Misra 	{ILBD_HC_COUNT, "count", SCF_TYPE_INTEGER}
117dbed73cbSSangeeta Misra };
118dbed73cbSSangeeta Misra 
119dbed73cbSSangeeta Misra #define	ILBD_PROP_VAR_NUM (ILBD_HC_COUNT + 1)
120dbed73cbSSangeeta Misra #define	ILBD_RULE_VAR_NUM (ILBD_SG_SERVER)
121dbed73cbSSangeeta Misra #define	ILBD_SG_VAR_NUM (ILBD_HC_TEST - ILBD_SG_SERVER)
122dbed73cbSSangeeta Misra #define	ILBD_HC_VAR_NUM (ILBD_PROP_VAR_NUM - ILBD_HC_TEST)
123dbed73cbSSangeeta Misra 
124dbed73cbSSangeeta Misra static ilb_status_t ilbd_scf_set_prop(scf_propertygroup_t *, const char *,
125dbed73cbSSangeeta Misra     scf_type_t, scf_value_t *);
126dbed73cbSSangeeta Misra static ilb_status_t ilbd_scf_retrieve_pg(const char *, scf_propertygroup_t **,
127dbed73cbSSangeeta Misra     boolean_t);
128dbed73cbSSangeeta Misra static ilb_status_t ilbd_scf_delete_pg(scf_propertygroup_t *);
129dbed73cbSSangeeta Misra static ilb_status_t ilbd_scf_get_prop_val(scf_propertygroup_t *, const char *,
130dbed73cbSSangeeta Misra     scf_value_t **);
131dbed73cbSSangeeta Misra 
132dbed73cbSSangeeta Misra #define	MIN(a, b)	((a) < (b) ? (a) : (b))
133dbed73cbSSangeeta Misra 
134dbed73cbSSangeeta Misra int
135dbed73cbSSangeeta Misra ilbd_scf_limit(int type)
136dbed73cbSSangeeta Misra {
137dbed73cbSSangeeta Misra 	return (MIN(scf_limit(type), 120));
138dbed73cbSSangeeta Misra }
139dbed73cbSSangeeta Misra 
140dbed73cbSSangeeta Misra /*
141dbed73cbSSangeeta Misra  * Translate libscf error to libilb status
142dbed73cbSSangeeta Misra  */
143dbed73cbSSangeeta Misra ilb_status_t
144dbed73cbSSangeeta Misra ilbd_scf_err_to_ilb_err()
145dbed73cbSSangeeta Misra {
146dbed73cbSSangeeta Misra 	switch (scf_error()) {
147dbed73cbSSangeeta Misra 	case SCF_ERROR_NONE:
148dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
149dbed73cbSSangeeta Misra 	case SCF_ERROR_HANDLE_MISMATCH:
150dbed73cbSSangeeta Misra 	case SCF_ERROR_HANDLE_DESTROYED:
151dbed73cbSSangeeta Misra 	case SCF_ERROR_VERSION_MISMATCH:
152dbed73cbSSangeeta Misra 	case SCF_ERROR_NOT_BOUND:
153dbed73cbSSangeeta Misra 	case SCF_ERROR_CONSTRAINT_VIOLATED:
154dbed73cbSSangeeta Misra 	case SCF_ERROR_NOT_SET:
155dbed73cbSSangeeta Misra 	case SCF_ERROR_TYPE_MISMATCH:
156dbed73cbSSangeeta Misra 	case SCF_ERROR_INVALID_ARGUMENT:
157dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
158dbed73cbSSangeeta Misra 	case SCF_ERROR_NO_MEMORY:
159dbed73cbSSangeeta Misra 	case SCF_ERROR_NO_RESOURCES:
160dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
161dbed73cbSSangeeta Misra 	case SCF_ERROR_NOT_FOUND:
162dbed73cbSSangeeta Misra 	case SCF_ERROR_DELETED:
163dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
164dbed73cbSSangeeta Misra 	case SCF_ERROR_EXISTS:
165dbed73cbSSangeeta Misra 		return (ILB_STATUS_EEXIST);
166dbed73cbSSangeeta Misra 	case SCF_ERROR_PERMISSION_DENIED:
167dbed73cbSSangeeta Misra 		return (ILB_STATUS_PERMIT);
168dbed73cbSSangeeta Misra 	case SCF_ERROR_CALLBACK_FAILED:
169dbed73cbSSangeeta Misra 		return (ILB_STATUS_CALLBACK);
170dbed73cbSSangeeta Misra 	case SCF_ERROR_IN_USE:
171dbed73cbSSangeeta Misra 		return (ILB_STATUS_INUSE);
172dbed73cbSSangeeta Misra 	default:
173dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
174dbed73cbSSangeeta Misra 	}
175dbed73cbSSangeeta Misra }
176dbed73cbSSangeeta Misra 
177dbed73cbSSangeeta Misra static void
178dbed73cbSSangeeta Misra ilbd_name_to_scfpgname(ilbd_scf_pg_type_t pg_type, const char *pgname,
179dbed73cbSSangeeta Misra     char *scf_pgname)
180dbed73cbSSangeeta Misra {
181dbed73cbSSangeeta Misra 	switch (pg_type) {
182dbed73cbSSangeeta Misra 	case ILBD_SCF_RULE:
183dbed73cbSSangeeta Misra 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
184dbed73cbSSangeeta Misra 		    ILBD_PG_NAME_RULE "%s", pgname);
185dbed73cbSSangeeta Misra 		return;
186dbed73cbSSangeeta Misra 	case ILBD_SCF_SG:
187dbed73cbSSangeeta Misra 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
188dbed73cbSSangeeta Misra 		    ILBD_PG_NAME_SG "%s", pgname);
189dbed73cbSSangeeta Misra 		return;
190dbed73cbSSangeeta Misra 	case ILBD_SCF_HC:
191dbed73cbSSangeeta Misra 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
192dbed73cbSSangeeta Misra 		    ILBD_PG_NAME_HC "%s", pgname);
193dbed73cbSSangeeta Misra 		return;
194dbed73cbSSangeeta Misra 	/* Should not happen.  Log it and put ILB service in maintenance. */
195dbed73cbSSangeeta Misra 	default:
196dbed73cbSSangeeta Misra 		logerr("ilbd_name_to_scfpgname: invalid pg type %d for pg %s",
197dbed73cbSSangeeta Misra 		    pg_type, pgname);
198dbed73cbSSangeeta Misra 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
199dbed73cbSSangeeta Misra 		exit(EXIT_FAILURE);
200dbed73cbSSangeeta Misra 		return;
201dbed73cbSSangeeta Misra 	}
202dbed73cbSSangeeta Misra }
203dbed73cbSSangeeta Misra 
204dbed73cbSSangeeta Misra static void
205dbed73cbSSangeeta Misra ilbd_scf_destroy(scf_handle_t *h, scf_service_t *s, scf_instance_t *inst,
206dbed73cbSSangeeta Misra     scf_propertygroup_t *pg)
207dbed73cbSSangeeta Misra {
208dbed73cbSSangeeta Misra 	if (pg != NULL)
209dbed73cbSSangeeta Misra 		scf_pg_destroy(pg);
210dbed73cbSSangeeta Misra 	if (inst != NULL)
211dbed73cbSSangeeta Misra 		scf_instance_destroy(inst);
212dbed73cbSSangeeta Misra 	if (s != NULL)
213dbed73cbSSangeeta Misra 		scf_service_destroy(s);
214dbed73cbSSangeeta Misra 	if (h != NULL)
215dbed73cbSSangeeta Misra 		scf_handle_destroy(h);
216dbed73cbSSangeeta Misra }
217dbed73cbSSangeeta Misra 
218dbed73cbSSangeeta Misra 
219dbed73cbSSangeeta Misra static ilb_status_t
220dbed73cbSSangeeta Misra ilbd_scf_get_inst(scf_handle_t **h, scf_service_t **svc, scf_instance_t **inst)
221dbed73cbSSangeeta Misra {
222dbed73cbSSangeeta Misra 	if ((*h = scf_handle_create(SCF_VERSION)) == NULL)
223dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
224dbed73cbSSangeeta Misra 
225dbed73cbSSangeeta Misra 	if (scf_handle_bind(*h) != 0) {
226dbed73cbSSangeeta Misra 		ilbd_scf_destroy(*h, NULL, NULL, NULL);
227dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
228dbed73cbSSangeeta Misra 	}
229dbed73cbSSangeeta Misra 
230dbed73cbSSangeeta Misra 	if ((*svc = scf_service_create(*h)) == NULL) {
231dbed73cbSSangeeta Misra 		ilbd_scf_destroy(*h, NULL, NULL, NULL);
232dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
233dbed73cbSSangeeta Misra 	}
234dbed73cbSSangeeta Misra 
235dbed73cbSSangeeta Misra 	if (scf_handle_decode_fmri(*h, ILBD_SVC_FMRI, NULL, *svc, NULL, NULL,
236dbed73cbSSangeeta Misra 	    NULL, SCF_DECODE_FMRI_EXACT) != 0) {
237dbed73cbSSangeeta Misra 		ilbd_scf_destroy(*h, *svc, NULL, NULL);
238dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
239dbed73cbSSangeeta Misra 	}
240dbed73cbSSangeeta Misra 
241dbed73cbSSangeeta Misra 	if ((*inst = scf_instance_create(*h)) == NULL) {
242dbed73cbSSangeeta Misra 		ilbd_scf_destroy(*h, *svc, NULL, NULL);
243dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
244dbed73cbSSangeeta Misra 	}
245dbed73cbSSangeeta Misra 
246dbed73cbSSangeeta Misra 	if (scf_service_get_instance(*svc, ILBD_INST_NAME, *inst) != 0) {
247dbed73cbSSangeeta Misra 		ilbd_scf_destroy(*h, *svc, *inst, NULL);
248dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
249dbed73cbSSangeeta Misra 	}
250dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
251dbed73cbSSangeeta Misra }
252dbed73cbSSangeeta Misra 
253dbed73cbSSangeeta Misra /*
254dbed73cbSSangeeta Misra  * If create is set, create a new prop group, destroy the old one if exists.
255dbed73cbSSangeeta Misra  * If create not set, try to find the prop group with given name.
256dbed73cbSSangeeta Misra  * The created or found entry is returned as *pg.
257dbed73cbSSangeeta Misra  * Caller frees *pg and its handle scf_pg_handle(pg)
258dbed73cbSSangeeta Misra  */
259dbed73cbSSangeeta Misra static ilb_status_t
260dbed73cbSSangeeta Misra ilbd_scf_retrieve_pg(const char *pgname, scf_propertygroup_t **pg,
261dbed73cbSSangeeta Misra     boolean_t create)
262dbed73cbSSangeeta Misra {
263dbed73cbSSangeeta Misra 	scf_instance_t *inst;
264dbed73cbSSangeeta Misra 	scf_handle_t *h;
265dbed73cbSSangeeta Misra 	scf_service_t *svc;
266dbed73cbSSangeeta Misra 	ilb_status_t ret;
267dbed73cbSSangeeta Misra 
268dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
269dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_OK)
270dbed73cbSSangeeta Misra 		return (ret);
271dbed73cbSSangeeta Misra 
272dbed73cbSSangeeta Misra 	*pg = scf_pg_create(h);
273dbed73cbSSangeeta Misra 	if (*pg == NULL)
274dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
275dbed73cbSSangeeta Misra 
276dbed73cbSSangeeta Misra 	if (scf_instance_get_pg(inst, pgname, *pg) != 0) {
277dbed73cbSSangeeta Misra 		if (scf_error() != SCF_ERROR_NOT_FOUND ||
278dbed73cbSSangeeta Misra 		    (scf_error() == SCF_ERROR_NOT_FOUND && (!create))) {
279dbed73cbSSangeeta Misra 			ilbd_scf_destroy(h, svc, inst, *pg);
280dbed73cbSSangeeta Misra 			*pg = NULL;
281dbed73cbSSangeeta Misra 			return (ilbd_scf_err_to_ilb_err());
282dbed73cbSSangeeta Misra 		}
283dbed73cbSSangeeta Misra 	} else {
284dbed73cbSSangeeta Misra 		/*
285dbed73cbSSangeeta Misra 		 * Found pg, don't want to create, return EEXIST.  Note that
286dbed73cbSSangeeta Misra 		 * h cannot be destroyed here since the caller needs to use it.
287dbed73cbSSangeeta Misra 		 * The caller gets it by calling scf_pg_handle().
288dbed73cbSSangeeta Misra 		 */
289dbed73cbSSangeeta Misra 		if (!create) {
290dbed73cbSSangeeta Misra 			ilbd_scf_destroy(NULL, svc, inst, NULL);
291dbed73cbSSangeeta Misra 			return (ILB_STATUS_EEXIST);
292dbed73cbSSangeeta Misra 		}
293dbed73cbSSangeeta Misra 		/* found pg, need to create, destroy the existing one */
294dbed73cbSSangeeta Misra 		else
295dbed73cbSSangeeta Misra 			(void) ilbd_scf_delete_pg(*pg);
296dbed73cbSSangeeta Misra 	}
297dbed73cbSSangeeta Misra 
298dbed73cbSSangeeta Misra 	if (create) {
299dbed73cbSSangeeta Misra 		if (scf_instance_add_pg(inst, pgname,
300dbed73cbSSangeeta Misra 		    SCF_GROUP_APPLICATION, 0, *pg) != 0) {
301dbed73cbSSangeeta Misra 			ilbd_scf_destroy(h, svc, inst, *pg);
302dbed73cbSSangeeta Misra 			*pg = NULL;
303dbed73cbSSangeeta Misra 			return (ilbd_scf_err_to_ilb_err());
304dbed73cbSSangeeta Misra 		}
305dbed73cbSSangeeta Misra 	}
306dbed73cbSSangeeta Misra 
307dbed73cbSSangeeta Misra 	/*
308dbed73cbSSangeeta Misra 	 * Note that handle cannot be destroyed here, caller sometimes needs
309dbed73cbSSangeeta Misra 	 * to use it.  It gets the handle by calling scf_pg_handle().
310dbed73cbSSangeeta Misra 	 */
311dbed73cbSSangeeta Misra 	ilbd_scf_destroy(NULL, svc, inst, NULL);
312dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
313dbed73cbSSangeeta Misra }
314dbed73cbSSangeeta Misra 
315dbed73cbSSangeeta Misra struct algo_tbl_entry {
316dbed73cbSSangeeta Misra 	ilb_algo_t algo_type;
317dbed73cbSSangeeta Misra 	const char *algo_str;
318dbed73cbSSangeeta Misra } algo_tbl[] = {
319dbed73cbSSangeeta Misra 	{ILB_ALG_ROUNDROBIN, "ROUNDROBIN"},
320dbed73cbSSangeeta Misra 	{ILB_ALG_HASH_IP, "HASH-IP"},
321dbed73cbSSangeeta Misra 	{ILB_ALG_HASH_IP_SPORT, "HASH-IP-PORT"},
322dbed73cbSSangeeta Misra 	{ILB_ALG_HASH_IP_VIP, "HASH-IP-VIP"}
323dbed73cbSSangeeta Misra };
324dbed73cbSSangeeta Misra 
325dbed73cbSSangeeta Misra #define	ILBD_ALGO_TBL_SIZE (sizeof (algo_tbl) / \
326dbed73cbSSangeeta Misra 	sizeof (*algo_tbl))
327dbed73cbSSangeeta Misra 
328dbed73cbSSangeeta Misra void
329dbed73cbSSangeeta Misra ilbd_algo_to_str(ilb_algo_t algo_type, char *valstr)
330dbed73cbSSangeeta Misra {
331dbed73cbSSangeeta Misra 	int i;
332dbed73cbSSangeeta Misra 
333dbed73cbSSangeeta Misra 	for (i = 0; i < ILBD_ALGO_TBL_SIZE; i++) {
334dbed73cbSSangeeta Misra 		if (algo_type == algo_tbl[i].algo_type) {
335dbed73cbSSangeeta Misra 			(void) strlcpy(valstr, algo_tbl[i].algo_str,
336dbed73cbSSangeeta Misra 			    ILBD_MAX_VALUE_LEN);
337dbed73cbSSangeeta Misra 			return;
338dbed73cbSSangeeta Misra 		}
339dbed73cbSSangeeta Misra 	}
340dbed73cbSSangeeta Misra 	logerr("ilbd_algo_to_str: algo not found");
341dbed73cbSSangeeta Misra }
342dbed73cbSSangeeta Misra 
343dbed73cbSSangeeta Misra static void
344dbed73cbSSangeeta Misra ilbd_scf_str_to_algo(ilb_algo_t *algo_type, char *valstr)
345dbed73cbSSangeeta Misra {
346dbed73cbSSangeeta Misra 	int i;
347dbed73cbSSangeeta Misra 
348dbed73cbSSangeeta Misra 	for (i = 0; i < ILBD_ALGO_TBL_SIZE; i++) {
349dbed73cbSSangeeta Misra 		if (strcmp(valstr, algo_tbl[i].algo_str) == 0) {
350dbed73cbSSangeeta Misra 			*algo_type = algo_tbl[i].algo_type;
351dbed73cbSSangeeta Misra 			return;
352dbed73cbSSangeeta Misra 		}
353dbed73cbSSangeeta Misra 	}
354dbed73cbSSangeeta Misra 	logerr("ilbd_scf_str_to_algo: algo not found");
355dbed73cbSSangeeta Misra }
356dbed73cbSSangeeta Misra 
357dbed73cbSSangeeta Misra struct topo_tbl_entry {
358dbed73cbSSangeeta Misra 	ilb_topo_t topo_type;
359dbed73cbSSangeeta Misra 	const char *topo_str;
360dbed73cbSSangeeta Misra } topo_tbl[] = {
361dbed73cbSSangeeta Misra 	{ILB_TOPO_DSR, "DSR"},
362dbed73cbSSangeeta Misra 	{ILB_TOPO_NAT, "NAT"},
363dbed73cbSSangeeta Misra 	{ILB_TOPO_HALF_NAT, "HALF-NAT"}
364dbed73cbSSangeeta Misra };
365dbed73cbSSangeeta Misra 
366dbed73cbSSangeeta Misra #define	ILBD_TOPO_TBL_SIZE (sizeof (topo_tbl) / \
367dbed73cbSSangeeta Misra 	sizeof (*topo_tbl))
368dbed73cbSSangeeta Misra 
369dbed73cbSSangeeta Misra void
370dbed73cbSSangeeta Misra ilbd_topo_to_str(ilb_topo_t topo_type, char *valstr)
371dbed73cbSSangeeta Misra {
372dbed73cbSSangeeta Misra 	int i;
373dbed73cbSSangeeta Misra 
374dbed73cbSSangeeta Misra 	for (i = 0; i < ILBD_TOPO_TBL_SIZE; i++) {
375dbed73cbSSangeeta Misra 		if (topo_type == topo_tbl[i].topo_type) {
376dbed73cbSSangeeta Misra 			(void) strlcpy(valstr, topo_tbl[i].topo_str,
377dbed73cbSSangeeta Misra 			    ILBD_MAX_VALUE_LEN);
378dbed73cbSSangeeta Misra 			return;
379dbed73cbSSangeeta Misra 		}
380dbed73cbSSangeeta Misra 	}
381dbed73cbSSangeeta Misra 	logerr("ilbd_scf_topo_to_str: topo not found");
382dbed73cbSSangeeta Misra }
383dbed73cbSSangeeta Misra 
384dbed73cbSSangeeta Misra static void
385dbed73cbSSangeeta Misra ilbd_scf_str_to_topo(ilb_topo_t *topo_type, char *valstr)
386dbed73cbSSangeeta Misra {
387dbed73cbSSangeeta Misra 	int i;
388dbed73cbSSangeeta Misra 
389dbed73cbSSangeeta Misra 	for (i = 0; i < ILBD_TOPO_TBL_SIZE; i++) {
390dbed73cbSSangeeta Misra 		if (strcmp(valstr, topo_tbl[i].topo_str) == 0) {
391dbed73cbSSangeeta Misra 			*topo_type = topo_tbl[i].topo_type;
392dbed73cbSSangeeta Misra 			return;
393dbed73cbSSangeeta Misra 		}
394dbed73cbSSangeeta Misra 	}
395dbed73cbSSangeeta Misra 	logerr("ilbd_scf_str_to_topo: topo not found");
396dbed73cbSSangeeta Misra }
397dbed73cbSSangeeta Misra 
398dbed73cbSSangeeta Misra static void
399dbed73cbSSangeeta Misra ilbd_get_svr_field(char *valstr, struct in6_addr *sgs_addr,
400dbed73cbSSangeeta Misra     int32_t *min_port, int32_t *max_port, int32_t *sgs_flags)
401dbed73cbSSangeeta Misra {
402dbed73cbSSangeeta Misra 	char *ipaddr, *ipverstr, *portstr, *flagstr;
403dbed73cbSSangeeta Misra 	int ip_ver;
404dbed73cbSSangeeta Misra 	ilb_ip_addr_t temp_ip;
405dbed73cbSSangeeta Misra 	void *addrptr;
406dbed73cbSSangeeta Misra 	char *max_portstr;
407dbed73cbSSangeeta Misra 
408dbed73cbSSangeeta Misra 	ipaddr = strtok(valstr, ";");
409dbed73cbSSangeeta Misra 	ipverstr = strtok(NULL, ";");
410dbed73cbSSangeeta Misra 	portstr = strtok(NULL, ";");
411dbed73cbSSangeeta Misra 	flagstr = strtok(NULL, ";");
412dbed73cbSSangeeta Misra 
413dbed73cbSSangeeta Misra 	if (ipaddr == NULL || ipverstr == NULL || portstr == NULL ||
414dbed73cbSSangeeta Misra 	    flagstr == NULL) {
415dbed73cbSSangeeta Misra 		logerr("%s: invalid server fields", __func__);
416dbed73cbSSangeeta Misra 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
417dbed73cbSSangeeta Misra 		exit(EXIT_FAILURE);
418dbed73cbSSangeeta Misra 	}
419dbed73cbSSangeeta Misra 	ip_ver = atoi(ipverstr);
420dbed73cbSSangeeta Misra 	addrptr = (ip_ver == AF_INET) ? (void *)&temp_ip.ia_v4 :
421dbed73cbSSangeeta Misra 	    (void *)&temp_ip.ia_v6;
422dbed73cbSSangeeta Misra 	if (inet_pton(ip_ver, ipaddr, addrptr) == NULL) {
423dbed73cbSSangeeta Misra 		logerr("ilbd_get_svr_field: inet_pton failed");
424dbed73cbSSangeeta Misra 		return;
425dbed73cbSSangeeta Misra 	}
426dbed73cbSSangeeta Misra 
427dbed73cbSSangeeta Misra 	if (ip_ver == AF_INET) {
428dbed73cbSSangeeta Misra 		IN6_INADDR_TO_V4MAPPED(&(temp_ip.ia_v4), sgs_addr);
429dbed73cbSSangeeta Misra 	} else {
430dbed73cbSSangeeta Misra 		(void) memcpy(sgs_addr, &(temp_ip.ia_v6),
431dbed73cbSSangeeta Misra 		    sizeof (struct in6_addr));
432dbed73cbSSangeeta Misra 	}
433dbed73cbSSangeeta Misra 
434dbed73cbSSangeeta Misra 	*sgs_flags = atoi(flagstr);
435dbed73cbSSangeeta Misra 	*min_port = atoi(strtok(portstr, "-"));
436dbed73cbSSangeeta Misra 	*min_port = ntohs(*min_port);
437dbed73cbSSangeeta Misra 	max_portstr = strtok(NULL, "-");
438dbed73cbSSangeeta Misra 	if (max_portstr != NULL) {
439dbed73cbSSangeeta Misra 		*max_port = atoi(max_portstr);
440dbed73cbSSangeeta Misra 		*max_port = ntohs(*max_port);
441dbed73cbSSangeeta Misra 	}
442dbed73cbSSangeeta Misra }
443dbed73cbSSangeeta Misra 
444dbed73cbSSangeeta Misra /*
445dbed73cbSSangeeta Misra  * Convert the info of a server to its SCF string value representation.
446dbed73cbSSangeeta Misra  * Argument value is assumed to be of size ILBD_MAX_VALUE_LEN.
447dbed73cbSSangeeta Misra  */
448dbed73cbSSangeeta Misra static void
449dbed73cbSSangeeta Misra ilbd_srv_scf_val(ilbd_srv_t *srv, char *value)
450dbed73cbSSangeeta Misra {
451dbed73cbSSangeeta Misra 	char ipstr[INET6_ADDRSTRLEN];
452dbed73cbSSangeeta Misra 	int ipver;
453dbed73cbSSangeeta Misra 
454dbed73cbSSangeeta Misra 	if (GET_AF(&srv->isv_addr) == AF_INET) {
455dbed73cbSSangeeta Misra 		struct in_addr v4_addr;
456dbed73cbSSangeeta Misra 
457dbed73cbSSangeeta Misra 		IN6_V4MAPPED_TO_INADDR(&srv->isv_addr, &v4_addr);
458dbed73cbSSangeeta Misra 		(void) inet_ntop(AF_INET, &v4_addr, ipstr, sizeof (ipstr));
459dbed73cbSSangeeta Misra 		ipver = AF_INET;
460dbed73cbSSangeeta Misra 	} else {
461dbed73cbSSangeeta Misra 		(void) inet_ntop(AF_INET6, &srv->isv_addr, ipstr,
462dbed73cbSSangeeta Misra 		    sizeof (ipstr));
463dbed73cbSSangeeta Misra 		ipver = AF_INET6;
464dbed73cbSSangeeta Misra 	}
465dbed73cbSSangeeta Misra 	(void) snprintf(value, ILBD_MAX_VALUE_LEN, "%s;%d;%d-%d;%d",
466dbed73cbSSangeeta Misra 	    ipstr, ipver, ntohs(srv->isv_minport), ntohs(srv->isv_maxport),
467dbed73cbSSangeeta Misra 	    srv->isv_flags);
468dbed73cbSSangeeta Misra }
469dbed73cbSSangeeta Misra 
470dbed73cbSSangeeta Misra /* get the "ip:port:status" str of the #num server in the servergroup */
471dbed73cbSSangeeta Misra ilb_status_t
472dbed73cbSSangeeta Misra ilbd_get_svr_info(ilbd_sg_t *sg, int num, char *valstr, char *svrname)
473dbed73cbSSangeeta Misra {
474dbed73cbSSangeeta Misra 	int i;
475dbed73cbSSangeeta Misra 	ilbd_srv_t *tmp_srv = NULL;
476dbed73cbSSangeeta Misra 
477dbed73cbSSangeeta Misra 	tmp_srv = list_head(&sg->isg_srvlist);
478dbed73cbSSangeeta Misra 	if (tmp_srv == NULL)
479dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
480dbed73cbSSangeeta Misra 
481dbed73cbSSangeeta Misra 	for (i = 0; i < num; i++)
482dbed73cbSSangeeta Misra 		tmp_srv = list_next(&sg->isg_srvlist, tmp_srv);
483dbed73cbSSangeeta Misra 
484dbed73cbSSangeeta Misra 	assert(tmp_srv != NULL);
485dbed73cbSSangeeta Misra 	if (valstr != NULL)
486dbed73cbSSangeeta Misra 		ilbd_srv_scf_val(tmp_srv, valstr);
487dbed73cbSSangeeta Misra 
488dbed73cbSSangeeta Misra 	if (svrname != NULL) {
489dbed73cbSSangeeta Misra 		(void) snprintf(svrname, ILBD_MAX_NAME_LEN, "server%d",
490dbed73cbSSangeeta Misra 		    tmp_srv->isv_id);
491dbed73cbSSangeeta Misra 	}
492dbed73cbSSangeeta Misra 
493dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
494dbed73cbSSangeeta Misra }
495dbed73cbSSangeeta Misra 
496dbed73cbSSangeeta Misra /* convert a struct in6_addr to valstr */
497dbed73cbSSangeeta Misra ilb_status_t
498dbed73cbSSangeeta Misra ilbd_scf_ip_to_str(uint16_t ipversion, struct in6_addr *addr,
499dbed73cbSSangeeta Misra     scf_type_t *scftype, char *valstr)
500dbed73cbSSangeeta Misra {
501dbed73cbSSangeeta Misra 	size_t vallen;
502dbed73cbSSangeeta Misra 	ilb_ip_addr_t ipaddr;
503dbed73cbSSangeeta Misra 	void *addrptr;
504dbed73cbSSangeeta Misra 
505dbed73cbSSangeeta Misra 	vallen = (ipversion == AF_INET) ? INET_ADDRSTRLEN :
506dbed73cbSSangeeta Misra 	    INET6_ADDRSTRLEN;
507dbed73cbSSangeeta Misra 	if (scftype != NULL)
508dbed73cbSSangeeta Misra 		*scftype = (ipversion == AF_INET) ? SCF_TYPE_NET_ADDR_V4 :
509dbed73cbSSangeeta Misra 		    SCF_TYPE_NET_ADDR_V6;
510dbed73cbSSangeeta Misra 
511dbed73cbSSangeeta Misra 	IP_COPY_IMPL_2_CLI(addr, &ipaddr);
512dbed73cbSSangeeta Misra 	addrptr = (ipversion == AF_INET) ?
513dbed73cbSSangeeta Misra 	    (void *)&ipaddr.ia_v4 : (void *)&ipaddr.ia_v6;
514dbed73cbSSangeeta Misra 	(void) inet_ntop(ipversion, (void *)addrptr, valstr, vallen);
515dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
516dbed73cbSSangeeta Misra }
517dbed73cbSSangeeta Misra 
518dbed73cbSSangeeta Misra /*
519dbed73cbSSangeeta Misra  * This function takes a ilbd internal data struct and translate its value to
520dbed73cbSSangeeta Misra  * scf value. The data struct is passed in within "data".
521dbed73cbSSangeeta Misra  * Upon successful return, the scf val will be stored in "val" and the scf type
522dbed73cbSSangeeta Misra  * will be returned in "scftype" if scftype != NULL, the number of values
523dbed73cbSSangeeta Misra  * translated will be in "numval"
524dbed73cbSSangeeta Misra  * If it failed, no data will be written to SCF
525dbed73cbSSangeeta Misra  */
526dbed73cbSSangeeta Misra static ilb_status_t
527dbed73cbSSangeeta Misra ilbd_data_to_scfval(ilbd_scf_pg_type_t pg_type, ilbd_var_type_t type,
528dbed73cbSSangeeta Misra     scf_handle_t *h, void *data, scf_value_t ***val, scf_type_t *scftype,
529dbed73cbSSangeeta Misra     int *numval)
530dbed73cbSSangeeta Misra {
531dbed73cbSSangeeta Misra 	scf_value_t *v, **varray = NULL;
532dbed73cbSSangeeta Misra 	int ret = ILB_STATUS_OK;
533dbed73cbSSangeeta Misra 	int i;
534dbed73cbSSangeeta Misra 	int scf_val_len = ILBD_MAX_VALUE_LEN;
535*3ae6a67dSSangeeta Misra 	char *valstr = NULL;
536dbed73cbSSangeeta Misra 	int valint;
537dbed73cbSSangeeta Misra 	uint8_t valbool = 0;
538dbed73cbSSangeeta Misra 	ilbd_rule_t *r_ent = NULL;
539dbed73cbSSangeeta Misra 	ilbd_sg_t *s_ent = NULL;
540dbed73cbSSangeeta Misra 	ilbd_hc_t *h_ent = NULL;
541dbed73cbSSangeeta Misra 
542dbed73cbSSangeeta Misra 	switch (pg_type) {
543dbed73cbSSangeeta Misra 	case ILBD_SCF_RULE:
544dbed73cbSSangeeta Misra 		r_ent = (ilbd_rule_t *)data;
545dbed73cbSSangeeta Misra 		break;
546dbed73cbSSangeeta Misra 	case ILBD_SCF_SG:
547dbed73cbSSangeeta Misra 		s_ent = (ilbd_sg_t *)data;
548dbed73cbSSangeeta Misra 		break;
549dbed73cbSSangeeta Misra 	case ILBD_SCF_HC:
550dbed73cbSSangeeta Misra 		h_ent = (ilbd_hc_t *)data;
551dbed73cbSSangeeta Misra 		break;
552dbed73cbSSangeeta Misra 	}
553dbed73cbSSangeeta Misra 
554dbed73cbSSangeeta Misra 	v = scf_value_create(h);
555dbed73cbSSangeeta Misra 	if (v == NULL)
556dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
557dbed73cbSSangeeta Misra 
558*3ae6a67dSSangeeta Misra 	if ((valstr = malloc(scf_val_len)) == NULL)
559*3ae6a67dSSangeeta Misra 			return (ILB_STATUS_ENOMEM);
560dbed73cbSSangeeta Misra 	switch (type) {
561dbed73cbSSangeeta Misra 	case ILBD_RULE_STATUS:
562dbed73cbSSangeeta Misra 		valbool = r_ent->irl_flags & ILB_FLAGS_RULE_ENABLED;
563dbed73cbSSangeeta Misra 		break;
564dbed73cbSSangeeta Misra 	case ILBD_RULE_VIP:
565dbed73cbSSangeeta Misra 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion, &r_ent->irl_vip,
566dbed73cbSSangeeta Misra 		    scftype, valstr);
567dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK) {
568*3ae6a67dSSangeeta Misra 			free(valstr);
569dbed73cbSSangeeta Misra 			scf_value_destroy(v);
570dbed73cbSSangeeta Misra 			return (ret);
571dbed73cbSSangeeta Misra 		}
572dbed73cbSSangeeta Misra 		break;
573dbed73cbSSangeeta Misra 	case ILBD_RULE_PROTO: {
574dbed73cbSSangeeta Misra 		struct protoent *protoent;
575dbed73cbSSangeeta Misra 
576dbed73cbSSangeeta Misra 		protoent = getprotobynumber(r_ent->irl_proto);
577*3ae6a67dSSangeeta Misra 		(void) strlcpy(valstr, protoent->p_name, scf_val_len);
578dbed73cbSSangeeta Misra 		break;
579dbed73cbSSangeeta Misra 	}
580dbed73cbSSangeeta Misra 	case ILBD_RULE_PORT:
581*3ae6a67dSSangeeta Misra 		(void) snprintf(valstr, scf_val_len, "%d-%d",
582dbed73cbSSangeeta Misra 		    r_ent->irl_minport, r_ent->irl_maxport);
583dbed73cbSSangeeta Misra 		break;
584dbed73cbSSangeeta Misra 	case ILBD_RULE_ALGO:
585dbed73cbSSangeeta Misra 		ilbd_algo_to_str(r_ent->irl_algo, valstr);
586dbed73cbSSangeeta Misra 		break;
587dbed73cbSSangeeta Misra 	case ILBD_RULE_TOPO:
588dbed73cbSSangeeta Misra 		ilbd_topo_to_str(r_ent->irl_topo, valstr);
589dbed73cbSSangeeta Misra 		break;
590dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_STR:
591dbed73cbSSangeeta Misra 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
592dbed73cbSSangeeta Misra 		    &r_ent->irl_nat_src_start, scftype, valstr);
593dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK) {
594*3ae6a67dSSangeeta Misra 			free(valstr);
595dbed73cbSSangeeta Misra 			scf_value_destroy(v);
596dbed73cbSSangeeta Misra 			return (ret);
597dbed73cbSSangeeta Misra 		}
598dbed73cbSSangeeta Misra 		break;
599dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_END:
600dbed73cbSSangeeta Misra 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
601dbed73cbSSangeeta Misra 		    &r_ent->irl_nat_src_end, scftype, valstr);
602dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK) {
603*3ae6a67dSSangeeta Misra 			free(valstr);
604dbed73cbSSangeeta Misra 			scf_value_destroy(v);
605dbed73cbSSangeeta Misra 			return (ret);
606dbed73cbSSangeeta Misra 		}
607dbed73cbSSangeeta Misra 		break;
608dbed73cbSSangeeta Misra 	case ILBD_RULE_STI_MASK:
609dbed73cbSSangeeta Misra 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
610dbed73cbSSangeeta Misra 		    &r_ent->irl_stickymask, scftype, valstr);
611dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK) {
612*3ae6a67dSSangeeta Misra 			free(valstr);
613dbed73cbSSangeeta Misra 			scf_value_destroy(v);
614dbed73cbSSangeeta Misra 			return (ret);
615dbed73cbSSangeeta Misra 		}
616dbed73cbSSangeeta Misra 		break;
617dbed73cbSSangeeta Misra 	case ILBD_RULE_SGNAME:
618*3ae6a67dSSangeeta Misra 		(void) strlcpy(valstr, r_ent->irl_sgname, scf_val_len);
619dbed73cbSSangeeta Misra 		break;
620dbed73cbSSangeeta Misra 	case ILBD_RULE_HCNAME:
621dbed73cbSSangeeta Misra 		if (r_ent->irl_hcname[0] != '\0')
622dbed73cbSSangeeta Misra 			(void) strlcpy(valstr, r_ent->irl_hcname,
623*3ae6a67dSSangeeta Misra 			    scf_val_len);
624dbed73cbSSangeeta Misra 		else
625dbed73cbSSangeeta Misra 			bzero(valstr, ILBD_MAX_VALUE_LEN);
626dbed73cbSSangeeta Misra 		break;
627dbed73cbSSangeeta Misra 	case ILBD_RULE_HCPORT:
628dbed73cbSSangeeta Misra 		valint = r_ent->irl_hcport;
629dbed73cbSSangeeta Misra 		break;
630dbed73cbSSangeeta Misra 	case ILBD_RULE_HCPFLAG:
631dbed73cbSSangeeta Misra 		valint = r_ent->irl_hcpflag;
632dbed73cbSSangeeta Misra 		break;
633dbed73cbSSangeeta Misra 	case ILBD_RULE_DRAINTIME:
634dbed73cbSSangeeta Misra 		valint = r_ent->irl_conndrain;
635dbed73cbSSangeeta Misra 		break;
636dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_TO:
637dbed73cbSSangeeta Misra 		valint = r_ent->irl_nat_timeout;
638dbed73cbSSangeeta Misra 		break;
639dbed73cbSSangeeta Misra 	case ILBD_RULE_PERS_TO:
640dbed73cbSSangeeta Misra 		valint = r_ent->irl_sticky_timeout;
641dbed73cbSSangeeta Misra 		break;
642dbed73cbSSangeeta Misra 
643dbed73cbSSangeeta Misra 	case ILBD_SG_SERVER:
644dbed73cbSSangeeta Misra 		if (s_ent->isg_srvcount == 0) {
645dbed73cbSSangeeta Misra 			(void) strlcpy(valstr, "EMPTY_SERVERGROUP",
646*3ae6a67dSSangeeta Misra 			    scf_val_len);
647dbed73cbSSangeeta Misra 			break;
648dbed73cbSSangeeta Misra 		}
649dbed73cbSSangeeta Misra 
650dbed73cbSSangeeta Misra 		varray = calloc(sizeof (*varray), s_ent->isg_srvcount);
651dbed73cbSSangeeta Misra 		if (varray == NULL) {
652dbed73cbSSangeeta Misra 			scf_value_destroy(v);
653*3ae6a67dSSangeeta Misra 			free(valstr);
654dbed73cbSSangeeta Misra 			return (ILB_STATUS_ENOMEM);
655dbed73cbSSangeeta Misra 		}
656dbed73cbSSangeeta Misra 
657dbed73cbSSangeeta Misra 		for (i = 0; i < s_ent->isg_srvcount; i++) {
658dbed73cbSSangeeta Misra 			if (v == NULL) {
659dbed73cbSSangeeta Misra 				for (i--; i >= 0; i--)
660dbed73cbSSangeeta Misra 					scf_value_destroy(varray[i]);
661*3ae6a67dSSangeeta Misra 				free(valstr);
662dbed73cbSSangeeta Misra 				return (ILB_STATUS_ENOMEM);
663dbed73cbSSangeeta Misra 			}
664dbed73cbSSangeeta Misra 
665dbed73cbSSangeeta Misra 			ret = ilbd_get_svr_info(s_ent, i, valstr, NULL);
666dbed73cbSSangeeta Misra 			if (ret != ILB_STATUS_OK) {
667dbed73cbSSangeeta Misra 				scf_value_destroy(v);
668dbed73cbSSangeeta Misra 				for (i--; i >= 0; i--)
669dbed73cbSSangeeta Misra 					scf_value_destroy(varray[i]);
670*3ae6a67dSSangeeta Misra 				free(valstr);
671dbed73cbSSangeeta Misra 				free(varray);
672dbed73cbSSangeeta Misra 				return (ret);
673dbed73cbSSangeeta Misra 			}
674dbed73cbSSangeeta Misra 			(void) scf_value_set_astring(v, valstr);
675dbed73cbSSangeeta Misra 			varray[i] = v;
676dbed73cbSSangeeta Misra 			v = scf_value_create(h);
677dbed73cbSSangeeta Misra 		}
678dbed73cbSSangeeta Misra 		/* the last 'v' we created will go unused, so drop it */
679dbed73cbSSangeeta Misra 		scf_value_destroy(v);
680dbed73cbSSangeeta Misra 		*numval = s_ent->isg_srvcount;
681dbed73cbSSangeeta Misra 		*val = varray;
682*3ae6a67dSSangeeta Misra 		free(valstr);
683dbed73cbSSangeeta Misra 		return (ret);
684dbed73cbSSangeeta Misra 	case ILBD_HC_TEST:
685*3ae6a67dSSangeeta Misra 		(void) strlcpy(valstr, h_ent->ihc_test, scf_val_len);
686dbed73cbSSangeeta Misra 		break;
687dbed73cbSSangeeta Misra 	case ILBD_HC_TIMEOUT:
688dbed73cbSSangeeta Misra 		valint = h_ent->ihc_timeout;
689dbed73cbSSangeeta Misra 		break;
690dbed73cbSSangeeta Misra 	case ILBD_HC_INTERVAL:
691dbed73cbSSangeeta Misra 		valint = h_ent->ihc_interval;
692dbed73cbSSangeeta Misra 		break;
693dbed73cbSSangeeta Misra 	case ILBD_HC_DEF_PING:
694dbed73cbSSangeeta Misra 		valbool = h_ent->ihc_def_ping;
695dbed73cbSSangeeta Misra 		break;
696dbed73cbSSangeeta Misra 	case ILBD_HC_COUNT:
697dbed73cbSSangeeta Misra 		valint = h_ent->ihc_count;
698dbed73cbSSangeeta Misra 		break;
699dbed73cbSSangeeta Misra 	}
700dbed73cbSSangeeta Misra 
701dbed73cbSSangeeta Misra 	switch (*scftype) {
702dbed73cbSSangeeta Misra 	case SCF_TYPE_BOOLEAN:
703dbed73cbSSangeeta Misra 		scf_value_set_boolean(v, valbool);
704dbed73cbSSangeeta Misra 		break;
705dbed73cbSSangeeta Misra 	case SCF_TYPE_ASTRING:
706dbed73cbSSangeeta Misra 		(void) scf_value_set_astring(v, valstr);
707dbed73cbSSangeeta Misra 		break;
708dbed73cbSSangeeta Misra 	case SCF_TYPE_INTEGER:
709dbed73cbSSangeeta Misra 		scf_value_set_integer(v, valint);
710dbed73cbSSangeeta Misra 		break;
711dbed73cbSSangeeta Misra 	case SCF_TYPE_NET_ADDR_V4:
712dbed73cbSSangeeta Misra 		(void) scf_value_set_from_string(v, SCF_TYPE_NET_ADDR_V4,
713dbed73cbSSangeeta Misra 		    valstr);
714dbed73cbSSangeeta Misra 		break;
715dbed73cbSSangeeta Misra 	case SCF_TYPE_NET_ADDR_V6:
716dbed73cbSSangeeta Misra 		(void) scf_value_set_from_string(v, SCF_TYPE_NET_ADDR_V6,
717dbed73cbSSangeeta Misra 		    valstr);
718dbed73cbSSangeeta Misra 		break;
719dbed73cbSSangeeta Misra 	}
720*3ae6a67dSSangeeta Misra 	free(valstr);
721dbed73cbSSangeeta Misra 
722dbed73cbSSangeeta Misra 	varray = calloc(1, sizeof (*varray));
723dbed73cbSSangeeta Misra 	if (varray == NULL) {
724dbed73cbSSangeeta Misra 		scf_value_destroy(v);
725dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
726dbed73cbSSangeeta Misra 	}
727dbed73cbSSangeeta Misra 	varray[0] = v;
728dbed73cbSSangeeta Misra 	*val = varray;
729dbed73cbSSangeeta Misra 	*numval = 1;
730dbed73cbSSangeeta Misra 	return (ret);
731dbed73cbSSangeeta Misra }
732dbed73cbSSangeeta Misra 
733dbed73cbSSangeeta Misra /*
734dbed73cbSSangeeta Misra  * create a scf property group
735dbed73cbSSangeeta Misra  */
736dbed73cbSSangeeta Misra ilb_status_t
737dbed73cbSSangeeta Misra ilbd_create_pg(ilbd_scf_pg_type_t pg_type, void *data)
738dbed73cbSSangeeta Misra {
739dbed73cbSSangeeta Misra 	ilb_status_t ret;
740dbed73cbSSangeeta Misra 	char *pgname;
741dbed73cbSSangeeta Misra 	scf_propertygroup_t *pg = NULL;
742dbed73cbSSangeeta Misra 	scf_value_t **val;
743dbed73cbSSangeeta Misra 	scf_handle_t *h;
744dbed73cbSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
745*3ae6a67dSSangeeta Misra 	char  *scfpgbuf; /* property group name or group type */
746dbed73cbSSangeeta Misra 	int i, i_st, i_end;
747dbed73cbSSangeeta Misra 
748dbed73cbSSangeeta Misra 	switch (pg_type) {
749dbed73cbSSangeeta Misra 	case ILBD_SCF_RULE: {
750dbed73cbSSangeeta Misra 		ilbd_rule_t *r_ent = (ilbd_rule_t *)data;
751dbed73cbSSangeeta Misra 
752dbed73cbSSangeeta Misra 		pgname = r_ent->irl_name;
753dbed73cbSSangeeta Misra 		i_st = 0;
754dbed73cbSSangeeta Misra 		i_end = ILBD_RULE_VAR_NUM;
755dbed73cbSSangeeta Misra 		break;
756dbed73cbSSangeeta Misra 	}
757dbed73cbSSangeeta Misra 	case ILBD_SCF_SG: {
758dbed73cbSSangeeta Misra 		ilbd_sg_t *s_ent = (ilbd_sg_t *)data;
759dbed73cbSSangeeta Misra 
760dbed73cbSSangeeta Misra 		pgname = s_ent->isg_name;
761dbed73cbSSangeeta Misra 		i_st = ILBD_RULE_VAR_NUM;
762dbed73cbSSangeeta Misra 		i_end = ILBD_RULE_VAR_NUM + ILBD_SG_VAR_NUM;
763dbed73cbSSangeeta Misra 		break;
764dbed73cbSSangeeta Misra 	}
765dbed73cbSSangeeta Misra 	case ILBD_SCF_HC: {
766dbed73cbSSangeeta Misra 		ilbd_hc_t *h_ent = (ilbd_hc_t *)data;
767dbed73cbSSangeeta Misra 
768dbed73cbSSangeeta Misra 		pgname = h_ent->ihc_name;
769dbed73cbSSangeeta Misra 		i_st = ILBD_RULE_VAR_NUM + ILBD_SG_VAR_NUM;
770dbed73cbSSangeeta Misra 		i_end = ILBD_PROP_VAR_NUM;
771dbed73cbSSangeeta Misra 		break;
772dbed73cbSSangeeta Misra 	}
773dbed73cbSSangeeta Misra 	default:
774dbed73cbSSangeeta Misra 		logdebug("ilbd_create_pg: invalid pg type %d for pg %s",
775dbed73cbSSangeeta Misra 		    pg_type, pgname);
776dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
777dbed73cbSSangeeta Misra 	}
778*3ae6a67dSSangeeta Misra 	if ((scfpgbuf = malloc(scf_name_len)) == NULL)
779*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
780dbed73cbSSangeeta Misra 
781*3ae6a67dSSangeeta Misra 	ilbd_name_to_scfpgname(pg_type, pgname, scfpgbuf);
782dbed73cbSSangeeta Misra 
783*3ae6a67dSSangeeta Misra 	ret = ilbd_scf_retrieve_pg(scfpgbuf, &pg, B_TRUE);
784*3ae6a67dSSangeeta Misra 	if (ret != ILB_STATUS_OK) {
785*3ae6a67dSSangeeta Misra 		free(scfpgbuf);
786dbed73cbSSangeeta Misra 		return (ret);
787*3ae6a67dSSangeeta Misra 	}
788dbed73cbSSangeeta Misra 	h = scf_pg_handle(pg);
789dbed73cbSSangeeta Misra 
790dbed73cbSSangeeta Misra 	/* fill in props */
791dbed73cbSSangeeta Misra 	for (i = i_st; i < i_end; i++) {
792dbed73cbSSangeeta Misra 		int num, j;
793dbed73cbSSangeeta Misra 		scf_type_t scftype = prop_tbl[i].scf_proptype;
794dbed73cbSSangeeta Misra 
795dbed73cbSSangeeta Misra 		ret = ilbd_data_to_scfval(pg_type, prop_tbl[i].val_type, h,
796dbed73cbSSangeeta Misra 		    data, &val, &scftype, &num);
797dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK)
798dbed73cbSSangeeta Misra 			goto done;
799dbed73cbSSangeeta Misra 
800dbed73cbSSangeeta Misra 		for (j = 0; j < num; j++) {
801dbed73cbSSangeeta Misra 			if (pg_type == ILBD_SCF_SG) {
802dbed73cbSSangeeta Misra 				ret = ilbd_get_svr_info(data, j, NULL,
803*3ae6a67dSSangeeta Misra 				    scfpgbuf);
804dbed73cbSSangeeta Misra 				if (ret == ILB_STATUS_ENOENT) {
805*3ae6a67dSSangeeta Misra 					(void) strlcpy(scfpgbuf,
806*3ae6a67dSSangeeta Misra 					    "EMPTY_SERVER", scf_name_len);
807dbed73cbSSangeeta Misra 				}
808*3ae6a67dSSangeeta Misra 				ret = ilbd_scf_set_prop(pg, scfpgbuf,
809dbed73cbSSangeeta Misra 				    scftype, val[j]);
810dbed73cbSSangeeta Misra 			} else {
811dbed73cbSSangeeta Misra 				ret = ilbd_scf_set_prop(pg,
812dbed73cbSSangeeta Misra 				    prop_tbl[i].scf_propname, scftype, val[j]);
813dbed73cbSSangeeta Misra 			}
814dbed73cbSSangeeta Misra 			scf_value_destroy(val[j]);
815dbed73cbSSangeeta Misra 		}
816dbed73cbSSangeeta Misra 		free(val);
817dbed73cbSSangeeta Misra 	}
818dbed73cbSSangeeta Misra 
819dbed73cbSSangeeta Misra done:
820*3ae6a67dSSangeeta Misra 	free(scfpgbuf);
821dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, NULL, NULL, pg);
822dbed73cbSSangeeta Misra 	return (ret);
823dbed73cbSSangeeta Misra }
824dbed73cbSSangeeta Misra 
825dbed73cbSSangeeta Misra /*
826dbed73cbSSangeeta Misra  * destroy a scf property group
827dbed73cbSSangeeta Misra  */
828dbed73cbSSangeeta Misra static ilb_status_t
829dbed73cbSSangeeta Misra ilbd_scf_delete_pg(scf_propertygroup_t *pg)
830dbed73cbSSangeeta Misra {
831dbed73cbSSangeeta Misra 	if (scf_pg_delete(pg) != 0)
832dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
833dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
834dbed73cbSSangeeta Misra }
835dbed73cbSSangeeta Misra 
836dbed73cbSSangeeta Misra /* sg can have same name as rule */
837dbed73cbSSangeeta Misra ilb_status_t
838dbed73cbSSangeeta Misra ilbd_destroy_pg(ilbd_scf_pg_type_t pg_t, const char *pgname)
839dbed73cbSSangeeta Misra {
840dbed73cbSSangeeta Misra 	ilb_status_t ret;
841dbed73cbSSangeeta Misra 	scf_propertygroup_t *pg;
842dbed73cbSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
843*3ae6a67dSSangeeta Misra 	char *scfname;
844dbed73cbSSangeeta Misra 
845*3ae6a67dSSangeeta Misra 	if ((scfname = malloc(scf_name_len)) == NULL)
846*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
847dbed73cbSSangeeta Misra 	ilbd_name_to_scfpgname(pg_t, pgname, scfname);
848dbed73cbSSangeeta Misra 
849dbed73cbSSangeeta Misra 	ret = ilbd_scf_retrieve_pg(scfname, &pg, B_FALSE);
850*3ae6a67dSSangeeta Misra 	free(scfname);
851dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_EEXIST)
852dbed73cbSSangeeta Misra 		return (ret);
853dbed73cbSSangeeta Misra 	ret = ilbd_scf_delete_pg(pg);
854dbed73cbSSangeeta Misra 	ilbd_scf_destroy(scf_pg_handle(pg), NULL, NULL, pg);
855dbed73cbSSangeeta Misra 	return (ret);
856dbed73cbSSangeeta Misra }
857dbed73cbSSangeeta Misra 
858dbed73cbSSangeeta Misra /*
859dbed73cbSSangeeta Misra  * Set named property to scf value specified.  If property is new,
860dbed73cbSSangeeta Misra  * create it.
861dbed73cbSSangeeta Misra  */
862dbed73cbSSangeeta Misra static ilb_status_t
863dbed73cbSSangeeta Misra ilbd_scf_set_prop(scf_propertygroup_t *pg, const char *propname,
864dbed73cbSSangeeta Misra     scf_type_t proptype, scf_value_t *val)
865dbed73cbSSangeeta Misra {
866dbed73cbSSangeeta Misra 	scf_handle_t *h = NULL;
867dbed73cbSSangeeta Misra 	scf_property_t *prop = NULL;
868dbed73cbSSangeeta Misra 	scf_value_t *oldval = NULL;
869dbed73cbSSangeeta Misra 	scf_transaction_t *tx = NULL;
870dbed73cbSSangeeta Misra 	scf_transaction_entry_t *ent = NULL;
871dbed73cbSSangeeta Misra 	boolean_t new = B_FALSE;
872dbed73cbSSangeeta Misra 	ilb_status_t ret = ILB_STATUS_OK;
873dbed73cbSSangeeta Misra 	int commit_ret;
874dbed73cbSSangeeta Misra 
875dbed73cbSSangeeta Misra 	h = scf_pg_handle(pg);
876dbed73cbSSangeeta Misra 	if (h == NULL || propname == NULL)
877dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
878dbed73cbSSangeeta Misra 
879dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_prop_val(pg, propname, &oldval);
880dbed73cbSSangeeta Misra 	if (oldval != NULL)
881dbed73cbSSangeeta Misra 		scf_value_destroy(oldval);
882dbed73cbSSangeeta Misra 	if (ret == ILB_STATUS_ENOENT)
883dbed73cbSSangeeta Misra 		new = B_TRUE;
884dbed73cbSSangeeta Misra 	else if (ret != ILB_STATUS_OK)
885dbed73cbSSangeeta Misra 		return (ret);
886dbed73cbSSangeeta Misra 
887dbed73cbSSangeeta Misra 	if ((prop = scf_property_create(h)) == NULL)
888dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
889dbed73cbSSangeeta Misra 	if ((tx = scf_transaction_create(h)) == NULL ||
890dbed73cbSSangeeta Misra 	    (ent = scf_entry_create(h)) == NULL) {
891dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
892dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: create scf transaction failed\n");
893dbed73cbSSangeeta Misra 		goto out;
894dbed73cbSSangeeta Misra 	}
895dbed73cbSSangeeta Misra 
896dbed73cbSSangeeta Misra 	if (scf_transaction_start(tx, pg) == -1) {
897dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
898dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: start scf transaction failed\n");
899dbed73cbSSangeeta Misra 		goto out;
900dbed73cbSSangeeta Misra 	}
901dbed73cbSSangeeta Misra 
902dbed73cbSSangeeta Misra 	if (new) {
903dbed73cbSSangeeta Misra 		if (scf_transaction_property_new(tx, ent, propname,
904dbed73cbSSangeeta Misra 		    proptype) == -1) {
905dbed73cbSSangeeta Misra 			ret = ilbd_scf_err_to_ilb_err();
906dbed73cbSSangeeta Misra 			logdebug("ilbd_scf_set_prop: create scf prop failed\n");
907dbed73cbSSangeeta Misra 			goto out;
908dbed73cbSSangeeta Misra 		}
909dbed73cbSSangeeta Misra 	} else {
910dbed73cbSSangeeta Misra 		if (scf_transaction_property_change(tx, ent, propname, proptype)
911dbed73cbSSangeeta Misra 		    == -1) {
912dbed73cbSSangeeta Misra 			ret = ilbd_scf_err_to_ilb_err();
913dbed73cbSSangeeta Misra 			logdebug("ilbd_scf_set_prop: change scf prop failed\n");
914dbed73cbSSangeeta Misra 			goto out;
915dbed73cbSSangeeta Misra 		}
916dbed73cbSSangeeta Misra 	}
917dbed73cbSSangeeta Misra 
918dbed73cbSSangeeta Misra 	if (scf_entry_add_value(ent, val) != 0) {
919dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: add scf entry failed\n");
920dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
921dbed73cbSSangeeta Misra 		goto out;
922dbed73cbSSangeeta Misra 	}
923dbed73cbSSangeeta Misra 
924dbed73cbSSangeeta Misra 	commit_ret = scf_transaction_commit(tx);
925dbed73cbSSangeeta Misra 	switch (commit_ret) {
926dbed73cbSSangeeta Misra 	case 1:
927dbed73cbSSangeeta Misra 		ret = ILB_STATUS_OK;
928dbed73cbSSangeeta Misra 		/* update pg here, so subsequent property setting  succeeds */
929dbed73cbSSangeeta Misra 		(void) scf_pg_update(pg);
930dbed73cbSSangeeta Misra 		break;
931dbed73cbSSangeeta Misra 	case 0:
932dbed73cbSSangeeta Misra 		/* transaction failed due to not having most recent pg */
933dbed73cbSSangeeta Misra 		ret = ILB_STATUS_INUSE;
934dbed73cbSSangeeta Misra 		break;
935dbed73cbSSangeeta Misra 	default:
936dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
937dbed73cbSSangeeta Misra 		break;
938dbed73cbSSangeeta Misra 	}
939dbed73cbSSangeeta Misra out:
940dbed73cbSSangeeta Misra 	if (tx != NULL)
941dbed73cbSSangeeta Misra 		scf_transaction_destroy(tx);
942dbed73cbSSangeeta Misra 	if (ent != NULL)
943dbed73cbSSangeeta Misra 		scf_entry_destroy(ent);
944dbed73cbSSangeeta Misra 	if (prop != NULL)
945dbed73cbSSangeeta Misra 		scf_property_destroy(prop);
946dbed73cbSSangeeta Misra 
947dbed73cbSSangeeta Misra 	return (ret);
948dbed73cbSSangeeta Misra }
949dbed73cbSSangeeta Misra 
950dbed73cbSSangeeta Misra /*
951dbed73cbSSangeeta Misra  * get a prop's scf val
952dbed73cbSSangeeta Misra  */
953dbed73cbSSangeeta Misra static ilb_status_t
954dbed73cbSSangeeta Misra ilbd_scf_get_prop_val(scf_propertygroup_t *pg, const char *propname,
955dbed73cbSSangeeta Misra     scf_value_t **val)
956dbed73cbSSangeeta Misra {
957dbed73cbSSangeeta Misra 	scf_handle_t *h = NULL;
958dbed73cbSSangeeta Misra 	scf_property_t *prop = NULL;
959dbed73cbSSangeeta Misra 	scf_value_t *value = NULL;
960dbed73cbSSangeeta Misra 	ilb_status_t ret = ILB_STATUS_OK;
961dbed73cbSSangeeta Misra 
962dbed73cbSSangeeta Misra 	h = scf_pg_handle(pg);
963dbed73cbSSangeeta Misra 	if (h == NULL || propname == NULL)
964dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
965dbed73cbSSangeeta Misra 
966dbed73cbSSangeeta Misra 	if ((prop = scf_property_create(h)) == NULL)
967dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
968dbed73cbSSangeeta Misra 
969dbed73cbSSangeeta Misra 	if (scf_pg_get_property(pg, propname, prop) != 0) {
970dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
971dbed73cbSSangeeta Misra 		goto out;
972dbed73cbSSangeeta Misra 	}
973dbed73cbSSangeeta Misra 
974dbed73cbSSangeeta Misra 	if ((value = scf_value_create(h)) == NULL) {
975dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
976dbed73cbSSangeeta Misra 		goto out;
977dbed73cbSSangeeta Misra 	}
978dbed73cbSSangeeta Misra 
979dbed73cbSSangeeta Misra 	if (scf_property_get_value(prop, value) != 0) {
980dbed73cbSSangeeta Misra 		scf_value_destroy(value);
981dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
982dbed73cbSSangeeta Misra 		goto out;
983dbed73cbSSangeeta Misra 	}
984dbed73cbSSangeeta Misra 
985dbed73cbSSangeeta Misra 	*val = value;
986dbed73cbSSangeeta Misra out:
987dbed73cbSSangeeta Misra 	if (prop != NULL)
988dbed73cbSSangeeta Misra 		scf_property_destroy(prop);
989dbed73cbSSangeeta Misra 
990dbed73cbSSangeeta Misra 	return (ret);
991dbed73cbSSangeeta Misra }
992dbed73cbSSangeeta Misra 
993dbed73cbSSangeeta Misra typedef struct ilbd_data
994dbed73cbSSangeeta Misra {
995dbed73cbSSangeeta Misra 	union {
996dbed73cbSSangeeta Misra 		ilb_sg_info_t *sg_info;
997dbed73cbSSangeeta Misra 		ilb_hc_info_t *hc_info;
998dbed73cbSSangeeta Misra 		ilb_rule_info_t *rule_info;
999dbed73cbSSangeeta Misra 	} data;
1000dbed73cbSSangeeta Misra 	ilbd_scf_pg_type_t pg_type;	/* type of data */
1001dbed73cbSSangeeta Misra #define	sg_data data.sg_info
1002dbed73cbSSangeeta Misra #define	hc_data data.hc_info
1003dbed73cbSSangeeta Misra #define	rule_data data.rule_info
1004dbed73cbSSangeeta Misra } ilbd_data_t;
1005dbed73cbSSangeeta Misra 
1006dbed73cbSSangeeta Misra void
1007dbed73cbSSangeeta Misra ilbd_scf_str_to_ip(int ipversion, char *ipstr, struct in6_addr *addr)
1008dbed73cbSSangeeta Misra {
1009dbed73cbSSangeeta Misra 	ilb_ip_addr_t ipaddr;
1010dbed73cbSSangeeta Misra 	void *addrptr;
1011dbed73cbSSangeeta Misra 
1012dbed73cbSSangeeta Misra 	addrptr = (ipversion == AF_INET) ?
1013dbed73cbSSangeeta Misra 	    (void *)&ipaddr.ia_v4 : (void *)&ipaddr.ia_v6;
1014dbed73cbSSangeeta Misra 	(void) inet_pton(ipversion, ipstr, addrptr);
1015dbed73cbSSangeeta Misra 	if (ipversion == AF_INET) {
1016dbed73cbSSangeeta Misra 		IN6_INADDR_TO_V4MAPPED(&(ipaddr.ia_v4), addr);
1017dbed73cbSSangeeta Misra 	} else {
1018dbed73cbSSangeeta Misra 		(void) memcpy(addr, &(ipaddr.ia_v6),
1019dbed73cbSSangeeta Misra 		    sizeof (struct in6_addr));
1020dbed73cbSSangeeta Misra 	}
1021dbed73cbSSangeeta Misra }
1022dbed73cbSSangeeta Misra 
1023dbed73cbSSangeeta Misra /*
1024dbed73cbSSangeeta Misra  * This function takes a scf value and writes it to the correct field of the
1025dbed73cbSSangeeta Misra  * corresponding data struct.
1026dbed73cbSSangeeta Misra  */
1027dbed73cbSSangeeta Misra static ilb_status_t
1028dbed73cbSSangeeta Misra ilbd_scfval_to_data(const char *propname, ilbd_var_type_t ilb_type,
1029dbed73cbSSangeeta Misra     scf_value_t *val, ilbd_data_t *ilb_data)
1030dbed73cbSSangeeta Misra {
1031dbed73cbSSangeeta Misra 
1032dbed73cbSSangeeta Misra 	scf_type_t scf_type = scf_value_type(val);
1033dbed73cbSSangeeta Misra 	ilbd_scf_pg_type_t pg_type = ilb_data->pg_type;
1034dbed73cbSSangeeta Misra 	int ret = 0;
1035dbed73cbSSangeeta Misra 	ilb_rule_info_t *r_ent = NULL;
1036dbed73cbSSangeeta Misra 	ilb_sg_info_t *s_ent = NULL;
1037dbed73cbSSangeeta Misra 	ilb_hc_info_t *h_ent = NULL;
1038dbed73cbSSangeeta Misra 	char ipstr[INET6_ADDRSTRLEN];
1039*3ae6a67dSSangeeta Misra 	char *valstr;
1040dbed73cbSSangeeta Misra 	int64_t valint;
1041dbed73cbSSangeeta Misra 	uint8_t valbool;
1042dbed73cbSSangeeta Misra 	int ipversion;
1043dbed73cbSSangeeta Misra 
1044dbed73cbSSangeeta Misra 	switch (pg_type) {
1045dbed73cbSSangeeta Misra 	case ILBD_SCF_RULE:
1046dbed73cbSSangeeta Misra 		r_ent = ilb_data->rule_data;
1047dbed73cbSSangeeta Misra 		break;
1048dbed73cbSSangeeta Misra 	case ILBD_SCF_HC:
1049dbed73cbSSangeeta Misra 		h_ent = ilb_data->hc_data;
1050dbed73cbSSangeeta Misra 		break;
1051dbed73cbSSangeeta Misra 	case ILBD_SCF_SG:
1052dbed73cbSSangeeta Misra 		s_ent = ilb_data->sg_data;
1053dbed73cbSSangeeta Misra 		break;
1054dbed73cbSSangeeta Misra 	}
1055dbed73cbSSangeeta Misra 
1056dbed73cbSSangeeta Misra 	/* get scf value out */
1057*3ae6a67dSSangeeta Misra 	if ((valstr = malloc(ILBD_MAX_VALUE_LEN)) == NULL)
1058*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
1059dbed73cbSSangeeta Misra 	switch (scf_type) {
1060dbed73cbSSangeeta Misra 		case SCF_TYPE_NET_ADDR_V4:
1061dbed73cbSSangeeta Misra 			if (scf_value_get_as_string_typed(val,
1062*3ae6a67dSSangeeta Misra 			    SCF_TYPE_NET_ADDR_V4, ipstr, INET_ADDRSTRLEN) < 0) {
1063*3ae6a67dSSangeeta Misra 				free(valstr);
1064dbed73cbSSangeeta Misra 				return (ILB_STATUS_INTERNAL);
1065*3ae6a67dSSangeeta Misra 			}
1066dbed73cbSSangeeta Misra 			ipversion = AF_INET;
1067dbed73cbSSangeeta Misra 			break;
1068dbed73cbSSangeeta Misra 		case SCF_TYPE_NET_ADDR_V6:
1069dbed73cbSSangeeta Misra 			if (scf_value_get_as_string_typed(val,
1070*3ae6a67dSSangeeta Misra 			    SCF_TYPE_NET_ADDR_V6, ipstr,
1071*3ae6a67dSSangeeta Misra 			    INET6_ADDRSTRLEN) < 0) {
1072*3ae6a67dSSangeeta Misra 				free(valstr);
1073dbed73cbSSangeeta Misra 				return (ILB_STATUS_INTERNAL);
1074*3ae6a67dSSangeeta Misra 			}
1075dbed73cbSSangeeta Misra 			ipversion = AF_INET6;
1076dbed73cbSSangeeta Misra 			break;
1077dbed73cbSSangeeta Misra 		case SCF_TYPE_BOOLEAN:
1078*3ae6a67dSSangeeta Misra 			if (scf_value_get_boolean(val, &valbool) < 0) {
1079*3ae6a67dSSangeeta Misra 				free(valstr);
1080dbed73cbSSangeeta Misra 				return (ILB_STATUS_INTERNAL);
1081*3ae6a67dSSangeeta Misra 			}
1082dbed73cbSSangeeta Misra 			break;
1083dbed73cbSSangeeta Misra 		case SCF_TYPE_ASTRING:
1084*3ae6a67dSSangeeta Misra 			if (scf_value_get_astring(val, valstr,
1085*3ae6a67dSSangeeta Misra 			    ILBD_MAX_VALUE_LEN) < 0) {
1086*3ae6a67dSSangeeta Misra 				free(valstr);
1087dbed73cbSSangeeta Misra 				return (ILB_STATUS_INTERNAL);
1088*3ae6a67dSSangeeta Misra 			}
1089dbed73cbSSangeeta Misra 			break;
1090dbed73cbSSangeeta Misra 		case SCF_TYPE_INTEGER:
1091*3ae6a67dSSangeeta Misra 			if (scf_value_get_integer(val, &valint) < 0) {
1092*3ae6a67dSSangeeta Misra 				free(valstr);
1093dbed73cbSSangeeta Misra 				return (ILB_STATUS_INTERNAL);
1094*3ae6a67dSSangeeta Misra 			}
1095dbed73cbSSangeeta Misra 			break;
1096dbed73cbSSangeeta Misra 		default:
1097*3ae6a67dSSangeeta Misra 			free(valstr);
1098dbed73cbSSangeeta Misra 			return (ILB_STATUS_INTERNAL);
1099dbed73cbSSangeeta Misra 	}
1100dbed73cbSSangeeta Misra 
1101dbed73cbSSangeeta Misra 	ret = ILB_STATUS_OK;
1102dbed73cbSSangeeta Misra 	switch (ilb_type) {
1103dbed73cbSSangeeta Misra 	case ILBD_RULE_STATUS:
1104dbed73cbSSangeeta Misra 		if (valbool)
1105dbed73cbSSangeeta Misra 			r_ent->rl_flags |= ILB_FLAGS_RULE_ENABLED;
1106dbed73cbSSangeeta Misra 		break;
1107dbed73cbSSangeeta Misra 	case ILBD_RULE_VIP:
1108dbed73cbSSangeeta Misra 		r_ent->rl_ipversion = ipversion;
1109dbed73cbSSangeeta Misra 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_vip);
1110dbed73cbSSangeeta Misra 		break;
1111dbed73cbSSangeeta Misra 	case ILBD_RULE_PROTO: {
1112dbed73cbSSangeeta Misra 		struct protoent *protoent;
1113dbed73cbSSangeeta Misra 
1114dbed73cbSSangeeta Misra 		protoent = getprotobyname(valstr);
1115dbed73cbSSangeeta Misra 		r_ent->rl_proto = protoent->p_proto;
1116dbed73cbSSangeeta Misra 		break;
1117dbed73cbSSangeeta Misra 	}
1118dbed73cbSSangeeta Misra 	case ILBD_RULE_PORT: {
1119dbed73cbSSangeeta Misra 		char *token1, *token2;
1120dbed73cbSSangeeta Misra 
1121dbed73cbSSangeeta Misra 		token1 = strtok(valstr, "-");
1122dbed73cbSSangeeta Misra 		token2 = strtok(NULL, "-");
1123dbed73cbSSangeeta Misra 		r_ent->rl_minport = atoi(token1);
1124dbed73cbSSangeeta Misra 		r_ent->rl_maxport = atoi(token2);
1125dbed73cbSSangeeta Misra 		break;
1126dbed73cbSSangeeta Misra 	}
1127dbed73cbSSangeeta Misra 	case ILBD_RULE_ALGO:
1128dbed73cbSSangeeta Misra 		ilbd_scf_str_to_algo(&(r_ent->rl_algo), valstr);
1129dbed73cbSSangeeta Misra 		break;
1130dbed73cbSSangeeta Misra 	case ILBD_RULE_TOPO:
1131dbed73cbSSangeeta Misra 		ilbd_scf_str_to_topo(&(r_ent->rl_topo), valstr);
1132dbed73cbSSangeeta Misra 		break;
1133dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_STR:
1134dbed73cbSSangeeta Misra 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_nat_src_start);
1135dbed73cbSSangeeta Misra 		break;
1136dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_END:
1137dbed73cbSSangeeta Misra 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_nat_src_end);
1138dbed73cbSSangeeta Misra 		break;
1139dbed73cbSSangeeta Misra 	case ILBD_RULE_STI_MASK:
1140dbed73cbSSangeeta Misra 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_stickymask);
1141dbed73cbSSangeeta Misra 		if (ipversion == AF_INET) {
1142dbed73cbSSangeeta Misra 			if (!IN6_IS_ADDR_V4MAPPED_ANY(&r_ent->rl_stickymask))
1143dbed73cbSSangeeta Misra 				r_ent->rl_flags |= ILB_FLAGS_RULE_STICKY;
1144dbed73cbSSangeeta Misra 		} else {
1145dbed73cbSSangeeta Misra 			if (!IN6_IS_ADDR_UNSPECIFIED(&r_ent->rl_stickymask))
1146dbed73cbSSangeeta Misra 				r_ent->rl_flags |= ILB_FLAGS_RULE_STICKY;
1147dbed73cbSSangeeta Misra 		}
1148dbed73cbSSangeeta Misra 		break;
1149dbed73cbSSangeeta Misra 	case ILBD_RULE_SGNAME:
1150dbed73cbSSangeeta Misra 		(void) strlcpy(r_ent->rl_sgname, valstr,
1151dbed73cbSSangeeta Misra 		    sizeof (r_ent->rl_sgname));
1152dbed73cbSSangeeta Misra 		break;
1153dbed73cbSSangeeta Misra 	case ILBD_RULE_HCNAME:
1154dbed73cbSSangeeta Misra 		(void) strlcpy(r_ent->rl_hcname, valstr,
1155dbed73cbSSangeeta Misra 		    sizeof (r_ent->rl_hcname));
1156dbed73cbSSangeeta Misra 		break;
1157dbed73cbSSangeeta Misra 	case ILBD_RULE_HCPORT:
1158dbed73cbSSangeeta Misra 		r_ent->rl_hcport = valint;
1159dbed73cbSSangeeta Misra 		break;
1160dbed73cbSSangeeta Misra 	case ILBD_RULE_HCPFLAG:
1161dbed73cbSSangeeta Misra 		r_ent->rl_hcpflag = valint;
1162dbed73cbSSangeeta Misra 		break;
1163dbed73cbSSangeeta Misra 	case ILBD_RULE_DRAINTIME:
1164dbed73cbSSangeeta Misra 		r_ent->rl_conndrain = valint;
1165dbed73cbSSangeeta Misra 		break;
1166dbed73cbSSangeeta Misra 	case ILBD_RULE_NAT_TO:
1167dbed73cbSSangeeta Misra 		r_ent->rl_nat_timeout = valint;
1168dbed73cbSSangeeta Misra 		break;
1169dbed73cbSSangeeta Misra 	case ILBD_RULE_PERS_TO:
1170dbed73cbSSangeeta Misra 		r_ent->rl_sticky_timeout = valint;
1171dbed73cbSSangeeta Misra 		break;
1172dbed73cbSSangeeta Misra 
1173dbed73cbSSangeeta Misra 	case ILBD_SG_SERVER: {
1174dbed73cbSSangeeta Misra 		int svr_cnt = s_ent->sg_srvcount;
1175dbed73cbSSangeeta Misra 
1176dbed73cbSSangeeta Misra 		/* found a new server, increase the svr count of this sg */
1177dbed73cbSSangeeta Misra 		s_ent->sg_srvcount++;
1178dbed73cbSSangeeta Misra 
1179dbed73cbSSangeeta Misra 		/*
1180dbed73cbSSangeeta Misra 		 * valstr contains information of one server in the servergroup
1181dbed73cbSSangeeta Misra 		 * valstr is in the format of "ip:minport-maxport:enable"
1182dbed73cbSSangeeta Misra 		 */
1183dbed73cbSSangeeta Misra 		s_ent = realloc(s_ent, sizeof (ilb_sg_info_t) +
1184dbed73cbSSangeeta Misra 		    s_ent->sg_srvcount * sizeof (ilb_sg_srv_t));
1185dbed73cbSSangeeta Misra 
1186dbed73cbSSangeeta Misra 		/* sgs_srvID is the sg name, leave it blank */
1187dbed73cbSSangeeta Misra 		/*
1188dbed73cbSSangeeta Misra 		 * sgs_id is the digit in propname, propname is in a format of
1189dbed73cbSSangeeta Misra 		 * "server" + the digital serverID. We get the serverID by
1190dbed73cbSSangeeta Misra 		 * reading from the 7th char of propname.
1191dbed73cbSSangeeta Misra 		 */
1192dbed73cbSSangeeta Misra 		s_ent->sg_servers[svr_cnt].sgs_id = atoi(&propname[6]);
1193dbed73cbSSangeeta Misra 
1194dbed73cbSSangeeta Misra 		ilbd_get_svr_field(valstr,
1195dbed73cbSSangeeta Misra 		    &s_ent->sg_servers[svr_cnt].sgs_addr,
1196dbed73cbSSangeeta Misra 		    &s_ent->sg_servers[svr_cnt].sgs_minport,
1197dbed73cbSSangeeta Misra 		    &s_ent->sg_servers[svr_cnt].sgs_maxport,
1198dbed73cbSSangeeta Misra 		    &s_ent->sg_servers[svr_cnt].sgs_flags);
1199dbed73cbSSangeeta Misra 		ilb_data->sg_data = s_ent;
1200dbed73cbSSangeeta Misra 
1201dbed73cbSSangeeta Misra 		break;
1202dbed73cbSSangeeta Misra 	}
1203dbed73cbSSangeeta Misra 	case ILBD_HC_TEST:
1204dbed73cbSSangeeta Misra 		(void) strlcpy(h_ent->hci_test, valstr,
1205dbed73cbSSangeeta Misra 		    sizeof (h_ent->hci_test));
1206dbed73cbSSangeeta Misra 		break;
1207dbed73cbSSangeeta Misra 	case ILBD_HC_TIMEOUT:
1208dbed73cbSSangeeta Misra 		h_ent->hci_timeout = valint;
1209dbed73cbSSangeeta Misra 		break;
1210dbed73cbSSangeeta Misra 	case ILBD_HC_INTERVAL:
1211dbed73cbSSangeeta Misra 		h_ent->hci_interval = valint;
1212dbed73cbSSangeeta Misra 		break;
1213dbed73cbSSangeeta Misra 	case ILBD_HC_DEF_PING:
1214dbed73cbSSangeeta Misra 		h_ent->hci_def_ping = valbool;
1215dbed73cbSSangeeta Misra 		break;
1216dbed73cbSSangeeta Misra 	case ILBD_HC_COUNT:
1217dbed73cbSSangeeta Misra 		h_ent->hci_count = valint;
1218dbed73cbSSangeeta Misra 		break;
1219dbed73cbSSangeeta Misra 	case ILBD_VAR_INVALID:
1220dbed73cbSSangeeta Misra 		/*
1221dbed73cbSSangeeta Misra 		 * An empty server group is represented by an invalid
1222dbed73cbSSangeeta Misra 		 * SCF property.  So when loading a server group, this
1223dbed73cbSSangeeta Misra 		 * case can be hit.  But it should happen only for this
1224dbed73cbSSangeeta Misra 		 * single case.  So if it happens in another case, move
1225dbed73cbSSangeeta Misra 		 * the service into maintenance mode.
1226dbed73cbSSangeeta Misra 		 */
1227dbed73cbSSangeeta Misra 		if (pg_type != ILBD_SCF_SG || scf_type != SCF_TYPE_ASTRING) {
1228dbed73cbSSangeeta Misra 			logerr("%s: invalid ilb type", __func__);
1229dbed73cbSSangeeta Misra 			(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
1230dbed73cbSSangeeta Misra 		} else {
1231dbed73cbSSangeeta Misra 			logdebug("%s: invalid ilb type", __func__);
1232dbed73cbSSangeeta Misra 		}
1233dbed73cbSSangeeta Misra 		break;
1234dbed73cbSSangeeta Misra 	}
1235dbed73cbSSangeeta Misra 
1236*3ae6a67dSSangeeta Misra 	free(valstr);
1237dbed73cbSSangeeta Misra 	return (ret);
1238dbed73cbSSangeeta Misra }
1239dbed73cbSSangeeta Misra 
1240dbed73cbSSangeeta Misra static ilbd_var_type_t
1241dbed73cbSSangeeta Misra ilbd_name_to_valtype(const char *prop_name)
1242dbed73cbSSangeeta Misra {
1243dbed73cbSSangeeta Misra 	int i;
1244dbed73cbSSangeeta Misra 
1245dbed73cbSSangeeta Misra 	for (i = 0; i < ILBD_PROP_VAR_NUM; i++)
1246dbed73cbSSangeeta Misra 		if (strncmp(prop_name, prop_tbl[i].scf_propname,
1247dbed73cbSSangeeta Misra 		    strlen(prop_tbl[i].scf_propname)) == 0)
1248dbed73cbSSangeeta Misra 			return (prop_tbl[i].val_type);
1249dbed73cbSSangeeta Misra 
1250dbed73cbSSangeeta Misra 	logdebug("ilbd_name_to_valtype: couldn't find prop %s", prop_name);
1251dbed73cbSSangeeta Misra 	return (ILBD_VAR_INVALID);
1252dbed73cbSSangeeta Misra }
1253dbed73cbSSangeeta Misra 
1254dbed73cbSSangeeta Misra /* callback for pg_walk_prop, arg is ilbd_data_t */
1255dbed73cbSSangeeta Misra static ilb_status_t
1256dbed73cbSSangeeta Misra ilbd_scf_load_prop(scf_propertygroup_t *pg, const char *prop_name, void *arg)
1257dbed73cbSSangeeta Misra {
1258dbed73cbSSangeeta Misra 	scf_handle_t *h;
1259dbed73cbSSangeeta Misra 	scf_value_t *val;
1260dbed73cbSSangeeta Misra 	ilb_status_t ret;
1261dbed73cbSSangeeta Misra 	ilbd_data_t *ilb_data = (ilbd_data_t *)arg;
1262dbed73cbSSangeeta Misra 	ilbd_var_type_t val_type = ilbd_name_to_valtype(prop_name);
1263dbed73cbSSangeeta Misra 
1264dbed73cbSSangeeta Misra 	h = scf_pg_handle(pg);
1265dbed73cbSSangeeta Misra 	if (h == NULL)
1266dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1267dbed73cbSSangeeta Misra 
1268dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_prop_val(pg, prop_name, &val);
1269dbed73cbSSangeeta Misra 	if (ret == ILB_STATUS_ENOENT)
1270dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
1271dbed73cbSSangeeta Misra 	else if (ret != ILB_STATUS_OK)
1272dbed73cbSSangeeta Misra 		return (ret);
1273dbed73cbSSangeeta Misra 
1274dbed73cbSSangeeta Misra 	/*
1275dbed73cbSSangeeta Misra 	 * Load value to ilb_data.
1276dbed73cbSSangeeta Misra 	 */
1277dbed73cbSSangeeta Misra 	ret = ilbd_scfval_to_data(prop_name, val_type, val, ilb_data);
1278dbed73cbSSangeeta Misra 
1279dbed73cbSSangeeta Misra out:
1280dbed73cbSSangeeta Misra 	if (val != NULL)
1281dbed73cbSSangeeta Misra 		scf_value_destroy(val);
1282dbed73cbSSangeeta Misra 
1283dbed73cbSSangeeta Misra 	return (ret);
1284dbed73cbSSangeeta Misra }
1285dbed73cbSSangeeta Misra 
1286dbed73cbSSangeeta Misra /*
1287dbed73cbSSangeeta Misra  * walk properties in one prop group, arg is ilbd_data
1288dbed73cbSSangeeta Misra  * cb is ilbd_scf_load_prop()
1289dbed73cbSSangeeta Misra  */
1290dbed73cbSSangeeta Misra static ilb_status_t
1291dbed73cbSSangeeta Misra ilbd_scf_pg_walk_props(scf_propertygroup_t *pg,
1292dbed73cbSSangeeta Misra     ilb_status_t (*cb)(scf_propertygroup_t *, const char *, void *),
1293dbed73cbSSangeeta Misra     void *arg)
1294dbed73cbSSangeeta Misra {
1295dbed73cbSSangeeta Misra 	scf_handle_t *h;
1296dbed73cbSSangeeta Misra 	scf_iter_t *propiter;
1297dbed73cbSSangeeta Misra 	scf_property_t *prop;
1298dbed73cbSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
1299*3ae6a67dSSangeeta Misra 	char *prop_name = NULL;
1300dbed73cbSSangeeta Misra 	ilb_status_t ret = ILB_STATUS_OK;
1301dbed73cbSSangeeta Misra 	int scf_ret = -1;
1302dbed73cbSSangeeta Misra 
1303dbed73cbSSangeeta Misra 	h = scf_pg_handle(pg);
1304dbed73cbSSangeeta Misra 	if (h == NULL)
1305dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1306dbed73cbSSangeeta Misra 
1307dbed73cbSSangeeta Misra 	prop = scf_property_create(h);
1308dbed73cbSSangeeta Misra 	propiter = scf_iter_create(h);
1309dbed73cbSSangeeta Misra 	if (prop == NULL || propiter == NULL)
1310dbed73cbSSangeeta Misra 		goto out;
1311dbed73cbSSangeeta Misra 
1312dbed73cbSSangeeta Misra 	if (scf_iter_pg_properties(propiter, pg) != 0)
1313dbed73cbSSangeeta Misra 		goto out;
1314dbed73cbSSangeeta Misra 
1315*3ae6a67dSSangeeta Misra 	if ((prop_name = malloc(scf_name_len)) == NULL) {
1316*3ae6a67dSSangeeta Misra 		ret = ILB_STATUS_ENOMEM;
1317*3ae6a67dSSangeeta Misra 		goto out;
1318*3ae6a67dSSangeeta Misra 	}
1319dbed73cbSSangeeta Misra 	while ((scf_ret = scf_iter_next_property(propiter, prop)) == 1) {
1320*3ae6a67dSSangeeta Misra 		if (scf_property_get_name(prop, prop_name, scf_name_len)
1321dbed73cbSSangeeta Misra 		    < 0) {
1322dbed73cbSSangeeta Misra 			ret = ilbd_scf_err_to_ilb_err();
1323dbed73cbSSangeeta Misra 			goto out;
1324dbed73cbSSangeeta Misra 		}
1325dbed73cbSSangeeta Misra 		ret = cb(pg, prop_name, arg);
1326dbed73cbSSangeeta Misra 		if (ret != ILB_STATUS_OK)
1327dbed73cbSSangeeta Misra 			break;
1328dbed73cbSSangeeta Misra 	}
1329dbed73cbSSangeeta Misra out:
1330*3ae6a67dSSangeeta Misra 	if (prop_name != NULL)
1331*3ae6a67dSSangeeta Misra 		free(prop_name);
1332dbed73cbSSangeeta Misra 	if (scf_ret == -1)
1333dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1334dbed73cbSSangeeta Misra 	if (prop != NULL)
1335dbed73cbSSangeeta Misra 		scf_property_destroy(prop);
1336dbed73cbSSangeeta Misra 	if (propiter != NULL)
1337dbed73cbSSangeeta Misra 		scf_iter_destroy(propiter);
1338dbed73cbSSangeeta Misra 
1339dbed73cbSSangeeta Misra 	return (ret);
1340dbed73cbSSangeeta Misra }
1341dbed73cbSSangeeta Misra 
1342dbed73cbSSangeeta Misra /* cbs are libd_create_X */
1343dbed73cbSSangeeta Misra static ilb_status_t
1344dbed73cbSSangeeta Misra ilbd_scf_instance_walk_pg(scf_instance_t *inst,
1345dbed73cbSSangeeta Misra     ilbd_scf_pg_type_t pg_type,
1346dbed73cbSSangeeta Misra     ilb_status_t (*cb)(void *, int, struct passwd *, ucred_t *),
1347dbed73cbSSangeeta Misra     void *arg1, void *arg2)
1348dbed73cbSSangeeta Misra {
1349dbed73cbSSangeeta Misra 	int			scf_ret;
1350dbed73cbSSangeeta Misra 	ilb_status_t		ret;
1351dbed73cbSSangeeta Misra 	scf_handle_t		*h;
1352dbed73cbSSangeeta Misra 	scf_iter_t		*pgiter;
1353dbed73cbSSangeeta Misra 	scf_propertygroup_t	*newpg;
1354dbed73cbSSangeeta Misra 	int			port = *((int *)arg1);
1355*3ae6a67dSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
1356*3ae6a67dSSangeeta Misra 	char *pg_name = NULL;
1357dbed73cbSSangeeta Misra 
1358dbed73cbSSangeeta Misra 	if (inst == NULL)
1359dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1360dbed73cbSSangeeta Misra 
1361dbed73cbSSangeeta Misra 	h = scf_instance_handle(inst);
1362dbed73cbSSangeeta Misra 	if (h == NULL)
1363dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1364dbed73cbSSangeeta Misra 
1365dbed73cbSSangeeta Misra 	if ((newpg = scf_pg_create(h)) == NULL)
1366dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
1367dbed73cbSSangeeta Misra 
1368dbed73cbSSangeeta Misra 	if ((pgiter = scf_iter_create(h)) == NULL) {
1369dbed73cbSSangeeta Misra 		scf_pg_destroy(newpg);
1370dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
1371dbed73cbSSangeeta Misra 	}
1372dbed73cbSSangeeta Misra 
1373dbed73cbSSangeeta Misra 	if ((scf_ret = scf_iter_instance_pgs(pgiter, inst)) < 0)
1374dbed73cbSSangeeta Misra 		goto out;
1375dbed73cbSSangeeta Misra 
1376*3ae6a67dSSangeeta Misra 	if ((pg_name = malloc(scf_name_len)) == NULL) {
1377*3ae6a67dSSangeeta Misra 		ret = ILB_STATUS_ENOMEM;
1378*3ae6a67dSSangeeta Misra 		goto out;
1379*3ae6a67dSSangeeta Misra 	}
1380dbed73cbSSangeeta Misra 	while ((scf_ret = scf_iter_next_pg(pgiter, newpg)) > 0) {
1381dbed73cbSSangeeta Misra 		ilbd_data_t data;
1382dbed73cbSSangeeta Misra 
1383*3ae6a67dSSangeeta Misra 		if (scf_pg_get_name(newpg, pg_name, scf_name_len) < 0) {
1384dbed73cbSSangeeta Misra 			ret = ilbd_scf_err_to_ilb_err();
1385dbed73cbSSangeeta Misra 			goto out;
1386dbed73cbSSangeeta Misra 		}
1387dbed73cbSSangeeta Misra 
1388dbed73cbSSangeeta Misra 		/*
1389dbed73cbSSangeeta Misra 		 * if pg name indicates it's a ilb configuration, walk its prop
1390dbed73cbSSangeeta Misra 		 */
1391dbed73cbSSangeeta Misra 		data.pg_type = pg_type;
1392dbed73cbSSangeeta Misra 		data.hc_data = NULL;
1393dbed73cbSSangeeta Misra 		data.sg_data = NULL;
1394dbed73cbSSangeeta Misra 		data.rule_data = NULL;
1395dbed73cbSSangeeta Misra 
1396dbed73cbSSangeeta Misra 		switch (pg_type) {
1397dbed73cbSSangeeta Misra 		case ILBD_SCF_RULE:
1398dbed73cbSSangeeta Misra 			if (strncmp(ILBD_PG_NAME_RULE, pg_name,
1399dbed73cbSSangeeta Misra 			    strlen(ILBD_PG_NAME_RULE)) == 0) {
1400dbed73cbSSangeeta Misra 				data.rule_data = calloc(1,
1401dbed73cbSSangeeta Misra 				    sizeof (ilb_rule_info_t));
1402dbed73cbSSangeeta Misra 				if (data.rule_data == NULL) {
1403dbed73cbSSangeeta Misra 					ret = ILB_STATUS_ENOMEM;
1404dbed73cbSSangeeta Misra 					goto out;
1405dbed73cbSSangeeta Misra 				}
1406dbed73cbSSangeeta Misra 				ret = ilbd_scf_pg_walk_props(newpg,
1407dbed73cbSSangeeta Misra 				    ilbd_scf_load_prop, &data);
1408dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK)
1409dbed73cbSSangeeta Misra 					goto out;
1410dbed73cbSSangeeta Misra 				assert(data.rule_data != NULL);
1411dbed73cbSSangeeta Misra 				/* set rule name */
1412dbed73cbSSangeeta Misra 				(void) strlcpy(data.rule_data->rl_name,
1413dbed73cbSSangeeta Misra 				    &pg_name[strlen(ILBD_PG_NAME_RULE)],
1414dbed73cbSSangeeta Misra 				    sizeof (data.rule_data->rl_name));
1415dbed73cbSSangeeta Misra 
1416dbed73cbSSangeeta Misra 				ret = cb(data.rule_data, port, arg2, NULL);
1417dbed73cbSSangeeta Misra 				free(data.rule_data);
1418dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK)
1419dbed73cbSSangeeta Misra 					goto out;
1420dbed73cbSSangeeta Misra 			}
1421dbed73cbSSangeeta Misra 			break;
1422dbed73cbSSangeeta Misra 		case ILBD_SCF_SG:
1423dbed73cbSSangeeta Misra 			if (strncmp(ILBD_PG_NAME_SG, pg_name,
1424dbed73cbSSangeeta Misra 			    strlen(ILBD_PG_NAME_SG)) == 0) {
1425dbed73cbSSangeeta Misra 				data.sg_data = calloc(1,
1426dbed73cbSSangeeta Misra 				    sizeof (ilb_sg_info_t));
1427*3ae6a67dSSangeeta Misra 				if (data.sg_data == NULL) {
1428*3ae6a67dSSangeeta Misra 					ret = ILB_STATUS_ENOMEM;
1429*3ae6a67dSSangeeta Misra 					goto out;
1430*3ae6a67dSSangeeta Misra 				}
1431dbed73cbSSangeeta Misra 				ret = ilbd_scf_pg_walk_props(newpg,
1432dbed73cbSSangeeta Misra 				    ilbd_scf_load_prop, &data);
1433dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK) {
1434dbed73cbSSangeeta Misra 					free(data.sg_data);
1435dbed73cbSSangeeta Misra 					goto out;
1436dbed73cbSSangeeta Misra 				}
1437dbed73cbSSangeeta Misra 				assert(data.sg_data != NULL);
1438dbed73cbSSangeeta Misra 				/* set sg name */
1439dbed73cbSSangeeta Misra 				(void) strlcpy(data.sg_data->sg_name,
1440dbed73cbSSangeeta Misra 				    &pg_name[strlen(ILBD_PG_NAME_SG)],
1441dbed73cbSSangeeta Misra 				    sizeof (data.sg_data->sg_name));
1442dbed73cbSSangeeta Misra 				ret = cb(data.sg_data, port, arg2, NULL);
1443dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK) {
1444dbed73cbSSangeeta Misra 					free(data.sg_data);
1445dbed73cbSSangeeta Misra 					goto out;
1446dbed73cbSSangeeta Misra 				}
1447dbed73cbSSangeeta Misra 				/*
1448dbed73cbSSangeeta Misra 				 * create a servergroup is two-step operation.
1449dbed73cbSSangeeta Misra 				 * 1. create an empty servergroup.
1450dbed73cbSSangeeta Misra 				 * 2. add server(s) to the group.
1451dbed73cbSSangeeta Misra 				 *
1452dbed73cbSSangeeta Misra 				 * since we are here from:
1453dbed73cbSSangeeta Misra 				 * main_loop()->ilbd_read_config()->
1454dbed73cbSSangeeta Misra 				 * ilbd_walk_sg_pgs()
1455dbed73cbSSangeeta Misra 				 * there is no cli to send. So in this
1456dbed73cbSSangeeta Misra 				 * path auditing will skip the
1457dbed73cbSSangeeta Misra 				 * adt_set_from_ucred() check
1458dbed73cbSSangeeta Misra 				 */
1459dbed73cbSSangeeta Misra 				if (data.sg_data->sg_srvcount > 0) {
1460dbed73cbSSangeeta Misra 					ret = ilbd_add_server_to_group(
1461dbed73cbSSangeeta Misra 					    data.sg_data, port, NULL, NULL);
1462dbed73cbSSangeeta Misra 					if (ret != ILB_STATUS_OK) {
1463dbed73cbSSangeeta Misra 						free(data.sg_data);
1464dbed73cbSSangeeta Misra 						goto out;
1465dbed73cbSSangeeta Misra 					}
1466dbed73cbSSangeeta Misra 					free(data.sg_data);
1467dbed73cbSSangeeta Misra 				}
1468dbed73cbSSangeeta Misra 			}
1469dbed73cbSSangeeta Misra 			break;
1470dbed73cbSSangeeta Misra 		case ILBD_SCF_HC:
1471dbed73cbSSangeeta Misra 			if (strncmp(ILBD_PG_NAME_HC, pg_name,
1472dbed73cbSSangeeta Misra 			    strlen(ILBD_PG_NAME_HC)) == 0) {
1473dbed73cbSSangeeta Misra 				data.hc_data = calloc(1,
1474dbed73cbSSangeeta Misra 				    sizeof (ilb_hc_info_t));
1475*3ae6a67dSSangeeta Misra 				if (data.hc_data == NULL) {
1476*3ae6a67dSSangeeta Misra 					ret = ILB_STATUS_ENOMEM;
1477*3ae6a67dSSangeeta Misra 					goto out;
1478*3ae6a67dSSangeeta Misra 				}
1479dbed73cbSSangeeta Misra 				ret = ilbd_scf_pg_walk_props(newpg,
1480dbed73cbSSangeeta Misra 				    ilbd_scf_load_prop, &data);
1481dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK)
1482dbed73cbSSangeeta Misra 					goto out;
1483dbed73cbSSangeeta Misra 				assert(data.hc_data != NULL);
1484dbed73cbSSangeeta Misra 				/* set hc name */
1485dbed73cbSSangeeta Misra 				(void) strlcpy(data.hc_data->hci_name,
1486dbed73cbSSangeeta Misra 				    &pg_name[strlen(ILBD_PG_NAME_HC)],
1487dbed73cbSSangeeta Misra 				    sizeof (data.hc_data->hci_name));
1488dbed73cbSSangeeta Misra 				ret = cb(data.hc_data, port, arg2, NULL);
1489dbed73cbSSangeeta Misra 				free(data.hc_data);
1490dbed73cbSSangeeta Misra 				if (ret != ILB_STATUS_OK)
1491dbed73cbSSangeeta Misra 					goto out;
1492dbed73cbSSangeeta Misra 			}
1493dbed73cbSSangeeta Misra 			break;
1494dbed73cbSSangeeta Misra 		}
1495dbed73cbSSangeeta Misra 	}
1496dbed73cbSSangeeta Misra 
1497dbed73cbSSangeeta Misra out:
1498*3ae6a67dSSangeeta Misra 	if (pg_name != NULL)
1499*3ae6a67dSSangeeta Misra 		free(pg_name);
1500dbed73cbSSangeeta Misra 	if (scf_ret < 0)
1501dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1502dbed73cbSSangeeta Misra 	scf_pg_destroy(newpg);
1503dbed73cbSSangeeta Misra 	scf_iter_destroy(pgiter);
1504dbed73cbSSangeeta Misra 	return (ret);
1505dbed73cbSSangeeta Misra }
1506dbed73cbSSangeeta Misra 
1507dbed73cbSSangeeta Misra typedef ilb_status_t (*ilbd_scf_walker_fn)(void *, int, struct passwd *,
1508dbed73cbSSangeeta Misra     ucred_t *);
1509dbed73cbSSangeeta Misra 
1510dbed73cbSSangeeta Misra ilb_status_t
1511dbed73cbSSangeeta Misra ilbd_walk_rule_pgs(ilb_status_t (*func)(ilb_rule_info_t *, int,
1512dbed73cbSSangeeta Misra     const struct passwd *, ucred_t *), void *arg1, void *arg2)
1513dbed73cbSSangeeta Misra {
1514dbed73cbSSangeeta Misra 	scf_instance_t *inst;
1515dbed73cbSSangeeta Misra 	scf_handle_t *h;
1516dbed73cbSSangeeta Misra 	scf_service_t *svc;
1517dbed73cbSSangeeta Misra 	ilb_status_t ret;
1518dbed73cbSSangeeta Misra 
1519dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
1520dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_OK)
1521dbed73cbSSangeeta Misra 		return (ret);
1522dbed73cbSSangeeta Misra 
1523dbed73cbSSangeeta Misra 	/* get rule prop group, transfer it to ilb_lrule_info_t */
1524dbed73cbSSangeeta Misra 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_RULE,
1525dbed73cbSSangeeta Misra 	    (ilbd_scf_walker_fn)func, arg1, arg2);
1526dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, svc, inst, NULL);
1527dbed73cbSSangeeta Misra 	return (ret);
1528dbed73cbSSangeeta Misra }
1529dbed73cbSSangeeta Misra 
1530dbed73cbSSangeeta Misra ilb_status_t
1531dbed73cbSSangeeta Misra ilbd_walk_sg_pgs(ilb_status_t (*func)(ilb_sg_info_t *, int,
1532dbed73cbSSangeeta Misra     const struct passwd *, ucred_t *), void *arg1, void *arg2)
1533dbed73cbSSangeeta Misra {
1534dbed73cbSSangeeta Misra 	scf_instance_t *inst;
1535dbed73cbSSangeeta Misra 	scf_handle_t *h;
1536dbed73cbSSangeeta Misra 	scf_service_t *svc;
1537dbed73cbSSangeeta Misra 	ilb_status_t ret;
1538dbed73cbSSangeeta Misra 
1539dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
1540dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_OK)
1541dbed73cbSSangeeta Misra 		return (ret);
1542dbed73cbSSangeeta Misra 
1543dbed73cbSSangeeta Misra 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_SG,
1544dbed73cbSSangeeta Misra 	    (ilbd_scf_walker_fn)func, arg1, arg2);
1545dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, svc, inst, NULL);
1546dbed73cbSSangeeta Misra 	return (ret);
1547dbed73cbSSangeeta Misra }
1548dbed73cbSSangeeta Misra 
1549dbed73cbSSangeeta Misra ilb_status_t
1550dbed73cbSSangeeta Misra ilbd_walk_hc_pgs(ilb_status_t (*func)(const ilb_hc_info_t *, int,
1551dbed73cbSSangeeta Misra     const struct passwd *, ucred_t *), void *arg1, void *arg2)
1552dbed73cbSSangeeta Misra {
1553dbed73cbSSangeeta Misra 	scf_instance_t *inst;
1554dbed73cbSSangeeta Misra 	scf_handle_t *h;
1555dbed73cbSSangeeta Misra 	scf_service_t *svc;
1556dbed73cbSSangeeta Misra 	ilb_status_t ret;
1557dbed73cbSSangeeta Misra 
1558dbed73cbSSangeeta Misra 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
1559dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_OK)
1560dbed73cbSSangeeta Misra 		return (ret);
1561dbed73cbSSangeeta Misra 
1562dbed73cbSSangeeta Misra 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_HC,
1563dbed73cbSSangeeta Misra 	    (ilbd_scf_walker_fn)func, arg1, arg2);
1564dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, svc, inst, NULL);
1565dbed73cbSSangeeta Misra 	return (ret);
1566dbed73cbSSangeeta Misra }
1567dbed73cbSSangeeta Misra 
1568dbed73cbSSangeeta Misra ilb_status_t
1569dbed73cbSSangeeta Misra ilbd_change_prop(ilbd_scf_pg_type_t pg_type, const char *pg_name,
1570dbed73cbSSangeeta Misra     const char *prop_name, void *new_val)
1571dbed73cbSSangeeta Misra {
1572dbed73cbSSangeeta Misra 	int ret;
1573dbed73cbSSangeeta Misra 	scf_propertygroup_t *scfpg = NULL;
1574*3ae6a67dSSangeeta Misra 	char *scf_pgname = NULL;
1575dbed73cbSSangeeta Misra 	scf_type_t scftype;
1576dbed73cbSSangeeta Misra 	scf_value_t *scfval;
1577dbed73cbSSangeeta Misra 	scf_handle_t *h;
1578dbed73cbSSangeeta Misra 
1579*3ae6a67dSSangeeta Misra 	if ((scf_pgname = malloc(ILBD_MAX_NAME_LEN)) == NULL)
1580*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
1581dbed73cbSSangeeta Misra 	ilbd_name_to_scfpgname(pg_type, pg_name, scf_pgname);
1582dbed73cbSSangeeta Misra 	ret = ilbd_scf_retrieve_pg(scf_pgname, &scfpg, B_FALSE);
1583*3ae6a67dSSangeeta Misra 	free(scf_pgname);
1584*3ae6a67dSSangeeta Misra 
1585dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_EEXIST)
1586dbed73cbSSangeeta Misra 		return (ret);
1587dbed73cbSSangeeta Misra 
1588dbed73cbSSangeeta Misra 	assert(scfpg != NULL);
1589dbed73cbSSangeeta Misra 
1590dbed73cbSSangeeta Misra 	h = scf_pg_handle(scfpg);
1591dbed73cbSSangeeta Misra 	if (h == NULL) {
1592dbed73cbSSangeeta Misra 		ret = ILB_STATUS_EINVAL;
1593dbed73cbSSangeeta Misra 		goto done;
1594dbed73cbSSangeeta Misra 	}
1595dbed73cbSSangeeta Misra 
1596dbed73cbSSangeeta Misra 	if ((scfval = scf_value_create(h)) == NULL) {
1597dbed73cbSSangeeta Misra 		ret = ILB_STATUS_ENOMEM;
1598dbed73cbSSangeeta Misra 		goto done;
1599dbed73cbSSangeeta Misra 	}
1600dbed73cbSSangeeta Misra 
1601dbed73cbSSangeeta Misra 	if (pg_type == ILBD_SCF_RULE) {
1602dbed73cbSSangeeta Misra 		scftype = SCF_TYPE_BOOLEAN;
1603dbed73cbSSangeeta Misra 		scf_value_set_boolean(scfval, *(boolean_t *)new_val);
1604dbed73cbSSangeeta Misra 	} else if (pg_type == ILBD_SCF_SG) {
1605dbed73cbSSangeeta Misra 		scftype = SCF_TYPE_ASTRING;
1606dbed73cbSSangeeta Misra 		(void) scf_value_set_astring(scfval, (char *)new_val);
1607dbed73cbSSangeeta Misra 	}
1608dbed73cbSSangeeta Misra 	ret = ilbd_scf_set_prop(scfpg, prop_name, scftype, scfval);
1609dbed73cbSSangeeta Misra 
1610dbed73cbSSangeeta Misra done:
1611dbed73cbSSangeeta Misra 	if (scf_pg_handle(scfpg) != NULL)
1612dbed73cbSSangeeta Misra 		scf_handle_destroy(scf_pg_handle(scfpg));
1613dbed73cbSSangeeta Misra 	if (scfpg != NULL)
1614dbed73cbSSangeeta Misra 		scf_pg_destroy(scfpg);
1615dbed73cbSSangeeta Misra 	if (scfval != NULL)
1616dbed73cbSSangeeta Misra 		scf_value_destroy(scfval);
1617dbed73cbSSangeeta Misra 	return (ret);
1618dbed73cbSSangeeta Misra }
1619dbed73cbSSangeeta Misra 
1620dbed73cbSSangeeta Misra /*
1621dbed73cbSSangeeta Misra  * Update the persistent configuration with a new server, srv, added to a
1622dbed73cbSSangeeta Misra  * server group, sg.
1623dbed73cbSSangeeta Misra  */
1624dbed73cbSSangeeta Misra ilb_status_t
1625dbed73cbSSangeeta Misra ilbd_scf_add_srv(ilbd_sg_t *sg, ilbd_srv_t *srv)
1626dbed73cbSSangeeta Misra {
1627dbed73cbSSangeeta Misra 	scf_propertygroup_t *pg;
1628dbed73cbSSangeeta Misra 	scf_handle_t *h;
1629dbed73cbSSangeeta Misra 	scf_value_t *val;
1630dbed73cbSSangeeta Misra 	ilb_status_t ret;
1631dbed73cbSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
1632*3ae6a67dSSangeeta Misra 	char *buf = NULL;
1633*3ae6a67dSSangeeta Misra 
1634*3ae6a67dSSangeeta Misra 	if ((buf = malloc(scf_name_len)) == NULL)
1635*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
1636dbed73cbSSangeeta Misra 
1637dbed73cbSSangeeta Misra 	ilbd_name_to_scfpgname(ILBD_SCF_SG, sg->isg_name, buf);
1638dbed73cbSSangeeta Misra 	ret = ilbd_scf_retrieve_pg(buf, &pg, B_FALSE);
1639dbed73cbSSangeeta Misra 	/*
1640dbed73cbSSangeeta Misra 	 * The server group does not exist in persistent storage.  This
1641dbed73cbSSangeeta Misra 	 * cannot happen.  Should probably transition the service to
1642dbed73cbSSangeeta Misra 	 * maintenance since it should be there.
1643dbed73cbSSangeeta Misra 	 */
1644dbed73cbSSangeeta Misra 	if (ret != ILB_STATUS_EEXIST) {
1645dbed73cbSSangeeta Misra 		logerr("ilbd_scf_add_srv: SCF update failed - entering"
1646dbed73cbSSangeeta Misra 		    " maintenance mode");
1647dbed73cbSSangeeta Misra 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
1648*3ae6a67dSSangeeta Misra 		free(buf);
1649dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
1650dbed73cbSSangeeta Misra 	}
1651dbed73cbSSangeeta Misra 
1652dbed73cbSSangeeta Misra 	if ((h = scf_pg_handle(pg)) == NULL) {
1653dbed73cbSSangeeta Misra 		ilbd_scf_destroy(NULL, NULL, NULL, pg);
1654*3ae6a67dSSangeeta Misra 		free(buf);
1655dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
1656dbed73cbSSangeeta Misra 	}
1657dbed73cbSSangeeta Misra 
1658dbed73cbSSangeeta Misra 	if ((val = scf_value_create(h)) == NULL) {
1659dbed73cbSSangeeta Misra 		ilbd_scf_destroy(h, NULL, NULL, pg);
1660*3ae6a67dSSangeeta Misra 		free(buf);
1661dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
1662dbed73cbSSangeeta Misra 	}
1663dbed73cbSSangeeta Misra 	ilbd_srv_scf_val(srv, buf);
1664dbed73cbSSangeeta Misra 	(void) scf_value_set_astring(val, buf);
1665dbed73cbSSangeeta Misra 
1666*3ae6a67dSSangeeta Misra 	(void) snprintf(buf, scf_name_len, "server%d", srv->isv_id);
1667*3ae6a67dSSangeeta Misra 	ret = ilbd_scf_set_prop(pg, buf, SCF_TYPE_ASTRING, val);
1668*3ae6a67dSSangeeta Misra 	free(buf);
1669dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, NULL, NULL, pg);
1670dbed73cbSSangeeta Misra 	scf_value_destroy(val);
1671dbed73cbSSangeeta Misra 
1672dbed73cbSSangeeta Misra 	return (ret);
1673dbed73cbSSangeeta Misra }
1674dbed73cbSSangeeta Misra 
1675dbed73cbSSangeeta Misra /*
1676dbed73cbSSangeeta Misra  * Delete a server, srv, of a server group, sg, from the persistent
1677dbed73cbSSangeeta Misra  * configuration.
1678dbed73cbSSangeeta Misra  */
1679dbed73cbSSangeeta Misra ilb_status_t
1680dbed73cbSSangeeta Misra ilbd_scf_del_srv(ilbd_sg_t *sg, ilbd_srv_t *srv)
1681dbed73cbSSangeeta Misra {
1682dbed73cbSSangeeta Misra 	ilb_status_t ret;
1683dbed73cbSSangeeta Misra 	scf_propertygroup_t *pg;
1684dbed73cbSSangeeta Misra 	scf_handle_t *h;
1685dbed73cbSSangeeta Misra 	int scf_name_len = ILBD_MAX_NAME_LEN;
1686*3ae6a67dSSangeeta Misra 	char *buf;
1687dbed73cbSSangeeta Misra 	scf_transaction_t *tx = NULL;
1688dbed73cbSSangeeta Misra 	scf_transaction_entry_t *entry = NULL;
1689dbed73cbSSangeeta Misra 
1690*3ae6a67dSSangeeta Misra 	if ((buf = malloc(scf_name_len)) == NULL)
1691*3ae6a67dSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
1692dbed73cbSSangeeta Misra 	ilbd_name_to_scfpgname(ILBD_SCF_SG, sg->isg_name, buf);
1693dbed73cbSSangeeta Misra 	ret = ilbd_scf_retrieve_pg(buf, &pg, B_FALSE);
1694dbed73cbSSangeeta Misra 	/*
1695dbed73cbSSangeeta Misra 	 * The server group does not exist in persistent storage.  This
1696dbed73cbSSangeeta Misra 	 * cannot happen. THe caller of this function puts service in
1697dbed73cbSSangeeta Misra 	 * maintenance mode.
1698dbed73cbSSangeeta Misra 	 */
1699*3ae6a67dSSangeeta Misra 	if (ret != ILB_STATUS_EEXIST) {
1700*3ae6a67dSSangeeta Misra 		free(buf);
1701dbed73cbSSangeeta Misra 		return (ILB_STATUS_INTERNAL);
1702*3ae6a67dSSangeeta Misra 	}
1703dbed73cbSSangeeta Misra 	ret = ILB_STATUS_OK;
1704dbed73cbSSangeeta Misra 
1705dbed73cbSSangeeta Misra 	if ((h = scf_pg_handle(pg)) == NULL) {
1706dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_del_srv: scf_pg_handle: %s\n",
1707dbed73cbSSangeeta Misra 		    scf_strerror(scf_error()));
1708dbed73cbSSangeeta Misra 		ilbd_scf_destroy(NULL, NULL, NULL, pg);
1709*3ae6a67dSSangeeta Misra 		free(buf);
1710dbed73cbSSangeeta Misra 		return (ilbd_scf_err_to_ilb_err());
1711dbed73cbSSangeeta Misra 	}
1712dbed73cbSSangeeta Misra 
1713dbed73cbSSangeeta Misra 	if ((tx = scf_transaction_create(h)) == NULL ||
1714dbed73cbSSangeeta Misra 	    (entry = scf_entry_create(h)) == NULL) {
1715dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_del_srv: create scf transaction failed: "
1716dbed73cbSSangeeta Misra 		    "%s\n", scf_strerror(scf_error()));
1717dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1718dbed73cbSSangeeta Misra 		goto out;
1719dbed73cbSSangeeta Misra 	}
1720dbed73cbSSangeeta Misra 
1721*3ae6a67dSSangeeta Misra 	(void) snprintf(buf, scf_name_len, "server%d", srv->isv_id);
1722dbed73cbSSangeeta Misra 
1723dbed73cbSSangeeta Misra 	if (scf_transaction_start(tx, pg) == -1) {
1724dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: start scf transaction failed: "
1725dbed73cbSSangeeta Misra 		    "%s\n", scf_strerror(scf_error()));
1726dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1727dbed73cbSSangeeta Misra 		goto out;
1728dbed73cbSSangeeta Misra 	}
1729dbed73cbSSangeeta Misra 	if (scf_transaction_property_delete(tx, entry, buf) == -1) {
1730dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: delete property failed: %s\n",
1731dbed73cbSSangeeta Misra 		    scf_strerror(scf_error()));
1732dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1733dbed73cbSSangeeta Misra 		goto out;
1734dbed73cbSSangeeta Misra 	}
1735dbed73cbSSangeeta Misra 	if (scf_transaction_commit(tx) != 1) {
1736dbed73cbSSangeeta Misra 		logdebug("ilbd_scf_set_prop: commit transaction failed: %s\n",
1737dbed73cbSSangeeta Misra 		    scf_strerror(scf_error()));
1738dbed73cbSSangeeta Misra 		ret = ilbd_scf_err_to_ilb_err();
1739dbed73cbSSangeeta Misra 	}
1740dbed73cbSSangeeta Misra 
1741dbed73cbSSangeeta Misra out:
1742*3ae6a67dSSangeeta Misra 	free(buf);
1743dbed73cbSSangeeta Misra 	if (entry != NULL)
1744dbed73cbSSangeeta Misra 		scf_entry_destroy(entry);
1745dbed73cbSSangeeta Misra 	if (tx != NULL)
1746dbed73cbSSangeeta Misra 		scf_transaction_destroy(tx);
1747dbed73cbSSangeeta Misra 	ilbd_scf_destroy(h, NULL, NULL, pg);
1748dbed73cbSSangeeta Misra 
1749dbed73cbSSangeeta Misra 	return (ret);
1750dbed73cbSSangeeta Misra }
1751