1*dbed73cbSSangeeta Misra /*
2*dbed73cbSSangeeta Misra  * CDDL HEADER START
3*dbed73cbSSangeeta Misra  *
4*dbed73cbSSangeeta Misra  * The contents of this file are subject to the terms of the
5*dbed73cbSSangeeta Misra  * Common Development and Distribution License (the "License").
6*dbed73cbSSangeeta Misra  * You may not use this file except in compliance with the License.
7*dbed73cbSSangeeta Misra  *
8*dbed73cbSSangeeta Misra  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*dbed73cbSSangeeta Misra  * or http://www.opensolaris.org/os/licensing.
10*dbed73cbSSangeeta Misra  * See the License for the specific language governing permissions
11*dbed73cbSSangeeta Misra  * and limitations under the License.
12*dbed73cbSSangeeta Misra  *
13*dbed73cbSSangeeta Misra  * When distributing Covered Code, include this CDDL HEADER in each
14*dbed73cbSSangeeta Misra  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*dbed73cbSSangeeta Misra  * If applicable, add the following below this CDDL HEADER, with the
16*dbed73cbSSangeeta Misra  * fields enclosed by brackets "[]" replaced with your own identifying
17*dbed73cbSSangeeta Misra  * information: Portions Copyright [yyyy] [name of copyright owner]
18*dbed73cbSSangeeta Misra  *
19*dbed73cbSSangeeta Misra  * CDDL HEADER END
20*dbed73cbSSangeeta Misra  */
21*dbed73cbSSangeeta Misra 
22*dbed73cbSSangeeta Misra /*
23*dbed73cbSSangeeta Misra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*dbed73cbSSangeeta Misra  * Use is subject to license terms.
25*dbed73cbSSangeeta Misra  */
26*dbed73cbSSangeeta Misra 
27*dbed73cbSSangeeta Misra #include <stdlib.h>
28*dbed73cbSSangeeta Misra #include <strings.h>
29*dbed73cbSSangeeta Misra #include <stddef.h>
30*dbed73cbSSangeeta Misra #include <sys/types.h>
31*dbed73cbSSangeeta Misra #include <sys/socket.h>
32*dbed73cbSSangeeta Misra #include <sys/list.h>
33*dbed73cbSSangeeta Misra #include <assert.h>
34*dbed73cbSSangeeta Misra #include <errno.h>
35*dbed73cbSSangeeta Misra #include <libilb.h>
36*dbed73cbSSangeeta Misra #include <net/if.h>
37*dbed73cbSSangeeta Misra #include <inet/ilb.h>
38*dbed73cbSSangeeta Misra #include <netinet/in.h>
39*dbed73cbSSangeeta Misra #include <arpa/inet.h>
40*dbed73cbSSangeeta Misra #include "libilb_impl.h"
41*dbed73cbSSangeeta Misra #include "ilbd.h"
42*dbed73cbSSangeeta Misra 
43*dbed73cbSSangeeta Misra typedef enum {
44*dbed73cbSSangeeta Misra 	not_searched,
45*dbed73cbSSangeeta Misra 	stop_found,
46*dbed73cbSSangeeta Misra 	cont_search,
47*dbed73cbSSangeeta Misra 	fail_search
48*dbed73cbSSangeeta Misra } srch_ind_t;
49*dbed73cbSSangeeta Misra 
50*dbed73cbSSangeeta Misra static list_t	ilbd_sg_hlist;
51*dbed73cbSSangeeta Misra 
52*dbed73cbSSangeeta Misra static ilb_status_t i_delete_srv(ilbd_sg_t *, ilbd_srv_t *, int);
53*dbed73cbSSangeeta Misra static void i_ilbd_free_srvID(ilbd_sg_t *, int32_t);
54*dbed73cbSSangeeta Misra 
55*dbed73cbSSangeeta Misra /* Last parameter to pass to i_find_srv(), specifying the matching mode */
56*dbed73cbSSangeeta Misra #define	MODE_ADDR	1
57*dbed73cbSSangeeta Misra #define	MODE_SRVID	2
58*dbed73cbSSangeeta Misra 
59*dbed73cbSSangeeta Misra static ilbd_srv_t *i_find_srv(list_t *, ilb_sg_srv_t *, int);
60*dbed73cbSSangeeta Misra 
61*dbed73cbSSangeeta Misra void
62*dbed73cbSSangeeta Misra i_setup_sg_hlist(void)
63*dbed73cbSSangeeta Misra {
64*dbed73cbSSangeeta Misra 	list_create(&ilbd_sg_hlist, sizeof (ilbd_sg_t),
65*dbed73cbSSangeeta Misra 	    offsetof(ilbd_sg_t, isg_link));
66*dbed73cbSSangeeta Misra }
67*dbed73cbSSangeeta Misra 
68*dbed73cbSSangeeta Misra /*
69*dbed73cbSSangeeta Misra  * allocate storage for a daemon-internal server group, init counters
70*dbed73cbSSangeeta Misra  */
71*dbed73cbSSangeeta Misra static ilbd_sg_t *
72*dbed73cbSSangeeta Misra i_ilbd_alloc_sg(char *name)
73*dbed73cbSSangeeta Misra {
74*dbed73cbSSangeeta Misra 	ilbd_sg_t	*d_sg;
75*dbed73cbSSangeeta Misra 
76*dbed73cbSSangeeta Misra 	d_sg = calloc(sizeof (*d_sg), 1);
77*dbed73cbSSangeeta Misra 	if (d_sg == NULL)
78*dbed73cbSSangeeta Misra 		goto out;
79*dbed73cbSSangeeta Misra 
80*dbed73cbSSangeeta Misra 	(void) strlcpy(d_sg->isg_name, name, sizeof (d_sg->isg_name));
81*dbed73cbSSangeeta Misra 
82*dbed73cbSSangeeta Misra 	list_create(&d_sg->isg_srvlist, sizeof (ilbd_srv_t),
83*dbed73cbSSangeeta Misra 	    offsetof(ilbd_srv_t, isv_srv_link));
84*dbed73cbSSangeeta Misra 	list_create(&d_sg->isg_rulelist, sizeof (ilbd_rule_t),
85*dbed73cbSSangeeta Misra 	    offsetof(ilbd_rule_t, irl_sglink));
86*dbed73cbSSangeeta Misra 
87*dbed73cbSSangeeta Misra 	list_insert_tail(&ilbd_sg_hlist, d_sg);
88*dbed73cbSSangeeta Misra out:
89*dbed73cbSSangeeta Misra 	return (d_sg);
90*dbed73cbSSangeeta Misra }
91*dbed73cbSSangeeta Misra 
92*dbed73cbSSangeeta Misra static ilb_status_t
93*dbed73cbSSangeeta Misra i_ilbd_save_sg(ilbd_sg_t *d_sg, ilbd_scf_cmd_t scf_cmd, const char *prop_name,
94*dbed73cbSSangeeta Misra     char *valstr)
95*dbed73cbSSangeeta Misra {
96*dbed73cbSSangeeta Misra 	switch (scf_cmd) {
97*dbed73cbSSangeeta Misra 	case ILBD_SCF_CREATE:
98*dbed73cbSSangeeta Misra 		return (ilbd_create_pg(ILBD_SCF_SG, (void *)d_sg));
99*dbed73cbSSangeeta Misra 	case ILBD_SCF_DESTROY:
100*dbed73cbSSangeeta Misra 		return (ilbd_destroy_pg(ILBD_SCF_SG, d_sg->isg_name));
101*dbed73cbSSangeeta Misra 	case ILBD_SCF_ENABLE_DISABLE:
102*dbed73cbSSangeeta Misra 		if (prop_name == NULL)
103*dbed73cbSSangeeta Misra 			return (ILB_STATUS_EINVAL);
104*dbed73cbSSangeeta Misra 		return (ilbd_change_prop(ILBD_SCF_SG, d_sg->isg_name,
105*dbed73cbSSangeeta Misra 		    prop_name, valstr));
106*dbed73cbSSangeeta Misra 	default:
107*dbed73cbSSangeeta Misra 		logdebug("i_ilbd_save_sg: invalid scf cmd %d", scf_cmd);
108*dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
109*dbed73cbSSangeeta Misra 	}
110*dbed73cbSSangeeta Misra }
111*dbed73cbSSangeeta Misra 
112*dbed73cbSSangeeta Misra ilb_status_t
113*dbed73cbSSangeeta Misra i_attach_rule2sg(ilbd_sg_t *sg, ilbd_rule_t *irl)
114*dbed73cbSSangeeta Misra {
115*dbed73cbSSangeeta Misra 	/* assert: the same rule is attached to any sg only once */
116*dbed73cbSSangeeta Misra 	list_insert_tail(&sg->isg_rulelist, irl);
117*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
118*dbed73cbSSangeeta Misra }
119*dbed73cbSSangeeta Misra 
120*dbed73cbSSangeeta Misra static void
121*dbed73cbSSangeeta Misra i_ilbd_free_sg(ilbd_sg_t *sg)
122*dbed73cbSSangeeta Misra {
123*dbed73cbSSangeeta Misra 	ilbd_srv_t *tmp_srv;
124*dbed73cbSSangeeta Misra 
125*dbed73cbSSangeeta Misra 	if (sg == NULL)
126*dbed73cbSSangeeta Misra 		return;
127*dbed73cbSSangeeta Misra 	list_remove(&ilbd_sg_hlist, sg);
128*dbed73cbSSangeeta Misra 	while ((tmp_srv = list_remove_tail(&sg->isg_srvlist)) != NULL) {
129*dbed73cbSSangeeta Misra 		i_ilbd_free_srvID(sg, tmp_srv->isv_id);
130*dbed73cbSSangeeta Misra 		free(tmp_srv);
131*dbed73cbSSangeeta Misra 		sg->isg_srvcount--;
132*dbed73cbSSangeeta Misra 	}
133*dbed73cbSSangeeta Misra 	free(sg);
134*dbed73cbSSangeeta Misra }
135*dbed73cbSSangeeta Misra 
136*dbed73cbSSangeeta Misra ilbd_sg_t *
137*dbed73cbSSangeeta Misra i_find_sg_byname(const char *name)
138*dbed73cbSSangeeta Misra {
139*dbed73cbSSangeeta Misra 	ilbd_sg_t *sg;
140*dbed73cbSSangeeta Misra 
141*dbed73cbSSangeeta Misra 	/* find position of sg in list */
142*dbed73cbSSangeeta Misra 	for (sg = list_head(&ilbd_sg_hlist); sg != NULL;
143*dbed73cbSSangeeta Misra 	    sg = list_next(&ilbd_sg_hlist, sg)) {
144*dbed73cbSSangeeta Misra 		if (strncmp(sg->isg_name, name, sizeof (sg->isg_name)) == 0)
145*dbed73cbSSangeeta Misra 			return (sg);
146*dbed73cbSSangeeta Misra 	}
147*dbed73cbSSangeeta Misra 	return (sg);
148*dbed73cbSSangeeta Misra }
149*dbed73cbSSangeeta Misra 
150*dbed73cbSSangeeta Misra /*
151*dbed73cbSSangeeta Misra  * Generates an audit record for enable-server, disable-server, remove-server
152*dbed73cbSSangeeta Misra  * delete-servergroup, create-servergroup and add-server subcommands.
153*dbed73cbSSangeeta Misra  */
154*dbed73cbSSangeeta Misra static void
155*dbed73cbSSangeeta Misra ilbd_audit_server_event(audit_sg_event_data_t *data,
156*dbed73cbSSangeeta Misra     ilbd_cmd_t cmd, ilb_status_t rc, ucred_t *ucredp)
157*dbed73cbSSangeeta Misra {
158*dbed73cbSSangeeta Misra 	adt_session_data_t	*ah;
159*dbed73cbSSangeeta Misra 	adt_event_data_t	*event;
160*dbed73cbSSangeeta Misra 	au_event_t	flag;
161*dbed73cbSSangeeta Misra 	int	audit_error;
162*dbed73cbSSangeeta Misra 
163*dbed73cbSSangeeta Misra 	if ((ucredp == NULL) && ((cmd == ILBD_ADD_SERVER_TO_GROUP) ||
164*dbed73cbSSangeeta Misra 	    (cmd == ILBD_CREATE_SERVERGROUP)))  {
165*dbed73cbSSangeeta Misra 		/*
166*dbed73cbSSangeeta Misra 		 * We came here from the path where ilbd is
167*dbed73cbSSangeeta Misra 		 * incorporating the ILB configuration from
168*dbed73cbSSangeeta Misra 		 * SCF. In that case, we skip auditing
169*dbed73cbSSangeeta Misra 		 */
170*dbed73cbSSangeeta Misra 		return;
171*dbed73cbSSangeeta Misra 	}
172*dbed73cbSSangeeta Misra 
173*dbed73cbSSangeeta Misra 	if (adt_start_session(&ah, NULL, 0) != 0) {
174*dbed73cbSSangeeta Misra 		logerr("ilbd_audit_server_event: adt_start_session failed");
175*dbed73cbSSangeeta Misra 		exit(EXIT_FAILURE);
176*dbed73cbSSangeeta Misra 	}
177*dbed73cbSSangeeta Misra 
178*dbed73cbSSangeeta Misra 	if (adt_set_from_ucred(ah, ucredp, ADT_NEW) != 0) {
179*dbed73cbSSangeeta Misra 		(void) adt_end_session(ah);
180*dbed73cbSSangeeta Misra 		logerr("ilbd_audit_server_event: adt_set_from_ucred failed");
181*dbed73cbSSangeeta Misra 		exit(EXIT_FAILURE);
182*dbed73cbSSangeeta Misra 	}
183*dbed73cbSSangeeta Misra 
184*dbed73cbSSangeeta Misra 	if (cmd == ILBD_ENABLE_SERVER)
185*dbed73cbSSangeeta Misra 		flag = ADT_ilb_enable_server;
186*dbed73cbSSangeeta Misra 	else if (cmd == ILBD_DISABLE_SERVER)
187*dbed73cbSSangeeta Misra 		flag = ADT_ilb_disable_server;
188*dbed73cbSSangeeta Misra 	else if (cmd == ILBD_REM_SERVER_FROM_GROUP)
189*dbed73cbSSangeeta Misra 		flag = ADT_ilb_remove_server;
190*dbed73cbSSangeeta Misra 	else if (cmd == ILBD_ADD_SERVER_TO_GROUP)
191*dbed73cbSSangeeta Misra 		flag = ADT_ilb_add_server;
192*dbed73cbSSangeeta Misra 	else if (cmd == ILBD_CREATE_SERVERGROUP)
193*dbed73cbSSangeeta Misra 		flag = ADT_ilb_create_servergroup;
194*dbed73cbSSangeeta Misra 	else if (cmd == ILBD_DESTROY_SERVERGROUP)
195*dbed73cbSSangeeta Misra 		flag = ADT_ilb_delete_servergroup;
196*dbed73cbSSangeeta Misra 
197*dbed73cbSSangeeta Misra 	if ((event = adt_alloc_event(ah, flag)) == NULL) {
198*dbed73cbSSangeeta Misra 		logerr("ilbd_audit_server_event: adt_alloc_event failed");
199*dbed73cbSSangeeta Misra 		exit(EXIT_FAILURE);
200*dbed73cbSSangeeta Misra 	}
201*dbed73cbSSangeeta Misra 	(void) memset((char *)event, 0, sizeof (adt_event_data_t));
202*dbed73cbSSangeeta Misra 
203*dbed73cbSSangeeta Misra 	switch (cmd) {
204*dbed73cbSSangeeta Misra 	case ILBD_ENABLE_SERVER:
205*dbed73cbSSangeeta Misra 		event->adt_ilb_enable_server.auth_used =
206*dbed73cbSSangeeta Misra 		    NET_ILB_ENABLE_AUTH;
207*dbed73cbSSangeeta Misra 		event->adt_ilb_enable_server.server_id =
208*dbed73cbSSangeeta Misra 		    data->ed_serverid;
209*dbed73cbSSangeeta Misra 		event->adt_ilb_enable_server.server_ipaddress =
210*dbed73cbSSangeeta Misra 		    data->ed_server_address;
211*dbed73cbSSangeeta Misra 		break;
212*dbed73cbSSangeeta Misra 	case ILBD_DISABLE_SERVER:
213*dbed73cbSSangeeta Misra 		event->adt_ilb_disable_server.auth_used =
214*dbed73cbSSangeeta Misra 		    NET_ILB_ENABLE_AUTH;
215*dbed73cbSSangeeta Misra 		event->adt_ilb_disable_server.server_id =
216*dbed73cbSSangeeta Misra 		    data->ed_serverid;
217*dbed73cbSSangeeta Misra 		event->adt_ilb_disable_server.server_ipaddress =
218*dbed73cbSSangeeta Misra 		    data->ed_server_address;
219*dbed73cbSSangeeta Misra 		break;
220*dbed73cbSSangeeta Misra 	case ILBD_REM_SERVER_FROM_GROUP:
221*dbed73cbSSangeeta Misra 		event->adt_ilb_remove_server.auth_used =
222*dbed73cbSSangeeta Misra 		    NET_ILB_CONFIG_AUTH;
223*dbed73cbSSangeeta Misra 		event->adt_ilb_remove_server.server_id =
224*dbed73cbSSangeeta Misra 		    data->ed_serverid;
225*dbed73cbSSangeeta Misra 		event->adt_ilb_remove_server.server_group = data->ed_sgroup;
226*dbed73cbSSangeeta Misra 		event->adt_ilb_remove_server.server_ipaddress =
227*dbed73cbSSangeeta Misra 		    data->ed_server_address;
228*dbed73cbSSangeeta Misra 		break;
229*dbed73cbSSangeeta Misra 	case ILBD_CREATE_SERVERGROUP:
230*dbed73cbSSangeeta Misra 		event->adt_ilb_create_servergroup.auth_used =
231*dbed73cbSSangeeta Misra 		    NET_ILB_CONFIG_AUTH;
232*dbed73cbSSangeeta Misra 		event->adt_ilb_create_servergroup.server_group =
233*dbed73cbSSangeeta Misra 		    data->ed_sgroup;
234*dbed73cbSSangeeta Misra 		break;
235*dbed73cbSSangeeta Misra 	case ILBD_ADD_SERVER_TO_GROUP:
236*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.auth_used =
237*dbed73cbSSangeeta Misra 		    NET_ILB_CONFIG_AUTH;
238*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.server_ipaddress =
239*dbed73cbSSangeeta Misra 		    data->ed_server_address;
240*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.server_id =
241*dbed73cbSSangeeta Misra 		    data->ed_serverid;
242*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.server_group =
243*dbed73cbSSangeeta Misra 		    data->ed_sgroup;
244*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.server_minport =
245*dbed73cbSSangeeta Misra 		    ntohs(data->ed_minport);
246*dbed73cbSSangeeta Misra 		event->adt_ilb_add_server.server_maxport =
247*dbed73cbSSangeeta Misra 		    ntohs(data->ed_maxport);
248*dbed73cbSSangeeta Misra 		break;
249*dbed73cbSSangeeta Misra 	case ILBD_DESTROY_SERVERGROUP:
250*dbed73cbSSangeeta Misra 		event->adt_ilb_delete_servergroup.auth_used =
251*dbed73cbSSangeeta Misra 		    NET_ILB_CONFIG_AUTH;
252*dbed73cbSSangeeta Misra 		event->adt_ilb_delete_servergroup.server_group =
253*dbed73cbSSangeeta Misra 		    data->ed_sgroup;
254*dbed73cbSSangeeta Misra 		break;
255*dbed73cbSSangeeta Misra 	}
256*dbed73cbSSangeeta Misra 
257*dbed73cbSSangeeta Misra 	/* Fill in success/failure */
258*dbed73cbSSangeeta Misra 	if (rc == ILB_STATUS_OK) {
259*dbed73cbSSangeeta Misra 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
260*dbed73cbSSangeeta Misra 			logerr("ilbd_audit_server_event:"
261*dbed73cbSSangeeta Misra 			    " adt_put_event failed");
262*dbed73cbSSangeeta Misra 			exit(EXIT_FAILURE);
263*dbed73cbSSangeeta Misra 		}
264*dbed73cbSSangeeta Misra 	} else {
265*dbed73cbSSangeeta Misra 		audit_error = ilberror2auditerror(rc);
266*dbed73cbSSangeeta Misra 		if (adt_put_event(event, ADT_FAILURE, audit_error) != 0) {
267*dbed73cbSSangeeta Misra 			logerr("ilbd_audit_server_event:"
268*dbed73cbSSangeeta Misra 			    " adt_put_event failed");
269*dbed73cbSSangeeta Misra 			exit(EXIT_FAILURE);
270*dbed73cbSSangeeta Misra 		}
271*dbed73cbSSangeeta Misra 	}
272*dbed73cbSSangeeta Misra 	adt_free_event(event);
273*dbed73cbSSangeeta Misra 	(void) adt_end_session(ah);
274*dbed73cbSSangeeta Misra }
275*dbed73cbSSangeeta Misra 
276*dbed73cbSSangeeta Misra ilb_status_t
277*dbed73cbSSangeeta Misra ilbd_destroy_sg(const char *sg_name, const struct passwd *ps,
278*dbed73cbSSangeeta Misra     ucred_t *ucredp)
279*dbed73cbSSangeeta Misra {
280*dbed73cbSSangeeta Misra 	ilb_status_t	rc;
281*dbed73cbSSangeeta Misra 	ilbd_sg_t	*tmp_sg;
282*dbed73cbSSangeeta Misra 	audit_sg_event_data_t   audit_sg_data;
283*dbed73cbSSangeeta Misra 
284*dbed73cbSSangeeta Misra 	(void) memset(&audit_sg_data, 0, sizeof (audit_sg_event_data_t));
285*dbed73cbSSangeeta Misra 	audit_sg_data.ed_sgroup = (char *)sg_name;
286*dbed73cbSSangeeta Misra 
287*dbed73cbSSangeeta Misra 	rc = ilbd_check_client_config_auth(ps);
288*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK) {
289*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
290*dbed73cbSSangeeta Misra 		    ILBD_DESTROY_SERVERGROUP, rc, ucredp);
291*dbed73cbSSangeeta Misra 		return (rc);
292*dbed73cbSSangeeta Misra 	}
293*dbed73cbSSangeeta Misra 
294*dbed73cbSSangeeta Misra 	tmp_sg = i_find_sg_byname(sg_name);
295*dbed73cbSSangeeta Misra 	if (tmp_sg == NULL) {
296*dbed73cbSSangeeta Misra 		logdebug("ilbd_destroy_sg: cannot find specified server"
297*dbed73cbSSangeeta Misra 		    " group %s", sg_name);
298*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
299*dbed73cbSSangeeta Misra 		    ILBD_DESTROY_SERVERGROUP, ILB_STATUS_SGUNAVAIL, ucredp);
300*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGUNAVAIL);
301*dbed73cbSSangeeta Misra 	}
302*dbed73cbSSangeeta Misra 
303*dbed73cbSSangeeta Misra 	/*
304*dbed73cbSSangeeta Misra 	 * we only destroy SGs that don't have any rules associated with
305*dbed73cbSSangeeta Misra 	 * them anymore.
306*dbed73cbSSangeeta Misra 	 */
307*dbed73cbSSangeeta Misra 	if (list_head(&tmp_sg->isg_rulelist) != NULL) {
308*dbed73cbSSangeeta Misra 		logdebug("ilbd_destroy_sg: server group %s has rules"
309*dbed73cbSSangeeta Misra 		" associated with it and thus cannot be"
310*dbed73cbSSangeeta Misra 		    " removed", tmp_sg->isg_name);
311*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
312*dbed73cbSSangeeta Misra 		    ILBD_DESTROY_SERVERGROUP, ILB_STATUS_SGINUSE, ucredp);
313*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGINUSE);
314*dbed73cbSSangeeta Misra 	}
315*dbed73cbSSangeeta Misra 
316*dbed73cbSSangeeta Misra 	if (ps != NULL) {
317*dbed73cbSSangeeta Misra 		rc = i_ilbd_save_sg(tmp_sg, ILBD_SCF_DESTROY, NULL, NULL);
318*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
319*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
320*dbed73cbSSangeeta Misra 		    ILBD_DESTROY_SERVERGROUP, rc, ucredp);
321*dbed73cbSSangeeta Misra 			return (rc);
322*dbed73cbSSangeeta Misra 		}
323*dbed73cbSSangeeta Misra 	}
324*dbed73cbSSangeeta Misra 	i_ilbd_free_sg(tmp_sg);
325*dbed73cbSSangeeta Misra 	ilbd_audit_server_event(&audit_sg_data, ILBD_DESTROY_SERVERGROUP,
326*dbed73cbSSangeeta Misra 	    rc, ucredp);
327*dbed73cbSSangeeta Misra 	return (rc);
328*dbed73cbSSangeeta Misra }
329*dbed73cbSSangeeta Misra 
330*dbed73cbSSangeeta Misra /* ARGSUSED */
331*dbed73cbSSangeeta Misra /*
332*dbed73cbSSangeeta Misra  * Parameter ev_port is not used but has to have for read persistent configure
333*dbed73cbSSangeeta Misra  * ilbd_create_sg(), ilbd_create_hc() and ilbd_create_rule() are callbacks
334*dbed73cbSSangeeta Misra  * for ilbd_scf_instance_walk_pg() which requires the same signature.
335*dbed73cbSSangeeta Misra  */
336*dbed73cbSSangeeta Misra ilb_status_t
337*dbed73cbSSangeeta Misra ilbd_create_sg(ilb_sg_info_t *sg, int ev_port, const struct passwd *ps,
338*dbed73cbSSangeeta Misra     ucred_t *ucredp)
339*dbed73cbSSangeeta Misra {
340*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
341*dbed73cbSSangeeta Misra 	ilbd_sg_t	*d_sg;
342*dbed73cbSSangeeta Misra 	audit_sg_event_data_t   audit_sg_data;
343*dbed73cbSSangeeta Misra 
344*dbed73cbSSangeeta Misra 	(void) memset(&audit_sg_data, 0, sizeof (audit_sg_event_data_t));
345*dbed73cbSSangeeta Misra 	audit_sg_data.ed_sgroup = sg->sg_name;
346*dbed73cbSSangeeta Misra 
347*dbed73cbSSangeeta Misra 	if (ps != NULL) {
348*dbed73cbSSangeeta Misra 		rc = ilbd_check_client_config_auth(ps);
349*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
350*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
351*dbed73cbSSangeeta Misra 			    ILBD_CREATE_SERVERGROUP, rc, ucredp);
352*dbed73cbSSangeeta Misra 			return (rc);
353*dbed73cbSSangeeta Misra 		}
354*dbed73cbSSangeeta Misra 	}
355*dbed73cbSSangeeta Misra 
356*dbed73cbSSangeeta Misra 	if (i_find_sg_byname(sg->sg_name) != NULL) {
357*dbed73cbSSangeeta Misra 		logdebug("ilbd_create_sg: server group %s already exists",
358*dbed73cbSSangeeta Misra 		    sg->sg_name);
359*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
360*dbed73cbSSangeeta Misra 		    ILBD_CREATE_SERVERGROUP, ILB_STATUS_SGEXISTS, ucredp);
361*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGEXISTS);
362*dbed73cbSSangeeta Misra 	}
363*dbed73cbSSangeeta Misra 
364*dbed73cbSSangeeta Misra 	d_sg = i_ilbd_alloc_sg(sg->sg_name);
365*dbed73cbSSangeeta Misra 	if (d_sg == NULL) {
366*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
367*dbed73cbSSangeeta Misra 		    ILBD_CREATE_SERVERGROUP, ILB_STATUS_ENOMEM, ucredp);
368*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
369*dbed73cbSSangeeta Misra 	}
370*dbed73cbSSangeeta Misra 
371*dbed73cbSSangeeta Misra 	/*
372*dbed73cbSSangeeta Misra 	 * we've successfully created the sg in memory. Before we can
373*dbed73cbSSangeeta Misra 	 * return "success", we need to reflect this in persistent
374*dbed73cbSSangeeta Misra 	 * storage
375*dbed73cbSSangeeta Misra 	 */
376*dbed73cbSSangeeta Misra 	if (ps != NULL) {
377*dbed73cbSSangeeta Misra 		rc = i_ilbd_save_sg(d_sg, ILBD_SCF_CREATE, NULL, NULL);
378*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
379*dbed73cbSSangeeta Misra 			i_ilbd_free_sg(d_sg);
380*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
381*dbed73cbSSangeeta Misra 			    ILBD_CREATE_SERVERGROUP, rc, ucredp);
382*dbed73cbSSangeeta Misra 			return (rc);
383*dbed73cbSSangeeta Misra 		}
384*dbed73cbSSangeeta Misra 	}
385*dbed73cbSSangeeta Misra 	ilbd_audit_server_event(&audit_sg_data,
386*dbed73cbSSangeeta Misra 	    ILBD_CREATE_SERVERGROUP, rc, ucredp);
387*dbed73cbSSangeeta Misra 	return (rc);
388*dbed73cbSSangeeta Misra }
389*dbed73cbSSangeeta Misra 
390*dbed73cbSSangeeta Misra /*
391*dbed73cbSSangeeta Misra  * This function checks whether tsrv should/can be inserted before lsrv
392*dbed73cbSSangeeta Misra  * and does so if possible.
393*dbed73cbSSangeeta Misra  * We keep the list in sorted order so we don't have to search it
394*dbed73cbSSangeeta Misra  * in its entirety for overlap every time we insert a new server.
395*dbed73cbSSangeeta Misra  * Return code:
396*dbed73cbSSangeeta Misra  *	stop_found: don't continue searching because we found a place
397*dbed73cbSSangeeta Misra  *	cont_search: continue with next element in the list
398*dbed73cbSSangeeta Misra  *	fail_search: search failed (caller translates to ILB_STATUS_EEXIST)
399*dbed73cbSSangeeta Misra  */
400*dbed73cbSSangeeta Misra static srch_ind_t
401*dbed73cbSSangeeta Misra i_test_and_insert(ilbd_srv_t *tsrv, ilbd_srv_t *lsrv, list_t *srvlist)
402*dbed73cbSSangeeta Misra {
403*dbed73cbSSangeeta Misra 	struct in6_addr	*t1, *l1;
404*dbed73cbSSangeeta Misra 	int		fnd;
405*dbed73cbSSangeeta Misra 
406*dbed73cbSSangeeta Misra 	t1 = &tsrv->isv_addr;
407*dbed73cbSSangeeta Misra 	l1 = &lsrv->isv_addr;
408*dbed73cbSSangeeta Misra 
409*dbed73cbSSangeeta Misra 	if ((fnd = ilb_cmp_in6_addr(t1, l1, NULL)) == 1)
410*dbed73cbSSangeeta Misra 		return (cont_search);	/* search can continue */
411*dbed73cbSSangeeta Misra 
412*dbed73cbSSangeeta Misra 	if (fnd == 0) {
413*dbed73cbSSangeeta Misra 		logdebug("i_test_and_insert: specified server already exists");
414*dbed73cbSSangeeta Misra 		return (fail_search);
415*dbed73cbSSangeeta Misra 	}
416*dbed73cbSSangeeta Misra 	/* the list is kept in ascending order */
417*dbed73cbSSangeeta Misra 	list_insert_before(srvlist, lsrv, tsrv);
418*dbed73cbSSangeeta Misra 	return (stop_found);
419*dbed73cbSSangeeta Misra }
420*dbed73cbSSangeeta Misra 
421*dbed73cbSSangeeta Misra 
422*dbed73cbSSangeeta Misra /*
423*dbed73cbSSangeeta Misra  * copy a server description [ip1,ip2,port1,port2,srvID,flags]
424*dbed73cbSSangeeta Misra  */
425*dbed73cbSSangeeta Misra #define	COPY_SERVER(src, dest)					\
426*dbed73cbSSangeeta Misra 	(dest)->sgs_addr = (src)->sgs_addr;			\
427*dbed73cbSSangeeta Misra 	(dest)->sgs_minport = (src)->sgs_minport;		\
428*dbed73cbSSangeeta Misra 	(dest)->sgs_maxport = (src)->sgs_maxport;		\
429*dbed73cbSSangeeta Misra 	(dest)->sgs_id = (src)->sgs_id;				\
430*dbed73cbSSangeeta Misra 	(void) strlcpy((dest)->sgs_srvID, (src)->sgs_srvID,	\
431*dbed73cbSSangeeta Misra 	    sizeof ((dest)->sgs_srvID));			\
432*dbed73cbSSangeeta Misra 	(dest)->sgs_flags = (src)->sgs_flags
433*dbed73cbSSangeeta Misra 
434*dbed73cbSSangeeta Misra static ilb_status_t
435*dbed73cbSSangeeta Misra i_add_srv2sg(ilbd_sg_t *dsg, ilb_sg_srv_t *srv, ilbd_srv_t **ret_srv)
436*dbed73cbSSangeeta Misra {
437*dbed73cbSSangeeta Misra 	ilb_sg_srv_t	*n_sg_srv;
438*dbed73cbSSangeeta Misra 	list_t		*srvlist;
439*dbed73cbSSangeeta Misra 	srch_ind_t	search = not_searched;
440*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
441*dbed73cbSSangeeta Misra 	ilbd_srv_t	*nsrv, *lsrv;
442*dbed73cbSSangeeta Misra 	in_port_t	h_minport, h_maxport;
443*dbed73cbSSangeeta Misra 
444*dbed73cbSSangeeta Misra 	nsrv = calloc(sizeof (*nsrv), 1);
445*dbed73cbSSangeeta Misra 	if (nsrv == NULL)
446*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOMEM);
447*dbed73cbSSangeeta Misra 	n_sg_srv = &nsrv->isv_srv;
448*dbed73cbSSangeeta Misra 	COPY_SERVER(srv, n_sg_srv);
449*dbed73cbSSangeeta Misra 
450*dbed73cbSSangeeta Misra 	/*
451*dbed73cbSSangeeta Misra 	 * port info is in network byte order - we need host byte order
452*dbed73cbSSangeeta Misra 	 * for comparisons purposes
453*dbed73cbSSangeeta Misra 	 */
454*dbed73cbSSangeeta Misra 	h_minport = ntohs(n_sg_srv->sgs_minport);
455*dbed73cbSSangeeta Misra 	h_maxport = ntohs(n_sg_srv->sgs_maxport);
456*dbed73cbSSangeeta Misra 	if (h_minport != 0 && h_minport > h_maxport)
457*dbed73cbSSangeeta Misra 		n_sg_srv->sgs_maxport = n_sg_srv->sgs_minport;
458*dbed73cbSSangeeta Misra 
459*dbed73cbSSangeeta Misra 	srvlist = &dsg->isg_srvlist;
460*dbed73cbSSangeeta Misra 
461*dbed73cbSSangeeta Misra 	lsrv = list_head(srvlist);
462*dbed73cbSSangeeta Misra 	if (lsrv == NULL) {
463*dbed73cbSSangeeta Misra 		list_insert_head(srvlist, nsrv);
464*dbed73cbSSangeeta Misra 	} else {
465*dbed73cbSSangeeta Misra 		while (lsrv != NULL) {
466*dbed73cbSSangeeta Misra 			search = i_test_and_insert(nsrv, lsrv,
467*dbed73cbSSangeeta Misra 			    srvlist);
468*dbed73cbSSangeeta Misra 
469*dbed73cbSSangeeta Misra 			if (search != cont_search)
470*dbed73cbSSangeeta Misra 				break;
471*dbed73cbSSangeeta Misra 			lsrv = list_next(srvlist, lsrv);
472*dbed73cbSSangeeta Misra 
473*dbed73cbSSangeeta Misra 			/* if reaches the end of list, insert to the tail */
474*dbed73cbSSangeeta Misra 			if (search == cont_search && lsrv == NULL)
475*dbed73cbSSangeeta Misra 				list_insert_tail(srvlist, nsrv);
476*dbed73cbSSangeeta Misra 		}
477*dbed73cbSSangeeta Misra 		if (search == fail_search)
478*dbed73cbSSangeeta Misra 			rc = ILB_STATUS_EEXIST;
479*dbed73cbSSangeeta Misra 	}
480*dbed73cbSSangeeta Misra 
481*dbed73cbSSangeeta Misra 	if (rc == ILB_STATUS_OK) {
482*dbed73cbSSangeeta Misra 		dsg->isg_srvcount++;
483*dbed73cbSSangeeta Misra 		*ret_srv = nsrv;
484*dbed73cbSSangeeta Misra 	} else {
485*dbed73cbSSangeeta Misra 		free(nsrv);
486*dbed73cbSSangeeta Misra 	}
487*dbed73cbSSangeeta Misra 
488*dbed73cbSSangeeta Misra 	return (rc);
489*dbed73cbSSangeeta Misra }
490*dbed73cbSSangeeta Misra 
491*dbed73cbSSangeeta Misra /*
492*dbed73cbSSangeeta Misra  * Allocate a server ID.  The algorithm is simple.  Just check the ID array
493*dbed73cbSSangeeta Misra  * of the server group and find an unused ID.  If *set_id is given, it
494*dbed73cbSSangeeta Misra  * means that the ID is already allocated and the ID array needs to be
495*dbed73cbSSangeeta Misra  * updated.  This is the case when ilbd reads from the persistent
496*dbed73cbSSangeeta Misra  * configuration.
497*dbed73cbSSangeeta Misra  */
498*dbed73cbSSangeeta Misra static int32_t
499*dbed73cbSSangeeta Misra i_ilbd_alloc_srvID(ilbd_sg_t *sg, int32_t *set_id)
500*dbed73cbSSangeeta Misra {
501*dbed73cbSSangeeta Misra 	int32_t		id;
502*dbed73cbSSangeeta Misra 	int32_t		i;
503*dbed73cbSSangeeta Misra 
504*dbed73cbSSangeeta Misra 	/* The server ID is already allocated, just update the ID array. */
505*dbed73cbSSangeeta Misra 	if (set_id != NULL) {
506*dbed73cbSSangeeta Misra 		assert(sg->isg_id_arr[*set_id] == 0);
507*dbed73cbSSangeeta Misra 		sg->isg_id_arr[*set_id] = 1;
508*dbed73cbSSangeeta Misra 		return (*set_id);
509*dbed73cbSSangeeta Misra 	}
510*dbed73cbSSangeeta Misra 
511*dbed73cbSSangeeta Misra 	/* if we're "full up", give back something invalid */
512*dbed73cbSSangeeta Misra 	if (sg->isg_srvcount == MAX_SRVCOUNT)
513*dbed73cbSSangeeta Misra 		return (BAD_SRVID);
514*dbed73cbSSangeeta Misra 
515*dbed73cbSSangeeta Misra 	i = sg->isg_max_id;
516*dbed73cbSSangeeta Misra 	for (id = 0; id < MAX_SRVCOUNT; id++) {
517*dbed73cbSSangeeta Misra 		if (sg->isg_id_arr[(id + i) % MAX_SRVCOUNT] == 0)
518*dbed73cbSSangeeta Misra 			break;
519*dbed73cbSSangeeta Misra 	}
520*dbed73cbSSangeeta Misra 
521*dbed73cbSSangeeta Misra 	sg->isg_max_id = (id + i) % MAX_SRVCOUNT;
522*dbed73cbSSangeeta Misra 	sg->isg_id_arr[sg->isg_max_id] = 1;
523*dbed73cbSSangeeta Misra 	return (sg->isg_max_id);
524*dbed73cbSSangeeta Misra }
525*dbed73cbSSangeeta Misra 
526*dbed73cbSSangeeta Misra /*
527*dbed73cbSSangeeta Misra  * Free a server ID by updating the server group's ID array.
528*dbed73cbSSangeeta Misra  */
529*dbed73cbSSangeeta Misra static void
530*dbed73cbSSangeeta Misra i_ilbd_free_srvID(ilbd_sg_t *sg, int32_t id)
531*dbed73cbSSangeeta Misra {
532*dbed73cbSSangeeta Misra 	assert(sg->isg_id_arr[id] == 1);
533*dbed73cbSSangeeta Misra 	sg->isg_id_arr[id] = 0;
534*dbed73cbSSangeeta Misra }
535*dbed73cbSSangeeta Misra 
536*dbed73cbSSangeeta Misra /*
537*dbed73cbSSangeeta Misra  * This function is called by ilbd_add_server_to_group() and
538*dbed73cbSSangeeta Misra  * ilb_remove_server_group() to create a audit record for a
539*dbed73cbSSangeeta Misra  * failed servicing of add-server/remove-server command
540*dbed73cbSSangeeta Misra  */
541*dbed73cbSSangeeta Misra static void
542*dbed73cbSSangeeta Misra fill_audit_record(ilb_sg_info_t *sg, audit_sg_event_data_t *audit_sg_data,
543*dbed73cbSSangeeta Misra     ilbd_cmd_t cmd, ilb_status_t rc, ucred_t *ucredp)
544*dbed73cbSSangeeta Misra {
545*dbed73cbSSangeeta Misra 	ilb_sg_srv_t	*tsrv;
546*dbed73cbSSangeeta Misra 	int	i;
547*dbed73cbSSangeeta Misra 
548*dbed73cbSSangeeta Misra 	for (i = 0; i < sg->sg_srvcount; i++) {
549*dbed73cbSSangeeta Misra 		tsrv = &sg->sg_servers[i];
550*dbed73cbSSangeeta Misra 		if (cmd == ILBD_ADD_SERVER_TO_GROUP)  {
551*dbed73cbSSangeeta Misra 			char	addrstr_buf[INET6_ADDRSTRLEN];
552*dbed73cbSSangeeta Misra 
553*dbed73cbSSangeeta Misra 			audit_sg_data->ed_serverid = NULL;
554*dbed73cbSSangeeta Misra 			ilbd_addr2str(&tsrv->sgs_addr, addrstr_buf,
555*dbed73cbSSangeeta Misra 			    sizeof (addrstr_buf));
556*dbed73cbSSangeeta Misra 			audit_sg_data->ed_server_address = addrstr_buf;
557*dbed73cbSSangeeta Misra 			audit_sg_data->ed_minport = tsrv->sgs_minport;
558*dbed73cbSSangeeta Misra 			audit_sg_data->ed_maxport = tsrv->sgs_maxport;
559*dbed73cbSSangeeta Misra 			audit_sg_data->ed_sgroup = sg->sg_name;
560*dbed73cbSSangeeta Misra 		} else if (cmd == ILBD_REM_SERVER_FROM_GROUP) {
561*dbed73cbSSangeeta Misra 			audit_sg_data->ed_serverid = tsrv->sgs_srvID;
562*dbed73cbSSangeeta Misra 			audit_sg_data->ed_sgroup = sg->sg_name;
563*dbed73cbSSangeeta Misra 			audit_sg_data->ed_server_address = NULL;
564*dbed73cbSSangeeta Misra 			audit_sg_data->ed_minport = 0;
565*dbed73cbSSangeeta Misra 			audit_sg_data->ed_maxport = 0;
566*dbed73cbSSangeeta Misra 		}
567*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(audit_sg_data, cmd, rc, ucredp);
568*dbed73cbSSangeeta Misra 	}
569*dbed73cbSSangeeta Misra }
570*dbed73cbSSangeeta Misra 
571*dbed73cbSSangeeta Misra /*
572*dbed73cbSSangeeta Misra  * the name(s) of the server(s) are encoded in the sg.
573*dbed73cbSSangeeta Misra  */
574*dbed73cbSSangeeta Misra ilb_status_t
575*dbed73cbSSangeeta Misra ilbd_add_server_to_group(ilb_sg_info_t *sg_info, int ev_port,
576*dbed73cbSSangeeta Misra     const struct passwd *ps, ucred_t *ucredp)
577*dbed73cbSSangeeta Misra {
578*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
579*dbed73cbSSangeeta Misra 	ilbd_sg_t	*tmp_sg;
580*dbed73cbSSangeeta Misra 	int		i, j;
581*dbed73cbSSangeeta Misra 	int32_t		new_id = BAD_SRVID;
582*dbed73cbSSangeeta Misra 	int32_t		af = AF_UNSPEC;
583*dbed73cbSSangeeta Misra 	ilbd_srv_t	*nsrv;
584*dbed73cbSSangeeta Misra 	ilb_sg_srv_t	*srv;
585*dbed73cbSSangeeta Misra 	audit_sg_event_data_t   audit_sg_data;
586*dbed73cbSSangeeta Misra 	char    addrstr_buf[INET6_ADDRSTRLEN];
587*dbed73cbSSangeeta Misra 
588*dbed73cbSSangeeta Misra 	if (ps != NULL) {
589*dbed73cbSSangeeta Misra 		rc = ilbd_check_client_config_auth(ps);
590*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
591*dbed73cbSSangeeta Misra 			fill_audit_record(sg_info, &audit_sg_data,
592*dbed73cbSSangeeta Misra 			    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
593*dbed73cbSSangeeta Misra 			return (rc);
594*dbed73cbSSangeeta Misra 		}
595*dbed73cbSSangeeta Misra 	}
596*dbed73cbSSangeeta Misra 
597*dbed73cbSSangeeta Misra 	tmp_sg = i_find_sg_byname(sg_info->sg_name);
598*dbed73cbSSangeeta Misra 	if (tmp_sg == NULL) {
599*dbed73cbSSangeeta Misra 		logdebug("ilbd_add_server_to_group: server"
600*dbed73cbSSangeeta Misra 		    " group %s does not exist", sg_info->sg_name);
601*dbed73cbSSangeeta Misra 		fill_audit_record(sg_info, &audit_sg_data,
602*dbed73cbSSangeeta Misra 		    ILBD_ADD_SERVER_TO_GROUP, ILB_STATUS_ENOENT, ucredp);
603*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
604*dbed73cbSSangeeta Misra 	}
605*dbed73cbSSangeeta Misra 
606*dbed73cbSSangeeta Misra 	/*
607*dbed73cbSSangeeta Misra 	 * we do the dance with address family below to make sure only
608*dbed73cbSSangeeta Misra 	 * IP addresses in the same AF get into an SG; the first one to get
609*dbed73cbSSangeeta Misra 	 * in sets the "tone"
610*dbed73cbSSangeeta Misra 	 * if this is the first server to join a group, check whether
611*dbed73cbSSangeeta Misra 	 * there's no mismatch with any *rules* already attached
612*dbed73cbSSangeeta Misra 	 */
613*dbed73cbSSangeeta Misra 	if (tmp_sg->isg_srvcount > 0) {
614*dbed73cbSSangeeta Misra 		ilbd_srv_t *tsrv = list_head(&tmp_sg->isg_srvlist);
615*dbed73cbSSangeeta Misra 
616*dbed73cbSSangeeta Misra 		af = GET_AF(&tsrv->isv_addr);
617*dbed73cbSSangeeta Misra 	} else {
618*dbed73cbSSangeeta Misra 		ilbd_rule_t	*irl = list_head(&tmp_sg->isg_rulelist);
619*dbed73cbSSangeeta Misra 
620*dbed73cbSSangeeta Misra 		if (irl != NULL)
621*dbed73cbSSangeeta Misra 			af = GET_AF(&irl->irl_vip);
622*dbed73cbSSangeeta Misra 	}
623*dbed73cbSSangeeta Misra 
624*dbed73cbSSangeeta Misra 	for (i = 0; i < sg_info->sg_srvcount; i++) {
625*dbed73cbSSangeeta Misra 		srv = &sg_info->sg_servers[i];
626*dbed73cbSSangeeta Misra 
627*dbed73cbSSangeeta Misra 		(void) memset(&audit_sg_data, 0, sizeof (audit_sg_data));
628*dbed73cbSSangeeta Misra 		ilbd_addr2str(&srv->sgs_addr, addrstr_buf,
629*dbed73cbSSangeeta Misra 		    sizeof (addrstr_buf));
630*dbed73cbSSangeeta Misra 		audit_sg_data.ed_server_address = addrstr_buf;
631*dbed73cbSSangeeta Misra 		audit_sg_data.ed_minport = srv->sgs_minport;
632*dbed73cbSSangeeta Misra 		audit_sg_data.ed_maxport = srv->sgs_maxport;
633*dbed73cbSSangeeta Misra 		audit_sg_data.ed_sgroup = sg_info->sg_name;
634*dbed73cbSSangeeta Misra 
635*dbed73cbSSangeeta Misra 		/* only test if we have sth to test against */
636*dbed73cbSSangeeta Misra 		if (af != AF_UNSPEC) {
637*dbed73cbSSangeeta Misra 			int32_t	sgs_af = GET_AF(&srv->sgs_addr);
638*dbed73cbSSangeeta Misra 
639*dbed73cbSSangeeta Misra 			if (af != sgs_af) {
640*dbed73cbSSangeeta Misra 				logdebug("address family mismatch with previous"
641*dbed73cbSSangeeta Misra 				    " hosts in servergroup or with rule");
642*dbed73cbSSangeeta Misra 				rc = ILB_STATUS_MISMATCHH;
643*dbed73cbSSangeeta Misra 				ilbd_audit_server_event(&audit_sg_data,
644*dbed73cbSSangeeta Misra 				    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
645*dbed73cbSSangeeta Misra 				goto rollback;
646*dbed73cbSSangeeta Misra 			}
647*dbed73cbSSangeeta Misra 		}
648*dbed73cbSSangeeta Misra 
649*dbed73cbSSangeeta Misra 		/*
650*dbed73cbSSangeeta Misra 		 * PS: NULL means daemon is loading configure from scf.
651*dbed73cbSSangeeta Misra 		 * ServerID is already assigned, just update the ID array.
652*dbed73cbSSangeeta Misra 		 */
653*dbed73cbSSangeeta Misra 		if (ps != NULL) {
654*dbed73cbSSangeeta Misra 			new_id = i_ilbd_alloc_srvID(tmp_sg, NULL);
655*dbed73cbSSangeeta Misra 			if (new_id == BAD_SRVID) {
656*dbed73cbSSangeeta Misra 				logdebug("ilbd_add_server_to_group: server"
657*dbed73cbSSangeeta Misra 				    "group %s is full, no more servers"
658*dbed73cbSSangeeta Misra 				    " can be added", sg_info->sg_name);
659*dbed73cbSSangeeta Misra 				rc = ILB_STATUS_SGFULL;
660*dbed73cbSSangeeta Misra 				ilbd_audit_server_event(&audit_sg_data,
661*dbed73cbSSangeeta Misra 				    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
662*dbed73cbSSangeeta Misra 				goto rollback;
663*dbed73cbSSangeeta Misra 			}
664*dbed73cbSSangeeta Misra 			srv->sgs_id = new_id;
665*dbed73cbSSangeeta Misra 		} else {
666*dbed73cbSSangeeta Misra 			new_id = i_ilbd_alloc_srvID(tmp_sg, &srv->sgs_id);
667*dbed73cbSSangeeta Misra 		}
668*dbed73cbSSangeeta Misra 
669*dbed73cbSSangeeta Misra 		/*
670*dbed73cbSSangeeta Misra 		 * here we implement the requirement that server IDs start
671*dbed73cbSSangeeta Misra 		 * with a character that is not legal in hostnames - in our
672*dbed73cbSSangeeta Misra 		 * case, a "_" (underscore).
673*dbed73cbSSangeeta Misra 		 */
674*dbed73cbSSangeeta Misra 		(void) snprintf(srv->sgs_srvID,
675*dbed73cbSSangeeta Misra 		    sizeof (srv->sgs_srvID), "%c%s.%d", ILB_SRVID_PREFIX,
676*dbed73cbSSangeeta Misra 		    tmp_sg->isg_name, srv->sgs_id);
677*dbed73cbSSangeeta Misra 		audit_sg_data.ed_serverid = srv->sgs_srvID;
678*dbed73cbSSangeeta Misra 
679*dbed73cbSSangeeta Misra 		/*
680*dbed73cbSSangeeta Misra 		 * Before we update the kernel rules by adding the server,
681*dbed73cbSSangeeta Misra 		 * we need to make checks and fail if any of the
682*dbed73cbSSangeeta Misra 		 * following is true:
683*dbed73cbSSangeeta Misra 		 *
684*dbed73cbSSangeeta Misra 		 * o if the server has single port and the servergroup
685*dbed73cbSSangeeta Misra 		 *   is associated to a DSR rule with a port range
686*dbed73cbSSangeeta Misra 		 * o if the server has a port range and the servergroup
687*dbed73cbSSangeeta Misra 		 *   is associated to a DSR rule with a port range and
688*dbed73cbSSangeeta Misra 		 *   the rule's min and max port does not exactly
689*dbed73cbSSangeeta Misra 		 *   match that of the server's.
690*dbed73cbSSangeeta Misra 		 * o if the the server has a port range and the servergroup
691*dbed73cbSSangeeta Misra 		 *   is associated to a NAT/Half-NAT rule with a port range
692*dbed73cbSSangeeta Misra 		 *   and the rule's port range size does not match that
693*dbed73cbSSangeeta Misra 		 *   of the server's.
694*dbed73cbSSangeeta Misra 		 * o if the rule has a fixed hc port, check that this port
695*dbed73cbSSangeeta Misra 		 *   is valid in the server's port specification.
696*dbed73cbSSangeeta Misra 		 */
697*dbed73cbSSangeeta Misra 		rc = i_check_srv2rules(&tmp_sg->isg_rulelist, srv);
698*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
699*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
700*dbed73cbSSangeeta Misra 			    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
701*dbed73cbSSangeeta Misra 			goto rollback;
702*dbed73cbSSangeeta Misra 		}
703*dbed73cbSSangeeta Misra 
704*dbed73cbSSangeeta Misra 		if ((rc = i_add_srv2sg(tmp_sg, srv, &nsrv)) != ILB_STATUS_OK) {
705*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
706*dbed73cbSSangeeta Misra 			    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
707*dbed73cbSSangeeta Misra 			goto rollback;
708*dbed73cbSSangeeta Misra 		}
709*dbed73cbSSangeeta Misra 
710*dbed73cbSSangeeta Misra 		rc = i_add_srv2krules(&tmp_sg->isg_rulelist, &nsrv->isv_srv,
711*dbed73cbSSangeeta Misra 		    ev_port);
712*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
713*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
714*dbed73cbSSangeeta Misra 			    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
715*dbed73cbSSangeeta Misra 			/*
716*dbed73cbSSangeeta Misra 			 * The failure may be due to the serverid being on
717*dbed73cbSSangeeta Misra 			 * hold in kernel for connection draining. But ilbd
718*dbed73cbSSangeeta Misra 			 * has no way of knowing that. So we are freeing up
719*dbed73cbSSangeeta Misra 			 * the serverid, and may run into the risk of
720*dbed73cbSSangeeta Misra 			 * having this failure again, if we choose this
721*dbed73cbSSangeeta Misra 			 * serverid  when processing the next add-server
722*dbed73cbSSangeeta Misra 			 * command for this servergroup, while connection
723*dbed73cbSSangeeta Misra 			 * draining is underway. We assume that the user
724*dbed73cbSSangeeta Misra 			 * will read the man page after he/she encounters
725*dbed73cbSSangeeta Misra 			 * this failure, and learn to not add any server
726*dbed73cbSSangeeta Misra 			 * to the servergroup until connection draining of
727*dbed73cbSSangeeta Misra 			 * all servers in the  servergroup is complete.
728*dbed73cbSSangeeta Misra 			 * XXX Need to revisit this when connection draining
729*dbed73cbSSangeeta Misra 			 * is reworked
730*dbed73cbSSangeeta Misra 			 */
731*dbed73cbSSangeeta Misra 			list_remove(&tmp_sg->isg_srvlist, nsrv);
732*dbed73cbSSangeeta Misra 			i_ilbd_free_srvID(tmp_sg, nsrv->isv_id);
733*dbed73cbSSangeeta Misra 			free(nsrv);
734*dbed73cbSSangeeta Misra 			tmp_sg->isg_srvcount--;
735*dbed73cbSSangeeta Misra 			goto rollback;
736*dbed73cbSSangeeta Misra 		}
737*dbed73cbSSangeeta Misra 		if (ps != NULL) {
738*dbed73cbSSangeeta Misra 			rc = ilbd_scf_add_srv(tmp_sg, nsrv);
739*dbed73cbSSangeeta Misra 			if (rc != ILB_STATUS_OK) {
740*dbed73cbSSangeeta Misra 				/*
741*dbed73cbSSangeeta Misra 				 * The following should not fail since the
742*dbed73cbSSangeeta Misra 				 * server is just added.  Just in case, we
743*dbed73cbSSangeeta Misra 				 * pass in -1 as the event port to avoid
744*dbed73cbSSangeeta Misra 				 * roll back in i_rem_srv_frm_krules() called
745*dbed73cbSSangeeta Misra 				 * by i_delete_srv().
746*dbed73cbSSangeeta Misra 				 */
747*dbed73cbSSangeeta Misra 				ilbd_audit_server_event(&audit_sg_data,
748*dbed73cbSSangeeta Misra 				    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
749*dbed73cbSSangeeta Misra 				(void) i_delete_srv(tmp_sg, nsrv, -1);
750*dbed73cbSSangeeta Misra 				break;
751*dbed73cbSSangeeta Misra 			}
752*dbed73cbSSangeeta Misra 		}
753*dbed73cbSSangeeta Misra 	}
754*dbed73cbSSangeeta Misra 
755*dbed73cbSSangeeta Misra 	if (rc == ILB_STATUS_OK) {
756*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
757*dbed73cbSSangeeta Misra 		    ILBD_ADD_SERVER_TO_GROUP, rc, ucredp);
758*dbed73cbSSangeeta Misra 		return (rc);
759*dbed73cbSSangeeta Misra 	}
760*dbed73cbSSangeeta Misra 
761*dbed73cbSSangeeta Misra rollback:
762*dbed73cbSSangeeta Misra 	/*
763*dbed73cbSSangeeta Misra 	 * If ilbd is initializing based on the SCF data and something fails,
764*dbed73cbSSangeeta Misra 	 * the only choice is to transition the service to maintanence mode...
765*dbed73cbSSangeeta Misra 	 */
766*dbed73cbSSangeeta Misra 	if (ps == NULL) {
767*dbed73cbSSangeeta Misra 		logerr("%s: failure during initialization -"
768*dbed73cbSSangeeta Misra 		    " entering maintenance mode", __func__);
769*dbed73cbSSangeeta Misra 		(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
770*dbed73cbSSangeeta Misra 		return (rc);
771*dbed73cbSSangeeta Misra 	}
772*dbed73cbSSangeeta Misra 
773*dbed73cbSSangeeta Misra 	/*
774*dbed73cbSSangeeta Misra 	 * we need to roll back all servers previous to the one
775*dbed73cbSSangeeta Misra 	 * that just caused the failure
776*dbed73cbSSangeeta Misra 	 */
777*dbed73cbSSangeeta Misra 	for (j = i-1; j >= 0; j--) {
778*dbed73cbSSangeeta Misra 		srv = &sg_info->sg_servers[j];
779*dbed73cbSSangeeta Misra 
780*dbed73cbSSangeeta Misra 		/* We should be able to find those servers just added. */
781*dbed73cbSSangeeta Misra 		nsrv = i_find_srv(&tmp_sg->isg_srvlist, srv, MODE_SRVID);
782*dbed73cbSSangeeta Misra 		assert(nsrv != NULL);
783*dbed73cbSSangeeta Misra 		(void) i_delete_srv(tmp_sg, nsrv, -1);
784*dbed73cbSSangeeta Misra 	}
785*dbed73cbSSangeeta Misra 	return (rc);
786*dbed73cbSSangeeta Misra }
787*dbed73cbSSangeeta Misra 
788*dbed73cbSSangeeta Misra static srch_ind_t
789*dbed73cbSSangeeta Misra i_match_srvID(ilb_sg_srv_t *sg_srv, ilbd_srv_t *lsrv)
790*dbed73cbSSangeeta Misra {
791*dbed73cbSSangeeta Misra 	if (strncmp(sg_srv->sgs_srvID, lsrv->isv_srvID,
792*dbed73cbSSangeeta Misra 	    sizeof (sg_srv->sgs_srvID)) == 0) {
793*dbed73cbSSangeeta Misra 		return (stop_found);
794*dbed73cbSSangeeta Misra 	}
795*dbed73cbSSangeeta Misra 	return (cont_search);
796*dbed73cbSSangeeta Misra }
797*dbed73cbSSangeeta Misra 
798*dbed73cbSSangeeta Misra /*
799*dbed73cbSSangeeta Misra  * Sanity check on a rule's port specification against all the servers'
800*dbed73cbSSangeeta Misra  * specification in its associated server group.
801*dbed73cbSSangeeta Misra  *
802*dbed73cbSSangeeta Misra  * 1. If the health check's probe port (hcport) is specified.
803*dbed73cbSSangeeta Misra  *    - if server port range is specified, check if hcport is inside
804*dbed73cbSSangeeta Misra  *      the range
805*dbed73cbSSangeeta Misra  *    - if no server port is specified (meaning the port range is the same as
806*dbed73cbSSangeeta Misra  *      the rule's port range), check if hcport is inside the rule's range.
807*dbed73cbSSangeeta Misra  *
808*dbed73cbSSangeeta Misra  * 2. If a server has no port specification, there is no conflict.
809*dbed73cbSSangeeta Misra  *
810*dbed73cbSSangeeta Misra  * 3. If the rule's load balance mode is DSR, a server port specification must
811*dbed73cbSSangeeta Misra  *    be exactly the same as the rule's.
812*dbed73cbSSangeeta Misra  *
813*dbed73cbSSangeeta Misra  * 4. In other modes (NAT and half-NAT), the server's port range must be
814*dbed73cbSSangeeta Misra  *    the same as the rule's, unless it is doing port collapsing (the server's
815*dbed73cbSSangeeta Misra  *    port range is only 1).
816*dbed73cbSSangeeta Misra  */
817*dbed73cbSSangeeta Misra ilb_status_t
818*dbed73cbSSangeeta Misra ilbd_sg_check_rule_port(ilbd_sg_t *sg, ilb_rule_info_t *rl)
819*dbed73cbSSangeeta Misra {
820*dbed73cbSSangeeta Misra 	ilbd_srv_t	*srv;
821*dbed73cbSSangeeta Misra 	in_port_t	r_minport, r_maxport;
822*dbed73cbSSangeeta Misra 
823*dbed73cbSSangeeta Misra 	/* Don't allow adding a rule to a sg with no server, for now... */
824*dbed73cbSSangeeta Misra 	if (sg->isg_srvcount == 0)
825*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGEMPTY);
826*dbed73cbSSangeeta Misra 
827*dbed73cbSSangeeta Misra 	r_minport = ntohs(rl->rl_minport);
828*dbed73cbSSangeeta Misra 	r_maxport = ntohs(rl->rl_maxport);
829*dbed73cbSSangeeta Misra 
830*dbed73cbSSangeeta Misra 	for (srv = list_head(&sg->isg_srvlist); srv != NULL;
831*dbed73cbSSangeeta Misra 	    srv = list_next(&sg->isg_srvlist, srv)) {
832*dbed73cbSSangeeta Misra 		in_port_t srv_minport, srv_maxport;
833*dbed73cbSSangeeta Misra 		int range;
834*dbed73cbSSangeeta Misra 
835*dbed73cbSSangeeta Misra 		srv_minport = ntohs(srv->isv_minport);
836*dbed73cbSSangeeta Misra 		srv_maxport = ntohs(srv->isv_maxport);
837*dbed73cbSSangeeta Misra 		range = srv_maxport - srv_minport;
838*dbed73cbSSangeeta Misra 
839*dbed73cbSSangeeta Misra 		/*
840*dbed73cbSSangeeta Misra 		 * If the rule has a specific probe port, check if that port is
841*dbed73cbSSangeeta Misra 		 * valid in all the servers' port specification.
842*dbed73cbSSangeeta Misra 		 */
843*dbed73cbSSangeeta Misra 		if (rl->rl_hcpflag == ILB_HCI_PROBE_FIX) {
844*dbed73cbSSangeeta Misra 			in_port_t hcport = ntohs(rl->rl_hcport);
845*dbed73cbSSangeeta Misra 
846*dbed73cbSSangeeta Misra 			/* No server port specified. */
847*dbed73cbSSangeeta Misra 			if (srv_minport == 0) {
848*dbed73cbSSangeeta Misra 				if (hcport > r_maxport || hcport < r_minport) {
849*dbed73cbSSangeeta Misra 					return (ILB_STATUS_BADSG);
850*dbed73cbSSangeeta Misra 				}
851*dbed73cbSSangeeta Misra 			} else {
852*dbed73cbSSangeeta Misra 				if (hcport > srv_maxport ||
853*dbed73cbSSangeeta Misra 				    hcport < srv_minport) {
854*dbed73cbSSangeeta Misra 					return (ILB_STATUS_BADSG);
855*dbed73cbSSangeeta Misra 				}
856*dbed73cbSSangeeta Misra 			}
857*dbed73cbSSangeeta Misra 		}
858*dbed73cbSSangeeta Misra 
859*dbed73cbSSangeeta Misra 		/*
860*dbed73cbSSangeeta Misra 		 * There is no server port specification, so there cannot be
861*dbed73cbSSangeeta Misra 		 * any conflict.
862*dbed73cbSSangeeta Misra 		 */
863*dbed73cbSSangeeta Misra 		if (srv_minport == 0)
864*dbed73cbSSangeeta Misra 			continue;
865*dbed73cbSSangeeta Misra 
866*dbed73cbSSangeeta Misra 		if (rl->rl_topo == ILB_TOPO_DSR) {
867*dbed73cbSSangeeta Misra 			if (r_minport != srv_minport ||
868*dbed73cbSSangeeta Misra 			    r_maxport != srv_maxport) {
869*dbed73cbSSangeeta Misra 				return (ILB_STATUS_BADSG);
870*dbed73cbSSangeeta Misra 			}
871*dbed73cbSSangeeta Misra 		} else {
872*dbed73cbSSangeeta Misra 			if ((range != r_maxport - r_minport) && range != 0)
873*dbed73cbSSangeeta Misra 				return (ILB_STATUS_BADSG);
874*dbed73cbSSangeeta Misra 		}
875*dbed73cbSSangeeta Misra 	}
876*dbed73cbSSangeeta Misra 
877*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
878*dbed73cbSSangeeta Misra }
879*dbed73cbSSangeeta Misra 
880*dbed73cbSSangeeta Misra static srch_ind_t
881*dbed73cbSSangeeta Misra i_match_srvIP(ilb_sg_srv_t *sg_srv, ilbd_srv_t *lsrv)
882*dbed73cbSSangeeta Misra {
883*dbed73cbSSangeeta Misra 	if (IN6_ARE_ADDR_EQUAL(&sg_srv->sgs_addr, &lsrv->isv_addr))
884*dbed73cbSSangeeta Misra 		return (stop_found);
885*dbed73cbSSangeeta Misra 	return (cont_search);
886*dbed73cbSSangeeta Misra }
887*dbed73cbSSangeeta Misra 
888*dbed73cbSSangeeta Misra static ilbd_srv_t *
889*dbed73cbSSangeeta Misra i_find_srv(list_t *srvlist, ilb_sg_srv_t *sg_srv, int cmpmode)
890*dbed73cbSSangeeta Misra {
891*dbed73cbSSangeeta Misra 	ilbd_srv_t	*tmp_srv;
892*dbed73cbSSangeeta Misra 	srch_ind_t	srch_res = cont_search;
893*dbed73cbSSangeeta Misra 
894*dbed73cbSSangeeta Misra 	for (tmp_srv = list_head(srvlist); tmp_srv != NULL;
895*dbed73cbSSangeeta Misra 	    tmp_srv = list_next(srvlist, tmp_srv)) {
896*dbed73cbSSangeeta Misra 		switch (cmpmode) {
897*dbed73cbSSangeeta Misra 		case MODE_ADDR:
898*dbed73cbSSangeeta Misra 			srch_res = i_match_srvIP(sg_srv, tmp_srv);
899*dbed73cbSSangeeta Misra 			break;
900*dbed73cbSSangeeta Misra 		case MODE_SRVID:
901*dbed73cbSSangeeta Misra 			srch_res = i_match_srvID(sg_srv, tmp_srv);
902*dbed73cbSSangeeta Misra 			break;
903*dbed73cbSSangeeta Misra 		}
904*dbed73cbSSangeeta Misra 		if (srch_res == stop_found)
905*dbed73cbSSangeeta Misra 			break;
906*dbed73cbSSangeeta Misra 	}
907*dbed73cbSSangeeta Misra 
908*dbed73cbSSangeeta Misra 	if (srch_res == stop_found)
909*dbed73cbSSangeeta Misra 		return (tmp_srv);
910*dbed73cbSSangeeta Misra 	return (NULL);
911*dbed73cbSSangeeta Misra }
912*dbed73cbSSangeeta Misra 
913*dbed73cbSSangeeta Misra static ilb_status_t
914*dbed73cbSSangeeta Misra i_delete_srv(ilbd_sg_t *sg, ilbd_srv_t *srv, int ev_port)
915*dbed73cbSSangeeta Misra {
916*dbed73cbSSangeeta Misra 	ilb_status_t	rc;
917*dbed73cbSSangeeta Misra 
918*dbed73cbSSangeeta Misra 	rc = i_rem_srv_frm_krules(&sg->isg_rulelist, &srv->isv_srv, ev_port);
919*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK)
920*dbed73cbSSangeeta Misra 		return (rc);
921*dbed73cbSSangeeta Misra 	list_remove(&sg->isg_srvlist, srv);
922*dbed73cbSSangeeta Misra 	i_ilbd_free_srvID(sg, srv->isv_id);
923*dbed73cbSSangeeta Misra 	free(srv);
924*dbed73cbSSangeeta Misra 	sg->isg_srvcount--;
925*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
926*dbed73cbSSangeeta Misra }
927*dbed73cbSSangeeta Misra 
928*dbed73cbSSangeeta Misra /*
929*dbed73cbSSangeeta Misra  * some people argue that returning anything here is
930*dbed73cbSSangeeta Misra  * useless - what *do* you do if you can't remove/destroy
931*dbed73cbSSangeeta Misra  * something anyway?
932*dbed73cbSSangeeta Misra  */
933*dbed73cbSSangeeta Misra ilb_status_t
934*dbed73cbSSangeeta Misra ilbd_rem_server_from_group(ilb_sg_info_t *sg_info, int ev_port,
935*dbed73cbSSangeeta Misra     const struct passwd *ps, ucred_t *ucredp)
936*dbed73cbSSangeeta Misra {
937*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
938*dbed73cbSSangeeta Misra 	ilbd_sg_t	*tmp_sg;
939*dbed73cbSSangeeta Misra 	ilbd_srv_t	*srv, tmp_srv;
940*dbed73cbSSangeeta Misra 	ilb_sg_srv_t    *tsrv;
941*dbed73cbSSangeeta Misra 	audit_sg_event_data_t   audit_sg_data;
942*dbed73cbSSangeeta Misra 	char    addrstr_buf[INET6_ADDRSTRLEN];
943*dbed73cbSSangeeta Misra 
944*dbed73cbSSangeeta Misra 	rc = ilbd_check_client_config_auth(ps);
945*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK) {
946*dbed73cbSSangeeta Misra 		fill_audit_record(sg_info, &audit_sg_data,
947*dbed73cbSSangeeta Misra 		    ILBD_REM_SERVER_FROM_GROUP, rc, ucredp);
948*dbed73cbSSangeeta Misra 		return (rc);
949*dbed73cbSSangeeta Misra 	}
950*dbed73cbSSangeeta Misra 
951*dbed73cbSSangeeta Misra 	tmp_sg = i_find_sg_byname(sg_info->sg_name);
952*dbed73cbSSangeeta Misra 	if (tmp_sg == NULL) {
953*dbed73cbSSangeeta Misra 		logdebug("%s: server group %s\n does not exist", __func__,
954*dbed73cbSSangeeta Misra 		    sg_info->sg_name);
955*dbed73cbSSangeeta Misra 		fill_audit_record(sg_info, &audit_sg_data,
956*dbed73cbSSangeeta Misra 		    ILBD_REM_SERVER_FROM_GROUP, ILB_STATUS_SGUNAVAIL, ucredp);
957*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGUNAVAIL);
958*dbed73cbSSangeeta Misra 	}
959*dbed73cbSSangeeta Misra 	tsrv = &sg_info->sg_servers[0];
960*dbed73cbSSangeeta Misra 	audit_sg_data.ed_serverid = tsrv->sgs_srvID;
961*dbed73cbSSangeeta Misra 	audit_sg_data.ed_sgroup = sg_info->sg_name;
962*dbed73cbSSangeeta Misra 	audit_sg_data.ed_server_address = NULL;
963*dbed73cbSSangeeta Misra 
964*dbed73cbSSangeeta Misra 	assert(sg_info->sg_srvcount == 1);
965*dbed73cbSSangeeta Misra 	srv = i_find_srv(&tmp_sg->isg_srvlist, &sg_info->sg_servers[0],
966*dbed73cbSSangeeta Misra 	    MODE_SRVID);
967*dbed73cbSSangeeta Misra 	if (srv == NULL) {
968*dbed73cbSSangeeta Misra 		logdebug("%s: cannot find server in server group %s", __func__,
969*dbed73cbSSangeeta Misra 		    sg_info->sg_name);
970*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
971*dbed73cbSSangeeta Misra 		    ILBD_REM_SERVER_FROM_GROUP, ILB_STATUS_SRVUNAVAIL, ucredp);
972*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SRVUNAVAIL);
973*dbed73cbSSangeeta Misra 	}
974*dbed73cbSSangeeta Misra 	tsrv = &srv->isv_srv;
975*dbed73cbSSangeeta Misra 	ilbd_addr2str(&tsrv->sgs_addr, addrstr_buf,
976*dbed73cbSSangeeta Misra 	    sizeof (addrstr_buf));
977*dbed73cbSSangeeta Misra 	audit_sg_data.ed_server_address = addrstr_buf;
978*dbed73cbSSangeeta Misra 	/*
979*dbed73cbSSangeeta Misra 	 * i_delete_srv frees srv, therefore we need to save
980*dbed73cbSSangeeta Misra 	 * this information for ilbd_scf_del_srv
981*dbed73cbSSangeeta Misra 	 */
982*dbed73cbSSangeeta Misra 	(void) memcpy(&tmp_srv, srv, sizeof (tmp_srv));
983*dbed73cbSSangeeta Misra 
984*dbed73cbSSangeeta Misra 	rc = i_delete_srv(tmp_sg, srv, ev_port);
985*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK) {
986*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
987*dbed73cbSSangeeta Misra 		    ILBD_REM_SERVER_FROM_GROUP, rc, ucredp);
988*dbed73cbSSangeeta Misra 		return (rc);
989*dbed73cbSSangeeta Misra 	}
990*dbed73cbSSangeeta Misra 
991*dbed73cbSSangeeta Misra 	if (ps != NULL) {
992*dbed73cbSSangeeta Misra 		if ((rc = ilbd_scf_del_srv(tmp_sg, &tmp_srv)) !=
993*dbed73cbSSangeeta Misra 		    ILB_STATUS_OK) {
994*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
995*dbed73cbSSangeeta Misra 			    ILBD_REM_SERVER_FROM_GROUP, rc, ucredp);
996*dbed73cbSSangeeta Misra 			logerr("%s: SCF update failed - entering maintenance"
997*dbed73cbSSangeeta Misra 			    " mode", __func__);
998*dbed73cbSSangeeta Misra 			(void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE);
999*dbed73cbSSangeeta Misra 		}
1000*dbed73cbSSangeeta Misra 	}
1001*dbed73cbSSangeeta Misra 	ilbd_audit_server_event(&audit_sg_data,
1002*dbed73cbSSangeeta Misra 	    ILBD_REM_SERVER_FROM_GROUP, rc, ucredp);
1003*dbed73cbSSangeeta Misra 	return (rc);
1004*dbed73cbSSangeeta Misra }
1005*dbed73cbSSangeeta Misra 
1006*dbed73cbSSangeeta Misra ilb_status_t
1007*dbed73cbSSangeeta Misra ilbd_retrieve_names(ilbd_cmd_t cmd, uint32_t *rbuf, size_t *rbufsz)
1008*dbed73cbSSangeeta Misra {
1009*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
1010*dbed73cbSSangeeta Misra 	ilbd_namelist_t	*nlist;
1011*dbed73cbSSangeeta Misra 	size_t		tmp_rbufsz;
1012*dbed73cbSSangeeta Misra 
1013*dbed73cbSSangeeta Misra 	tmp_rbufsz = *rbufsz;
1014*dbed73cbSSangeeta Misra 	/* Set up the reply buffer.  rbufsz will be set to the new size. */
1015*dbed73cbSSangeeta Misra 	ilbd_reply_ok(rbuf, rbufsz);
1016*dbed73cbSSangeeta Misra 
1017*dbed73cbSSangeeta Misra 	/* Calculate how much space is left for holding name info. */
1018*dbed73cbSSangeeta Misra 	*rbufsz += sizeof (ilbd_namelist_t);
1019*dbed73cbSSangeeta Misra 	tmp_rbufsz -= *rbufsz;
1020*dbed73cbSSangeeta Misra 
1021*dbed73cbSSangeeta Misra 	nlist = (ilbd_namelist_t *)&((ilb_comm_t *)rbuf)->ic_data;
1022*dbed73cbSSangeeta Misra 	nlist->ilbl_count = 0;
1023*dbed73cbSSangeeta Misra 
1024*dbed73cbSSangeeta Misra 	switch (cmd) {
1025*dbed73cbSSangeeta Misra 	case ILBD_RETRIEVE_SG_NAMES: {
1026*dbed73cbSSangeeta Misra 		ilbd_sg_t	*sg;
1027*dbed73cbSSangeeta Misra 
1028*dbed73cbSSangeeta Misra 		for (sg = list_head(&ilbd_sg_hlist);
1029*dbed73cbSSangeeta Misra 		    sg != NULL && tmp_rbufsz >= sizeof (ilbd_name_t);
1030*dbed73cbSSangeeta Misra 		    sg = list_next(&ilbd_sg_hlist, sg),
1031*dbed73cbSSangeeta Misra 		    tmp_rbufsz -= sizeof (ilbd_name_t)) {
1032*dbed73cbSSangeeta Misra 			(void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++],
1033*dbed73cbSSangeeta Misra 			    sg->isg_name, sizeof (ilbd_name_t));
1034*dbed73cbSSangeeta Misra 		}
1035*dbed73cbSSangeeta Misra 		break;
1036*dbed73cbSSangeeta Misra 	}
1037*dbed73cbSSangeeta Misra 	case ILBD_RETRIEVE_RULE_NAMES: {
1038*dbed73cbSSangeeta Misra 		ilbd_rule_t	*irl;
1039*dbed73cbSSangeeta Misra 		extern list_t	ilbd_rule_hlist;
1040*dbed73cbSSangeeta Misra 
1041*dbed73cbSSangeeta Misra 		for (irl = list_head(&ilbd_rule_hlist);
1042*dbed73cbSSangeeta Misra 		    irl != NULL && tmp_rbufsz >= sizeof (ilbd_name_t);
1043*dbed73cbSSangeeta Misra 		    irl = list_next(&ilbd_rule_hlist, irl),
1044*dbed73cbSSangeeta Misra 		    tmp_rbufsz -= sizeof (ilbd_name_t)) {
1045*dbed73cbSSangeeta Misra 			(void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++],
1046*dbed73cbSSangeeta Misra 			    irl->irl_name, sizeof (ilbd_name_t));
1047*dbed73cbSSangeeta Misra 		}
1048*dbed73cbSSangeeta Misra 		break;
1049*dbed73cbSSangeeta Misra 	}
1050*dbed73cbSSangeeta Misra 	case ILBD_RETRIEVE_HC_NAMES: {
1051*dbed73cbSSangeeta Misra 		extern list_t	ilbd_hc_list;
1052*dbed73cbSSangeeta Misra 		ilbd_hc_t	*hc;
1053*dbed73cbSSangeeta Misra 
1054*dbed73cbSSangeeta Misra 		for (hc = list_head(&ilbd_hc_list);
1055*dbed73cbSSangeeta Misra 		    hc != NULL && tmp_rbufsz >= sizeof (ilbd_name_t);
1056*dbed73cbSSangeeta Misra 		    hc = list_next(&ilbd_hc_list, hc)) {
1057*dbed73cbSSangeeta Misra 			(void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++],
1058*dbed73cbSSangeeta Misra 			    hc->ihc_name, sizeof (ilbd_name_t));
1059*dbed73cbSSangeeta Misra 		}
1060*dbed73cbSSangeeta Misra 		break;
1061*dbed73cbSSangeeta Misra 	}
1062*dbed73cbSSangeeta Misra 	default:
1063*dbed73cbSSangeeta Misra 		logdebug("ilbd_retrieve_names: unknown command");
1064*dbed73cbSSangeeta Misra 		return (ILB_STATUS_INVAL_CMD);
1065*dbed73cbSSangeeta Misra 	}
1066*dbed73cbSSangeeta Misra 
1067*dbed73cbSSangeeta Misra 	*rbufsz += nlist->ilbl_count * sizeof (ilbd_name_t);
1068*dbed73cbSSangeeta Misra 	return (rc);
1069*dbed73cbSSangeeta Misra }
1070*dbed73cbSSangeeta Misra 
1071*dbed73cbSSangeeta Misra ilb_status_t
1072*dbed73cbSSangeeta Misra ilbd_retrieve_sg_hosts(const char *sg_name, uint32_t *rbuf, size_t *rbufsz)
1073*dbed73cbSSangeeta Misra {
1074*dbed73cbSSangeeta Misra 	ilbd_sg_t	*dsg;
1075*dbed73cbSSangeeta Misra 	ilbd_srv_t	*dsrv;
1076*dbed73cbSSangeeta Misra 	list_t		*srvlist;
1077*dbed73cbSSangeeta Misra 	ilb_sg_info_t	*sg_info;
1078*dbed73cbSSangeeta Misra 	size_t		tmp_rbufsz;
1079*dbed73cbSSangeeta Misra 
1080*dbed73cbSSangeeta Misra 	dsg = i_find_sg_byname(sg_name);
1081*dbed73cbSSangeeta Misra 	if (dsg == NULL) {
1082*dbed73cbSSangeeta Misra 		logdebug("ilbd_retrieve_sg_hosts: server group"
1083*dbed73cbSSangeeta Misra 		    " %s not found", sg_name);
1084*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGUNAVAIL);
1085*dbed73cbSSangeeta Misra 	}
1086*dbed73cbSSangeeta Misra 
1087*dbed73cbSSangeeta Misra 	srvlist = &dsg->isg_srvlist;
1088*dbed73cbSSangeeta Misra 	dsrv = list_head(srvlist);
1089*dbed73cbSSangeeta Misra 
1090*dbed73cbSSangeeta Misra 	tmp_rbufsz = *rbufsz;
1091*dbed73cbSSangeeta Misra 	ilbd_reply_ok(rbuf, rbufsz);
1092*dbed73cbSSangeeta Misra 
1093*dbed73cbSSangeeta Misra 	/* Calculate the size to hold all the hosts info. */
1094*dbed73cbSSangeeta Misra 	*rbufsz += sizeof (ilb_sg_info_t);
1095*dbed73cbSSangeeta Misra 	tmp_rbufsz -= *rbufsz;
1096*dbed73cbSSangeeta Misra 
1097*dbed73cbSSangeeta Misra 	sg_info = (ilb_sg_info_t *)&((ilb_comm_t *)rbuf)->ic_data;
1098*dbed73cbSSangeeta Misra 	(void) strlcpy(sg_info->sg_name, sg_name, sizeof (sg_info->sg_name));
1099*dbed73cbSSangeeta Misra 	sg_info->sg_srvcount = 0;
1100*dbed73cbSSangeeta Misra 
1101*dbed73cbSSangeeta Misra 	while (dsrv != NULL && tmp_rbufsz >= sizeof (ilb_sg_srv_t)) {
1102*dbed73cbSSangeeta Misra 		sg_info->sg_servers[sg_info->sg_srvcount++] = dsrv->isv_srv;
1103*dbed73cbSSangeeta Misra 		dsrv = list_next(srvlist, dsrv);
1104*dbed73cbSSangeeta Misra 		tmp_rbufsz -= sizeof (ilb_sg_srv_t);
1105*dbed73cbSSangeeta Misra 	}
1106*dbed73cbSSangeeta Misra 	*rbufsz += sg_info->sg_srvcount * sizeof (ilb_sg_srv_t);
1107*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
1108*dbed73cbSSangeeta Misra }
1109*dbed73cbSSangeeta Misra 
1110*dbed73cbSSangeeta Misra /*
1111*dbed73cbSSangeeta Misra  * this mapping function works on the assumption that HC only is
1112*dbed73cbSSangeeta Misra  * active when a server is enabled.
1113*dbed73cbSSangeeta Misra  */
1114*dbed73cbSSangeeta Misra static ilb_cmd_t
1115*dbed73cbSSangeeta Misra i_srvcmd_d2k(ilbd_srv_status_ind_t dcmd)
1116*dbed73cbSSangeeta Misra {
1117*dbed73cbSSangeeta Misra 	ilb_cmd_t	cmd;
1118*dbed73cbSSangeeta Misra 
1119*dbed73cbSSangeeta Misra 	switch (dcmd) {
1120*dbed73cbSSangeeta Misra 	case stat_enable_server:
1121*dbed73cbSSangeeta Misra 	case stat_declare_srv_alive:
1122*dbed73cbSSangeeta Misra 		cmd = ILB_ENABLE_SERVERS;
1123*dbed73cbSSangeeta Misra 		break;
1124*dbed73cbSSangeeta Misra 	case stat_disable_server:
1125*dbed73cbSSangeeta Misra 	case stat_declare_srv_dead:
1126*dbed73cbSSangeeta Misra 		cmd = ILB_DISABLE_SERVERS;
1127*dbed73cbSSangeeta Misra 		break;
1128*dbed73cbSSangeeta Misra 	}
1129*dbed73cbSSangeeta Misra 
1130*dbed73cbSSangeeta Misra 	return (cmd);
1131*dbed73cbSSangeeta Misra }
1132*dbed73cbSSangeeta Misra 
1133*dbed73cbSSangeeta Misra ilb_status_t
1134*dbed73cbSSangeeta Misra ilbd_k_Xable_server(const struct in6_addr *addr, const char *rlname,
1135*dbed73cbSSangeeta Misra     ilbd_srv_status_ind_t cmd)
1136*dbed73cbSSangeeta Misra {
1137*dbed73cbSSangeeta Misra 	ilb_status_t		rc;
1138*dbed73cbSSangeeta Misra 	ilb_servers_cmd_t	kcmd;
1139*dbed73cbSSangeeta Misra 	int			e;
1140*dbed73cbSSangeeta Misra 
1141*dbed73cbSSangeeta Misra 	kcmd.cmd = i_srvcmd_d2k(cmd);
1142*dbed73cbSSangeeta Misra 	(void) strlcpy(kcmd.name, rlname, sizeof (kcmd.name));
1143*dbed73cbSSangeeta Misra 	kcmd.num_servers = 1;
1144*dbed73cbSSangeeta Misra 
1145*dbed73cbSSangeeta Misra 	kcmd.servers[0].addr = *addr;
1146*dbed73cbSSangeeta Misra 	kcmd.servers[0].err = 0;
1147*dbed73cbSSangeeta Misra 
1148*dbed73cbSSangeeta Misra 	rc = do_ioctl(&kcmd, 0);
1149*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK)
1150*dbed73cbSSangeeta Misra 		return (rc);
1151*dbed73cbSSangeeta Misra 
1152*dbed73cbSSangeeta Misra 	if ((e = kcmd.servers[0].err) != 0) {
1153*dbed73cbSSangeeta Misra 		logdebug("ilbd_k_Xable_server: error %s occurred",
1154*dbed73cbSSangeeta Misra 		    strerror(e));
1155*dbed73cbSSangeeta Misra 		return (ilb_map_errno2ilbstat(e));
1156*dbed73cbSSangeeta Misra 	}
1157*dbed73cbSSangeeta Misra 
1158*dbed73cbSSangeeta Misra 	return (rc);
1159*dbed73cbSSangeeta Misra }
1160*dbed73cbSSangeeta Misra 
1161*dbed73cbSSangeeta Misra #define	IS_SRV_ENABLED(s)	ILB_IS_SRV_ENABLED((s)->sgs_flags)
1162*dbed73cbSSangeeta Misra #define	IS_SRV_DISABLED(s)	(!(IS_SRV_ENABLED(s)))
1163*dbed73cbSSangeeta Misra 
1164*dbed73cbSSangeeta Misra #define	SET_SRV_ENABLED(s)	ILB_SET_ENABLED((s)->sgs_flags)
1165*dbed73cbSSangeeta Misra #define	SET_SRV_DISABLED(s)	ILB_SET_DISABLED((s)->sgs_flags)
1166*dbed73cbSSangeeta Misra 
1167*dbed73cbSSangeeta Misra static ilb_status_t
1168*dbed73cbSSangeeta Misra ilbd_Xable_server(ilb_sg_info_t *sg, const struct passwd *ps,
1169*dbed73cbSSangeeta Misra     ilbd_srv_status_ind_t cmd, ucred_t *ucredp)
1170*dbed73cbSSangeeta Misra {
1171*dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
1172*dbed73cbSSangeeta Misra 	ilbd_sg_t	*isg;
1173*dbed73cbSSangeeta Misra 	ilbd_srv_t	*tmp_srv;
1174*dbed73cbSSangeeta Misra 	ilb_sg_srv_t 	*srv;
1175*dbed73cbSSangeeta Misra 	ilbd_rule_t	*irl;
1176*dbed73cbSSangeeta Misra 	char		*dot;
1177*dbed73cbSSangeeta Misra 	int		scf_name_len = ILBD_MAX_NAME_LEN;
1178*dbed73cbSSangeeta Misra 	int		scf_val_len = ILBD_MAX_VALUE_LEN;
1179*dbed73cbSSangeeta Misra 	char		prop_name[scf_name_len];
1180*dbed73cbSSangeeta Misra 	ilb_ip_addr_t	ipaddr;
1181*dbed73cbSSangeeta Misra 	void		*addrptr;
1182*dbed73cbSSangeeta Misra 	char		ipstr[INET6_ADDRSTRLEN], valstr[scf_val_len];
1183*dbed73cbSSangeeta Misra 	int		ipver, vallen;
1184*dbed73cbSSangeeta Misra 	char		sgname[ILB_NAMESZ];
1185*dbed73cbSSangeeta Misra 	uint32_t	nflags;
1186*dbed73cbSSangeeta Misra 	ilbd_srv_status_ind_t u_cmd;
1187*dbed73cbSSangeeta Misra 	audit_sg_event_data_t   audit_sg_data;
1188*dbed73cbSSangeeta Misra 	char    addrstr_buf[INET6_ADDRSTRLEN];
1189*dbed73cbSSangeeta Misra 
1190*dbed73cbSSangeeta Misra 	(void) memset(&audit_sg_data, 0, sizeof (audit_sg_data));
1191*dbed73cbSSangeeta Misra 
1192*dbed73cbSSangeeta Misra 	/* we currently only implement a "list" of one */
1193*dbed73cbSSangeeta Misra 	assert(sg->sg_srvcount == 1);
1194*dbed73cbSSangeeta Misra 
1195*dbed73cbSSangeeta Misra 	srv = &sg->sg_servers[0];
1196*dbed73cbSSangeeta Misra 	audit_sg_data.ed_serverid = srv->sgs_srvID;
1197*dbed73cbSSangeeta Misra 	audit_sg_data.ed_server_address = NULL;
1198*dbed73cbSSangeeta Misra 
1199*dbed73cbSSangeeta Misra 	rc = ilbd_check_client_enable_auth(ps);
1200*dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK) {
1201*dbed73cbSSangeeta Misra 		ilbd_audit_server_event(&audit_sg_data,
1202*dbed73cbSSangeeta Misra 		    ILBD_ENABLE_SERVER, rc, ucredp);
1203*dbed73cbSSangeeta Misra 		return (rc);
1204*dbed73cbSSangeeta Misra 	}
1205*dbed73cbSSangeeta Misra 
1206*dbed73cbSSangeeta Misra 	if (srv->sgs_srvID[0] != ILB_SRVID_PREFIX) {
1207*dbed73cbSSangeeta Misra 		switch (cmd) {
1208*dbed73cbSSangeeta Misra 		case stat_disable_server:
1209*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1210*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER,
1211*dbed73cbSSangeeta Misra 			    ILB_STATUS_EINVAL, ucredp);
1212*dbed73cbSSangeeta Misra 			break;
1213*dbed73cbSSangeeta Misra 		case stat_enable_server:
1214*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1215*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER,
1216*dbed73cbSSangeeta Misra 			    ILB_STATUS_EINVAL, ucredp);
1217*dbed73cbSSangeeta Misra 			break;
1218*dbed73cbSSangeeta Misra 		}
1219*dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1220*dbed73cbSSangeeta Misra 	}
1221*dbed73cbSSangeeta Misra 
1222*dbed73cbSSangeeta Misra 	/*
1223*dbed73cbSSangeeta Misra 	 * the following asserts that serverIDs are constructed
1224*dbed73cbSSangeeta Misra 	 * along the pattern "_"<SG name>"."<number>
1225*dbed73cbSSangeeta Misra 	 * so we look for the final "." to recreate the SG name.
1226*dbed73cbSSangeeta Misra 	 */
1227*dbed73cbSSangeeta Misra 	(void) strlcpy(sgname, srv->sgs_srvID + 1, sizeof (sgname));
1228*dbed73cbSSangeeta Misra 	dot = strrchr(sgname, (int)'.');
1229*dbed73cbSSangeeta Misra 	if (dot == NULL) {
1230*dbed73cbSSangeeta Misra 		switch (cmd) {
1231*dbed73cbSSangeeta Misra 		case stat_disable_server:
1232*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1233*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER,
1234*dbed73cbSSangeeta Misra 			    ILB_STATUS_EINVAL, ucredp);
1235*dbed73cbSSangeeta Misra 			break;
1236*dbed73cbSSangeeta Misra 		case stat_enable_server:
1237*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1238*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER,
1239*dbed73cbSSangeeta Misra 			    ILB_STATUS_EINVAL, ucredp);
1240*dbed73cbSSangeeta Misra 			break;
1241*dbed73cbSSangeeta Misra 		}
1242*dbed73cbSSangeeta Misra 		return (ILB_STATUS_EINVAL);
1243*dbed73cbSSangeeta Misra 	}
1244*dbed73cbSSangeeta Misra 
1245*dbed73cbSSangeeta Misra 	/* make the non-sg_name part "invisible" */
1246*dbed73cbSSangeeta Misra 	*dot = '\0';
1247*dbed73cbSSangeeta Misra 	isg = i_find_sg_byname(sgname);
1248*dbed73cbSSangeeta Misra 	if (isg == NULL) {
1249*dbed73cbSSangeeta Misra 		switch (cmd) {
1250*dbed73cbSSangeeta Misra 		case stat_disable_server:
1251*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1252*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER,
1253*dbed73cbSSangeeta Misra 			    ILB_STATUS_ENOENT, ucredp);
1254*dbed73cbSSangeeta Misra 			break;
1255*dbed73cbSSangeeta Misra 		case stat_enable_server:
1256*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1257*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER,
1258*dbed73cbSSangeeta Misra 			    ILB_STATUS_ENOENT, ucredp);
1259*dbed73cbSSangeeta Misra 			break;
1260*dbed73cbSSangeeta Misra 		}
1261*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
1262*dbed73cbSSangeeta Misra 	}
1263*dbed73cbSSangeeta Misra 
1264*dbed73cbSSangeeta Misra 	tmp_srv = i_find_srv(&isg->isg_srvlist, srv, MODE_SRVID);
1265*dbed73cbSSangeeta Misra 	if (tmp_srv == NULL) {
1266*dbed73cbSSangeeta Misra 		switch (cmd) {
1267*dbed73cbSSangeeta Misra 		case stat_disable_server:
1268*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1269*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER,
1270*dbed73cbSSangeeta Misra 			    ILB_STATUS_ENOENT, ucredp);
1271*dbed73cbSSangeeta Misra 			break;
1272*dbed73cbSSangeeta Misra 		case stat_enable_server:
1273*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1274*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER,
1275*dbed73cbSSangeeta Misra 			    ILB_STATUS_ENOENT, ucredp);
1276*dbed73cbSSangeeta Misra 			break;
1277*dbed73cbSSangeeta Misra 		}
1278*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
1279*dbed73cbSSangeeta Misra 	}
1280*dbed73cbSSangeeta Misra 
1281*dbed73cbSSangeeta Misra 	/*
1282*dbed73cbSSangeeta Misra 	 * if server's servergroup is not associated with
1283*dbed73cbSSangeeta Misra 	 * a rule, do not enable it.
1284*dbed73cbSSangeeta Misra 	 */
1285*dbed73cbSSangeeta Misra 	irl = list_head(&isg->isg_rulelist);
1286*dbed73cbSSangeeta Misra 	if (irl == NULL) {
1287*dbed73cbSSangeeta Misra 		switch (cmd) {
1288*dbed73cbSSangeeta Misra 		case stat_disable_server:
1289*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1290*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER,
1291*dbed73cbSSangeeta Misra 			    ILB_STATUS_INVAL_ENBSRVR, ucredp);
1292*dbed73cbSSangeeta Misra 			break;
1293*dbed73cbSSangeeta Misra 		case stat_enable_server:
1294*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1295*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER,
1296*dbed73cbSSangeeta Misra 			    ILB_STATUS_INVAL_ENBSRVR, ucredp);
1297*dbed73cbSSangeeta Misra 			break;
1298*dbed73cbSSangeeta Misra 		}
1299*dbed73cbSSangeeta Misra 		return (ILB_STATUS_INVAL_ENBSRVR);
1300*dbed73cbSSangeeta Misra 	}
1301*dbed73cbSSangeeta Misra 	/* Fill in the server IP address for audit record */
1302*dbed73cbSSangeeta Misra 	ilbd_addr2str(&tmp_srv->isv_addr, addrstr_buf,
1303*dbed73cbSSangeeta Misra 	    sizeof (addrstr_buf));
1304*dbed73cbSSangeeta Misra 	audit_sg_data.ed_server_address = addrstr_buf;
1305*dbed73cbSSangeeta Misra 
1306*dbed73cbSSangeeta Misra 	/*
1307*dbed73cbSSangeeta Misra 	 * We have found the server in memory, perform the following
1308*dbed73cbSSangeeta Misra 	 * tasks.
1309*dbed73cbSSangeeta Misra 	 *
1310*dbed73cbSSangeeta Misra 	 * 1. For every rule associated with this SG,
1311*dbed73cbSSangeeta Misra 	 *    - tell the kernel
1312*dbed73cbSSangeeta Misra 	 *    - tell the hc
1313*dbed73cbSSangeeta Misra 	 * 2. Update our internal state and persistent configuration
1314*dbed73cbSSangeeta Misra 	 *    if the new state is not the same as the old one.
1315*dbed73cbSSangeeta Misra 	 */
1316*dbed73cbSSangeeta Misra 	/* 1. */
1317*dbed73cbSSangeeta Misra 	for (; irl != NULL; irl = list_next(&isg->isg_rulelist, irl)) {
1318*dbed73cbSSangeeta Misra 		rc = ilbd_k_Xable_server(&tmp_srv->isv_addr,
1319*dbed73cbSSangeeta Misra 		    irl->irl_name, cmd);
1320*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
1321*dbed73cbSSangeeta Misra 			switch (cmd) {
1322*dbed73cbSSangeeta Misra 			case stat_disable_server:
1323*dbed73cbSSangeeta Misra 				ilbd_audit_server_event(&audit_sg_data,
1324*dbed73cbSSangeeta Misra 				    ILBD_DISABLE_SERVER, rc, ucredp);
1325*dbed73cbSSangeeta Misra 				break;
1326*dbed73cbSSangeeta Misra 			case stat_enable_server:
1327*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1328*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER, rc, ucredp);
1329*dbed73cbSSangeeta Misra 			break;
1330*dbed73cbSSangeeta Misra 			}
1331*dbed73cbSSangeeta Misra 			goto rollback_rules;
1332*dbed73cbSSangeeta Misra 		}
1333*dbed73cbSSangeeta Misra 		if (!RULE_HAS_HC(irl))
1334*dbed73cbSSangeeta Misra 			continue;
1335*dbed73cbSSangeeta Misra 
1336*dbed73cbSSangeeta Misra 		if (cmd == stat_disable_server) {
1337*dbed73cbSSangeeta Misra 			rc = ilbd_hc_disable_server(irl,
1338*dbed73cbSSangeeta Misra 			    &tmp_srv->isv_srv);
1339*dbed73cbSSangeeta Misra 		} else {
1340*dbed73cbSSangeeta Misra 			assert(cmd == stat_enable_server);
1341*dbed73cbSSangeeta Misra 			rc = ilbd_hc_enable_server(irl,
1342*dbed73cbSSangeeta Misra 			    &tmp_srv->isv_srv);
1343*dbed73cbSSangeeta Misra 		}
1344*dbed73cbSSangeeta Misra 		if (rc != ILB_STATUS_OK) {
1345*dbed73cbSSangeeta Misra 			logdebug("ilbd_Xable_server: cannot toggle srv "
1346*dbed73cbSSangeeta Misra 			    "timer, rc =%d, srv =%s%d\n", rc,
1347*dbed73cbSSangeeta Misra 			    tmp_srv->isv_srvID,
1348*dbed73cbSSangeeta Misra 			    tmp_srv->isv_id);
1349*dbed73cbSSangeeta Misra 		}
1350*dbed73cbSSangeeta Misra 	}
1351*dbed73cbSSangeeta Misra 
1352*dbed73cbSSangeeta Misra 	/* 2. */
1353*dbed73cbSSangeeta Misra 	if ((cmd == stat_disable_server &&
1354*dbed73cbSSangeeta Misra 	    IS_SRV_DISABLED(&tmp_srv->isv_srv)) ||
1355*dbed73cbSSangeeta Misra 	    (cmd == stat_enable_server &&
1356*dbed73cbSSangeeta Misra 	    IS_SRV_ENABLED(&tmp_srv->isv_srv))) {
1357*dbed73cbSSangeeta Misra 		switch (cmd) {
1358*dbed73cbSSangeeta Misra 		case stat_disable_server:
1359*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1360*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER, ILB_STATUS_OK, ucredp);
1361*dbed73cbSSangeeta Misra 			break;
1362*dbed73cbSSangeeta Misra 		case stat_enable_server:
1363*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1364*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER, ILB_STATUS_OK, ucredp);
1365*dbed73cbSSangeeta Misra 			break;
1366*dbed73cbSSangeeta Misra 		}
1367*dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
1368*dbed73cbSSangeeta Misra 	}
1369*dbed73cbSSangeeta Misra 
1370*dbed73cbSSangeeta Misra 	nflags = tmp_srv->isv_flags;
1371*dbed73cbSSangeeta Misra 	if (cmd == stat_enable_server)
1372*dbed73cbSSangeeta Misra 		ILB_SET_ENABLED(nflags);
1373*dbed73cbSSangeeta Misra 	else
1374*dbed73cbSSangeeta Misra 		ILB_SET_DISABLED(nflags);
1375*dbed73cbSSangeeta Misra 
1376*dbed73cbSSangeeta Misra 	IP_COPY_IMPL_2_CLI(&tmp_srv->isv_addr, &ipaddr);
1377*dbed73cbSSangeeta Misra 	ipver = GET_AF(&tmp_srv->isv_addr);
1378*dbed73cbSSangeeta Misra 	vallen = (ipver == AF_INET) ? INET_ADDRSTRLEN :
1379*dbed73cbSSangeeta Misra 	    INET6_ADDRSTRLEN;
1380*dbed73cbSSangeeta Misra 	addrptr = (ipver == AF_INET) ? (void *)&ipaddr.ia_v4 :
1381*dbed73cbSSangeeta Misra 	    (void *)&ipaddr.ia_v6;
1382*dbed73cbSSangeeta Misra 	if (inet_ntop(ipver, addrptr, ipstr, vallen) == NULL) {
1383*dbed73cbSSangeeta Misra 		logerr("ilbd_Xable_server: failed transfer ip addr to"
1384*dbed73cbSSangeeta Misra 		    " str");
1385*dbed73cbSSangeeta Misra 		if (errno == ENOSPC)
1386*dbed73cbSSangeeta Misra 			rc = ILB_STATUS_ENOMEM;
1387*dbed73cbSSangeeta Misra 		else
1388*dbed73cbSSangeeta Misra 			rc = ILB_STATUS_GENERIC;
1389*dbed73cbSSangeeta Misra 		switch (cmd) {
1390*dbed73cbSSangeeta Misra 		case stat_disable_server:
1391*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1392*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER, rc, ucredp);
1393*dbed73cbSSangeeta Misra 			break;
1394*dbed73cbSSangeeta Misra 		case stat_enable_server:
1395*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1396*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER, rc, ucredp);
1397*dbed73cbSSangeeta Misra 			break;
1398*dbed73cbSSangeeta Misra 		}
1399*dbed73cbSSangeeta Misra 		goto rollback_rules;
1400*dbed73cbSSangeeta Misra 	}
1401*dbed73cbSSangeeta Misra 
1402*dbed73cbSSangeeta Misra 	(void) snprintf(valstr, sizeof (valstr), "%s;%d;%d-%d;%d",
1403*dbed73cbSSangeeta Misra 	    ipstr, ipver,
1404*dbed73cbSSangeeta Misra 	    ntohs(tmp_srv->isv_minport),
1405*dbed73cbSSangeeta Misra 	    ntohs(tmp_srv->isv_maxport), nflags);
1406*dbed73cbSSangeeta Misra 	(void) snprintf(prop_name, sizeof (prop_name), "server%d",
1407*dbed73cbSSangeeta Misra 	    tmp_srv->isv_id);
1408*dbed73cbSSangeeta Misra 
1409*dbed73cbSSangeeta Misra 	switch (cmd) {
1410*dbed73cbSSangeeta Misra 	case stat_disable_server:
1411*dbed73cbSSangeeta Misra 		rc = i_ilbd_save_sg(isg, ILBD_SCF_ENABLE_DISABLE,
1412*dbed73cbSSangeeta Misra 		    prop_name, valstr);
1413*dbed73cbSSangeeta Misra 		if (rc == ILB_STATUS_OK)
1414*dbed73cbSSangeeta Misra 			SET_SRV_DISABLED(&tmp_srv->isv_srv);
1415*dbed73cbSSangeeta Misra 		break;
1416*dbed73cbSSangeeta Misra 	case stat_enable_server:
1417*dbed73cbSSangeeta Misra 		rc = i_ilbd_save_sg(isg, ILBD_SCF_ENABLE_DISABLE,
1418*dbed73cbSSangeeta Misra 		    prop_name, valstr);
1419*dbed73cbSSangeeta Misra 		if (rc == ILB_STATUS_OK)
1420*dbed73cbSSangeeta Misra 			SET_SRV_ENABLED(&tmp_srv->isv_srv);
1421*dbed73cbSSangeeta Misra 		break;
1422*dbed73cbSSangeeta Misra 	}
1423*dbed73cbSSangeeta Misra 	if (rc == ILB_STATUS_OK) {
1424*dbed73cbSSangeeta Misra 		switch (cmd) {
1425*dbed73cbSSangeeta Misra 		case stat_disable_server:
1426*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1427*dbed73cbSSangeeta Misra 			    ILBD_DISABLE_SERVER, ILB_STATUS_OK, ucredp);
1428*dbed73cbSSangeeta Misra 			break;
1429*dbed73cbSSangeeta Misra 		case stat_enable_server:
1430*dbed73cbSSangeeta Misra 			ilbd_audit_server_event(&audit_sg_data,
1431*dbed73cbSSangeeta Misra 			    ILBD_ENABLE_SERVER, ILB_STATUS_OK, ucredp);
1432*dbed73cbSSangeeta Misra 			break;
1433*dbed73cbSSangeeta Misra 		}
1434*dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
1435*dbed73cbSSangeeta Misra 	}
1436*dbed73cbSSangeeta Misra 
1437*dbed73cbSSangeeta Misra rollback_rules:
1438*dbed73cbSSangeeta Misra 	if (cmd == stat_disable_server)
1439*dbed73cbSSangeeta Misra 		u_cmd = stat_enable_server;
1440*dbed73cbSSangeeta Misra 	else
1441*dbed73cbSSangeeta Misra 		u_cmd = stat_disable_server;
1442*dbed73cbSSangeeta Misra 
1443*dbed73cbSSangeeta Misra 	if (irl == NULL)
1444*dbed73cbSSangeeta Misra 		irl = list_tail(&isg->isg_rulelist);
1445*dbed73cbSSangeeta Misra 	else
1446*dbed73cbSSangeeta Misra 		irl = list_prev(&isg->isg_rulelist, irl);
1447*dbed73cbSSangeeta Misra 
1448*dbed73cbSSangeeta Misra 	for (; irl != NULL; irl = list_prev(&isg->isg_rulelist, irl)) {
1449*dbed73cbSSangeeta Misra 		(void) ilbd_k_Xable_server(&tmp_srv->isv_addr,
1450*dbed73cbSSangeeta Misra 		    irl->irl_name, u_cmd);
1451*dbed73cbSSangeeta Misra 		if (!RULE_HAS_HC(irl))
1452*dbed73cbSSangeeta Misra 			continue;
1453*dbed73cbSSangeeta Misra 
1454*dbed73cbSSangeeta Misra 		if (u_cmd == stat_disable_server)
1455*dbed73cbSSangeeta Misra 			(void) ilbd_hc_disable_server(irl, &tmp_srv->isv_srv);
1456*dbed73cbSSangeeta Misra 		else
1457*dbed73cbSSangeeta Misra 			(void) ilbd_hc_enable_server(irl, &tmp_srv->isv_srv);
1458*dbed73cbSSangeeta Misra 	}
1459*dbed73cbSSangeeta Misra 
1460*dbed73cbSSangeeta Misra 	return (rc);
1461*dbed73cbSSangeeta Misra }
1462*dbed73cbSSangeeta Misra 
1463*dbed73cbSSangeeta Misra ilb_status_t
1464*dbed73cbSSangeeta Misra ilbd_disable_server(ilb_sg_info_t *sg, const struct passwd *ps,
1465*dbed73cbSSangeeta Misra     ucred_t *ucredp)
1466*dbed73cbSSangeeta Misra {
1467*dbed73cbSSangeeta Misra 	return (ilbd_Xable_server(sg, ps, stat_disable_server, ucredp));
1468*dbed73cbSSangeeta Misra }
1469*dbed73cbSSangeeta Misra 
1470*dbed73cbSSangeeta Misra ilb_status_t
1471*dbed73cbSSangeeta Misra ilbd_enable_server(ilb_sg_info_t *sg, const struct passwd *ps,
1472*dbed73cbSSangeeta Misra     ucred_t *ucredp)
1473*dbed73cbSSangeeta Misra {
1474*dbed73cbSSangeeta Misra 	return (ilbd_Xable_server(sg, ps, stat_enable_server, ucredp));
1475*dbed73cbSSangeeta Misra }
1476*dbed73cbSSangeeta Misra 
1477*dbed73cbSSangeeta Misra /*
1478*dbed73cbSSangeeta Misra  * fill in the srvID for the given IP address in the 0th server
1479*dbed73cbSSangeeta Misra  */
1480*dbed73cbSSangeeta Misra ilb_status_t
1481*dbed73cbSSangeeta Misra ilbd_address_to_srvID(ilb_sg_info_t *sg, uint32_t *rbuf, size_t *rbufsz)
1482*dbed73cbSSangeeta Misra {
1483*dbed73cbSSangeeta Misra 	ilbd_srv_t 	*tmp_srv;
1484*dbed73cbSSangeeta Misra 	ilb_sg_srv_t 	*tsrv;
1485*dbed73cbSSangeeta Misra 	ilbd_sg_t	*tmp_sg;
1486*dbed73cbSSangeeta Misra 
1487*dbed73cbSSangeeta Misra 	ilbd_reply_ok(rbuf, rbufsz);
1488*dbed73cbSSangeeta Misra 	tsrv = (ilb_sg_srv_t *)&((ilb_comm_t *)rbuf)->ic_data;
1489*dbed73cbSSangeeta Misra 	*rbufsz += sizeof (ilb_sg_srv_t);
1490*dbed73cbSSangeeta Misra 
1491*dbed73cbSSangeeta Misra 	tmp_sg = i_find_sg_byname(sg->sg_name);
1492*dbed73cbSSangeeta Misra 	if (tmp_sg == NULL)
1493*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGUNAVAIL);
1494*dbed73cbSSangeeta Misra 	tsrv->sgs_addr = sg->sg_servers[0].sgs_addr;
1495*dbed73cbSSangeeta Misra 
1496*dbed73cbSSangeeta Misra 	tmp_srv = i_find_srv(&tmp_sg->isg_srvlist, tsrv, MODE_ADDR);
1497*dbed73cbSSangeeta Misra 	if (tmp_srv == NULL)
1498*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
1499*dbed73cbSSangeeta Misra 
1500*dbed73cbSSangeeta Misra 	(void) strlcpy(tsrv->sgs_srvID, tmp_srv->isv_srvID,
1501*dbed73cbSSangeeta Misra 	    sizeof (tsrv->sgs_srvID));
1502*dbed73cbSSangeeta Misra 
1503*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
1504*dbed73cbSSangeeta Misra }
1505*dbed73cbSSangeeta Misra 
1506*dbed73cbSSangeeta Misra /*
1507*dbed73cbSSangeeta Misra  * fill in the address for the given serverID in the 0th server
1508*dbed73cbSSangeeta Misra  */
1509*dbed73cbSSangeeta Misra ilb_status_t
1510*dbed73cbSSangeeta Misra ilbd_srvID_to_address(ilb_sg_info_t *sg, uint32_t *rbuf, size_t *rbufsz)
1511*dbed73cbSSangeeta Misra {
1512*dbed73cbSSangeeta Misra 	ilbd_srv_t 	*tmp_srv;
1513*dbed73cbSSangeeta Misra 	ilb_sg_srv_t 	*tsrv;
1514*dbed73cbSSangeeta Misra 	ilbd_sg_t	*tmp_sg;
1515*dbed73cbSSangeeta Misra 
1516*dbed73cbSSangeeta Misra 	ilbd_reply_ok(rbuf, rbufsz);
1517*dbed73cbSSangeeta Misra 	tsrv = (ilb_sg_srv_t *)&((ilb_comm_t *)rbuf)->ic_data;
1518*dbed73cbSSangeeta Misra 
1519*dbed73cbSSangeeta Misra 	tmp_sg = i_find_sg_byname(sg->sg_name);
1520*dbed73cbSSangeeta Misra 	if (tmp_sg == NULL)
1521*dbed73cbSSangeeta Misra 		return (ILB_STATUS_SGUNAVAIL);
1522*dbed73cbSSangeeta Misra 	(void) strlcpy(tsrv->sgs_srvID, sg->sg_servers[0].sgs_srvID,
1523*dbed73cbSSangeeta Misra 	    sizeof (tsrv->sgs_srvID));
1524*dbed73cbSSangeeta Misra 
1525*dbed73cbSSangeeta Misra 	tmp_srv = i_find_srv(&tmp_sg->isg_srvlist, tsrv, MODE_SRVID);
1526*dbed73cbSSangeeta Misra 	if (tmp_srv == NULL)
1527*dbed73cbSSangeeta Misra 		return (ILB_STATUS_ENOENT);
1528*dbed73cbSSangeeta Misra 
1529*dbed73cbSSangeeta Misra 	tsrv->sgs_addr = tmp_srv->isv_addr;
1530*dbed73cbSSangeeta Misra 	*rbufsz += sizeof (ilb_sg_srv_t);
1531*dbed73cbSSangeeta Misra 
1532*dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
1533*dbed73cbSSangeeta Misra }
1534*dbed73cbSSangeeta Misra 
1535*dbed73cbSSangeeta Misra void
1536*dbed73cbSSangeeta Misra ilbd_addr2str(struct in6_addr *ipaddr, char *addrstr_buf, size_t sz)
1537*dbed73cbSSangeeta Misra {
1538*dbed73cbSSangeeta Misra 	ilb_ip_addr_t	ilb_ip;
1539*dbed73cbSSangeeta Misra 
1540*dbed73cbSSangeeta Misra 	IP_COPY_IMPL_2_CLI(ipaddr, &ilb_ip);
1541*dbed73cbSSangeeta Misra 	addr2str(ilb_ip, addrstr_buf, sz);
1542*dbed73cbSSangeeta Misra }
1543*dbed73cbSSangeeta Misra 
1544*dbed73cbSSangeeta Misra /* Convert ip address to a address string */
1545*dbed73cbSSangeeta Misra void
1546*dbed73cbSSangeeta Misra addr2str(ilb_ip_addr_t ip, char *buf, size_t sz)
1547*dbed73cbSSangeeta Misra {
1548*dbed73cbSSangeeta Misra 
1549*dbed73cbSSangeeta Misra 	switch (ip.ia_af) {
1550*dbed73cbSSangeeta Misra 	case AF_INET:
1551*dbed73cbSSangeeta Misra 		if ((uint32_t *)&(ip).ia_v4 == 0)
1552*dbed73cbSSangeeta Misra 			buf[0] = '\0';
1553*dbed73cbSSangeeta Misra 		else
1554*dbed73cbSSangeeta Misra 			(void) inet_ntop(AF_INET, (void *)&(ip).ia_v4, buf, sz);
1555*dbed73cbSSangeeta Misra 		break;
1556*dbed73cbSSangeeta Misra 	case AF_INET6:
1557*dbed73cbSSangeeta Misra 		if (IN6_IS_ADDR_UNSPECIFIED(&(ip).ia_v6)) {
1558*dbed73cbSSangeeta Misra 			buf[0] = '\0';
1559*dbed73cbSSangeeta Misra 			break;
1560*dbed73cbSSangeeta Misra 		}
1561*dbed73cbSSangeeta Misra 		(void) inet_ntop(ip.ia_af, (void *)&(ip).ia_v6, buf, sz);
1562*dbed73cbSSangeeta Misra 		break;
1563*dbed73cbSSangeeta Misra 	default: buf[0] = '\0';
1564*dbed73cbSSangeeta Misra 	}
1565*dbed73cbSSangeeta Misra }
1566*dbed73cbSSangeeta Misra 
1567*dbed73cbSSangeeta Misra /*
1568*dbed73cbSSangeeta Misra  * Map ilb_status errors to similar errno values from errno.h or
1569*dbed73cbSSangeeta Misra  * adt_event.h to be used for audit record
1570*dbed73cbSSangeeta Misra  */
1571*dbed73cbSSangeeta Misra int
1572*dbed73cbSSangeeta Misra ilberror2auditerror(ilb_status_t rc)
1573*dbed73cbSSangeeta Misra {
1574*dbed73cbSSangeeta Misra 	int audit_error;
1575*dbed73cbSSangeeta Misra 
1576*dbed73cbSSangeeta Misra 	switch (rc) {
1577*dbed73cbSSangeeta Misra 	case ILB_STATUS_CFGAUTH:
1578*dbed73cbSSangeeta Misra 		audit_error = ADT_FAIL_VALUE_AUTH;
1579*dbed73cbSSangeeta Misra 		break;
1580*dbed73cbSSangeeta Misra 	case ILB_STATUS_ENOMEM:
1581*dbed73cbSSangeeta Misra 		audit_error = ENOMEM;
1582*dbed73cbSSangeeta Misra 		break;
1583*dbed73cbSSangeeta Misra 	case ILB_STATUS_ENOENT:
1584*dbed73cbSSangeeta Misra 	case ILB_STATUS_ENOHCINFO:
1585*dbed73cbSSangeeta Misra 	case ILB_STATUS_INVAL_HCTESTTYPE:
1586*dbed73cbSSangeeta Misra 	case ILB_STATUS_INVAL_CMD:
1587*dbed73cbSSangeeta Misra 	case ILB_STATUS_DUP_RULE:
1588*dbed73cbSSangeeta Misra 	case ILB_STATUS_ENORULE:
1589*dbed73cbSSangeeta Misra 	case ILB_STATUS_SGUNAVAIL:
1590*dbed73cbSSangeeta Misra 		audit_error = ENOENT;
1591*dbed73cbSSangeeta Misra 		break;
1592*dbed73cbSSangeeta Misra 	case ILB_STATUS_EINVAL:
1593*dbed73cbSSangeeta Misra 	case ILB_STATUS_MISMATCHSG:
1594*dbed73cbSSangeeta Misra 	case ILB_STATUS_MISMATCHH:
1595*dbed73cbSSangeeta Misra 	case ILB_STATUS_BADSG:
1596*dbed73cbSSangeeta Misra 	case ILB_STATUS_INVAL_SRVR:
1597*dbed73cbSSangeeta Misra 	case ILB_STATUS_INVAL_ENBSRVR:
1598*dbed73cbSSangeeta Misra 	case ILB_STATUS_BADPORT:
1599*dbed73cbSSangeeta Misra 		audit_error = EINVAL;
1600*dbed73cbSSangeeta Misra 		break;
1601*dbed73cbSSangeeta Misra 	case ILB_STATUS_EEXIST:
1602*dbed73cbSSangeeta Misra 	case ILB_STATUS_SGEXISTS:
1603*dbed73cbSSangeeta Misra 		audit_error = EEXIST;
1604*dbed73cbSSangeeta Misra 		break;
1605*dbed73cbSSangeeta Misra 	case ILB_STATUS_EWOULDBLOCK:
1606*dbed73cbSSangeeta Misra 		audit_error = EWOULDBLOCK;
1607*dbed73cbSSangeeta Misra 		break;
1608*dbed73cbSSangeeta Misra 	case ILB_STATUS_INPROGRESS:
1609*dbed73cbSSangeeta Misra 		audit_error = EINPROGRESS;
1610*dbed73cbSSangeeta Misra 		break;
1611*dbed73cbSSangeeta Misra 	case ILB_STATUS_INTERNAL:
1612*dbed73cbSSangeeta Misra 	case ILB_STATUS_CALLBACK:
1613*dbed73cbSSangeeta Misra 	case ILB_STATUS_PERMIT:
1614*dbed73cbSSangeeta Misra 	case ILB_STATUS_RULE_NO_HC:
1615*dbed73cbSSangeeta Misra 		audit_error = ADT_FAIL_VALUE_PROGRAM;
1616*dbed73cbSSangeeta Misra 		break;
1617*dbed73cbSSangeeta Misra 	case ILB_STATUS_SOCKET:
1618*dbed73cbSSangeeta Misra 		audit_error = ENOTSOCK;
1619*dbed73cbSSangeeta Misra 		break;
1620*dbed73cbSSangeeta Misra 	case ILB_STATUS_READ:
1621*dbed73cbSSangeeta Misra 	case ILB_STATUS_WRITE:
1622*dbed73cbSSangeeta Misra 		audit_error = ENOTCONN;
1623*dbed73cbSSangeeta Misra 		break;
1624*dbed73cbSSangeeta Misra 	case ILB_STATUS_SGINUSE:
1625*dbed73cbSSangeeta Misra 		audit_error = EADDRINUSE;
1626*dbed73cbSSangeeta Misra 		break;
1627*dbed73cbSSangeeta Misra 	case ILB_STATUS_SEND:
1628*dbed73cbSSangeeta Misra 		audit_error = ECOMM;
1629*dbed73cbSSangeeta Misra 		break;
1630*dbed73cbSSangeeta Misra 	case ILB_STATUS_SGFULL:
1631*dbed73cbSSangeeta Misra 		audit_error = EOVERFLOW;
1632*dbed73cbSSangeeta Misra 		break;
1633*dbed73cbSSangeeta Misra 	case ILB_STATUS_NAMETOOLONG:
1634*dbed73cbSSangeeta Misra 		audit_error = ENAMETOOLONG;
1635*dbed73cbSSangeeta Misra 		break;
1636*dbed73cbSSangeeta Misra 	case ILB_STATUS_SRVUNAVAIL:
1637*dbed73cbSSangeeta Misra 		audit_error = EHOSTUNREACH;
1638*dbed73cbSSangeeta Misra 		break;
1639*dbed73cbSSangeeta Misra 	default:
1640*dbed73cbSSangeeta Misra 		audit_error = ADT_FAIL_VALUE_UNKNOWN;
1641*dbed73cbSSangeeta Misra 		break;
1642*dbed73cbSSangeeta Misra 	}
1643*dbed73cbSSangeeta Misra 	return (audit_error);
1644*dbed73cbSSangeeta Misra }
1645