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