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