xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.lib/ilbd/ilbd_scf.c (revision 12857:fe654b6a1645)
110946SSangeeta.Misra@Sun.COM /*
210946SSangeeta.Misra@Sun.COM  * CDDL HEADER START
310946SSangeeta.Misra@Sun.COM  *
410946SSangeeta.Misra@Sun.COM  * The contents of this file are subject to the terms of the
510946SSangeeta.Misra@Sun.COM  * Common Development and Distribution License (the "License").
610946SSangeeta.Misra@Sun.COM  * You may not use this file except in compliance with the License.
710946SSangeeta.Misra@Sun.COM  *
810946SSangeeta.Misra@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910946SSangeeta.Misra@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010946SSangeeta.Misra@Sun.COM  * See the License for the specific language governing permissions
1110946SSangeeta.Misra@Sun.COM  * and limitations under the License.
1210946SSangeeta.Misra@Sun.COM  *
1310946SSangeeta.Misra@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410946SSangeeta.Misra@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510946SSangeeta.Misra@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610946SSangeeta.Misra@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710946SSangeeta.Misra@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810946SSangeeta.Misra@Sun.COM  *
1910946SSangeeta.Misra@Sun.COM  * CDDL HEADER END
2010946SSangeeta.Misra@Sun.COM  */
2110946SSangeeta.Misra@Sun.COM 
2210946SSangeeta.Misra@Sun.COM /*
23*12857SSangeeta.Misra@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410946SSangeeta.Misra@Sun.COM  */
2510946SSangeeta.Misra@Sun.COM 
2610946SSangeeta.Misra@Sun.COM #include <stdlib.h>
2710946SSangeeta.Misra@Sun.COM #include <stdio.h>
2810946SSangeeta.Misra@Sun.COM #include <strings.h>
2910946SSangeeta.Misra@Sun.COM #include <sys/types.h>
3010946SSangeeta.Misra@Sun.COM #include <sys/socket.h>
3110946SSangeeta.Misra@Sun.COM #include <netinet/in.h>
3210946SSangeeta.Misra@Sun.COM #include <arpa/inet.h>
3310946SSangeeta.Misra@Sun.COM #include <sys/list.h>
3410946SSangeeta.Misra@Sun.COM #include <libilb.h>
3510946SSangeeta.Misra@Sun.COM #include <assert.h>
3610946SSangeeta.Misra@Sun.COM #include <libscf.h>
3710946SSangeeta.Misra@Sun.COM #include "libilb_impl.h"
3810946SSangeeta.Misra@Sun.COM #include "ilbd.h"
3910946SSangeeta.Misra@Sun.COM 
4010946SSangeeta.Misra@Sun.COM #define	ILBD_PG_NAME_RULE "rule_"
4110946SSangeeta.Misra@Sun.COM #define	ILBD_PG_NAME_SG "sg_"
4210946SSangeeta.Misra@Sun.COM #define	ILBD_PG_NAME_HC "hc_"
4310946SSangeeta.Misra@Sun.COM #define	ILBD_SVC_FMRI "svc:/network/loadbalancer/ilb"
4410946SSangeeta.Misra@Sun.COM #define	ILBD_INST_NAME "default"
4510946SSangeeta.Misra@Sun.COM 
4610946SSangeeta.Misra@Sun.COM typedef enum {
4710946SSangeeta.Misra@Sun.COM 	ILBD_RULE_STATUS,
4810946SSangeeta.Misra@Sun.COM 	ILBD_RULE_VIP,
4910946SSangeeta.Misra@Sun.COM 	ILBD_RULE_PROTO,
5010946SSangeeta.Misra@Sun.COM 	ILBD_RULE_PORT,
5110946SSangeeta.Misra@Sun.COM 	ILBD_RULE_ALGO,
5210946SSangeeta.Misra@Sun.COM 	ILBD_RULE_TOPO,
5310946SSangeeta.Misra@Sun.COM 	ILBD_RULE_NAT_STR,
5410946SSangeeta.Misra@Sun.COM 	ILBD_RULE_NAT_END,
5510946SSangeeta.Misra@Sun.COM 	ILBD_RULE_STI_MASK,
5610946SSangeeta.Misra@Sun.COM 	ILBD_RULE_SGNAME,
5710946SSangeeta.Misra@Sun.COM 	ILBD_RULE_HCNAME,
5810946SSangeeta.Misra@Sun.COM 	ILBD_RULE_HCPORT,
5910946SSangeeta.Misra@Sun.COM 	ILBD_RULE_HCPFLAG,
6010946SSangeeta.Misra@Sun.COM 	ILBD_RULE_DRAINTIME,
6110946SSangeeta.Misra@Sun.COM 	ILBD_RULE_NAT_TO,
6210946SSangeeta.Misra@Sun.COM 	ILBD_RULE_PERS_TO,
6310946SSangeeta.Misra@Sun.COM 
6410946SSangeeta.Misra@Sun.COM 	ILBD_SG_SERVER,
6510946SSangeeta.Misra@Sun.COM 
6610946SSangeeta.Misra@Sun.COM 	ILBD_HC_TEST,
6710946SSangeeta.Misra@Sun.COM 	ILBD_HC_TIMEOUT,
6810946SSangeeta.Misra@Sun.COM 	ILBD_HC_INTERVAL,
6910946SSangeeta.Misra@Sun.COM 	ILBD_HC_DEF_PING,
7010946SSangeeta.Misra@Sun.COM 	ILBD_HC_COUNT,
7110946SSangeeta.Misra@Sun.COM 
7210946SSangeeta.Misra@Sun.COM 	ILBD_VAR_INVALID
7310946SSangeeta.Misra@Sun.COM } ilbd_var_type_t;
7410946SSangeeta.Misra@Sun.COM 
7510946SSangeeta.Misra@Sun.COM typedef struct prop_tbl_entry {
7610946SSangeeta.Misra@Sun.COM 	ilbd_var_type_t val_type;
7710946SSangeeta.Misra@Sun.COM 	const char *scf_propname;
7810946SSangeeta.Misra@Sun.COM 	scf_type_t scf_proptype;
7910946SSangeeta.Misra@Sun.COM } prop_tbl_entry_t;
8010946SSangeeta.Misra@Sun.COM 
8110946SSangeeta.Misra@Sun.COM /*
8210946SSangeeta.Misra@Sun.COM  * this table contains a map of all SCF properties, including rules,
8310946SSangeeta.Misra@Sun.COM  * servergroups and health checks. The place to add new property needs to be
8410946SSangeeta.Misra@Sun.COM  * watched carefully. When new properties are added, corresponding *VAR_NUM
8510946SSangeeta.Misra@Sun.COM  * needs to be adjusted to reflect the correct index of the table
8610946SSangeeta.Misra@Sun.COM  */
8710946SSangeeta.Misra@Sun.COM prop_tbl_entry_t prop_tbl[] = {
8810946SSangeeta.Misra@Sun.COM 	/* entried for rule */
8910946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_STATUS, "status", SCF_TYPE_BOOLEAN},
9010946SSangeeta.Misra@Sun.COM 	/* SCF_TYPE_NET_ADDR_V4 or SCF_TYPE_NET_ADDR_V6 */
9110946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_VIP, "vip", SCF_TYPE_INVALID},
9210946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_PROTO, "protocol", SCF_TYPE_ASTRING},
9310946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_PORT, "port", SCF_TYPE_ASTRING},
9410946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_ALGO, "ilb-algo", SCF_TYPE_ASTRING},
9510946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_TOPO, "ilb-type", SCF_TYPE_ASTRING},
9610946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_NAT_STR, "ilb-nat-start", SCF_TYPE_INVALID},
9710946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_NAT_END, "ilb-nat-end", SCF_TYPE_INVALID},
9810946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_STI_MASK, "ilb-sti-mask", SCF_TYPE_INVALID},
9910946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_SGNAME, "servergroup", SCF_TYPE_ASTRING},
10010946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_HCNAME, "healthcheck", SCF_TYPE_ASTRING},
10110946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_HCPORT, "hc-port", SCF_TYPE_INTEGER},
10210946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_HCPFLAG, "hcp-flag", SCF_TYPE_INTEGER},
10310946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_DRAINTIME, "drain-time", SCF_TYPE_INTEGER},
10410946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_NAT_TO, "nat-timeout", SCF_TYPE_INTEGER},
10510946SSangeeta.Misra@Sun.COM 	{ILBD_RULE_PERS_TO, "pers-timeout", SCF_TYPE_INTEGER},
10610946SSangeeta.Misra@Sun.COM 	/* add new rule related prop here */
10710946SSangeeta.Misra@Sun.COM 	/* entries for sg */
10810946SSangeeta.Misra@Sun.COM 	{ILBD_SG_SERVER, "server", SCF_TYPE_ASTRING},
10910946SSangeeta.Misra@Sun.COM 	/* add new sg related prop here */
11010946SSangeeta.Misra@Sun.COM 	/* entries for hc */
11110946SSangeeta.Misra@Sun.COM 	{ILBD_HC_TEST, "test", SCF_TYPE_ASTRING},
11210946SSangeeta.Misra@Sun.COM 	{ILBD_HC_TIMEOUT, "timeout", SCF_TYPE_INTEGER},
11310946SSangeeta.Misra@Sun.COM 	{ILBD_HC_INTERVAL, "interval", SCF_TYPE_INTEGER},
11410946SSangeeta.Misra@Sun.COM 	{ILBD_HC_DEF_PING, "ping", SCF_TYPE_BOOLEAN},
11510946SSangeeta.Misra@Sun.COM 	/* add new hc related prop here */
11610946SSangeeta.Misra@Sun.COM 	{ILBD_HC_COUNT, "count", SCF_TYPE_INTEGER}
11710946SSangeeta.Misra@Sun.COM };
11810946SSangeeta.Misra@Sun.COM 
11910946SSangeeta.Misra@Sun.COM #define	ILBD_PROP_VAR_NUM (ILBD_HC_COUNT + 1)
12010946SSangeeta.Misra@Sun.COM #define	ILBD_RULE_VAR_NUM (ILBD_SG_SERVER)
12110946SSangeeta.Misra@Sun.COM #define	ILBD_SG_VAR_NUM (ILBD_HC_TEST - ILBD_SG_SERVER)
12210946SSangeeta.Misra@Sun.COM #define	ILBD_HC_VAR_NUM (ILBD_PROP_VAR_NUM - ILBD_HC_TEST)
12310946SSangeeta.Misra@Sun.COM 
12410946SSangeeta.Misra@Sun.COM static ilb_status_t ilbd_scf_set_prop(scf_propertygroup_t *, const char *,
12510946SSangeeta.Misra@Sun.COM     scf_type_t, scf_value_t *);
12610946SSangeeta.Misra@Sun.COM static ilb_status_t ilbd_scf_retrieve_pg(const char *, scf_propertygroup_t **,
12710946SSangeeta.Misra@Sun.COM     boolean_t);
12810946SSangeeta.Misra@Sun.COM static ilb_status_t ilbd_scf_delete_pg(scf_propertygroup_t *);
12910946SSangeeta.Misra@Sun.COM static ilb_status_t ilbd_scf_get_prop_val(scf_propertygroup_t *, const char *,
13010946SSangeeta.Misra@Sun.COM     scf_value_t **);
13110946SSangeeta.Misra@Sun.COM 
13210946SSangeeta.Misra@Sun.COM #define	MIN(a, b)	((a) < (b) ? (a) : (b))
13310946SSangeeta.Misra@Sun.COM 
13410946SSangeeta.Misra@Sun.COM int
ilbd_scf_limit(int type)13510946SSangeeta.Misra@Sun.COM ilbd_scf_limit(int type)
13610946SSangeeta.Misra@Sun.COM {
13710946SSangeeta.Misra@Sun.COM 	return (MIN(scf_limit(type), 120));
13810946SSangeeta.Misra@Sun.COM }
13910946SSangeeta.Misra@Sun.COM 
14010946SSangeeta.Misra@Sun.COM /*
14110946SSangeeta.Misra@Sun.COM  * Translate libscf error to libilb status
14210946SSangeeta.Misra@Sun.COM  */
14310946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_scf_err_to_ilb_err()14410946SSangeeta.Misra@Sun.COM ilbd_scf_err_to_ilb_err()
14510946SSangeeta.Misra@Sun.COM {
14610946SSangeeta.Misra@Sun.COM 	switch (scf_error()) {
14710946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NONE:
14810946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_OK);
14910946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_HANDLE_MISMATCH:
15010946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_HANDLE_DESTROYED:
15110946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_VERSION_MISMATCH:
15210946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NOT_BOUND:
15310946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_CONSTRAINT_VIOLATED:
15410946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NOT_SET:
15510946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_TYPE_MISMATCH:
15610946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_INVALID_ARGUMENT:
15710946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
15810946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NO_MEMORY:
15910946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NO_RESOURCES:
16010946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
16110946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_NOT_FOUND:
16210946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_DELETED:
16310946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOENT);
16410946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_EXISTS:
16510946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EEXIST);
16610946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_PERMISSION_DENIED:
16710946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_PERMIT);
16810946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_CALLBACK_FAILED:
16910946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_CALLBACK);
17010946SSangeeta.Misra@Sun.COM 	case SCF_ERROR_IN_USE:
17110946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INUSE);
17210946SSangeeta.Misra@Sun.COM 	default:
17310946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
17410946SSangeeta.Misra@Sun.COM 	}
17510946SSangeeta.Misra@Sun.COM }
17610946SSangeeta.Misra@Sun.COM 
17710946SSangeeta.Misra@Sun.COM static void
ilbd_name_to_scfpgname(ilbd_scf_pg_type_t pg_type,const char * pgname,char * scf_pgname)17810946SSangeeta.Misra@Sun.COM ilbd_name_to_scfpgname(ilbd_scf_pg_type_t pg_type, const char *pgname,
17910946SSangeeta.Misra@Sun.COM     char *scf_pgname)
18010946SSangeeta.Misra@Sun.COM {
18110946SSangeeta.Misra@Sun.COM 	switch (pg_type) {
18210946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_RULE:
18310946SSangeeta.Misra@Sun.COM 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
18410946SSangeeta.Misra@Sun.COM 		    ILBD_PG_NAME_RULE "%s", pgname);
18510946SSangeeta.Misra@Sun.COM 		return;
18610946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_SG:
18710946SSangeeta.Misra@Sun.COM 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
18810946SSangeeta.Misra@Sun.COM 		    ILBD_PG_NAME_SG "%s", pgname);
18910946SSangeeta.Misra@Sun.COM 		return;
19010946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_HC:
19110946SSangeeta.Misra@Sun.COM 		(void) snprintf(scf_pgname, ILBD_MAX_NAME_LEN,
19210946SSangeeta.Misra@Sun.COM 		    ILBD_PG_NAME_HC "%s", pgname);
19310946SSangeeta.Misra@Sun.COM 		return;
19410946SSangeeta.Misra@Sun.COM 	/* Should not happen.  Log it and put ILB service in maintenance. */
19510946SSangeeta.Misra@Sun.COM 	default:
19610946SSangeeta.Misra@Sun.COM 		logerr("ilbd_name_to_scfpgname: invalid pg type %d for pg %s",
19710946SSangeeta.Misra@Sun.COM 		    pg_type, pgname);
19810946SSangeeta.Misra@Sun.COM 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
19910946SSangeeta.Misra@Sun.COM 		exit(EXIT_FAILURE);
20010946SSangeeta.Misra@Sun.COM 		return;
20110946SSangeeta.Misra@Sun.COM 	}
20210946SSangeeta.Misra@Sun.COM }
20310946SSangeeta.Misra@Sun.COM 
20410946SSangeeta.Misra@Sun.COM static void
ilbd_scf_destroy(scf_handle_t * h,scf_service_t * s,scf_instance_t * inst,scf_propertygroup_t * pg)20510946SSangeeta.Misra@Sun.COM ilbd_scf_destroy(scf_handle_t *h, scf_service_t *s, scf_instance_t *inst,
20610946SSangeeta.Misra@Sun.COM     scf_propertygroup_t *pg)
20710946SSangeeta.Misra@Sun.COM {
20810946SSangeeta.Misra@Sun.COM 	if (pg != NULL)
20910946SSangeeta.Misra@Sun.COM 		scf_pg_destroy(pg);
21010946SSangeeta.Misra@Sun.COM 	if (inst != NULL)
21110946SSangeeta.Misra@Sun.COM 		scf_instance_destroy(inst);
21210946SSangeeta.Misra@Sun.COM 	if (s != NULL)
21310946SSangeeta.Misra@Sun.COM 		scf_service_destroy(s);
21410946SSangeeta.Misra@Sun.COM 	if (h != NULL)
21510946SSangeeta.Misra@Sun.COM 		scf_handle_destroy(h);
21610946SSangeeta.Misra@Sun.COM }
21710946SSangeeta.Misra@Sun.COM 
21810946SSangeeta.Misra@Sun.COM 
21910946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_get_inst(scf_handle_t ** h,scf_service_t ** svc,scf_instance_t ** inst)22010946SSangeeta.Misra@Sun.COM ilbd_scf_get_inst(scf_handle_t **h, scf_service_t **svc, scf_instance_t **inst)
22110946SSangeeta.Misra@Sun.COM {
22210946SSangeeta.Misra@Sun.COM 	if ((*h = scf_handle_create(SCF_VERSION)) == NULL)
22310946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
22410946SSangeeta.Misra@Sun.COM 
22510946SSangeeta.Misra@Sun.COM 	if (scf_handle_bind(*h) != 0) {
22610946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(*h, NULL, NULL, NULL);
22710946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
22810946SSangeeta.Misra@Sun.COM 	}
22910946SSangeeta.Misra@Sun.COM 
23010946SSangeeta.Misra@Sun.COM 	if ((*svc = scf_service_create(*h)) == NULL) {
23110946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(*h, NULL, NULL, NULL);
23210946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
23310946SSangeeta.Misra@Sun.COM 	}
23410946SSangeeta.Misra@Sun.COM 
23510946SSangeeta.Misra@Sun.COM 	if (scf_handle_decode_fmri(*h, ILBD_SVC_FMRI, NULL, *svc, NULL, NULL,
23610946SSangeeta.Misra@Sun.COM 	    NULL, SCF_DECODE_FMRI_EXACT) != 0) {
23710946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(*h, *svc, NULL, NULL);
23810946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
23910946SSangeeta.Misra@Sun.COM 	}
24010946SSangeeta.Misra@Sun.COM 
24110946SSangeeta.Misra@Sun.COM 	if ((*inst = scf_instance_create(*h)) == NULL) {
24210946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(*h, *svc, NULL, NULL);
24310946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
24410946SSangeeta.Misra@Sun.COM 	}
24510946SSangeeta.Misra@Sun.COM 
24610946SSangeeta.Misra@Sun.COM 	if (scf_service_get_instance(*svc, ILBD_INST_NAME, *inst) != 0) {
24710946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(*h, *svc, *inst, NULL);
24810946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
24910946SSangeeta.Misra@Sun.COM 	}
25010946SSangeeta.Misra@Sun.COM 	return (ILB_STATUS_OK);
25110946SSangeeta.Misra@Sun.COM }
25210946SSangeeta.Misra@Sun.COM 
25310946SSangeeta.Misra@Sun.COM /*
25410946SSangeeta.Misra@Sun.COM  * If create is set, create a new prop group, destroy the old one if exists.
25510946SSangeeta.Misra@Sun.COM  * If create not set, try to find the prop group with given name.
25610946SSangeeta.Misra@Sun.COM  * The created or found entry is returned as *pg.
25710946SSangeeta.Misra@Sun.COM  * Caller frees *pg and its handle scf_pg_handle(pg)
25810946SSangeeta.Misra@Sun.COM  */
25910946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_retrieve_pg(const char * pgname,scf_propertygroup_t ** pg,boolean_t create)26010946SSangeeta.Misra@Sun.COM ilbd_scf_retrieve_pg(const char *pgname, scf_propertygroup_t **pg,
26110946SSangeeta.Misra@Sun.COM     boolean_t create)
26210946SSangeeta.Misra@Sun.COM {
26310946SSangeeta.Misra@Sun.COM 	scf_instance_t *inst;
26410946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
26510946SSangeeta.Misra@Sun.COM 	scf_service_t *svc;
26610946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
26710946SSangeeta.Misra@Sun.COM 
26810946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
26910946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_OK)
27010946SSangeeta.Misra@Sun.COM 		return (ret);
27110946SSangeeta.Misra@Sun.COM 
27210946SSangeeta.Misra@Sun.COM 	*pg = scf_pg_create(h);
27310946SSangeeta.Misra@Sun.COM 	if (*pg == NULL)
27410946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
27510946SSangeeta.Misra@Sun.COM 
27610946SSangeeta.Misra@Sun.COM 	if (scf_instance_get_pg(inst, pgname, *pg) != 0) {
27710946SSangeeta.Misra@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND ||
27810946SSangeeta.Misra@Sun.COM 		    (scf_error() == SCF_ERROR_NOT_FOUND && (!create))) {
27910946SSangeeta.Misra@Sun.COM 			ilbd_scf_destroy(h, svc, inst, *pg);
28010946SSangeeta.Misra@Sun.COM 			*pg = NULL;
28110946SSangeeta.Misra@Sun.COM 			return (ilbd_scf_err_to_ilb_err());
28210946SSangeeta.Misra@Sun.COM 		}
28310946SSangeeta.Misra@Sun.COM 	} else {
28410946SSangeeta.Misra@Sun.COM 		/*
28510946SSangeeta.Misra@Sun.COM 		 * Found pg, don't want to create, return EEXIST.  Note that
28610946SSangeeta.Misra@Sun.COM 		 * h cannot be destroyed here since the caller needs to use it.
28710946SSangeeta.Misra@Sun.COM 		 * The caller gets it by calling scf_pg_handle().
28810946SSangeeta.Misra@Sun.COM 		 */
28910946SSangeeta.Misra@Sun.COM 		if (!create) {
29010946SSangeeta.Misra@Sun.COM 			ilbd_scf_destroy(NULL, svc, inst, NULL);
29110946SSangeeta.Misra@Sun.COM 			return (ILB_STATUS_EEXIST);
29210946SSangeeta.Misra@Sun.COM 		}
29310946SSangeeta.Misra@Sun.COM 		/* found pg, need to create, destroy the existing one */
29410946SSangeeta.Misra@Sun.COM 		else
29510946SSangeeta.Misra@Sun.COM 			(void) ilbd_scf_delete_pg(*pg);
29610946SSangeeta.Misra@Sun.COM 	}
29710946SSangeeta.Misra@Sun.COM 
29810946SSangeeta.Misra@Sun.COM 	if (create) {
29910946SSangeeta.Misra@Sun.COM 		if (scf_instance_add_pg(inst, pgname,
30010946SSangeeta.Misra@Sun.COM 		    SCF_GROUP_APPLICATION, 0, *pg) != 0) {
30110946SSangeeta.Misra@Sun.COM 			ilbd_scf_destroy(h, svc, inst, *pg);
30210946SSangeeta.Misra@Sun.COM 			*pg = NULL;
30310946SSangeeta.Misra@Sun.COM 			return (ilbd_scf_err_to_ilb_err());
30410946SSangeeta.Misra@Sun.COM 		}
30510946SSangeeta.Misra@Sun.COM 	}
30610946SSangeeta.Misra@Sun.COM 
30710946SSangeeta.Misra@Sun.COM 	/*
30810946SSangeeta.Misra@Sun.COM 	 * Note that handle cannot be destroyed here, caller sometimes needs
30910946SSangeeta.Misra@Sun.COM 	 * to use it.  It gets the handle by calling scf_pg_handle().
31010946SSangeeta.Misra@Sun.COM 	 */
31110946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(NULL, svc, inst, NULL);
31210946SSangeeta.Misra@Sun.COM 	return (ILB_STATUS_OK);
31310946SSangeeta.Misra@Sun.COM }
31410946SSangeeta.Misra@Sun.COM 
31510946SSangeeta.Misra@Sun.COM struct algo_tbl_entry {
31610946SSangeeta.Misra@Sun.COM 	ilb_algo_t algo_type;
31710946SSangeeta.Misra@Sun.COM 	const char *algo_str;
31810946SSangeeta.Misra@Sun.COM } algo_tbl[] = {
31910946SSangeeta.Misra@Sun.COM 	{ILB_ALG_ROUNDROBIN, "ROUNDROBIN"},
32010946SSangeeta.Misra@Sun.COM 	{ILB_ALG_HASH_IP, "HASH-IP"},
32110946SSangeeta.Misra@Sun.COM 	{ILB_ALG_HASH_IP_SPORT, "HASH-IP-PORT"},
32210946SSangeeta.Misra@Sun.COM 	{ILB_ALG_HASH_IP_VIP, "HASH-IP-VIP"}
32310946SSangeeta.Misra@Sun.COM };
32410946SSangeeta.Misra@Sun.COM 
32510946SSangeeta.Misra@Sun.COM #define	ILBD_ALGO_TBL_SIZE (sizeof (algo_tbl) / \
32610946SSangeeta.Misra@Sun.COM 	sizeof (*algo_tbl))
32710946SSangeeta.Misra@Sun.COM 
32810946SSangeeta.Misra@Sun.COM void
ilbd_algo_to_str(ilb_algo_t algo_type,char * valstr)32910946SSangeeta.Misra@Sun.COM ilbd_algo_to_str(ilb_algo_t algo_type, char *valstr)
33010946SSangeeta.Misra@Sun.COM {
33110946SSangeeta.Misra@Sun.COM 	int i;
33210946SSangeeta.Misra@Sun.COM 
33310946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ILBD_ALGO_TBL_SIZE; i++) {
33410946SSangeeta.Misra@Sun.COM 		if (algo_type == algo_tbl[i].algo_type) {
33510946SSangeeta.Misra@Sun.COM 			(void) strlcpy(valstr, algo_tbl[i].algo_str,
33610946SSangeeta.Misra@Sun.COM 			    ILBD_MAX_VALUE_LEN);
33710946SSangeeta.Misra@Sun.COM 			return;
33810946SSangeeta.Misra@Sun.COM 		}
33910946SSangeeta.Misra@Sun.COM 	}
34010946SSangeeta.Misra@Sun.COM 	logerr("ilbd_algo_to_str: algo not found");
34110946SSangeeta.Misra@Sun.COM }
34210946SSangeeta.Misra@Sun.COM 
34310946SSangeeta.Misra@Sun.COM static void
ilbd_scf_str_to_algo(ilb_algo_t * algo_type,char * valstr)34410946SSangeeta.Misra@Sun.COM ilbd_scf_str_to_algo(ilb_algo_t *algo_type, char *valstr)
34510946SSangeeta.Misra@Sun.COM {
34610946SSangeeta.Misra@Sun.COM 	int i;
34710946SSangeeta.Misra@Sun.COM 
34810946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ILBD_ALGO_TBL_SIZE; i++) {
34910946SSangeeta.Misra@Sun.COM 		if (strcmp(valstr, algo_tbl[i].algo_str) == 0) {
35010946SSangeeta.Misra@Sun.COM 			*algo_type = algo_tbl[i].algo_type;
35110946SSangeeta.Misra@Sun.COM 			return;
35210946SSangeeta.Misra@Sun.COM 		}
35310946SSangeeta.Misra@Sun.COM 	}
35410946SSangeeta.Misra@Sun.COM 	logerr("ilbd_scf_str_to_algo: algo not found");
35510946SSangeeta.Misra@Sun.COM }
35610946SSangeeta.Misra@Sun.COM 
35710946SSangeeta.Misra@Sun.COM struct topo_tbl_entry {
35810946SSangeeta.Misra@Sun.COM 	ilb_topo_t topo_type;
35910946SSangeeta.Misra@Sun.COM 	const char *topo_str;
36010946SSangeeta.Misra@Sun.COM } topo_tbl[] = {
36110946SSangeeta.Misra@Sun.COM 	{ILB_TOPO_DSR, "DSR"},
36210946SSangeeta.Misra@Sun.COM 	{ILB_TOPO_NAT, "NAT"},
36310946SSangeeta.Misra@Sun.COM 	{ILB_TOPO_HALF_NAT, "HALF-NAT"}
36410946SSangeeta.Misra@Sun.COM };
36510946SSangeeta.Misra@Sun.COM 
36610946SSangeeta.Misra@Sun.COM #define	ILBD_TOPO_TBL_SIZE (sizeof (topo_tbl) / \
36710946SSangeeta.Misra@Sun.COM 	sizeof (*topo_tbl))
36810946SSangeeta.Misra@Sun.COM 
36910946SSangeeta.Misra@Sun.COM void
ilbd_topo_to_str(ilb_topo_t topo_type,char * valstr)37010946SSangeeta.Misra@Sun.COM ilbd_topo_to_str(ilb_topo_t topo_type, char *valstr)
37110946SSangeeta.Misra@Sun.COM {
37210946SSangeeta.Misra@Sun.COM 	int i;
37310946SSangeeta.Misra@Sun.COM 
37410946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ILBD_TOPO_TBL_SIZE; i++) {
37510946SSangeeta.Misra@Sun.COM 		if (topo_type == topo_tbl[i].topo_type) {
37610946SSangeeta.Misra@Sun.COM 			(void) strlcpy(valstr, topo_tbl[i].topo_str,
37710946SSangeeta.Misra@Sun.COM 			    ILBD_MAX_VALUE_LEN);
37810946SSangeeta.Misra@Sun.COM 			return;
37910946SSangeeta.Misra@Sun.COM 		}
38010946SSangeeta.Misra@Sun.COM 	}
38110946SSangeeta.Misra@Sun.COM 	logerr("ilbd_scf_topo_to_str: topo not found");
38210946SSangeeta.Misra@Sun.COM }
38310946SSangeeta.Misra@Sun.COM 
38410946SSangeeta.Misra@Sun.COM static void
ilbd_scf_str_to_topo(ilb_topo_t * topo_type,char * valstr)38510946SSangeeta.Misra@Sun.COM ilbd_scf_str_to_topo(ilb_topo_t *topo_type, char *valstr)
38610946SSangeeta.Misra@Sun.COM {
38710946SSangeeta.Misra@Sun.COM 	int i;
38810946SSangeeta.Misra@Sun.COM 
38910946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ILBD_TOPO_TBL_SIZE; i++) {
39010946SSangeeta.Misra@Sun.COM 		if (strcmp(valstr, topo_tbl[i].topo_str) == 0) {
39110946SSangeeta.Misra@Sun.COM 			*topo_type = topo_tbl[i].topo_type;
39210946SSangeeta.Misra@Sun.COM 			return;
39310946SSangeeta.Misra@Sun.COM 		}
39410946SSangeeta.Misra@Sun.COM 	}
39510946SSangeeta.Misra@Sun.COM 	logerr("ilbd_scf_str_to_topo: topo not found");
39610946SSangeeta.Misra@Sun.COM }
39710946SSangeeta.Misra@Sun.COM 
39810946SSangeeta.Misra@Sun.COM static void
ilbd_get_svr_field(char * valstr,struct in6_addr * sgs_addr,int32_t * min_port,int32_t * max_port,int32_t * sgs_flags)39910946SSangeeta.Misra@Sun.COM ilbd_get_svr_field(char *valstr, struct in6_addr *sgs_addr,
40010946SSangeeta.Misra@Sun.COM     int32_t *min_port, int32_t *max_port, int32_t *sgs_flags)
40110946SSangeeta.Misra@Sun.COM {
40210946SSangeeta.Misra@Sun.COM 	char *ipaddr, *ipverstr, *portstr, *flagstr;
40310946SSangeeta.Misra@Sun.COM 	int ip_ver;
40410946SSangeeta.Misra@Sun.COM 	ilb_ip_addr_t temp_ip;
40510946SSangeeta.Misra@Sun.COM 	void *addrptr;
40610946SSangeeta.Misra@Sun.COM 	char *max_portstr;
40710946SSangeeta.Misra@Sun.COM 
40810946SSangeeta.Misra@Sun.COM 	ipaddr = strtok(valstr, ";");
40910946SSangeeta.Misra@Sun.COM 	ipverstr = strtok(NULL, ";");
41010946SSangeeta.Misra@Sun.COM 	portstr = strtok(NULL, ";");
41110946SSangeeta.Misra@Sun.COM 	flagstr = strtok(NULL, ";");
41210946SSangeeta.Misra@Sun.COM 
41310946SSangeeta.Misra@Sun.COM 	if (ipaddr == NULL || ipverstr == NULL || portstr == NULL ||
41410946SSangeeta.Misra@Sun.COM 	    flagstr == NULL) {
41510946SSangeeta.Misra@Sun.COM 		logerr("%s: invalid server fields", __func__);
41610946SSangeeta.Misra@Sun.COM 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
41710946SSangeeta.Misra@Sun.COM 		exit(EXIT_FAILURE);
41810946SSangeeta.Misra@Sun.COM 	}
41910946SSangeeta.Misra@Sun.COM 	ip_ver = atoi(ipverstr);
42010946SSangeeta.Misra@Sun.COM 	addrptr = (ip_ver == AF_INET) ? (void *)&temp_ip.ia_v4 :
42110946SSangeeta.Misra@Sun.COM 	    (void *)&temp_ip.ia_v6;
42210946SSangeeta.Misra@Sun.COM 	if (inet_pton(ip_ver, ipaddr, addrptr) == NULL) {
42310946SSangeeta.Misra@Sun.COM 		logerr("ilbd_get_svr_field: inet_pton failed");
42410946SSangeeta.Misra@Sun.COM 		return;
42510946SSangeeta.Misra@Sun.COM 	}
42610946SSangeeta.Misra@Sun.COM 
42710946SSangeeta.Misra@Sun.COM 	if (ip_ver == AF_INET) {
42810946SSangeeta.Misra@Sun.COM 		IN6_INADDR_TO_V4MAPPED(&(temp_ip.ia_v4), sgs_addr);
42910946SSangeeta.Misra@Sun.COM 	} else {
43010946SSangeeta.Misra@Sun.COM 		(void) memcpy(sgs_addr, &(temp_ip.ia_v6),
43110946SSangeeta.Misra@Sun.COM 		    sizeof (struct in6_addr));
43210946SSangeeta.Misra@Sun.COM 	}
43310946SSangeeta.Misra@Sun.COM 
43410946SSangeeta.Misra@Sun.COM 	*sgs_flags = atoi(flagstr);
43510946SSangeeta.Misra@Sun.COM 	*min_port = atoi(strtok(portstr, "-"));
43610946SSangeeta.Misra@Sun.COM 	*min_port = ntohs(*min_port);
43710946SSangeeta.Misra@Sun.COM 	max_portstr = strtok(NULL, "-");
43810946SSangeeta.Misra@Sun.COM 	if (max_portstr != NULL) {
43910946SSangeeta.Misra@Sun.COM 		*max_port = atoi(max_portstr);
44010946SSangeeta.Misra@Sun.COM 		*max_port = ntohs(*max_port);
44110946SSangeeta.Misra@Sun.COM 	}
44210946SSangeeta.Misra@Sun.COM }
44310946SSangeeta.Misra@Sun.COM 
44410946SSangeeta.Misra@Sun.COM /*
44510946SSangeeta.Misra@Sun.COM  * Convert the info of a server to its SCF string value representation.
44610946SSangeeta.Misra@Sun.COM  * Argument value is assumed to be of size ILBD_MAX_VALUE_LEN.
44710946SSangeeta.Misra@Sun.COM  */
44810946SSangeeta.Misra@Sun.COM static void
ilbd_srv_scf_val(ilbd_srv_t * srv,char * value)44910946SSangeeta.Misra@Sun.COM ilbd_srv_scf_val(ilbd_srv_t *srv, char *value)
45010946SSangeeta.Misra@Sun.COM {
45110946SSangeeta.Misra@Sun.COM 	char ipstr[INET6_ADDRSTRLEN];
45210946SSangeeta.Misra@Sun.COM 	int ipver;
45310946SSangeeta.Misra@Sun.COM 
45410946SSangeeta.Misra@Sun.COM 	if (GET_AF(&srv->isv_addr) == AF_INET) {
45510946SSangeeta.Misra@Sun.COM 		struct in_addr v4_addr;
45610946SSangeeta.Misra@Sun.COM 
45710946SSangeeta.Misra@Sun.COM 		IN6_V4MAPPED_TO_INADDR(&srv->isv_addr, &v4_addr);
45810946SSangeeta.Misra@Sun.COM 		(void) inet_ntop(AF_INET, &v4_addr, ipstr, sizeof (ipstr));
45910946SSangeeta.Misra@Sun.COM 		ipver = AF_INET;
46010946SSangeeta.Misra@Sun.COM 	} else {
46110946SSangeeta.Misra@Sun.COM 		(void) inet_ntop(AF_INET6, &srv->isv_addr, ipstr,
46210946SSangeeta.Misra@Sun.COM 		    sizeof (ipstr));
46310946SSangeeta.Misra@Sun.COM 		ipver = AF_INET6;
46410946SSangeeta.Misra@Sun.COM 	}
46510946SSangeeta.Misra@Sun.COM 	(void) snprintf(value, ILBD_MAX_VALUE_LEN, "%s;%d;%d-%d;%d",
46610946SSangeeta.Misra@Sun.COM 	    ipstr, ipver, ntohs(srv->isv_minport), ntohs(srv->isv_maxport),
46710946SSangeeta.Misra@Sun.COM 	    srv->isv_flags);
46810946SSangeeta.Misra@Sun.COM }
46910946SSangeeta.Misra@Sun.COM 
47010946SSangeeta.Misra@Sun.COM /* get the "ip:port:status" str of the #num server in the servergroup */
47110946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_get_svr_info(ilbd_sg_t * sg,int num,char * valstr,char * svrname)47210946SSangeeta.Misra@Sun.COM ilbd_get_svr_info(ilbd_sg_t *sg, int num, char *valstr, char *svrname)
47310946SSangeeta.Misra@Sun.COM {
47410946SSangeeta.Misra@Sun.COM 	int i;
47510946SSangeeta.Misra@Sun.COM 	ilbd_srv_t *tmp_srv = NULL;
47610946SSangeeta.Misra@Sun.COM 
47710946SSangeeta.Misra@Sun.COM 	tmp_srv = list_head(&sg->isg_srvlist);
47810946SSangeeta.Misra@Sun.COM 	if (tmp_srv == NULL)
47910946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOENT);
48010946SSangeeta.Misra@Sun.COM 
48110946SSangeeta.Misra@Sun.COM 	for (i = 0; i < num; i++)
48210946SSangeeta.Misra@Sun.COM 		tmp_srv = list_next(&sg->isg_srvlist, tmp_srv);
48310946SSangeeta.Misra@Sun.COM 
48410946SSangeeta.Misra@Sun.COM 	assert(tmp_srv != NULL);
48510946SSangeeta.Misra@Sun.COM 	if (valstr != NULL)
48610946SSangeeta.Misra@Sun.COM 		ilbd_srv_scf_val(tmp_srv, valstr);
48710946SSangeeta.Misra@Sun.COM 
48810946SSangeeta.Misra@Sun.COM 	if (svrname != NULL) {
48910946SSangeeta.Misra@Sun.COM 		(void) snprintf(svrname, ILBD_MAX_NAME_LEN, "server%d",
49010946SSangeeta.Misra@Sun.COM 		    tmp_srv->isv_id);
49110946SSangeeta.Misra@Sun.COM 	}
49210946SSangeeta.Misra@Sun.COM 
49310946SSangeeta.Misra@Sun.COM 	return (ILB_STATUS_OK);
49410946SSangeeta.Misra@Sun.COM }
49510946SSangeeta.Misra@Sun.COM 
49610946SSangeeta.Misra@Sun.COM /* convert a struct in6_addr to valstr */
49710946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_scf_ip_to_str(uint16_t ipversion,struct in6_addr * addr,scf_type_t * scftype,char * valstr)49810946SSangeeta.Misra@Sun.COM ilbd_scf_ip_to_str(uint16_t ipversion, struct in6_addr *addr,
49910946SSangeeta.Misra@Sun.COM     scf_type_t *scftype, char *valstr)
50010946SSangeeta.Misra@Sun.COM {
50110946SSangeeta.Misra@Sun.COM 	size_t vallen;
50210946SSangeeta.Misra@Sun.COM 	ilb_ip_addr_t ipaddr;
50310946SSangeeta.Misra@Sun.COM 	void *addrptr;
50410946SSangeeta.Misra@Sun.COM 
50510946SSangeeta.Misra@Sun.COM 	vallen = (ipversion == AF_INET) ? INET_ADDRSTRLEN :
50610946SSangeeta.Misra@Sun.COM 	    INET6_ADDRSTRLEN;
50710946SSangeeta.Misra@Sun.COM 	if (scftype != NULL)
50810946SSangeeta.Misra@Sun.COM 		*scftype = (ipversion == AF_INET) ? SCF_TYPE_NET_ADDR_V4 :
50910946SSangeeta.Misra@Sun.COM 		    SCF_TYPE_NET_ADDR_V6;
51010946SSangeeta.Misra@Sun.COM 
51110946SSangeeta.Misra@Sun.COM 	IP_COPY_IMPL_2_CLI(addr, &ipaddr);
51210946SSangeeta.Misra@Sun.COM 	addrptr = (ipversion == AF_INET) ?
51310946SSangeeta.Misra@Sun.COM 	    (void *)&ipaddr.ia_v4 : (void *)&ipaddr.ia_v6;
51410946SSangeeta.Misra@Sun.COM 	(void) inet_ntop(ipversion, (void *)addrptr, valstr, vallen);
51510946SSangeeta.Misra@Sun.COM 	return (ILB_STATUS_OK);
51610946SSangeeta.Misra@Sun.COM }
51710946SSangeeta.Misra@Sun.COM 
51810946SSangeeta.Misra@Sun.COM /*
51910946SSangeeta.Misra@Sun.COM  * This function takes a ilbd internal data struct and translate its value to
52010946SSangeeta.Misra@Sun.COM  * scf value. The data struct is passed in within "data".
52110946SSangeeta.Misra@Sun.COM  * Upon successful return, the scf val will be stored in "val" and the scf type
52210946SSangeeta.Misra@Sun.COM  * will be returned in "scftype" if scftype != NULL, the number of values
52310946SSangeeta.Misra@Sun.COM  * translated will be in "numval"
52410946SSangeeta.Misra@Sun.COM  * If it failed, no data will be written to SCF
52510946SSangeeta.Misra@Sun.COM  */
52610946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_data_to_scfval(ilbd_scf_pg_type_t pg_type,ilbd_var_type_t type,scf_handle_t * h,void * data,scf_value_t *** val,scf_type_t * scftype,int * numval)52710946SSangeeta.Misra@Sun.COM ilbd_data_to_scfval(ilbd_scf_pg_type_t pg_type, ilbd_var_type_t type,
52810946SSangeeta.Misra@Sun.COM     scf_handle_t *h, void *data, scf_value_t ***val, scf_type_t *scftype,
52910946SSangeeta.Misra@Sun.COM     int *numval)
53010946SSangeeta.Misra@Sun.COM {
53110946SSangeeta.Misra@Sun.COM 	scf_value_t *v, **varray = NULL;
53210946SSangeeta.Misra@Sun.COM 	int ret = ILB_STATUS_OK;
53310946SSangeeta.Misra@Sun.COM 	int i;
53410946SSangeeta.Misra@Sun.COM 	int scf_val_len = ILBD_MAX_VALUE_LEN;
535*12857SSangeeta.Misra@Sun.COM 	char *valstr = NULL;
53610946SSangeeta.Misra@Sun.COM 	int valint;
53710946SSangeeta.Misra@Sun.COM 	uint8_t valbool = 0;
53810946SSangeeta.Misra@Sun.COM 	ilbd_rule_t *r_ent = NULL;
53910946SSangeeta.Misra@Sun.COM 	ilbd_sg_t *s_ent = NULL;
54010946SSangeeta.Misra@Sun.COM 	ilbd_hc_t *h_ent = NULL;
54110946SSangeeta.Misra@Sun.COM 
54210946SSangeeta.Misra@Sun.COM 	switch (pg_type) {
54310946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_RULE:
54410946SSangeeta.Misra@Sun.COM 		r_ent = (ilbd_rule_t *)data;
54510946SSangeeta.Misra@Sun.COM 		break;
54610946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_SG:
54710946SSangeeta.Misra@Sun.COM 		s_ent = (ilbd_sg_t *)data;
54810946SSangeeta.Misra@Sun.COM 		break;
54910946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_HC:
55010946SSangeeta.Misra@Sun.COM 		h_ent = (ilbd_hc_t *)data;
55110946SSangeeta.Misra@Sun.COM 		break;
55210946SSangeeta.Misra@Sun.COM 	}
55310946SSangeeta.Misra@Sun.COM 
55410946SSangeeta.Misra@Sun.COM 	v = scf_value_create(h);
55510946SSangeeta.Misra@Sun.COM 	if (v == NULL)
55610946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
55710946SSangeeta.Misra@Sun.COM 
558*12857SSangeeta.Misra@Sun.COM 	if ((valstr = malloc(scf_val_len)) == NULL)
559*12857SSangeeta.Misra@Sun.COM 			return (ILB_STATUS_ENOMEM);
56010946SSangeeta.Misra@Sun.COM 	switch (type) {
56110946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_STATUS:
56210946SSangeeta.Misra@Sun.COM 		valbool = r_ent->irl_flags & ILB_FLAGS_RULE_ENABLED;
56310946SSangeeta.Misra@Sun.COM 		break;
56410946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_VIP:
56510946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion, &r_ent->irl_vip,
56610946SSangeeta.Misra@Sun.COM 		    scftype, valstr);
56710946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK) {
568*12857SSangeeta.Misra@Sun.COM 			free(valstr);
56910946SSangeeta.Misra@Sun.COM 			scf_value_destroy(v);
57010946SSangeeta.Misra@Sun.COM 			return (ret);
57110946SSangeeta.Misra@Sun.COM 		}
57210946SSangeeta.Misra@Sun.COM 		break;
57310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PROTO: {
57410946SSangeeta.Misra@Sun.COM 		struct protoent *protoent;
57510946SSangeeta.Misra@Sun.COM 
57610946SSangeeta.Misra@Sun.COM 		protoent = getprotobynumber(r_ent->irl_proto);
577*12857SSangeeta.Misra@Sun.COM 		(void) strlcpy(valstr, protoent->p_name, scf_val_len);
57810946SSangeeta.Misra@Sun.COM 		break;
57910946SSangeeta.Misra@Sun.COM 	}
58010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PORT:
581*12857SSangeeta.Misra@Sun.COM 		(void) snprintf(valstr, scf_val_len, "%d-%d",
58210946SSangeeta.Misra@Sun.COM 		    r_ent->irl_minport, r_ent->irl_maxport);
58310946SSangeeta.Misra@Sun.COM 		break;
58410946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_ALGO:
58510946SSangeeta.Misra@Sun.COM 		ilbd_algo_to_str(r_ent->irl_algo, valstr);
58610946SSangeeta.Misra@Sun.COM 		break;
58710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_TOPO:
58810946SSangeeta.Misra@Sun.COM 		ilbd_topo_to_str(r_ent->irl_topo, valstr);
58910946SSangeeta.Misra@Sun.COM 		break;
59010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_STR:
59110946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
59210946SSangeeta.Misra@Sun.COM 		    &r_ent->irl_nat_src_start, scftype, valstr);
59310946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK) {
594*12857SSangeeta.Misra@Sun.COM 			free(valstr);
59510946SSangeeta.Misra@Sun.COM 			scf_value_destroy(v);
59610946SSangeeta.Misra@Sun.COM 			return (ret);
59710946SSangeeta.Misra@Sun.COM 		}
59810946SSangeeta.Misra@Sun.COM 		break;
59910946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_END:
60010946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
60110946SSangeeta.Misra@Sun.COM 		    &r_ent->irl_nat_src_end, scftype, valstr);
60210946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK) {
603*12857SSangeeta.Misra@Sun.COM 			free(valstr);
60410946SSangeeta.Misra@Sun.COM 			scf_value_destroy(v);
60510946SSangeeta.Misra@Sun.COM 			return (ret);
60610946SSangeeta.Misra@Sun.COM 		}
60710946SSangeeta.Misra@Sun.COM 		break;
60810946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_STI_MASK:
60910946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_ip_to_str(r_ent->irl_ipversion,
61010946SSangeeta.Misra@Sun.COM 		    &r_ent->irl_stickymask, scftype, valstr);
61110946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK) {
612*12857SSangeeta.Misra@Sun.COM 			free(valstr);
61310946SSangeeta.Misra@Sun.COM 			scf_value_destroy(v);
61410946SSangeeta.Misra@Sun.COM 			return (ret);
61510946SSangeeta.Misra@Sun.COM 		}
61610946SSangeeta.Misra@Sun.COM 		break;
61710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_SGNAME:
618*12857SSangeeta.Misra@Sun.COM 		(void) strlcpy(valstr, r_ent->irl_sgname, scf_val_len);
61910946SSangeeta.Misra@Sun.COM 		break;
62010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCNAME:
62110946SSangeeta.Misra@Sun.COM 		if (r_ent->irl_hcname[0] != '\0')
62210946SSangeeta.Misra@Sun.COM 			(void) strlcpy(valstr, r_ent->irl_hcname,
623*12857SSangeeta.Misra@Sun.COM 			    scf_val_len);
62410946SSangeeta.Misra@Sun.COM 		else
62510946SSangeeta.Misra@Sun.COM 			bzero(valstr, ILBD_MAX_VALUE_LEN);
62610946SSangeeta.Misra@Sun.COM 		break;
62710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCPORT:
62810946SSangeeta.Misra@Sun.COM 		valint = r_ent->irl_hcport;
62910946SSangeeta.Misra@Sun.COM 		break;
63010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCPFLAG:
63110946SSangeeta.Misra@Sun.COM 		valint = r_ent->irl_hcpflag;
63210946SSangeeta.Misra@Sun.COM 		break;
63310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_DRAINTIME:
63410946SSangeeta.Misra@Sun.COM 		valint = r_ent->irl_conndrain;
63510946SSangeeta.Misra@Sun.COM 		break;
63610946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_TO:
63710946SSangeeta.Misra@Sun.COM 		valint = r_ent->irl_nat_timeout;
63810946SSangeeta.Misra@Sun.COM 		break;
63910946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PERS_TO:
64010946SSangeeta.Misra@Sun.COM 		valint = r_ent->irl_sticky_timeout;
64110946SSangeeta.Misra@Sun.COM 		break;
64210946SSangeeta.Misra@Sun.COM 
64310946SSangeeta.Misra@Sun.COM 	case ILBD_SG_SERVER:
64410946SSangeeta.Misra@Sun.COM 		if (s_ent->isg_srvcount == 0) {
64510946SSangeeta.Misra@Sun.COM 			(void) strlcpy(valstr, "EMPTY_SERVERGROUP",
646*12857SSangeeta.Misra@Sun.COM 			    scf_val_len);
64710946SSangeeta.Misra@Sun.COM 			break;
64810946SSangeeta.Misra@Sun.COM 		}
64910946SSangeeta.Misra@Sun.COM 
65010946SSangeeta.Misra@Sun.COM 		varray = calloc(sizeof (*varray), s_ent->isg_srvcount);
65110946SSangeeta.Misra@Sun.COM 		if (varray == NULL) {
65210946SSangeeta.Misra@Sun.COM 			scf_value_destroy(v);
653*12857SSangeeta.Misra@Sun.COM 			free(valstr);
65410946SSangeeta.Misra@Sun.COM 			return (ILB_STATUS_ENOMEM);
65510946SSangeeta.Misra@Sun.COM 		}
65610946SSangeeta.Misra@Sun.COM 
65710946SSangeeta.Misra@Sun.COM 		for (i = 0; i < s_ent->isg_srvcount; i++) {
65810946SSangeeta.Misra@Sun.COM 			if (v == NULL) {
65910946SSangeeta.Misra@Sun.COM 				for (i--; i >= 0; i--)
66010946SSangeeta.Misra@Sun.COM 					scf_value_destroy(varray[i]);
661*12857SSangeeta.Misra@Sun.COM 				free(valstr);
66210946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_ENOMEM);
66310946SSangeeta.Misra@Sun.COM 			}
66410946SSangeeta.Misra@Sun.COM 
66510946SSangeeta.Misra@Sun.COM 			ret = ilbd_get_svr_info(s_ent, i, valstr, NULL);
66610946SSangeeta.Misra@Sun.COM 			if (ret != ILB_STATUS_OK) {
66710946SSangeeta.Misra@Sun.COM 				scf_value_destroy(v);
66810946SSangeeta.Misra@Sun.COM 				for (i--; i >= 0; i--)
66910946SSangeeta.Misra@Sun.COM 					scf_value_destroy(varray[i]);
670*12857SSangeeta.Misra@Sun.COM 				free(valstr);
67110946SSangeeta.Misra@Sun.COM 				free(varray);
67210946SSangeeta.Misra@Sun.COM 				return (ret);
67310946SSangeeta.Misra@Sun.COM 			}
67410946SSangeeta.Misra@Sun.COM 			(void) scf_value_set_astring(v, valstr);
67510946SSangeeta.Misra@Sun.COM 			varray[i] = v;
67610946SSangeeta.Misra@Sun.COM 			v = scf_value_create(h);
67710946SSangeeta.Misra@Sun.COM 		}
67810946SSangeeta.Misra@Sun.COM 		/* the last 'v' we created will go unused, so drop it */
67910946SSangeeta.Misra@Sun.COM 		scf_value_destroy(v);
68010946SSangeeta.Misra@Sun.COM 		*numval = s_ent->isg_srvcount;
68110946SSangeeta.Misra@Sun.COM 		*val = varray;
682*12857SSangeeta.Misra@Sun.COM 		free(valstr);
68310946SSangeeta.Misra@Sun.COM 		return (ret);
68410946SSangeeta.Misra@Sun.COM 	case ILBD_HC_TEST:
685*12857SSangeeta.Misra@Sun.COM 		(void) strlcpy(valstr, h_ent->ihc_test, scf_val_len);
68610946SSangeeta.Misra@Sun.COM 		break;
68710946SSangeeta.Misra@Sun.COM 	case ILBD_HC_TIMEOUT:
68810946SSangeeta.Misra@Sun.COM 		valint = h_ent->ihc_timeout;
68910946SSangeeta.Misra@Sun.COM 		break;
69010946SSangeeta.Misra@Sun.COM 	case ILBD_HC_INTERVAL:
69110946SSangeeta.Misra@Sun.COM 		valint = h_ent->ihc_interval;
69210946SSangeeta.Misra@Sun.COM 		break;
69310946SSangeeta.Misra@Sun.COM 	case ILBD_HC_DEF_PING:
69410946SSangeeta.Misra@Sun.COM 		valbool = h_ent->ihc_def_ping;
69510946SSangeeta.Misra@Sun.COM 		break;
69610946SSangeeta.Misra@Sun.COM 	case ILBD_HC_COUNT:
69710946SSangeeta.Misra@Sun.COM 		valint = h_ent->ihc_count;
69810946SSangeeta.Misra@Sun.COM 		break;
69910946SSangeeta.Misra@Sun.COM 	}
70010946SSangeeta.Misra@Sun.COM 
70110946SSangeeta.Misra@Sun.COM 	switch (*scftype) {
70210946SSangeeta.Misra@Sun.COM 	case SCF_TYPE_BOOLEAN:
70310946SSangeeta.Misra@Sun.COM 		scf_value_set_boolean(v, valbool);
70410946SSangeeta.Misra@Sun.COM 		break;
70510946SSangeeta.Misra@Sun.COM 	case SCF_TYPE_ASTRING:
70610946SSangeeta.Misra@Sun.COM 		(void) scf_value_set_astring(v, valstr);
70710946SSangeeta.Misra@Sun.COM 		break;
70810946SSangeeta.Misra@Sun.COM 	case SCF_TYPE_INTEGER:
70910946SSangeeta.Misra@Sun.COM 		scf_value_set_integer(v, valint);
71010946SSangeeta.Misra@Sun.COM 		break;
71110946SSangeeta.Misra@Sun.COM 	case SCF_TYPE_NET_ADDR_V4:
71210946SSangeeta.Misra@Sun.COM 		(void) scf_value_set_from_string(v, SCF_TYPE_NET_ADDR_V4,
71310946SSangeeta.Misra@Sun.COM 		    valstr);
71410946SSangeeta.Misra@Sun.COM 		break;
71510946SSangeeta.Misra@Sun.COM 	case SCF_TYPE_NET_ADDR_V6:
71610946SSangeeta.Misra@Sun.COM 		(void) scf_value_set_from_string(v, SCF_TYPE_NET_ADDR_V6,
71710946SSangeeta.Misra@Sun.COM 		    valstr);
71810946SSangeeta.Misra@Sun.COM 		break;
71910946SSangeeta.Misra@Sun.COM 	}
720*12857SSangeeta.Misra@Sun.COM 	free(valstr);
72110946SSangeeta.Misra@Sun.COM 
72210946SSangeeta.Misra@Sun.COM 	varray = calloc(1, sizeof (*varray));
72310946SSangeeta.Misra@Sun.COM 	if (varray == NULL) {
72410946SSangeeta.Misra@Sun.COM 		scf_value_destroy(v);
72510946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
72610946SSangeeta.Misra@Sun.COM 	}
72710946SSangeeta.Misra@Sun.COM 	varray[0] = v;
72810946SSangeeta.Misra@Sun.COM 	*val = varray;
72910946SSangeeta.Misra@Sun.COM 	*numval = 1;
73010946SSangeeta.Misra@Sun.COM 	return (ret);
73110946SSangeeta.Misra@Sun.COM }
73210946SSangeeta.Misra@Sun.COM 
73310946SSangeeta.Misra@Sun.COM /*
73410946SSangeeta.Misra@Sun.COM  * create a scf property group
73510946SSangeeta.Misra@Sun.COM  */
73610946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_create_pg(ilbd_scf_pg_type_t pg_type,void * data)73710946SSangeeta.Misra@Sun.COM ilbd_create_pg(ilbd_scf_pg_type_t pg_type, void *data)
73810946SSangeeta.Misra@Sun.COM {
73910946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
74010946SSangeeta.Misra@Sun.COM 	char *pgname;
74110946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t *pg = NULL;
74210946SSangeeta.Misra@Sun.COM 	scf_value_t **val;
74310946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
74410946SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
745*12857SSangeeta.Misra@Sun.COM 	char  *scfpgbuf; /* property group name or group type */
74610946SSangeeta.Misra@Sun.COM 	int i, i_st, i_end;
74710946SSangeeta.Misra@Sun.COM 
74810946SSangeeta.Misra@Sun.COM 	switch (pg_type) {
74910946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_RULE: {
75010946SSangeeta.Misra@Sun.COM 		ilbd_rule_t *r_ent = (ilbd_rule_t *)data;
75110946SSangeeta.Misra@Sun.COM 
75210946SSangeeta.Misra@Sun.COM 		pgname = r_ent->irl_name;
75310946SSangeeta.Misra@Sun.COM 		i_st = 0;
75410946SSangeeta.Misra@Sun.COM 		i_end = ILBD_RULE_VAR_NUM;
75510946SSangeeta.Misra@Sun.COM 		break;
75610946SSangeeta.Misra@Sun.COM 	}
75710946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_SG: {
75810946SSangeeta.Misra@Sun.COM 		ilbd_sg_t *s_ent = (ilbd_sg_t *)data;
75910946SSangeeta.Misra@Sun.COM 
76010946SSangeeta.Misra@Sun.COM 		pgname = s_ent->isg_name;
76110946SSangeeta.Misra@Sun.COM 		i_st = ILBD_RULE_VAR_NUM;
76210946SSangeeta.Misra@Sun.COM 		i_end = ILBD_RULE_VAR_NUM + ILBD_SG_VAR_NUM;
76310946SSangeeta.Misra@Sun.COM 		break;
76410946SSangeeta.Misra@Sun.COM 	}
76510946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_HC: {
76610946SSangeeta.Misra@Sun.COM 		ilbd_hc_t *h_ent = (ilbd_hc_t *)data;
76710946SSangeeta.Misra@Sun.COM 
76810946SSangeeta.Misra@Sun.COM 		pgname = h_ent->ihc_name;
76910946SSangeeta.Misra@Sun.COM 		i_st = ILBD_RULE_VAR_NUM + ILBD_SG_VAR_NUM;
77010946SSangeeta.Misra@Sun.COM 		i_end = ILBD_PROP_VAR_NUM;
77110946SSangeeta.Misra@Sun.COM 		break;
77210946SSangeeta.Misra@Sun.COM 	}
77310946SSangeeta.Misra@Sun.COM 	default:
77410946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_create_pg: invalid pg type %d for pg %s",
77510946SSangeeta.Misra@Sun.COM 		    pg_type, pgname);
77610946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
77710946SSangeeta.Misra@Sun.COM 	}
778*12857SSangeeta.Misra@Sun.COM 	if ((scfpgbuf = malloc(scf_name_len)) == NULL)
779*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
78010946SSangeeta.Misra@Sun.COM 
781*12857SSangeeta.Misra@Sun.COM 	ilbd_name_to_scfpgname(pg_type, pgname, scfpgbuf);
78210946SSangeeta.Misra@Sun.COM 
783*12857SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_retrieve_pg(scfpgbuf, &pg, B_TRUE);
784*12857SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_OK) {
785*12857SSangeeta.Misra@Sun.COM 		free(scfpgbuf);
78610946SSangeeta.Misra@Sun.COM 		return (ret);
787*12857SSangeeta.Misra@Sun.COM 	}
78810946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(pg);
78910946SSangeeta.Misra@Sun.COM 
79010946SSangeeta.Misra@Sun.COM 	/* fill in props */
79110946SSangeeta.Misra@Sun.COM 	for (i = i_st; i < i_end; i++) {
79210946SSangeeta.Misra@Sun.COM 		int num, j;
79310946SSangeeta.Misra@Sun.COM 		scf_type_t scftype = prop_tbl[i].scf_proptype;
79410946SSangeeta.Misra@Sun.COM 
79510946SSangeeta.Misra@Sun.COM 		ret = ilbd_data_to_scfval(pg_type, prop_tbl[i].val_type, h,
79610946SSangeeta.Misra@Sun.COM 		    data, &val, &scftype, &num);
79710946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK)
79810946SSangeeta.Misra@Sun.COM 			goto done;
79910946SSangeeta.Misra@Sun.COM 
80010946SSangeeta.Misra@Sun.COM 		for (j = 0; j < num; j++) {
80110946SSangeeta.Misra@Sun.COM 			if (pg_type == ILBD_SCF_SG) {
80210946SSangeeta.Misra@Sun.COM 				ret = ilbd_get_svr_info(data, j, NULL,
803*12857SSangeeta.Misra@Sun.COM 				    scfpgbuf);
80410946SSangeeta.Misra@Sun.COM 				if (ret == ILB_STATUS_ENOENT) {
805*12857SSangeeta.Misra@Sun.COM 					(void) strlcpy(scfpgbuf,
806*12857SSangeeta.Misra@Sun.COM 					    "EMPTY_SERVER", scf_name_len);
80710946SSangeeta.Misra@Sun.COM 				}
808*12857SSangeeta.Misra@Sun.COM 				ret = ilbd_scf_set_prop(pg, scfpgbuf,
80910946SSangeeta.Misra@Sun.COM 				    scftype, val[j]);
81010946SSangeeta.Misra@Sun.COM 			} else {
81110946SSangeeta.Misra@Sun.COM 				ret = ilbd_scf_set_prop(pg,
81210946SSangeeta.Misra@Sun.COM 				    prop_tbl[i].scf_propname, scftype, val[j]);
81310946SSangeeta.Misra@Sun.COM 			}
81410946SSangeeta.Misra@Sun.COM 			scf_value_destroy(val[j]);
81510946SSangeeta.Misra@Sun.COM 		}
81610946SSangeeta.Misra@Sun.COM 		free(val);
81710946SSangeeta.Misra@Sun.COM 	}
81810946SSangeeta.Misra@Sun.COM 
81910946SSangeeta.Misra@Sun.COM done:
820*12857SSangeeta.Misra@Sun.COM 	free(scfpgbuf);
82110946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, NULL, NULL, pg);
82210946SSangeeta.Misra@Sun.COM 	return (ret);
82310946SSangeeta.Misra@Sun.COM }
82410946SSangeeta.Misra@Sun.COM 
82510946SSangeeta.Misra@Sun.COM /*
82610946SSangeeta.Misra@Sun.COM  * destroy a scf property group
82710946SSangeeta.Misra@Sun.COM  */
82810946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_delete_pg(scf_propertygroup_t * pg)82910946SSangeeta.Misra@Sun.COM ilbd_scf_delete_pg(scf_propertygroup_t *pg)
83010946SSangeeta.Misra@Sun.COM {
83110946SSangeeta.Misra@Sun.COM 	if (scf_pg_delete(pg) != 0)
83210946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
83310946SSangeeta.Misra@Sun.COM 	return (ILB_STATUS_OK);
83410946SSangeeta.Misra@Sun.COM }
83510946SSangeeta.Misra@Sun.COM 
83610946SSangeeta.Misra@Sun.COM /* sg can have same name as rule */
83710946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_destroy_pg(ilbd_scf_pg_type_t pg_t,const char * pgname)83810946SSangeeta.Misra@Sun.COM ilbd_destroy_pg(ilbd_scf_pg_type_t pg_t, const char *pgname)
83910946SSangeeta.Misra@Sun.COM {
84010946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
84110946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t *pg;
84210946SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
843*12857SSangeeta.Misra@Sun.COM 	char *scfname;
84410946SSangeeta.Misra@Sun.COM 
845*12857SSangeeta.Misra@Sun.COM 	if ((scfname = malloc(scf_name_len)) == NULL)
846*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
84710946SSangeeta.Misra@Sun.COM 	ilbd_name_to_scfpgname(pg_t, pgname, scfname);
84810946SSangeeta.Misra@Sun.COM 
84910946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_retrieve_pg(scfname, &pg, B_FALSE);
850*12857SSangeeta.Misra@Sun.COM 	free(scfname);
85110946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_EEXIST)
85210946SSangeeta.Misra@Sun.COM 		return (ret);
85310946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_delete_pg(pg);
85410946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(scf_pg_handle(pg), NULL, NULL, pg);
85510946SSangeeta.Misra@Sun.COM 	return (ret);
85610946SSangeeta.Misra@Sun.COM }
85710946SSangeeta.Misra@Sun.COM 
85810946SSangeeta.Misra@Sun.COM /*
85910946SSangeeta.Misra@Sun.COM  * Set named property to scf value specified.  If property is new,
86010946SSangeeta.Misra@Sun.COM  * create it.
86110946SSangeeta.Misra@Sun.COM  */
86210946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_set_prop(scf_propertygroup_t * pg,const char * propname,scf_type_t proptype,scf_value_t * val)86310946SSangeeta.Misra@Sun.COM ilbd_scf_set_prop(scf_propertygroup_t *pg, const char *propname,
86410946SSangeeta.Misra@Sun.COM     scf_type_t proptype, scf_value_t *val)
86510946SSangeeta.Misra@Sun.COM {
86610946SSangeeta.Misra@Sun.COM 	scf_handle_t *h = NULL;
86710946SSangeeta.Misra@Sun.COM 	scf_property_t *prop = NULL;
86810946SSangeeta.Misra@Sun.COM 	scf_value_t *oldval = NULL;
86910946SSangeeta.Misra@Sun.COM 	scf_transaction_t *tx = NULL;
87010946SSangeeta.Misra@Sun.COM 	scf_transaction_entry_t *ent = NULL;
87110946SSangeeta.Misra@Sun.COM 	boolean_t new = B_FALSE;
87210946SSangeeta.Misra@Sun.COM 	ilb_status_t ret = ILB_STATUS_OK;
87310946SSangeeta.Misra@Sun.COM 	int commit_ret;
87410946SSangeeta.Misra@Sun.COM 
87510946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(pg);
87610946SSangeeta.Misra@Sun.COM 	if (h == NULL || propname == NULL)
87710946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
87810946SSangeeta.Misra@Sun.COM 
87910946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_prop_val(pg, propname, &oldval);
88010946SSangeeta.Misra@Sun.COM 	if (oldval != NULL)
88110946SSangeeta.Misra@Sun.COM 		scf_value_destroy(oldval);
88210946SSangeeta.Misra@Sun.COM 	if (ret == ILB_STATUS_ENOENT)
88310946SSangeeta.Misra@Sun.COM 		new = B_TRUE;
88410946SSangeeta.Misra@Sun.COM 	else if (ret != ILB_STATUS_OK)
88510946SSangeeta.Misra@Sun.COM 		return (ret);
88610946SSangeeta.Misra@Sun.COM 
88710946SSangeeta.Misra@Sun.COM 	if ((prop = scf_property_create(h)) == NULL)
88810946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
88910946SSangeeta.Misra@Sun.COM 	if ((tx = scf_transaction_create(h)) == NULL ||
89010946SSangeeta.Misra@Sun.COM 	    (ent = scf_entry_create(h)) == NULL) {
89110946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
89210946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: create scf transaction failed\n");
89310946SSangeeta.Misra@Sun.COM 		goto out;
89410946SSangeeta.Misra@Sun.COM 	}
89510946SSangeeta.Misra@Sun.COM 
89610946SSangeeta.Misra@Sun.COM 	if (scf_transaction_start(tx, pg) == -1) {
89710946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
89810946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: start scf transaction failed\n");
89910946SSangeeta.Misra@Sun.COM 		goto out;
90010946SSangeeta.Misra@Sun.COM 	}
90110946SSangeeta.Misra@Sun.COM 
90210946SSangeeta.Misra@Sun.COM 	if (new) {
90310946SSangeeta.Misra@Sun.COM 		if (scf_transaction_property_new(tx, ent, propname,
90410946SSangeeta.Misra@Sun.COM 		    proptype) == -1) {
90510946SSangeeta.Misra@Sun.COM 			ret = ilbd_scf_err_to_ilb_err();
90610946SSangeeta.Misra@Sun.COM 			logdebug("ilbd_scf_set_prop: create scf prop failed\n");
90710946SSangeeta.Misra@Sun.COM 			goto out;
90810946SSangeeta.Misra@Sun.COM 		}
90910946SSangeeta.Misra@Sun.COM 	} else {
91010946SSangeeta.Misra@Sun.COM 		if (scf_transaction_property_change(tx, ent, propname, proptype)
91110946SSangeeta.Misra@Sun.COM 		    == -1) {
91210946SSangeeta.Misra@Sun.COM 			ret = ilbd_scf_err_to_ilb_err();
91310946SSangeeta.Misra@Sun.COM 			logdebug("ilbd_scf_set_prop: change scf prop failed\n");
91410946SSangeeta.Misra@Sun.COM 			goto out;
91510946SSangeeta.Misra@Sun.COM 		}
91610946SSangeeta.Misra@Sun.COM 	}
91710946SSangeeta.Misra@Sun.COM 
91810946SSangeeta.Misra@Sun.COM 	if (scf_entry_add_value(ent, val) != 0) {
91910946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: add scf entry failed\n");
92010946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
92110946SSangeeta.Misra@Sun.COM 		goto out;
92210946SSangeeta.Misra@Sun.COM 	}
92310946SSangeeta.Misra@Sun.COM 
92410946SSangeeta.Misra@Sun.COM 	commit_ret = scf_transaction_commit(tx);
92510946SSangeeta.Misra@Sun.COM 	switch (commit_ret) {
92610946SSangeeta.Misra@Sun.COM 	case 1:
92710946SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_OK;
92810946SSangeeta.Misra@Sun.COM 		/* update pg here, so subsequent property setting  succeeds */
92910946SSangeeta.Misra@Sun.COM 		(void) scf_pg_update(pg);
93010946SSangeeta.Misra@Sun.COM 		break;
93110946SSangeeta.Misra@Sun.COM 	case 0:
93210946SSangeeta.Misra@Sun.COM 		/* transaction failed due to not having most recent pg */
93310946SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_INUSE;
93410946SSangeeta.Misra@Sun.COM 		break;
93510946SSangeeta.Misra@Sun.COM 	default:
93610946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
93710946SSangeeta.Misra@Sun.COM 		break;
93810946SSangeeta.Misra@Sun.COM 	}
93910946SSangeeta.Misra@Sun.COM out:
94010946SSangeeta.Misra@Sun.COM 	if (tx != NULL)
94110946SSangeeta.Misra@Sun.COM 		scf_transaction_destroy(tx);
94210946SSangeeta.Misra@Sun.COM 	if (ent != NULL)
94310946SSangeeta.Misra@Sun.COM 		scf_entry_destroy(ent);
94410946SSangeeta.Misra@Sun.COM 	if (prop != NULL)
94510946SSangeeta.Misra@Sun.COM 		scf_property_destroy(prop);
94610946SSangeeta.Misra@Sun.COM 
94710946SSangeeta.Misra@Sun.COM 	return (ret);
94810946SSangeeta.Misra@Sun.COM }
94910946SSangeeta.Misra@Sun.COM 
95010946SSangeeta.Misra@Sun.COM /*
95110946SSangeeta.Misra@Sun.COM  * get a prop's scf val
95210946SSangeeta.Misra@Sun.COM  */
95310946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_get_prop_val(scf_propertygroup_t * pg,const char * propname,scf_value_t ** val)95410946SSangeeta.Misra@Sun.COM ilbd_scf_get_prop_val(scf_propertygroup_t *pg, const char *propname,
95510946SSangeeta.Misra@Sun.COM     scf_value_t **val)
95610946SSangeeta.Misra@Sun.COM {
95710946SSangeeta.Misra@Sun.COM 	scf_handle_t *h = NULL;
95810946SSangeeta.Misra@Sun.COM 	scf_property_t *prop = NULL;
95910946SSangeeta.Misra@Sun.COM 	scf_value_t *value = NULL;
96010946SSangeeta.Misra@Sun.COM 	ilb_status_t ret = ILB_STATUS_OK;
96110946SSangeeta.Misra@Sun.COM 
96210946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(pg);
96310946SSangeeta.Misra@Sun.COM 	if (h == NULL || propname == NULL)
96410946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
96510946SSangeeta.Misra@Sun.COM 
96610946SSangeeta.Misra@Sun.COM 	if ((prop = scf_property_create(h)) == NULL)
96710946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
96810946SSangeeta.Misra@Sun.COM 
96910946SSangeeta.Misra@Sun.COM 	if (scf_pg_get_property(pg, propname, prop) != 0) {
97010946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
97110946SSangeeta.Misra@Sun.COM 		goto out;
97210946SSangeeta.Misra@Sun.COM 	}
97310946SSangeeta.Misra@Sun.COM 
97410946SSangeeta.Misra@Sun.COM 	if ((value = scf_value_create(h)) == NULL) {
97510946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
97610946SSangeeta.Misra@Sun.COM 		goto out;
97710946SSangeeta.Misra@Sun.COM 	}
97810946SSangeeta.Misra@Sun.COM 
97910946SSangeeta.Misra@Sun.COM 	if (scf_property_get_value(prop, value) != 0) {
98010946SSangeeta.Misra@Sun.COM 		scf_value_destroy(value);
98110946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
98210946SSangeeta.Misra@Sun.COM 		goto out;
98310946SSangeeta.Misra@Sun.COM 	}
98410946SSangeeta.Misra@Sun.COM 
98510946SSangeeta.Misra@Sun.COM 	*val = value;
98610946SSangeeta.Misra@Sun.COM out:
98710946SSangeeta.Misra@Sun.COM 	if (prop != NULL)
98810946SSangeeta.Misra@Sun.COM 		scf_property_destroy(prop);
98910946SSangeeta.Misra@Sun.COM 
99010946SSangeeta.Misra@Sun.COM 	return (ret);
99110946SSangeeta.Misra@Sun.COM }
99210946SSangeeta.Misra@Sun.COM 
99310946SSangeeta.Misra@Sun.COM typedef struct ilbd_data
99410946SSangeeta.Misra@Sun.COM {
99510946SSangeeta.Misra@Sun.COM 	union {
99610946SSangeeta.Misra@Sun.COM 		ilb_sg_info_t *sg_info;
99710946SSangeeta.Misra@Sun.COM 		ilb_hc_info_t *hc_info;
99810946SSangeeta.Misra@Sun.COM 		ilb_rule_info_t *rule_info;
99910946SSangeeta.Misra@Sun.COM 	} data;
100010946SSangeeta.Misra@Sun.COM 	ilbd_scf_pg_type_t pg_type;	/* type of data */
100110946SSangeeta.Misra@Sun.COM #define	sg_data data.sg_info
100210946SSangeeta.Misra@Sun.COM #define	hc_data data.hc_info
100310946SSangeeta.Misra@Sun.COM #define	rule_data data.rule_info
100410946SSangeeta.Misra@Sun.COM } ilbd_data_t;
100510946SSangeeta.Misra@Sun.COM 
100610946SSangeeta.Misra@Sun.COM void
ilbd_scf_str_to_ip(int ipversion,char * ipstr,struct in6_addr * addr)100710946SSangeeta.Misra@Sun.COM ilbd_scf_str_to_ip(int ipversion, char *ipstr, struct in6_addr *addr)
100810946SSangeeta.Misra@Sun.COM {
100910946SSangeeta.Misra@Sun.COM 	ilb_ip_addr_t ipaddr;
101010946SSangeeta.Misra@Sun.COM 	void *addrptr;
101110946SSangeeta.Misra@Sun.COM 
101210946SSangeeta.Misra@Sun.COM 	addrptr = (ipversion == AF_INET) ?
101310946SSangeeta.Misra@Sun.COM 	    (void *)&ipaddr.ia_v4 : (void *)&ipaddr.ia_v6;
101410946SSangeeta.Misra@Sun.COM 	(void) inet_pton(ipversion, ipstr, addrptr);
101510946SSangeeta.Misra@Sun.COM 	if (ipversion == AF_INET) {
101610946SSangeeta.Misra@Sun.COM 		IN6_INADDR_TO_V4MAPPED(&(ipaddr.ia_v4), addr);
101710946SSangeeta.Misra@Sun.COM 	} else {
101810946SSangeeta.Misra@Sun.COM 		(void) memcpy(addr, &(ipaddr.ia_v6),
101910946SSangeeta.Misra@Sun.COM 		    sizeof (struct in6_addr));
102010946SSangeeta.Misra@Sun.COM 	}
102110946SSangeeta.Misra@Sun.COM }
102210946SSangeeta.Misra@Sun.COM 
102310946SSangeeta.Misra@Sun.COM /*
102410946SSangeeta.Misra@Sun.COM  * This function takes a scf value and writes it to the correct field of the
102510946SSangeeta.Misra@Sun.COM  * corresponding data struct.
102610946SSangeeta.Misra@Sun.COM  */
102710946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scfval_to_data(const char * propname,ilbd_var_type_t ilb_type,scf_value_t * val,ilbd_data_t * ilb_data)102810946SSangeeta.Misra@Sun.COM ilbd_scfval_to_data(const char *propname, ilbd_var_type_t ilb_type,
102910946SSangeeta.Misra@Sun.COM     scf_value_t *val, ilbd_data_t *ilb_data)
103010946SSangeeta.Misra@Sun.COM {
103110946SSangeeta.Misra@Sun.COM 
103210946SSangeeta.Misra@Sun.COM 	scf_type_t scf_type = scf_value_type(val);
103310946SSangeeta.Misra@Sun.COM 	ilbd_scf_pg_type_t pg_type = ilb_data->pg_type;
103410946SSangeeta.Misra@Sun.COM 	int ret = 0;
103510946SSangeeta.Misra@Sun.COM 	ilb_rule_info_t *r_ent = NULL;
103610946SSangeeta.Misra@Sun.COM 	ilb_sg_info_t *s_ent = NULL;
103710946SSangeeta.Misra@Sun.COM 	ilb_hc_info_t *h_ent = NULL;
103810946SSangeeta.Misra@Sun.COM 	char ipstr[INET6_ADDRSTRLEN];
1039*12857SSangeeta.Misra@Sun.COM 	char *valstr;
104010946SSangeeta.Misra@Sun.COM 	int64_t valint;
104110946SSangeeta.Misra@Sun.COM 	uint8_t valbool;
104210946SSangeeta.Misra@Sun.COM 	int ipversion;
104310946SSangeeta.Misra@Sun.COM 
104410946SSangeeta.Misra@Sun.COM 	switch (pg_type) {
104510946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_RULE:
104610946SSangeeta.Misra@Sun.COM 		r_ent = ilb_data->rule_data;
104710946SSangeeta.Misra@Sun.COM 		break;
104810946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_HC:
104910946SSangeeta.Misra@Sun.COM 		h_ent = ilb_data->hc_data;
105010946SSangeeta.Misra@Sun.COM 		break;
105110946SSangeeta.Misra@Sun.COM 	case ILBD_SCF_SG:
105210946SSangeeta.Misra@Sun.COM 		s_ent = ilb_data->sg_data;
105310946SSangeeta.Misra@Sun.COM 		break;
105410946SSangeeta.Misra@Sun.COM 	}
105510946SSangeeta.Misra@Sun.COM 
105610946SSangeeta.Misra@Sun.COM 	/* get scf value out */
1057*12857SSangeeta.Misra@Sun.COM 	if ((valstr = malloc(ILBD_MAX_VALUE_LEN)) == NULL)
1058*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
105910946SSangeeta.Misra@Sun.COM 	switch (scf_type) {
106010946SSangeeta.Misra@Sun.COM 		case SCF_TYPE_NET_ADDR_V4:
106110946SSangeeta.Misra@Sun.COM 			if (scf_value_get_as_string_typed(val,
1062*12857SSangeeta.Misra@Sun.COM 			    SCF_TYPE_NET_ADDR_V4, ipstr, INET_ADDRSTRLEN) < 0) {
1063*12857SSangeeta.Misra@Sun.COM 				free(valstr);
106410946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_INTERNAL);
1065*12857SSangeeta.Misra@Sun.COM 			}
106610946SSangeeta.Misra@Sun.COM 			ipversion = AF_INET;
106710946SSangeeta.Misra@Sun.COM 			break;
106810946SSangeeta.Misra@Sun.COM 		case SCF_TYPE_NET_ADDR_V6:
106910946SSangeeta.Misra@Sun.COM 			if (scf_value_get_as_string_typed(val,
1070*12857SSangeeta.Misra@Sun.COM 			    SCF_TYPE_NET_ADDR_V6, ipstr,
1071*12857SSangeeta.Misra@Sun.COM 			    INET6_ADDRSTRLEN) < 0) {
1072*12857SSangeeta.Misra@Sun.COM 				free(valstr);
107310946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_INTERNAL);
1074*12857SSangeeta.Misra@Sun.COM 			}
107510946SSangeeta.Misra@Sun.COM 			ipversion = AF_INET6;
107610946SSangeeta.Misra@Sun.COM 			break;
107710946SSangeeta.Misra@Sun.COM 		case SCF_TYPE_BOOLEAN:
1078*12857SSangeeta.Misra@Sun.COM 			if (scf_value_get_boolean(val, &valbool) < 0) {
1079*12857SSangeeta.Misra@Sun.COM 				free(valstr);
108010946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_INTERNAL);
1081*12857SSangeeta.Misra@Sun.COM 			}
108210946SSangeeta.Misra@Sun.COM 			break;
108310946SSangeeta.Misra@Sun.COM 		case SCF_TYPE_ASTRING:
1084*12857SSangeeta.Misra@Sun.COM 			if (scf_value_get_astring(val, valstr,
1085*12857SSangeeta.Misra@Sun.COM 			    ILBD_MAX_VALUE_LEN) < 0) {
1086*12857SSangeeta.Misra@Sun.COM 				free(valstr);
108710946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_INTERNAL);
1088*12857SSangeeta.Misra@Sun.COM 			}
108910946SSangeeta.Misra@Sun.COM 			break;
109010946SSangeeta.Misra@Sun.COM 		case SCF_TYPE_INTEGER:
1091*12857SSangeeta.Misra@Sun.COM 			if (scf_value_get_integer(val, &valint) < 0) {
1092*12857SSangeeta.Misra@Sun.COM 				free(valstr);
109310946SSangeeta.Misra@Sun.COM 				return (ILB_STATUS_INTERNAL);
1094*12857SSangeeta.Misra@Sun.COM 			}
109510946SSangeeta.Misra@Sun.COM 			break;
109610946SSangeeta.Misra@Sun.COM 		default:
1097*12857SSangeeta.Misra@Sun.COM 			free(valstr);
109810946SSangeeta.Misra@Sun.COM 			return (ILB_STATUS_INTERNAL);
109910946SSangeeta.Misra@Sun.COM 	}
110010946SSangeeta.Misra@Sun.COM 
110110946SSangeeta.Misra@Sun.COM 	ret = ILB_STATUS_OK;
110210946SSangeeta.Misra@Sun.COM 	switch (ilb_type) {
110310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_STATUS:
110410946SSangeeta.Misra@Sun.COM 		if (valbool)
110510946SSangeeta.Misra@Sun.COM 			r_ent->rl_flags |= ILB_FLAGS_RULE_ENABLED;
110610946SSangeeta.Misra@Sun.COM 		break;
110710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_VIP:
110810946SSangeeta.Misra@Sun.COM 		r_ent->rl_ipversion = ipversion;
110910946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_vip);
111010946SSangeeta.Misra@Sun.COM 		break;
111110946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PROTO: {
111210946SSangeeta.Misra@Sun.COM 		struct protoent *protoent;
111310946SSangeeta.Misra@Sun.COM 
111410946SSangeeta.Misra@Sun.COM 		protoent = getprotobyname(valstr);
111510946SSangeeta.Misra@Sun.COM 		r_ent->rl_proto = protoent->p_proto;
111610946SSangeeta.Misra@Sun.COM 		break;
111710946SSangeeta.Misra@Sun.COM 	}
111810946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PORT: {
111910946SSangeeta.Misra@Sun.COM 		char *token1, *token2;
112010946SSangeeta.Misra@Sun.COM 
112110946SSangeeta.Misra@Sun.COM 		token1 = strtok(valstr, "-");
112210946SSangeeta.Misra@Sun.COM 		token2 = strtok(NULL, "-");
112310946SSangeeta.Misra@Sun.COM 		r_ent->rl_minport = atoi(token1);
112410946SSangeeta.Misra@Sun.COM 		r_ent->rl_maxport = atoi(token2);
112510946SSangeeta.Misra@Sun.COM 		break;
112610946SSangeeta.Misra@Sun.COM 	}
112710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_ALGO:
112810946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_algo(&(r_ent->rl_algo), valstr);
112910946SSangeeta.Misra@Sun.COM 		break;
113010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_TOPO:
113110946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_topo(&(r_ent->rl_topo), valstr);
113210946SSangeeta.Misra@Sun.COM 		break;
113310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_STR:
113410946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_nat_src_start);
113510946SSangeeta.Misra@Sun.COM 		break;
113610946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_END:
113710946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_nat_src_end);
113810946SSangeeta.Misra@Sun.COM 		break;
113910946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_STI_MASK:
114010946SSangeeta.Misra@Sun.COM 		ilbd_scf_str_to_ip(ipversion, ipstr, &r_ent->rl_stickymask);
114110946SSangeeta.Misra@Sun.COM 		if (ipversion == AF_INET) {
114210946SSangeeta.Misra@Sun.COM 			if (!IN6_IS_ADDR_V4MAPPED_ANY(&r_ent->rl_stickymask))
114310946SSangeeta.Misra@Sun.COM 				r_ent->rl_flags |= ILB_FLAGS_RULE_STICKY;
114410946SSangeeta.Misra@Sun.COM 		} else {
114510946SSangeeta.Misra@Sun.COM 			if (!IN6_IS_ADDR_UNSPECIFIED(&r_ent->rl_stickymask))
114610946SSangeeta.Misra@Sun.COM 				r_ent->rl_flags |= ILB_FLAGS_RULE_STICKY;
114710946SSangeeta.Misra@Sun.COM 		}
114810946SSangeeta.Misra@Sun.COM 		break;
114910946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_SGNAME:
115010946SSangeeta.Misra@Sun.COM 		(void) strlcpy(r_ent->rl_sgname, valstr,
115110946SSangeeta.Misra@Sun.COM 		    sizeof (r_ent->rl_sgname));
115210946SSangeeta.Misra@Sun.COM 		break;
115310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCNAME:
115410946SSangeeta.Misra@Sun.COM 		(void) strlcpy(r_ent->rl_hcname, valstr,
115510946SSangeeta.Misra@Sun.COM 		    sizeof (r_ent->rl_hcname));
115610946SSangeeta.Misra@Sun.COM 		break;
115710946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCPORT:
115810946SSangeeta.Misra@Sun.COM 		r_ent->rl_hcport = valint;
115910946SSangeeta.Misra@Sun.COM 		break;
116010946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_HCPFLAG:
116110946SSangeeta.Misra@Sun.COM 		r_ent->rl_hcpflag = valint;
116210946SSangeeta.Misra@Sun.COM 		break;
116310946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_DRAINTIME:
116410946SSangeeta.Misra@Sun.COM 		r_ent->rl_conndrain = valint;
116510946SSangeeta.Misra@Sun.COM 		break;
116610946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_NAT_TO:
116710946SSangeeta.Misra@Sun.COM 		r_ent->rl_nat_timeout = valint;
116810946SSangeeta.Misra@Sun.COM 		break;
116910946SSangeeta.Misra@Sun.COM 	case ILBD_RULE_PERS_TO:
117010946SSangeeta.Misra@Sun.COM 		r_ent->rl_sticky_timeout = valint;
117110946SSangeeta.Misra@Sun.COM 		break;
117210946SSangeeta.Misra@Sun.COM 
117310946SSangeeta.Misra@Sun.COM 	case ILBD_SG_SERVER: {
117410946SSangeeta.Misra@Sun.COM 		int svr_cnt = s_ent->sg_srvcount;
117510946SSangeeta.Misra@Sun.COM 
117610946SSangeeta.Misra@Sun.COM 		/* found a new server, increase the svr count of this sg */
117710946SSangeeta.Misra@Sun.COM 		s_ent->sg_srvcount++;
117810946SSangeeta.Misra@Sun.COM 
117910946SSangeeta.Misra@Sun.COM 		/*
118010946SSangeeta.Misra@Sun.COM 		 * valstr contains information of one server in the servergroup
118110946SSangeeta.Misra@Sun.COM 		 * valstr is in the format of "ip:minport-maxport:enable"
118210946SSangeeta.Misra@Sun.COM 		 */
118310946SSangeeta.Misra@Sun.COM 		s_ent = realloc(s_ent, sizeof (ilb_sg_info_t) +
118410946SSangeeta.Misra@Sun.COM 		    s_ent->sg_srvcount * sizeof (ilb_sg_srv_t));
118510946SSangeeta.Misra@Sun.COM 
118610946SSangeeta.Misra@Sun.COM 		/* sgs_srvID is the sg name, leave it blank */
118710946SSangeeta.Misra@Sun.COM 		/*
118810946SSangeeta.Misra@Sun.COM 		 * sgs_id is the digit in propname, propname is in a format of
118910946SSangeeta.Misra@Sun.COM 		 * "server" + the digital serverID. We get the serverID by
119010946SSangeeta.Misra@Sun.COM 		 * reading from the 7th char of propname.
119110946SSangeeta.Misra@Sun.COM 		 */
119210946SSangeeta.Misra@Sun.COM 		s_ent->sg_servers[svr_cnt].sgs_id = atoi(&propname[6]);
119310946SSangeeta.Misra@Sun.COM 
119410946SSangeeta.Misra@Sun.COM 		ilbd_get_svr_field(valstr,
119510946SSangeeta.Misra@Sun.COM 		    &s_ent->sg_servers[svr_cnt].sgs_addr,
119610946SSangeeta.Misra@Sun.COM 		    &s_ent->sg_servers[svr_cnt].sgs_minport,
119710946SSangeeta.Misra@Sun.COM 		    &s_ent->sg_servers[svr_cnt].sgs_maxport,
119810946SSangeeta.Misra@Sun.COM 		    &s_ent->sg_servers[svr_cnt].sgs_flags);
119910946SSangeeta.Misra@Sun.COM 		ilb_data->sg_data = s_ent;
120010946SSangeeta.Misra@Sun.COM 
120110946SSangeeta.Misra@Sun.COM 		break;
120210946SSangeeta.Misra@Sun.COM 	}
120310946SSangeeta.Misra@Sun.COM 	case ILBD_HC_TEST:
120410946SSangeeta.Misra@Sun.COM 		(void) strlcpy(h_ent->hci_test, valstr,
120510946SSangeeta.Misra@Sun.COM 		    sizeof (h_ent->hci_test));
120610946SSangeeta.Misra@Sun.COM 		break;
120710946SSangeeta.Misra@Sun.COM 	case ILBD_HC_TIMEOUT:
120810946SSangeeta.Misra@Sun.COM 		h_ent->hci_timeout = valint;
120910946SSangeeta.Misra@Sun.COM 		break;
121010946SSangeeta.Misra@Sun.COM 	case ILBD_HC_INTERVAL:
121110946SSangeeta.Misra@Sun.COM 		h_ent->hci_interval = valint;
121210946SSangeeta.Misra@Sun.COM 		break;
121310946SSangeeta.Misra@Sun.COM 	case ILBD_HC_DEF_PING:
121410946SSangeeta.Misra@Sun.COM 		h_ent->hci_def_ping = valbool;
121510946SSangeeta.Misra@Sun.COM 		break;
121610946SSangeeta.Misra@Sun.COM 	case ILBD_HC_COUNT:
121710946SSangeeta.Misra@Sun.COM 		h_ent->hci_count = valint;
121810946SSangeeta.Misra@Sun.COM 		break;
121910946SSangeeta.Misra@Sun.COM 	case ILBD_VAR_INVALID:
122010946SSangeeta.Misra@Sun.COM 		/*
122110946SSangeeta.Misra@Sun.COM 		 * An empty server group is represented by an invalid
122210946SSangeeta.Misra@Sun.COM 		 * SCF property.  So when loading a server group, this
122310946SSangeeta.Misra@Sun.COM 		 * case can be hit.  But it should happen only for this
122410946SSangeeta.Misra@Sun.COM 		 * single case.  So if it happens in another case, move
122510946SSangeeta.Misra@Sun.COM 		 * the service into maintenance mode.
122610946SSangeeta.Misra@Sun.COM 		 */
122710946SSangeeta.Misra@Sun.COM 		if (pg_type != ILBD_SCF_SG || scf_type != SCF_TYPE_ASTRING) {
122810946SSangeeta.Misra@Sun.COM 			logerr("%s: invalid ilb type", __func__);
122910946SSangeeta.Misra@Sun.COM 			(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
123010946SSangeeta.Misra@Sun.COM 		} else {
123110946SSangeeta.Misra@Sun.COM 			logdebug("%s: invalid ilb type", __func__);
123210946SSangeeta.Misra@Sun.COM 		}
123310946SSangeeta.Misra@Sun.COM 		break;
123410946SSangeeta.Misra@Sun.COM 	}
123510946SSangeeta.Misra@Sun.COM 
1236*12857SSangeeta.Misra@Sun.COM 	free(valstr);
123710946SSangeeta.Misra@Sun.COM 	return (ret);
123810946SSangeeta.Misra@Sun.COM }
123910946SSangeeta.Misra@Sun.COM 
124010946SSangeeta.Misra@Sun.COM static ilbd_var_type_t
ilbd_name_to_valtype(const char * prop_name)124110946SSangeeta.Misra@Sun.COM ilbd_name_to_valtype(const char *prop_name)
124210946SSangeeta.Misra@Sun.COM {
124310946SSangeeta.Misra@Sun.COM 	int i;
124410946SSangeeta.Misra@Sun.COM 
124510946SSangeeta.Misra@Sun.COM 	for (i = 0; i < ILBD_PROP_VAR_NUM; i++)
124610946SSangeeta.Misra@Sun.COM 		if (strncmp(prop_name, prop_tbl[i].scf_propname,
124710946SSangeeta.Misra@Sun.COM 		    strlen(prop_tbl[i].scf_propname)) == 0)
124810946SSangeeta.Misra@Sun.COM 			return (prop_tbl[i].val_type);
124910946SSangeeta.Misra@Sun.COM 
125010946SSangeeta.Misra@Sun.COM 	logdebug("ilbd_name_to_valtype: couldn't find prop %s", prop_name);
125110946SSangeeta.Misra@Sun.COM 	return (ILBD_VAR_INVALID);
125210946SSangeeta.Misra@Sun.COM }
125310946SSangeeta.Misra@Sun.COM 
125410946SSangeeta.Misra@Sun.COM /* callback for pg_walk_prop, arg is ilbd_data_t */
125510946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_load_prop(scf_propertygroup_t * pg,const char * prop_name,void * arg)125610946SSangeeta.Misra@Sun.COM ilbd_scf_load_prop(scf_propertygroup_t *pg, const char *prop_name, void *arg)
125710946SSangeeta.Misra@Sun.COM {
125810946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
125910946SSangeeta.Misra@Sun.COM 	scf_value_t *val;
126010946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
126110946SSangeeta.Misra@Sun.COM 	ilbd_data_t *ilb_data = (ilbd_data_t *)arg;
126210946SSangeeta.Misra@Sun.COM 	ilbd_var_type_t val_type = ilbd_name_to_valtype(prop_name);
126310946SSangeeta.Misra@Sun.COM 
126410946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(pg);
126510946SSangeeta.Misra@Sun.COM 	if (h == NULL)
126610946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
126710946SSangeeta.Misra@Sun.COM 
126810946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_prop_val(pg, prop_name, &val);
126910946SSangeeta.Misra@Sun.COM 	if (ret == ILB_STATUS_ENOENT)
127010946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_OK);
127110946SSangeeta.Misra@Sun.COM 	else if (ret != ILB_STATUS_OK)
127210946SSangeeta.Misra@Sun.COM 		return (ret);
127310946SSangeeta.Misra@Sun.COM 
127410946SSangeeta.Misra@Sun.COM 	/*
127510946SSangeeta.Misra@Sun.COM 	 * Load value to ilb_data.
127610946SSangeeta.Misra@Sun.COM 	 */
127710946SSangeeta.Misra@Sun.COM 	ret = ilbd_scfval_to_data(prop_name, val_type, val, ilb_data);
127810946SSangeeta.Misra@Sun.COM 
127910946SSangeeta.Misra@Sun.COM out:
128010946SSangeeta.Misra@Sun.COM 	if (val != NULL)
128110946SSangeeta.Misra@Sun.COM 		scf_value_destroy(val);
128210946SSangeeta.Misra@Sun.COM 
128310946SSangeeta.Misra@Sun.COM 	return (ret);
128410946SSangeeta.Misra@Sun.COM }
128510946SSangeeta.Misra@Sun.COM 
128610946SSangeeta.Misra@Sun.COM /*
128710946SSangeeta.Misra@Sun.COM  * walk properties in one prop group, arg is ilbd_data
128810946SSangeeta.Misra@Sun.COM  * cb is ilbd_scf_load_prop()
128910946SSangeeta.Misra@Sun.COM  */
129010946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_pg_walk_props(scf_propertygroup_t * pg,ilb_status_t (* cb)(scf_propertygroup_t *,const char *,void *),void * arg)129110946SSangeeta.Misra@Sun.COM ilbd_scf_pg_walk_props(scf_propertygroup_t *pg,
129210946SSangeeta.Misra@Sun.COM     ilb_status_t (*cb)(scf_propertygroup_t *, const char *, void *),
129310946SSangeeta.Misra@Sun.COM     void *arg)
129410946SSangeeta.Misra@Sun.COM {
129510946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
129610946SSangeeta.Misra@Sun.COM 	scf_iter_t *propiter;
129710946SSangeeta.Misra@Sun.COM 	scf_property_t *prop;
129810946SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
1299*12857SSangeeta.Misra@Sun.COM 	char *prop_name = NULL;
130010946SSangeeta.Misra@Sun.COM 	ilb_status_t ret = ILB_STATUS_OK;
130110946SSangeeta.Misra@Sun.COM 	int scf_ret = -1;
130210946SSangeeta.Misra@Sun.COM 
130310946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(pg);
130410946SSangeeta.Misra@Sun.COM 	if (h == NULL)
130510946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
130610946SSangeeta.Misra@Sun.COM 
130710946SSangeeta.Misra@Sun.COM 	prop = scf_property_create(h);
130810946SSangeeta.Misra@Sun.COM 	propiter = scf_iter_create(h);
130910946SSangeeta.Misra@Sun.COM 	if (prop == NULL || propiter == NULL)
131010946SSangeeta.Misra@Sun.COM 		goto out;
131110946SSangeeta.Misra@Sun.COM 
131210946SSangeeta.Misra@Sun.COM 	if (scf_iter_pg_properties(propiter, pg) != 0)
131310946SSangeeta.Misra@Sun.COM 		goto out;
131410946SSangeeta.Misra@Sun.COM 
1315*12857SSangeeta.Misra@Sun.COM 	if ((prop_name = malloc(scf_name_len)) == NULL) {
1316*12857SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_ENOMEM;
1317*12857SSangeeta.Misra@Sun.COM 		goto out;
1318*12857SSangeeta.Misra@Sun.COM 	}
131910946SSangeeta.Misra@Sun.COM 	while ((scf_ret = scf_iter_next_property(propiter, prop)) == 1) {
1320*12857SSangeeta.Misra@Sun.COM 		if (scf_property_get_name(prop, prop_name, scf_name_len)
132110946SSangeeta.Misra@Sun.COM 		    < 0) {
132210946SSangeeta.Misra@Sun.COM 			ret = ilbd_scf_err_to_ilb_err();
132310946SSangeeta.Misra@Sun.COM 			goto out;
132410946SSangeeta.Misra@Sun.COM 		}
132510946SSangeeta.Misra@Sun.COM 		ret = cb(pg, prop_name, arg);
132610946SSangeeta.Misra@Sun.COM 		if (ret != ILB_STATUS_OK)
132710946SSangeeta.Misra@Sun.COM 			break;
132810946SSangeeta.Misra@Sun.COM 	}
132910946SSangeeta.Misra@Sun.COM out:
1330*12857SSangeeta.Misra@Sun.COM 	if (prop_name != NULL)
1331*12857SSangeeta.Misra@Sun.COM 		free(prop_name);
133210946SSangeeta.Misra@Sun.COM 	if (scf_ret == -1)
133310946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
133410946SSangeeta.Misra@Sun.COM 	if (prop != NULL)
133510946SSangeeta.Misra@Sun.COM 		scf_property_destroy(prop);
133610946SSangeeta.Misra@Sun.COM 	if (propiter != NULL)
133710946SSangeeta.Misra@Sun.COM 		scf_iter_destroy(propiter);
133810946SSangeeta.Misra@Sun.COM 
133910946SSangeeta.Misra@Sun.COM 	return (ret);
134010946SSangeeta.Misra@Sun.COM }
134110946SSangeeta.Misra@Sun.COM 
134210946SSangeeta.Misra@Sun.COM /* cbs are libd_create_X */
134310946SSangeeta.Misra@Sun.COM static ilb_status_t
ilbd_scf_instance_walk_pg(scf_instance_t * inst,ilbd_scf_pg_type_t pg_type,ilb_status_t (* cb)(void *,int,struct passwd *,ucred_t *),void * arg1,void * arg2)134410946SSangeeta.Misra@Sun.COM ilbd_scf_instance_walk_pg(scf_instance_t *inst,
134510946SSangeeta.Misra@Sun.COM     ilbd_scf_pg_type_t pg_type,
134610946SSangeeta.Misra@Sun.COM     ilb_status_t (*cb)(void *, int, struct passwd *, ucred_t *),
134710946SSangeeta.Misra@Sun.COM     void *arg1, void *arg2)
134810946SSangeeta.Misra@Sun.COM {
134910946SSangeeta.Misra@Sun.COM 	int			scf_ret;
135010946SSangeeta.Misra@Sun.COM 	ilb_status_t		ret;
135110946SSangeeta.Misra@Sun.COM 	scf_handle_t		*h;
135210946SSangeeta.Misra@Sun.COM 	scf_iter_t		*pgiter;
135310946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t	*newpg;
135410946SSangeeta.Misra@Sun.COM 	int			port = *((int *)arg1);
1355*12857SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
1356*12857SSangeeta.Misra@Sun.COM 	char *pg_name = NULL;
135710946SSangeeta.Misra@Sun.COM 
135810946SSangeeta.Misra@Sun.COM 	if (inst == NULL)
135910946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
136010946SSangeeta.Misra@Sun.COM 
136110946SSangeeta.Misra@Sun.COM 	h = scf_instance_handle(inst);
136210946SSangeeta.Misra@Sun.COM 	if (h == NULL)
136310946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_EINVAL);
136410946SSangeeta.Misra@Sun.COM 
136510946SSangeeta.Misra@Sun.COM 	if ((newpg = scf_pg_create(h)) == NULL)
136610946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
136710946SSangeeta.Misra@Sun.COM 
136810946SSangeeta.Misra@Sun.COM 	if ((pgiter = scf_iter_create(h)) == NULL) {
136910946SSangeeta.Misra@Sun.COM 		scf_pg_destroy(newpg);
137010946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
137110946SSangeeta.Misra@Sun.COM 	}
137210946SSangeeta.Misra@Sun.COM 
137310946SSangeeta.Misra@Sun.COM 	if ((scf_ret = scf_iter_instance_pgs(pgiter, inst)) < 0)
137410946SSangeeta.Misra@Sun.COM 		goto out;
137510946SSangeeta.Misra@Sun.COM 
1376*12857SSangeeta.Misra@Sun.COM 	if ((pg_name = malloc(scf_name_len)) == NULL) {
1377*12857SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_ENOMEM;
1378*12857SSangeeta.Misra@Sun.COM 		goto out;
1379*12857SSangeeta.Misra@Sun.COM 	}
138010946SSangeeta.Misra@Sun.COM 	while ((scf_ret = scf_iter_next_pg(pgiter, newpg)) > 0) {
138110946SSangeeta.Misra@Sun.COM 		ilbd_data_t data;
138210946SSangeeta.Misra@Sun.COM 
1383*12857SSangeeta.Misra@Sun.COM 		if (scf_pg_get_name(newpg, pg_name, scf_name_len) < 0) {
138410946SSangeeta.Misra@Sun.COM 			ret = ilbd_scf_err_to_ilb_err();
138510946SSangeeta.Misra@Sun.COM 			goto out;
138610946SSangeeta.Misra@Sun.COM 		}
138710946SSangeeta.Misra@Sun.COM 
138810946SSangeeta.Misra@Sun.COM 		/*
138910946SSangeeta.Misra@Sun.COM 		 * if pg name indicates it's a ilb configuration, walk its prop
139010946SSangeeta.Misra@Sun.COM 		 */
139110946SSangeeta.Misra@Sun.COM 		data.pg_type = pg_type;
139210946SSangeeta.Misra@Sun.COM 		data.hc_data = NULL;
139310946SSangeeta.Misra@Sun.COM 		data.sg_data = NULL;
139410946SSangeeta.Misra@Sun.COM 		data.rule_data = NULL;
139510946SSangeeta.Misra@Sun.COM 
139610946SSangeeta.Misra@Sun.COM 		switch (pg_type) {
139710946SSangeeta.Misra@Sun.COM 		case ILBD_SCF_RULE:
139810946SSangeeta.Misra@Sun.COM 			if (strncmp(ILBD_PG_NAME_RULE, pg_name,
139910946SSangeeta.Misra@Sun.COM 			    strlen(ILBD_PG_NAME_RULE)) == 0) {
140010946SSangeeta.Misra@Sun.COM 				data.rule_data = calloc(1,
140110946SSangeeta.Misra@Sun.COM 				    sizeof (ilb_rule_info_t));
140210946SSangeeta.Misra@Sun.COM 				if (data.rule_data == NULL) {
140310946SSangeeta.Misra@Sun.COM 					ret = ILB_STATUS_ENOMEM;
140410946SSangeeta.Misra@Sun.COM 					goto out;
140510946SSangeeta.Misra@Sun.COM 				}
140610946SSangeeta.Misra@Sun.COM 				ret = ilbd_scf_pg_walk_props(newpg,
140710946SSangeeta.Misra@Sun.COM 				    ilbd_scf_load_prop, &data);
140810946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK)
140910946SSangeeta.Misra@Sun.COM 					goto out;
141010946SSangeeta.Misra@Sun.COM 				assert(data.rule_data != NULL);
141110946SSangeeta.Misra@Sun.COM 				/* set rule name */
141210946SSangeeta.Misra@Sun.COM 				(void) strlcpy(data.rule_data->rl_name,
141310946SSangeeta.Misra@Sun.COM 				    &pg_name[strlen(ILBD_PG_NAME_RULE)],
141410946SSangeeta.Misra@Sun.COM 				    sizeof (data.rule_data->rl_name));
141510946SSangeeta.Misra@Sun.COM 
141610946SSangeeta.Misra@Sun.COM 				ret = cb(data.rule_data, port, arg2, NULL);
141710946SSangeeta.Misra@Sun.COM 				free(data.rule_data);
141810946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK)
141910946SSangeeta.Misra@Sun.COM 					goto out;
142010946SSangeeta.Misra@Sun.COM 			}
142110946SSangeeta.Misra@Sun.COM 			break;
142210946SSangeeta.Misra@Sun.COM 		case ILBD_SCF_SG:
142310946SSangeeta.Misra@Sun.COM 			if (strncmp(ILBD_PG_NAME_SG, pg_name,
142410946SSangeeta.Misra@Sun.COM 			    strlen(ILBD_PG_NAME_SG)) == 0) {
142510946SSangeeta.Misra@Sun.COM 				data.sg_data = calloc(1,
142610946SSangeeta.Misra@Sun.COM 				    sizeof (ilb_sg_info_t));
1427*12857SSangeeta.Misra@Sun.COM 				if (data.sg_data == NULL) {
1428*12857SSangeeta.Misra@Sun.COM 					ret = ILB_STATUS_ENOMEM;
1429*12857SSangeeta.Misra@Sun.COM 					goto out;
1430*12857SSangeeta.Misra@Sun.COM 				}
143110946SSangeeta.Misra@Sun.COM 				ret = ilbd_scf_pg_walk_props(newpg,
143210946SSangeeta.Misra@Sun.COM 				    ilbd_scf_load_prop, &data);
143310946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK) {
143410946SSangeeta.Misra@Sun.COM 					free(data.sg_data);
143510946SSangeeta.Misra@Sun.COM 					goto out;
143610946SSangeeta.Misra@Sun.COM 				}
143710946SSangeeta.Misra@Sun.COM 				assert(data.sg_data != NULL);
143810946SSangeeta.Misra@Sun.COM 				/* set sg name */
143910946SSangeeta.Misra@Sun.COM 				(void) strlcpy(data.sg_data->sg_name,
144010946SSangeeta.Misra@Sun.COM 				    &pg_name[strlen(ILBD_PG_NAME_SG)],
144110946SSangeeta.Misra@Sun.COM 				    sizeof (data.sg_data->sg_name));
144210946SSangeeta.Misra@Sun.COM 				ret = cb(data.sg_data, port, arg2, NULL);
144310946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK) {
144410946SSangeeta.Misra@Sun.COM 					free(data.sg_data);
144510946SSangeeta.Misra@Sun.COM 					goto out;
144610946SSangeeta.Misra@Sun.COM 				}
144710946SSangeeta.Misra@Sun.COM 				/*
144810946SSangeeta.Misra@Sun.COM 				 * create a servergroup is two-step operation.
144910946SSangeeta.Misra@Sun.COM 				 * 1. create an empty servergroup.
145010946SSangeeta.Misra@Sun.COM 				 * 2. add server(s) to the group.
145110946SSangeeta.Misra@Sun.COM 				 *
145210946SSangeeta.Misra@Sun.COM 				 * since we are here from:
145310946SSangeeta.Misra@Sun.COM 				 * main_loop()->ilbd_read_config()->
145410946SSangeeta.Misra@Sun.COM 				 * ilbd_walk_sg_pgs()
145510946SSangeeta.Misra@Sun.COM 				 * there is no cli to send. So in this
145610946SSangeeta.Misra@Sun.COM 				 * path auditing will skip the
145710946SSangeeta.Misra@Sun.COM 				 * adt_set_from_ucred() check
145810946SSangeeta.Misra@Sun.COM 				 */
145910946SSangeeta.Misra@Sun.COM 				if (data.sg_data->sg_srvcount > 0) {
146010946SSangeeta.Misra@Sun.COM 					ret = ilbd_add_server_to_group(
146110946SSangeeta.Misra@Sun.COM 					    data.sg_data, port, NULL, NULL);
146210946SSangeeta.Misra@Sun.COM 					if (ret != ILB_STATUS_OK) {
146310946SSangeeta.Misra@Sun.COM 						free(data.sg_data);
146410946SSangeeta.Misra@Sun.COM 						goto out;
146510946SSangeeta.Misra@Sun.COM 					}
146610946SSangeeta.Misra@Sun.COM 					free(data.sg_data);
146710946SSangeeta.Misra@Sun.COM 				}
146810946SSangeeta.Misra@Sun.COM 			}
146910946SSangeeta.Misra@Sun.COM 			break;
147010946SSangeeta.Misra@Sun.COM 		case ILBD_SCF_HC:
147110946SSangeeta.Misra@Sun.COM 			if (strncmp(ILBD_PG_NAME_HC, pg_name,
147210946SSangeeta.Misra@Sun.COM 			    strlen(ILBD_PG_NAME_HC)) == 0) {
147310946SSangeeta.Misra@Sun.COM 				data.hc_data = calloc(1,
147410946SSangeeta.Misra@Sun.COM 				    sizeof (ilb_hc_info_t));
1475*12857SSangeeta.Misra@Sun.COM 				if (data.hc_data == NULL) {
1476*12857SSangeeta.Misra@Sun.COM 					ret = ILB_STATUS_ENOMEM;
1477*12857SSangeeta.Misra@Sun.COM 					goto out;
1478*12857SSangeeta.Misra@Sun.COM 				}
147910946SSangeeta.Misra@Sun.COM 				ret = ilbd_scf_pg_walk_props(newpg,
148010946SSangeeta.Misra@Sun.COM 				    ilbd_scf_load_prop, &data);
148110946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK)
148210946SSangeeta.Misra@Sun.COM 					goto out;
148310946SSangeeta.Misra@Sun.COM 				assert(data.hc_data != NULL);
148410946SSangeeta.Misra@Sun.COM 				/* set hc name */
148510946SSangeeta.Misra@Sun.COM 				(void) strlcpy(data.hc_data->hci_name,
148610946SSangeeta.Misra@Sun.COM 				    &pg_name[strlen(ILBD_PG_NAME_HC)],
148710946SSangeeta.Misra@Sun.COM 				    sizeof (data.hc_data->hci_name));
148810946SSangeeta.Misra@Sun.COM 				ret = cb(data.hc_data, port, arg2, NULL);
148910946SSangeeta.Misra@Sun.COM 				free(data.hc_data);
149010946SSangeeta.Misra@Sun.COM 				if (ret != ILB_STATUS_OK)
149110946SSangeeta.Misra@Sun.COM 					goto out;
149210946SSangeeta.Misra@Sun.COM 			}
149310946SSangeeta.Misra@Sun.COM 			break;
149410946SSangeeta.Misra@Sun.COM 		}
149510946SSangeeta.Misra@Sun.COM 	}
149610946SSangeeta.Misra@Sun.COM 
149710946SSangeeta.Misra@Sun.COM out:
1498*12857SSangeeta.Misra@Sun.COM 	if (pg_name != NULL)
1499*12857SSangeeta.Misra@Sun.COM 		free(pg_name);
150010946SSangeeta.Misra@Sun.COM 	if (scf_ret < 0)
150110946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
150210946SSangeeta.Misra@Sun.COM 	scf_pg_destroy(newpg);
150310946SSangeeta.Misra@Sun.COM 	scf_iter_destroy(pgiter);
150410946SSangeeta.Misra@Sun.COM 	return (ret);
150510946SSangeeta.Misra@Sun.COM }
150610946SSangeeta.Misra@Sun.COM 
150710946SSangeeta.Misra@Sun.COM typedef ilb_status_t (*ilbd_scf_walker_fn)(void *, int, struct passwd *,
150810946SSangeeta.Misra@Sun.COM     ucred_t *);
150910946SSangeeta.Misra@Sun.COM 
151010946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_walk_rule_pgs(ilb_status_t (* func)(ilb_rule_info_t *,int,const struct passwd *,ucred_t *),void * arg1,void * arg2)151110946SSangeeta.Misra@Sun.COM ilbd_walk_rule_pgs(ilb_status_t (*func)(ilb_rule_info_t *, int,
151210946SSangeeta.Misra@Sun.COM     const struct passwd *, ucred_t *), void *arg1, void *arg2)
151310946SSangeeta.Misra@Sun.COM {
151410946SSangeeta.Misra@Sun.COM 	scf_instance_t *inst;
151510946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
151610946SSangeeta.Misra@Sun.COM 	scf_service_t *svc;
151710946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
151810946SSangeeta.Misra@Sun.COM 
151910946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
152010946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_OK)
152110946SSangeeta.Misra@Sun.COM 		return (ret);
152210946SSangeeta.Misra@Sun.COM 
152310946SSangeeta.Misra@Sun.COM 	/* get rule prop group, transfer it to ilb_lrule_info_t */
152410946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_RULE,
152510946SSangeeta.Misra@Sun.COM 	    (ilbd_scf_walker_fn)func, arg1, arg2);
152610946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, svc, inst, NULL);
152710946SSangeeta.Misra@Sun.COM 	return (ret);
152810946SSangeeta.Misra@Sun.COM }
152910946SSangeeta.Misra@Sun.COM 
153010946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_walk_sg_pgs(ilb_status_t (* func)(ilb_sg_info_t *,int,const struct passwd *,ucred_t *),void * arg1,void * arg2)153110946SSangeeta.Misra@Sun.COM ilbd_walk_sg_pgs(ilb_status_t (*func)(ilb_sg_info_t *, int,
153210946SSangeeta.Misra@Sun.COM     const struct passwd *, ucred_t *), void *arg1, void *arg2)
153310946SSangeeta.Misra@Sun.COM {
153410946SSangeeta.Misra@Sun.COM 	scf_instance_t *inst;
153510946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
153610946SSangeeta.Misra@Sun.COM 	scf_service_t *svc;
153710946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
153810946SSangeeta.Misra@Sun.COM 
153910946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
154010946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_OK)
154110946SSangeeta.Misra@Sun.COM 		return (ret);
154210946SSangeeta.Misra@Sun.COM 
154310946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_SG,
154410946SSangeeta.Misra@Sun.COM 	    (ilbd_scf_walker_fn)func, arg1, arg2);
154510946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, svc, inst, NULL);
154610946SSangeeta.Misra@Sun.COM 	return (ret);
154710946SSangeeta.Misra@Sun.COM }
154810946SSangeeta.Misra@Sun.COM 
154910946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_walk_hc_pgs(ilb_status_t (* func)(const ilb_hc_info_t *,int,const struct passwd *,ucred_t *),void * arg1,void * arg2)155010946SSangeeta.Misra@Sun.COM ilbd_walk_hc_pgs(ilb_status_t (*func)(const ilb_hc_info_t *, int,
155110946SSangeeta.Misra@Sun.COM     const struct passwd *, ucred_t *), void *arg1, void *arg2)
155210946SSangeeta.Misra@Sun.COM {
155310946SSangeeta.Misra@Sun.COM 	scf_instance_t *inst;
155410946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
155510946SSangeeta.Misra@Sun.COM 	scf_service_t *svc;
155610946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
155710946SSangeeta.Misra@Sun.COM 
155810946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_get_inst(&h, &svc, &inst);
155910946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_OK)
156010946SSangeeta.Misra@Sun.COM 		return (ret);
156110946SSangeeta.Misra@Sun.COM 
156210946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_instance_walk_pg(inst, ILBD_SCF_HC,
156310946SSangeeta.Misra@Sun.COM 	    (ilbd_scf_walker_fn)func, arg1, arg2);
156410946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, svc, inst, NULL);
156510946SSangeeta.Misra@Sun.COM 	return (ret);
156610946SSangeeta.Misra@Sun.COM }
156710946SSangeeta.Misra@Sun.COM 
156810946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_change_prop(ilbd_scf_pg_type_t pg_type,const char * pg_name,const char * prop_name,void * new_val)156910946SSangeeta.Misra@Sun.COM ilbd_change_prop(ilbd_scf_pg_type_t pg_type, const char *pg_name,
157010946SSangeeta.Misra@Sun.COM     const char *prop_name, void *new_val)
157110946SSangeeta.Misra@Sun.COM {
157210946SSangeeta.Misra@Sun.COM 	int ret;
157310946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t *scfpg = NULL;
1574*12857SSangeeta.Misra@Sun.COM 	char *scf_pgname = NULL;
157510946SSangeeta.Misra@Sun.COM 	scf_type_t scftype;
157610946SSangeeta.Misra@Sun.COM 	scf_value_t *scfval;
157710946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
157810946SSangeeta.Misra@Sun.COM 
1579*12857SSangeeta.Misra@Sun.COM 	if ((scf_pgname = malloc(ILBD_MAX_NAME_LEN)) == NULL)
1580*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
158110946SSangeeta.Misra@Sun.COM 	ilbd_name_to_scfpgname(pg_type, pg_name, scf_pgname);
158210946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_retrieve_pg(scf_pgname, &scfpg, B_FALSE);
1583*12857SSangeeta.Misra@Sun.COM 	free(scf_pgname);
1584*12857SSangeeta.Misra@Sun.COM 
158510946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_EEXIST)
158610946SSangeeta.Misra@Sun.COM 		return (ret);
158710946SSangeeta.Misra@Sun.COM 
158810946SSangeeta.Misra@Sun.COM 	assert(scfpg != NULL);
158910946SSangeeta.Misra@Sun.COM 
159010946SSangeeta.Misra@Sun.COM 	h = scf_pg_handle(scfpg);
159110946SSangeeta.Misra@Sun.COM 	if (h == NULL) {
159210946SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_EINVAL;
159310946SSangeeta.Misra@Sun.COM 		goto done;
159410946SSangeeta.Misra@Sun.COM 	}
159510946SSangeeta.Misra@Sun.COM 
159610946SSangeeta.Misra@Sun.COM 	if ((scfval = scf_value_create(h)) == NULL) {
159710946SSangeeta.Misra@Sun.COM 		ret = ILB_STATUS_ENOMEM;
159810946SSangeeta.Misra@Sun.COM 		goto done;
159910946SSangeeta.Misra@Sun.COM 	}
160010946SSangeeta.Misra@Sun.COM 
160110946SSangeeta.Misra@Sun.COM 	if (pg_type == ILBD_SCF_RULE) {
160210946SSangeeta.Misra@Sun.COM 		scftype = SCF_TYPE_BOOLEAN;
160310946SSangeeta.Misra@Sun.COM 		scf_value_set_boolean(scfval, *(boolean_t *)new_val);
160410946SSangeeta.Misra@Sun.COM 	} else if (pg_type == ILBD_SCF_SG) {
160510946SSangeeta.Misra@Sun.COM 		scftype = SCF_TYPE_ASTRING;
160610946SSangeeta.Misra@Sun.COM 		(void) scf_value_set_astring(scfval, (char *)new_val);
160710946SSangeeta.Misra@Sun.COM 	}
160810946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_set_prop(scfpg, prop_name, scftype, scfval);
160910946SSangeeta.Misra@Sun.COM 
161010946SSangeeta.Misra@Sun.COM done:
161110946SSangeeta.Misra@Sun.COM 	if (scf_pg_handle(scfpg) != NULL)
161210946SSangeeta.Misra@Sun.COM 		scf_handle_destroy(scf_pg_handle(scfpg));
161310946SSangeeta.Misra@Sun.COM 	if (scfpg != NULL)
161410946SSangeeta.Misra@Sun.COM 		scf_pg_destroy(scfpg);
161510946SSangeeta.Misra@Sun.COM 	if (scfval != NULL)
161610946SSangeeta.Misra@Sun.COM 		scf_value_destroy(scfval);
161710946SSangeeta.Misra@Sun.COM 	return (ret);
161810946SSangeeta.Misra@Sun.COM }
161910946SSangeeta.Misra@Sun.COM 
162010946SSangeeta.Misra@Sun.COM /*
162110946SSangeeta.Misra@Sun.COM  * Update the persistent configuration with a new server, srv, added to a
162210946SSangeeta.Misra@Sun.COM  * server group, sg.
162310946SSangeeta.Misra@Sun.COM  */
162410946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_scf_add_srv(ilbd_sg_t * sg,ilbd_srv_t * srv)162510946SSangeeta.Misra@Sun.COM ilbd_scf_add_srv(ilbd_sg_t *sg, ilbd_srv_t *srv)
162610946SSangeeta.Misra@Sun.COM {
162710946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t *pg;
162810946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
162910946SSangeeta.Misra@Sun.COM 	scf_value_t *val;
163010946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
163110946SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
1632*12857SSangeeta.Misra@Sun.COM 	char *buf = NULL;
1633*12857SSangeeta.Misra@Sun.COM 
1634*12857SSangeeta.Misra@Sun.COM 	if ((buf = malloc(scf_name_len)) == NULL)
1635*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
163610946SSangeeta.Misra@Sun.COM 
163710946SSangeeta.Misra@Sun.COM 	ilbd_name_to_scfpgname(ILBD_SCF_SG, sg->isg_name, buf);
163810946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_retrieve_pg(buf, &pg, B_FALSE);
163910946SSangeeta.Misra@Sun.COM 	/*
164010946SSangeeta.Misra@Sun.COM 	 * The server group does not exist in persistent storage.  This
164110946SSangeeta.Misra@Sun.COM 	 * cannot happen.  Should probably transition the service to
164210946SSangeeta.Misra@Sun.COM 	 * maintenance since it should be there.
164310946SSangeeta.Misra@Sun.COM 	 */
164410946SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_EEXIST) {
164510946SSangeeta.Misra@Sun.COM 		logerr("ilbd_scf_add_srv: SCF update failed - entering"
164610946SSangeeta.Misra@Sun.COM 		    " maintenance mode");
164710946SSangeeta.Misra@Sun.COM 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
1648*12857SSangeeta.Misra@Sun.COM 		free(buf);
164910946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
165010946SSangeeta.Misra@Sun.COM 	}
165110946SSangeeta.Misra@Sun.COM 
165210946SSangeeta.Misra@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
165310946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(NULL, NULL, NULL, pg);
1654*12857SSangeeta.Misra@Sun.COM 		free(buf);
165510946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
165610946SSangeeta.Misra@Sun.COM 	}
165710946SSangeeta.Misra@Sun.COM 
165810946SSangeeta.Misra@Sun.COM 	if ((val = scf_value_create(h)) == NULL) {
165910946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(h, NULL, NULL, pg);
1660*12857SSangeeta.Misra@Sun.COM 		free(buf);
166110946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
166210946SSangeeta.Misra@Sun.COM 	}
166310946SSangeeta.Misra@Sun.COM 	ilbd_srv_scf_val(srv, buf);
166410946SSangeeta.Misra@Sun.COM 	(void) scf_value_set_astring(val, buf);
166510946SSangeeta.Misra@Sun.COM 
1666*12857SSangeeta.Misra@Sun.COM 	(void) snprintf(buf, scf_name_len, "server%d", srv->isv_id);
1667*12857SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_set_prop(pg, buf, SCF_TYPE_ASTRING, val);
1668*12857SSangeeta.Misra@Sun.COM 	free(buf);
166910946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, NULL, NULL, pg);
167010946SSangeeta.Misra@Sun.COM 	scf_value_destroy(val);
167110946SSangeeta.Misra@Sun.COM 
167210946SSangeeta.Misra@Sun.COM 	return (ret);
167310946SSangeeta.Misra@Sun.COM }
167410946SSangeeta.Misra@Sun.COM 
167510946SSangeeta.Misra@Sun.COM /*
167610946SSangeeta.Misra@Sun.COM  * Delete a server, srv, of a server group, sg, from the persistent
167710946SSangeeta.Misra@Sun.COM  * configuration.
167810946SSangeeta.Misra@Sun.COM  */
167910946SSangeeta.Misra@Sun.COM ilb_status_t
ilbd_scf_del_srv(ilbd_sg_t * sg,ilbd_srv_t * srv)168010946SSangeeta.Misra@Sun.COM ilbd_scf_del_srv(ilbd_sg_t *sg, ilbd_srv_t *srv)
168110946SSangeeta.Misra@Sun.COM {
168210946SSangeeta.Misra@Sun.COM 	ilb_status_t ret;
168310946SSangeeta.Misra@Sun.COM 	scf_propertygroup_t *pg;
168410946SSangeeta.Misra@Sun.COM 	scf_handle_t *h;
168510946SSangeeta.Misra@Sun.COM 	int scf_name_len = ILBD_MAX_NAME_LEN;
1686*12857SSangeeta.Misra@Sun.COM 	char *buf;
168710946SSangeeta.Misra@Sun.COM 	scf_transaction_t *tx = NULL;
168810946SSangeeta.Misra@Sun.COM 	scf_transaction_entry_t *entry = NULL;
168910946SSangeeta.Misra@Sun.COM 
1690*12857SSangeeta.Misra@Sun.COM 	if ((buf = malloc(scf_name_len)) == NULL)
1691*12857SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_ENOMEM);
169210946SSangeeta.Misra@Sun.COM 	ilbd_name_to_scfpgname(ILBD_SCF_SG, sg->isg_name, buf);
169310946SSangeeta.Misra@Sun.COM 	ret = ilbd_scf_retrieve_pg(buf, &pg, B_FALSE);
169410946SSangeeta.Misra@Sun.COM 	/*
169510946SSangeeta.Misra@Sun.COM 	 * The server group does not exist in persistent storage.  This
169610946SSangeeta.Misra@Sun.COM 	 * cannot happen. THe caller of this function puts service in
169710946SSangeeta.Misra@Sun.COM 	 * maintenance mode.
169810946SSangeeta.Misra@Sun.COM 	 */
1699*12857SSangeeta.Misra@Sun.COM 	if (ret != ILB_STATUS_EEXIST) {
1700*12857SSangeeta.Misra@Sun.COM 		free(buf);
170110946SSangeeta.Misra@Sun.COM 		return (ILB_STATUS_INTERNAL);
1702*12857SSangeeta.Misra@Sun.COM 	}
170310946SSangeeta.Misra@Sun.COM 	ret = ILB_STATUS_OK;
170410946SSangeeta.Misra@Sun.COM 
170510946SSangeeta.Misra@Sun.COM 	if ((h = scf_pg_handle(pg)) == NULL) {
170610946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_del_srv: scf_pg_handle: %s\n",
170710946SSangeeta.Misra@Sun.COM 		    scf_strerror(scf_error()));
170810946SSangeeta.Misra@Sun.COM 		ilbd_scf_destroy(NULL, NULL, NULL, pg);
1709*12857SSangeeta.Misra@Sun.COM 		free(buf);
171010946SSangeeta.Misra@Sun.COM 		return (ilbd_scf_err_to_ilb_err());
171110946SSangeeta.Misra@Sun.COM 	}
171210946SSangeeta.Misra@Sun.COM 
171310946SSangeeta.Misra@Sun.COM 	if ((tx = scf_transaction_create(h)) == NULL ||
171410946SSangeeta.Misra@Sun.COM 	    (entry = scf_entry_create(h)) == NULL) {
171510946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_del_srv: create scf transaction failed: "
171610946SSangeeta.Misra@Sun.COM 		    "%s\n", scf_strerror(scf_error()));
171710946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
171810946SSangeeta.Misra@Sun.COM 		goto out;
171910946SSangeeta.Misra@Sun.COM 	}
172010946SSangeeta.Misra@Sun.COM 
1721*12857SSangeeta.Misra@Sun.COM 	(void) snprintf(buf, scf_name_len, "server%d", srv->isv_id);
172210946SSangeeta.Misra@Sun.COM 
172310946SSangeeta.Misra@Sun.COM 	if (scf_transaction_start(tx, pg) == -1) {
172410946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: start scf transaction failed: "
172510946SSangeeta.Misra@Sun.COM 		    "%s\n", scf_strerror(scf_error()));
172610946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
172710946SSangeeta.Misra@Sun.COM 		goto out;
172810946SSangeeta.Misra@Sun.COM 	}
172910946SSangeeta.Misra@Sun.COM 	if (scf_transaction_property_delete(tx, entry, buf) == -1) {
173010946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: delete property failed: %s\n",
173110946SSangeeta.Misra@Sun.COM 		    scf_strerror(scf_error()));
173210946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
173310946SSangeeta.Misra@Sun.COM 		goto out;
173410946SSangeeta.Misra@Sun.COM 	}
173510946SSangeeta.Misra@Sun.COM 	if (scf_transaction_commit(tx) != 1) {
173610946SSangeeta.Misra@Sun.COM 		logdebug("ilbd_scf_set_prop: commit transaction failed: %s\n",
173710946SSangeeta.Misra@Sun.COM 		    scf_strerror(scf_error()));
173810946SSangeeta.Misra@Sun.COM 		ret = ilbd_scf_err_to_ilb_err();
173910946SSangeeta.Misra@Sun.COM 	}
174010946SSangeeta.Misra@Sun.COM 
174110946SSangeeta.Misra@Sun.COM out:
1742*12857SSangeeta.Misra@Sun.COM 	free(buf);
174310946SSangeeta.Misra@Sun.COM 	if (entry != NULL)
174410946SSangeeta.Misra@Sun.COM 		scf_entry_destroy(entry);
174510946SSangeeta.Misra@Sun.COM 	if (tx != NULL)
174610946SSangeeta.Misra@Sun.COM 		scf_transaction_destroy(tx);
174710946SSangeeta.Misra@Sun.COM 	ilbd_scf_destroy(h, NULL, NULL, pg);
174810946SSangeeta.Misra@Sun.COM 
174910946SSangeeta.Misra@Sun.COM 	return (ret);
175010946SSangeeta.Misra@Sun.COM }
1751