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 /*
23dbed73cbSSangeeta Misra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24dbed73cbSSangeeta Misra  * Use is subject to license terms.
2533f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
26dbed73cbSSangeeta Misra  */
27dbed73cbSSangeeta Misra 
28dbed73cbSSangeeta Misra #include <stdio.h>
29dbed73cbSSangeeta Misra #include <unistd.h>
30dbed73cbSSangeeta Misra #include <stdlib.h>
31dbed73cbSSangeeta Misra #include <strings.h>
32dbed73cbSSangeeta Misra #include <stddef.h>
33dbed73cbSSangeeta Misra #include <assert.h>
34dbed73cbSSangeeta Misra #include <errno.h>
35dbed73cbSSangeeta Misra #include <sys/types.h>
36dbed73cbSSangeeta Misra #include <sys/socket.h>
37dbed73cbSSangeeta Misra #include <netinet/in.h>
38dbed73cbSSangeeta Misra #include <arpa/inet.h>
39dbed73cbSSangeeta Misra #include <sys/list.h>
40dbed73cbSSangeeta Misra #include <ofmt.h>
41dbed73cbSSangeeta Misra #include <libilb.h>
42dbed73cbSSangeeta Misra #include "ilbadm.h"
43dbed73cbSSangeeta Misra 
44dbed73cbSSangeeta Misra static ilbadm_key_name_t servrange_keys[] = {
45dbed73cbSSangeeta Misra 	{ILB_KEY_SERVER, "server", "servers"},
46dbed73cbSSangeeta Misra 	{ILB_KEY_SERVRANGE, "server", "servers"},
47dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
48dbed73cbSSangeeta Misra };
49dbed73cbSSangeeta Misra 
50dbed73cbSSangeeta Misra static ilbadm_key_name_t serverID_keys[] = {
51dbed73cbSSangeeta Misra 	{ILB_KEY_SERVERID, "server", ""},
52dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
53dbed73cbSSangeeta Misra };
54dbed73cbSSangeeta Misra 
55dbed73cbSSangeeta Misra typedef struct sg_export_arg {
56dbed73cbSSangeeta Misra 	FILE		*fp;
57dbed73cbSSangeeta Misra 	ilbadm_sgroup_t	*sg;
58dbed73cbSSangeeta Misra } sg_export_arg_t;
59dbed73cbSSangeeta Misra 
60dbed73cbSSangeeta Misra typedef struct arg_struct {
61dbed73cbSSangeeta Misra 	int		flags;
62dbed73cbSSangeeta Misra 	char		*o_str;
63dbed73cbSSangeeta Misra 	ofmt_field_t	*o_fields;
64dbed73cbSSangeeta Misra 	ofmt_handle_t	oh;
65dbed73cbSSangeeta Misra } list_arg_t;
66dbed73cbSSangeeta Misra 
67dbed73cbSSangeeta Misra typedef struct sg_srv_o_struct {
68dbed73cbSSangeeta Misra 	char		*sgname;
69dbed73cbSSangeeta Misra 	ilb_server_data_t	*sd;
70dbed73cbSSangeeta Misra } sg_srv_o_arg_t;
71dbed73cbSSangeeta Misra 
72dbed73cbSSangeeta Misra static ofmt_cb_t of_sgname;
73dbed73cbSSangeeta Misra static ofmt_cb_t of_srvID;
74dbed73cbSSangeeta Misra static ofmt_cb_t of_port;
75dbed73cbSSangeeta Misra static ofmt_cb_t of_ip;
76dbed73cbSSangeeta Misra 
77dbed73cbSSangeeta Misra static ofmt_field_t sgfields_v4[] = {
78dbed73cbSSangeeta Misra 	{"SGNAME", ILB_SGNAME_SZ, 0, of_sgname},
79dbed73cbSSangeeta Misra 	{"SERVERID", ILB_NAMESZ, 0, of_srvID},
80dbed73cbSSangeeta Misra 	{"MINPORT", 8, 0, of_port},
81dbed73cbSSangeeta Misra 	{"MAXPORT", 8, 1, of_port},
82dbed73cbSSangeeta Misra 	{"IP_ADDRESS", 15, 0, of_ip},
83dbed73cbSSangeeta Misra 	{NULL, 0, 0, NULL}
84dbed73cbSSangeeta Misra };
85dbed73cbSSangeeta Misra static ofmt_field_t sgfields_v6[] = {
86dbed73cbSSangeeta Misra 	{"SGNAME", ILB_SGNAME_SZ, 0, of_sgname},
87dbed73cbSSangeeta Misra 	{"SERVERID", ILB_NAMESZ, 0, of_srvID},
88dbed73cbSSangeeta Misra 	{"MINPORT", 8, 0, of_port},
89dbed73cbSSangeeta Misra 	{"MAXPORT", 8, 1, of_port},
90dbed73cbSSangeeta Misra 	{"IP_ADDRESS", 39, 0, of_ip},
91dbed73cbSSangeeta Misra 	{NULL, 0, 0, NULL}
92dbed73cbSSangeeta Misra };
93dbed73cbSSangeeta Misra 
94dbed73cbSSangeeta Misra #define	MAXCOLS	80 /* make flexible? */
95dbed73cbSSangeeta Misra 
96dbed73cbSSangeeta Misra extern int	optind, optopt, opterr;
97dbed73cbSSangeeta Misra extern char	*optarg;
98dbed73cbSSangeeta Misra 
99dbed73cbSSangeeta Misra static boolean_t
of_sgname(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)100dbed73cbSSangeeta Misra of_sgname(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
101dbed73cbSSangeeta Misra {
102dbed73cbSSangeeta Misra 	sg_srv_o_arg_t	*l = (sg_srv_o_arg_t *)of_arg->ofmt_cbarg;
103dbed73cbSSangeeta Misra 
104dbed73cbSSangeeta Misra 	(void) strlcpy(buf, l->sgname, bufsize);
105dbed73cbSSangeeta Misra 	return (B_TRUE);
106dbed73cbSSangeeta Misra }
107dbed73cbSSangeeta Misra 
108dbed73cbSSangeeta Misra static boolean_t
of_srvID(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)109dbed73cbSSangeeta Misra of_srvID(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
110dbed73cbSSangeeta Misra {
111dbed73cbSSangeeta Misra 	sg_srv_o_arg_t	*l = (sg_srv_o_arg_t *)of_arg->ofmt_cbarg;
112dbed73cbSSangeeta Misra 
113dbed73cbSSangeeta Misra 	(void) strlcpy(buf, l->sd->sd_srvID, bufsize);
114dbed73cbSSangeeta Misra 	return (B_TRUE);
115dbed73cbSSangeeta Misra }
116dbed73cbSSangeeta Misra 
117dbed73cbSSangeeta Misra static boolean_t
of_port(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)118dbed73cbSSangeeta Misra of_port(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
119dbed73cbSSangeeta Misra {
120dbed73cbSSangeeta Misra 	sg_srv_o_arg_t	*l = (sg_srv_o_arg_t *)of_arg->ofmt_cbarg;
121dbed73cbSSangeeta Misra 	int		port;
122dbed73cbSSangeeta Misra 
123dbed73cbSSangeeta Misra 	if (of_arg->ofmt_id == 0) {
124dbed73cbSSangeeta Misra 		port = ntohs(l->sd->sd_minport);
125dbed73cbSSangeeta Misra 		if (port == 0)
126dbed73cbSSangeeta Misra 			*buf = '\0';
127dbed73cbSSangeeta Misra 		else
128dbed73cbSSangeeta Misra 			(void) snprintf(buf, bufsize, "%d", port);
129dbed73cbSSangeeta Misra 	} else {
130dbed73cbSSangeeta Misra 		port = ntohs(l->sd->sd_maxport);
131dbed73cbSSangeeta Misra 		if (port == 0)
132dbed73cbSSangeeta Misra 			*buf = '\0';
133dbed73cbSSangeeta Misra 		else
134dbed73cbSSangeeta Misra 			(void) snprintf(buf, bufsize, "%d", port);
135dbed73cbSSangeeta Misra 	}
136dbed73cbSSangeeta Misra 	return (B_TRUE);
137dbed73cbSSangeeta Misra }
138dbed73cbSSangeeta Misra 
139dbed73cbSSangeeta Misra static boolean_t
of_ip(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)140dbed73cbSSangeeta Misra of_ip(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
141dbed73cbSSangeeta Misra {
142dbed73cbSSangeeta Misra 	sg_srv_o_arg_t	*l = (sg_srv_o_arg_t *)of_arg->ofmt_cbarg;
143dbed73cbSSangeeta Misra 
144dbed73cbSSangeeta Misra 	ip2str(&l->sd->sd_addr, buf, bufsize, V6_ADDRONLY);
145dbed73cbSSangeeta Misra 	return (B_TRUE);
146dbed73cbSSangeeta Misra }
147dbed73cbSSangeeta Misra 
148dbed73cbSSangeeta Misra ilbadm_status_t
i_list_sg_srv_ofmt(char * sgname,ilb_server_data_t * sd,void * arg)149dbed73cbSSangeeta Misra i_list_sg_srv_ofmt(char *sgname, ilb_server_data_t *sd, void *arg)
150dbed73cbSSangeeta Misra {
151dbed73cbSSangeeta Misra 	list_arg_t	*larg = (list_arg_t *)arg;
152dbed73cbSSangeeta Misra 	sg_srv_o_arg_t	line_arg;
153dbed73cbSSangeeta Misra 
154dbed73cbSSangeeta Misra 	line_arg.sgname = sgname;
155dbed73cbSSangeeta Misra 	line_arg.sd = sd;
156dbed73cbSSangeeta Misra 	ofmt_print(larg->oh, &line_arg);
157dbed73cbSSangeeta Misra 	return (ILBADM_OK);
158dbed73cbSSangeeta Misra }
159dbed73cbSSangeeta Misra 
160dbed73cbSSangeeta Misra /*
161dbed73cbSSangeeta Misra  * This function is always called via ilb_walk_servergroups()
162dbed73cbSSangeeta Misra  * and so must return libilb errors.
163dbed73cbSSangeeta Misra  * That's why we need to retain currently unused "h" argument
164dbed73cbSSangeeta Misra  */
165dbed73cbSSangeeta Misra /* ARGSUSED */
166dbed73cbSSangeeta Misra static ilb_status_t
ilbadm_list_sg_srv(ilb_handle_t h,ilb_server_data_t * sd,const char * sgname,void * arg)167dbed73cbSSangeeta Misra ilbadm_list_sg_srv(ilb_handle_t h, ilb_server_data_t *sd, const char *sgname,
168dbed73cbSSangeeta Misra     void *arg)
169dbed73cbSSangeeta Misra {
170dbed73cbSSangeeta Misra 	char		ip_str[2*INET6_ADDRSTRLEN + 3] = "";
171dbed73cbSSangeeta Misra 	char		port_str[INET6_ADDRSTRLEN];
172dbed73cbSSangeeta Misra 	list_arg_t	*larg = (list_arg_t *)arg;
173dbed73cbSSangeeta Misra 	ofmt_status_t	oerr;
174dbed73cbSSangeeta Misra 	int		oflags = 0;
175dbed73cbSSangeeta Misra 	int		ocols = MAXCOLS;
176dbed73cbSSangeeta Misra 	int		h_minport, h_maxport;
177dbed73cbSSangeeta Misra 	static ofmt_handle_t	oh = (ofmt_handle_t)NULL;
178dbed73cbSSangeeta Misra 	ofmt_field_t	*ofp;
179dbed73cbSSangeeta Misra 
180dbed73cbSSangeeta Misra 	if (larg->o_str != NULL) {
181dbed73cbSSangeeta Misra 		if (oh == NULL) {
182dbed73cbSSangeeta Misra 			if (sd->sd_addr.ia_af == AF_INET)
183dbed73cbSSangeeta Misra 				ofp = sgfields_v6;
184dbed73cbSSangeeta Misra 			else
185dbed73cbSSangeeta Misra 				ofp = sgfields_v4;
186dbed73cbSSangeeta Misra 
187dbed73cbSSangeeta Misra 			if (larg->flags & ILBADM_LIST_PARSE)
188dbed73cbSSangeeta Misra 				oflags |= OFMT_PARSABLE;
189dbed73cbSSangeeta Misra 
190dbed73cbSSangeeta Misra 			oerr = ofmt_open(larg->o_str, ofp, oflags, ocols, &oh);
191dbed73cbSSangeeta Misra 			if (oerr != OFMT_SUCCESS) {
192dbed73cbSSangeeta Misra 				char	e[80];
193dbed73cbSSangeeta Misra 
194dbed73cbSSangeeta Misra 				ilbadm_err(gettext("ofmt_open failed: %s"),
195dbed73cbSSangeeta Misra 				    ofmt_strerror(oh, oerr, e, sizeof (e)));
196dbed73cbSSangeeta Misra 				return (ILB_STATUS_GENERIC);
197dbed73cbSSangeeta Misra 			}
198dbed73cbSSangeeta Misra 			larg->oh = oh;
199dbed73cbSSangeeta Misra 		}
200dbed73cbSSangeeta Misra 
201dbed73cbSSangeeta Misra 
202dbed73cbSSangeeta Misra 		(void) i_list_sg_srv_ofmt((char *)sgname, sd, arg);
203dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
204dbed73cbSSangeeta Misra 	}
205dbed73cbSSangeeta Misra 
206dbed73cbSSangeeta Misra 	ip2str(&sd->sd_addr, ip_str, sizeof (ip_str), 0);
207dbed73cbSSangeeta Misra 
208dbed73cbSSangeeta Misra 	h_minport = ntohs(sd->sd_minport);
209dbed73cbSSangeeta Misra 	h_maxport = ntohs(sd->sd_maxport);
210dbed73cbSSangeeta Misra 	if (h_minport == 0)
211dbed73cbSSangeeta Misra 		*port_str = '\0';
212dbed73cbSSangeeta Misra 	else if (h_maxport > h_minport)
213dbed73cbSSangeeta Misra 		(void) sprintf(port_str, ":%d-%d", h_minport, h_maxport);
214dbed73cbSSangeeta Misra 	else
215dbed73cbSSangeeta Misra 		(void) sprintf(port_str, ":%d", h_minport);
216dbed73cbSSangeeta Misra 
217dbed73cbSSangeeta Misra 	(void) printf("%s: id:%s %s%s\n", sgname,
218*e8ef49e9SToomas Soome 	    sd->sd_srvID, ip_str, port_str);
219dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
220dbed73cbSSangeeta Misra }
221dbed73cbSSangeeta Misra 
222dbed73cbSSangeeta Misra ilb_status_t
ilbadm_list_sg(ilb_handle_t h,ilb_sg_data_t * sg,void * arg)223dbed73cbSSangeeta Misra ilbadm_list_sg(ilb_handle_t h, ilb_sg_data_t *sg, void *arg)
224dbed73cbSSangeeta Misra {
225dbed73cbSSangeeta Misra 	if (sg->sgd_srvcount == 0) {
226dbed73cbSSangeeta Misra 		ilb_server_data_t	tmp_srv;
227dbed73cbSSangeeta Misra 
228dbed73cbSSangeeta Misra 		bzero(&tmp_srv, sizeof (tmp_srv));
229dbed73cbSSangeeta Misra 		return (ilbadm_list_sg_srv(h, &tmp_srv, sg->sgd_name, arg));
230dbed73cbSSangeeta Misra 	}
231dbed73cbSSangeeta Misra 
232dbed73cbSSangeeta Misra 	return (ilb_walk_servers(h, ilbadm_list_sg_srv, sg->sgd_name, arg));
233dbed73cbSSangeeta Misra }
234dbed73cbSSangeeta Misra 
235dbed73cbSSangeeta Misra static char *def_fields = "SGNAME,SERVERID,MINPORT,MAXPORT,IP_ADDRESS";
236dbed73cbSSangeeta Misra 
237dbed73cbSSangeeta Misra /* ARGSUSED */
238dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_show_servergroups(int argc,char * argv[])239dbed73cbSSangeeta Misra ilbadm_show_servergroups(int argc, char *argv[])
240dbed73cbSSangeeta Misra {
241dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
242dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
243dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
244dbed73cbSSangeeta Misra 	int		c;
245dbed73cbSSangeeta Misra 	char		optstr[] = ":po:";
246dbed73cbSSangeeta Misra 
247dbed73cbSSangeeta Misra 	boolean_t	o_opt = B_FALSE, p_opt = B_FALSE;
248dbed73cbSSangeeta Misra 	list_arg_t	larg = {0, def_fields, NULL, NULL};
249dbed73cbSSangeeta Misra 
250dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, optstr)) != -1) {
251dbed73cbSSangeeta Misra 		switch ((char)c) {
252dbed73cbSSangeeta Misra 		case 'p': p_opt = B_TRUE;
253dbed73cbSSangeeta Misra 			larg.flags |= ILBADM_LIST_PARSE;
254dbed73cbSSangeeta Misra 			break;
255dbed73cbSSangeeta Misra 		case 'o': larg.o_str = optarg;
256dbed73cbSSangeeta Misra 			o_opt = B_TRUE;
257dbed73cbSSangeeta Misra 			break;
258dbed73cbSSangeeta Misra 		case ':': ilbadm_err(gettext("missing option argument"
259dbed73cbSSangeeta Misra 			    " for %c"), (char)optopt);
260dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
261dbed73cbSSangeeta Misra 			goto out;
262dbed73cbSSangeeta Misra 		default: unknown_opt(argv, optind-1);
263dbed73cbSSangeeta Misra 			/* not reached */
264dbed73cbSSangeeta Misra 			break;
265dbed73cbSSangeeta Misra 		}
266dbed73cbSSangeeta Misra 	}
267dbed73cbSSangeeta Misra 
268dbed73cbSSangeeta Misra 	if (p_opt && !o_opt) {
269dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires -o"));
270dbed73cbSSangeeta Misra 		exit(1);
271dbed73cbSSangeeta Misra 	}
272dbed73cbSSangeeta Misra 
273dbed73cbSSangeeta Misra 	if (p_opt && larg.o_str != NULL &&
274dbed73cbSSangeeta Misra 	    (strcasecmp(larg.o_str, "all") == 0)) {
275dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires explicit field"
276dbed73cbSSangeeta Misra 		    " names for -o"));
277dbed73cbSSangeeta Misra 		exit(1);
278dbed73cbSSangeeta Misra 	}
279dbed73cbSSangeeta Misra 
280dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
281dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
282dbed73cbSSangeeta Misra 		goto out;
283dbed73cbSSangeeta Misra 
284dbed73cbSSangeeta Misra 	if (optind >= argc) {
285dbed73cbSSangeeta Misra 		rclib = ilb_walk_servergroups(h, ilbadm_list_sg, NULL,
286dbed73cbSSangeeta Misra 		    (void*)&larg);
287dbed73cbSSangeeta Misra 		if (rclib != ILB_STATUS_OK)
288dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
289dbed73cbSSangeeta Misra 	} else {
290dbed73cbSSangeeta Misra 		while (optind < argc) {
291dbed73cbSSangeeta Misra 			rclib = ilb_walk_servergroups(h, ilbadm_list_sg,
292dbed73cbSSangeeta Misra 			    argv[optind++], (void*)&larg);
293dbed73cbSSangeeta Misra 			if (rclib != ILB_STATUS_OK) {
294dbed73cbSSangeeta Misra 				rc = ILBADM_LIBERR;
295dbed73cbSSangeeta Misra 				break;
296dbed73cbSSangeeta Misra 			}
297dbed73cbSSangeeta Misra 		}
298dbed73cbSSangeeta Misra 	}
299dbed73cbSSangeeta Misra 
300dbed73cbSSangeeta Misra 	if (larg.oh != NULL)
301dbed73cbSSangeeta Misra 		ofmt_close(larg.oh);
302dbed73cbSSangeeta Misra out:
303dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
304dbed73cbSSangeeta Misra 		(void) ilb_close(h);
305dbed73cbSSangeeta Misra 
306dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
307dbed73cbSSangeeta Misra 		/*
308dbed73cbSSangeeta Misra 		 * The show function returns ILB_STATUS_GENERIC after printing
309dbed73cbSSangeeta Misra 		 * out an error message.  So we don't need to print it again.
310dbed73cbSSangeeta Misra 		 */
311dbed73cbSSangeeta Misra 		if (rclib != ILB_STATUS_GENERIC)
312dbed73cbSSangeeta Misra 			ilbadm_err(ilb_errstr(rclib));
313dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
314dbed73cbSSangeeta Misra 	}
315dbed73cbSSangeeta Misra 
316dbed73cbSSangeeta Misra 	return (rc);
317dbed73cbSSangeeta Misra }
318dbed73cbSSangeeta Misra 
319dbed73cbSSangeeta Misra ilbadm_servnode_t *
i_new_sg_elem(ilbadm_sgroup_t * sgp)320dbed73cbSSangeeta Misra i_new_sg_elem(ilbadm_sgroup_t *sgp)
321dbed73cbSSangeeta Misra {
322dbed73cbSSangeeta Misra 	ilbadm_servnode_t *s;
323dbed73cbSSangeeta Misra 
324dbed73cbSSangeeta Misra 	s = (ilbadm_servnode_t *)calloc(sizeof (*s), 1);
325dbed73cbSSangeeta Misra 	if (s != NULL) {
326dbed73cbSSangeeta Misra 		list_insert_tail(&sgp->sg_serv_list, s);
327dbed73cbSSangeeta Misra 		sgp->sg_count++;
328dbed73cbSSangeeta Misra 	}
329dbed73cbSSangeeta Misra 	return (s);
330dbed73cbSSangeeta Misra }
331dbed73cbSSangeeta Misra 
332dbed73cbSSangeeta Misra static ilbadm_status_t
i_parse_servrange_list(char * arg,ilbadm_sgroup_t * sgp)333dbed73cbSSangeeta Misra i_parse_servrange_list(char *arg, ilbadm_sgroup_t *sgp)
334dbed73cbSSangeeta Misra {
335dbed73cbSSangeeta Misra 	ilbadm_status_t	rc;
336dbed73cbSSangeeta Misra 	int		count;
337dbed73cbSSangeeta Misra 
338dbed73cbSSangeeta Misra 	rc = i_parse_optstring(arg, (void *) sgp, servrange_keys,
339dbed73cbSSangeeta Misra 	    OPT_VALUE_LIST|OPT_IP_RANGE|OPT_PORTS, &count);
340dbed73cbSSangeeta Misra 	return (rc);
341dbed73cbSSangeeta Misra }
342dbed73cbSSangeeta Misra 
343dbed73cbSSangeeta Misra static ilbadm_status_t
i_parse_serverIDs(char * arg,ilbadm_sgroup_t * sgp)344dbed73cbSSangeeta Misra i_parse_serverIDs(char *arg, ilbadm_sgroup_t *sgp)
345dbed73cbSSangeeta Misra {
346dbed73cbSSangeeta Misra 	ilbadm_status_t	rc;
347dbed73cbSSangeeta Misra 	int		count;
348dbed73cbSSangeeta Misra 
349dbed73cbSSangeeta Misra 	rc = i_parse_optstring(arg, (void *) sgp, serverID_keys,
350dbed73cbSSangeeta Misra 	    OPT_VALUE_LIST|OPT_PORTS, &count);
351dbed73cbSSangeeta Misra 	return (rc);
352dbed73cbSSangeeta Misra }
353dbed73cbSSangeeta Misra 
354dbed73cbSSangeeta Misra static ilbadm_status_t
i_mod_sg(ilb_handle_t h,ilbadm_sgroup_t * sgp,ilbadm_cmd_t cmd,int flags)355dbed73cbSSangeeta Misra i_mod_sg(ilb_handle_t h, ilbadm_sgroup_t *sgp, ilbadm_cmd_t cmd,
356dbed73cbSSangeeta Misra     int flags)
357dbed73cbSSangeeta Misra {
358dbed73cbSSangeeta Misra 	ilbadm_servnode_t	*sn;
359dbed73cbSSangeeta Misra 	ilb_server_data_t	*srv;
360dbed73cbSSangeeta Misra 	ilb_status_t		rclib = ILB_STATUS_OK;
361dbed73cbSSangeeta Misra 	ilbadm_status_t		rc = ILBADM_OK;
362dbed73cbSSangeeta Misra 
363dbed73cbSSangeeta Misra 	if (h == ILB_INVALID_HANDLE && cmd != cmd_enable_server &&
364dbed73cbSSangeeta Misra 	    cmd != cmd_disable_server)
365dbed73cbSSangeeta Misra 		return (ILBADM_LIBERR);
366dbed73cbSSangeeta Misra 
367dbed73cbSSangeeta Misra 	sn = list_head(&sgp->sg_serv_list);
368dbed73cbSSangeeta Misra 	while (sn != NULL) {
369dbed73cbSSangeeta Misra 		srv = &sn->s_spec;
370dbed73cbSSangeeta Misra 
371dbed73cbSSangeeta Misra 		srv->sd_flags |= flags;
372dbed73cbSSangeeta Misra 		if (cmd == cmd_create_sg || cmd == cmd_add_srv) {
373dbed73cbSSangeeta Misra 			rclib = ilb_add_server_to_group(h, sgp->sg_name,
374dbed73cbSSangeeta Misra 			    srv);
375dbed73cbSSangeeta Misra 			if (rclib != ILB_STATUS_OK) {
376dbed73cbSSangeeta Misra 				char	buf[INET6_ADDRSTRLEN + 1];
377dbed73cbSSangeeta Misra 
378dbed73cbSSangeeta Misra 				rc = ILBADM_LIBERR;
379dbed73cbSSangeeta Misra 				ip2str(&srv->sd_addr, buf, sizeof (buf),
380dbed73cbSSangeeta Misra 				    V6_ADDRONLY);
381dbed73cbSSangeeta Misra 				ilbadm_err(gettext("cannot add %s to %s: %s"),
382dbed73cbSSangeeta Misra 				    buf, sgp->sg_name, ilb_errstr(rclib));
383dbed73cbSSangeeta Misra 				/* if we created the SG, we bail out */
384dbed73cbSSangeeta Misra 				if (cmd == cmd_create_sg)
385dbed73cbSSangeeta Misra 					return (rc);
386dbed73cbSSangeeta Misra 			}
387dbed73cbSSangeeta Misra 		} else {
388dbed73cbSSangeeta Misra 			assert(cmd == cmd_rem_srv);
389dbed73cbSSangeeta Misra 			rclib = ilb_rem_server_from_group(h, sgp->sg_name,
390dbed73cbSSangeeta Misra 			    srv);
391dbed73cbSSangeeta Misra 			/* if we fail, we tell user and continue */
392dbed73cbSSangeeta Misra 			if (rclib != ILB_STATUS_OK) {
393dbed73cbSSangeeta Misra 				rc = ILBADM_LIBERR;
394dbed73cbSSangeeta Misra 				ilbadm_err(
395dbed73cbSSangeeta Misra 				    gettext("cannot remove %s from %s: %s"),
396dbed73cbSSangeeta Misra 				    srv->sd_srvID, sgp->sg_name,
397dbed73cbSSangeeta Misra 				    ilb_errstr(rclib));
398dbed73cbSSangeeta Misra 			}
399dbed73cbSSangeeta Misra 		}
400dbed73cbSSangeeta Misra 
401dbed73cbSSangeeta Misra 		/*
402dbed73cbSSangeeta Misra 		 * list_next returns NULL instead of cycling back to head
403dbed73cbSSangeeta Misra 		 * so we don't have to check for list_head explicitly.
404dbed73cbSSangeeta Misra 		 */
405dbed73cbSSangeeta Misra 		sn = list_next(&sgp->sg_serv_list, sn);
406dbed73cbSSangeeta Misra 	};
407dbed73cbSSangeeta Misra 
408dbed73cbSSangeeta Misra 	return (rc);
409dbed73cbSSangeeta Misra }
410dbed73cbSSangeeta Misra 
411dbed73cbSSangeeta Misra static void
i_ilbadm_alloc_sgroup(ilbadm_sgroup_t ** sgp)412dbed73cbSSangeeta Misra i_ilbadm_alloc_sgroup(ilbadm_sgroup_t **sgp)
413dbed73cbSSangeeta Misra {
414dbed73cbSSangeeta Misra 	ilbadm_sgroup_t	*sg;
415dbed73cbSSangeeta Misra 
416dbed73cbSSangeeta Misra 	*sgp = sg = (ilbadm_sgroup_t *)calloc(sizeof (*sg), 1);
417dbed73cbSSangeeta Misra 	if (sg == NULL)
418dbed73cbSSangeeta Misra 		return;
419dbed73cbSSangeeta Misra 	list_create(&sg->sg_serv_list, sizeof (ilbadm_servnode_t),
420dbed73cbSSangeeta Misra 	    offsetof(ilbadm_servnode_t, s_link));
421dbed73cbSSangeeta Misra }
422dbed73cbSSangeeta Misra 
423dbed73cbSSangeeta Misra static void
i_ilbadm_free_sgroup(ilbadm_sgroup_t * sg)424dbed73cbSSangeeta Misra i_ilbadm_free_sgroup(ilbadm_sgroup_t *sg)
425dbed73cbSSangeeta Misra {
426dbed73cbSSangeeta Misra 	ilbadm_servnode_t	*s;
427dbed73cbSSangeeta Misra 
428dbed73cbSSangeeta Misra 	while ((s = list_remove_head(&sg->sg_serv_list)) != NULL)
429dbed73cbSSangeeta Misra 		free(s);
430dbed73cbSSangeeta Misra 
431dbed73cbSSangeeta Misra 	list_destroy(&sg->sg_serv_list);
432dbed73cbSSangeeta Misra }
433dbed73cbSSangeeta Misra 
434dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_create_servergroup(int argc,char * argv[])435dbed73cbSSangeeta Misra ilbadm_create_servergroup(int argc, char *argv[])
436dbed73cbSSangeeta Misra {
437dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
438dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
439dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
440dbed73cbSSangeeta Misra 	ilbadm_sgroup_t	*sg;
441dbed73cbSSangeeta Misra 	int		c;
442dbed73cbSSangeeta Misra 	int		flags = 0;
443dbed73cbSSangeeta Misra 
444dbed73cbSSangeeta Misra 	i_ilbadm_alloc_sgroup(&sg);
445dbed73cbSSangeeta Misra 
446dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":s:")) != -1) {
447dbed73cbSSangeeta Misra 		switch ((char)c) {
448dbed73cbSSangeeta Misra 		case 's':
449dbed73cbSSangeeta Misra 			rc = i_parse_servrange_list(optarg, sg);
450dbed73cbSSangeeta Misra 			break;
451dbed73cbSSangeeta Misra 		case ':':
452dbed73cbSSangeeta Misra 			ilbadm_err(gettext("missing option-argument for"
453dbed73cbSSangeeta Misra 			    " %c"), (char)optopt);
454dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
455dbed73cbSSangeeta Misra 			break;
456dbed73cbSSangeeta Misra 		case '?':
457dbed73cbSSangeeta Misra 		default:
458dbed73cbSSangeeta Misra 			unknown_opt(argv, optind-1);
459dbed73cbSSangeeta Misra 			/* not reached */
460dbed73cbSSangeeta Misra 			break;
461dbed73cbSSangeeta Misra 		}
462dbed73cbSSangeeta Misra 
463dbed73cbSSangeeta Misra 		if (rc != ILBADM_OK)
464dbed73cbSSangeeta Misra 			goto out;
465dbed73cbSSangeeta Misra 	}
466dbed73cbSSangeeta Misra 
467dbed73cbSSangeeta Misra 	if (optind >= argc) {
468dbed73cbSSangeeta Misra 		ilbadm_err(gettext("missing mandatory arguments - please refer"
469dbed73cbSSangeeta Misra 		    " to 'create-servergroup' subcommand"
470bbf21555SRichard Lowe 		    "  description in ilbadm(8)"));
471dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
472dbed73cbSSangeeta Misra 		goto out;
473dbed73cbSSangeeta Misra 	}
474dbed73cbSSangeeta Misra 
475dbed73cbSSangeeta Misra 	if (strlen(argv[optind]) > ILB_SGNAME_SZ - 1) {
476dbed73cbSSangeeta Misra 		ilbadm_err(gettext("servergroup name %s is too long -"
477dbed73cbSSangeeta Misra 		    " must not exceed %d chars"), argv[optind],
478dbed73cbSSangeeta Misra 		    ILB_SGNAME_SZ - 1);
479dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
480dbed73cbSSangeeta Misra 		goto out;
481dbed73cbSSangeeta Misra 	}
482dbed73cbSSangeeta Misra 
483dbed73cbSSangeeta Misra 	sg->sg_name = argv[optind];
484dbed73cbSSangeeta Misra 
485dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
486dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
487dbed73cbSSangeeta Misra 		goto out;
488dbed73cbSSangeeta Misra 
489dbed73cbSSangeeta Misra 	rclib = ilb_create_servergroup(h, sg->sg_name);
490dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
491dbed73cbSSangeeta Misra 		goto out;
492dbed73cbSSangeeta Misra 
493dbed73cbSSangeeta Misra 	/* we create a servergroup with all servers enabled */
494dbed73cbSSangeeta Misra 	ILB_SET_ENABLED(flags);
495dbed73cbSSangeeta Misra 	rc = i_mod_sg(h, sg, cmd_create_sg, flags);
496dbed73cbSSangeeta Misra 
497dbed73cbSSangeeta Misra 	if (rc != ILBADM_OK)
498dbed73cbSSangeeta Misra 		(void) ilb_destroy_servergroup(h, sg->sg_name);
499dbed73cbSSangeeta Misra 
500dbed73cbSSangeeta Misra out:
501dbed73cbSSangeeta Misra 	i_ilbadm_free_sgroup(sg);
502dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
503dbed73cbSSangeeta Misra 		(void) ilb_close(h);
504dbed73cbSSangeeta Misra 
505dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
506dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
507dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
508dbed73cbSSangeeta Misra 	}
509dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
510dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
511dbed73cbSSangeeta Misra 
512dbed73cbSSangeeta Misra 	return (rc);
513dbed73cbSSangeeta Misra }
514dbed73cbSSangeeta Misra 
515dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_add_server_to_group(int argc,char ** argv)516dbed73cbSSangeeta Misra ilbadm_add_server_to_group(int argc, char **argv)
517dbed73cbSSangeeta Misra {
518dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
519dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
520dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
521dbed73cbSSangeeta Misra 	ilbadm_sgroup_t	*sg;
522dbed73cbSSangeeta Misra 	int		c;
523dbed73cbSSangeeta Misra 	int		flags = 0;
524dbed73cbSSangeeta Misra 
525dbed73cbSSangeeta Misra 	i_ilbadm_alloc_sgroup(&sg);
526dbed73cbSSangeeta Misra 
527dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":s:")) != -1) {
528dbed73cbSSangeeta Misra 		switch ((char)c) {
529dbed73cbSSangeeta Misra 		case 's':
530dbed73cbSSangeeta Misra 			rc = i_parse_servrange_list(optarg, sg);
531dbed73cbSSangeeta Misra 			break;
532dbed73cbSSangeeta Misra 		case ':':
533dbed73cbSSangeeta Misra 			ilbadm_err(gettext("missing option-argument for"
534dbed73cbSSangeeta Misra 			    " %c"), (char)optopt);
535dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
536dbed73cbSSangeeta Misra 			break;
537dbed73cbSSangeeta Misra 		case '?':
538dbed73cbSSangeeta Misra 		default: unknown_opt(argv, optind-1);
539dbed73cbSSangeeta Misra 			/* not reached */
540dbed73cbSSangeeta Misra 			break;
541dbed73cbSSangeeta Misra 		}
542dbed73cbSSangeeta Misra 
543dbed73cbSSangeeta Misra 		if (rc != ILBADM_OK)
544dbed73cbSSangeeta Misra 			goto out;
545dbed73cbSSangeeta Misra 	}
546dbed73cbSSangeeta Misra 
547dbed73cbSSangeeta Misra 	if (optind >= argc) {
548dbed73cbSSangeeta Misra 		ilbadm_err(gettext("missing mandatory arguments - please refer"
549bbf21555SRichard Lowe 		    " to 'add-server' subcommand description in ilbadm(8)"));
550dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
551dbed73cbSSangeeta Misra 		goto out;
552dbed73cbSSangeeta Misra 	}
553dbed73cbSSangeeta Misra 
554dbed73cbSSangeeta Misra 	sg->sg_name = argv[optind];
555dbed73cbSSangeeta Misra 
556dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
557dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
558dbed73cbSSangeeta Misra 		goto out;
559dbed73cbSSangeeta Misra 
560dbed73cbSSangeeta Misra 	/* A server is added enabled */
561dbed73cbSSangeeta Misra 	ILB_SET_ENABLED(flags);
562dbed73cbSSangeeta Misra 	rc = i_mod_sg(h, sg, cmd_add_srv, flags);
563dbed73cbSSangeeta Misra out:
564dbed73cbSSangeeta Misra 	i_ilbadm_free_sgroup(sg);
565dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
566dbed73cbSSangeeta Misra 		(void) ilb_close(h);
567dbed73cbSSangeeta Misra 
568dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
569dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
570dbed73cbSSangeeta Misra 	return (rc);
571dbed73cbSSangeeta Misra }
572dbed73cbSSangeeta Misra 
573dbed73cbSSangeeta Misra /* ARGSUSED */
574dbed73cbSSangeeta Misra static ilbadm_status_t
ilbadm_Xable_server(int argc,char * argv[],ilbadm_cmd_t cmd)575dbed73cbSSangeeta Misra ilbadm_Xable_server(int argc, char *argv[], ilbadm_cmd_t cmd)
576dbed73cbSSangeeta Misra {
577dbed73cbSSangeeta Misra 	ilb_handle_t		h = ILB_INVALID_HANDLE;
578dbed73cbSSangeeta Misra 	ilbadm_status_t		rc = ILBADM_OK;
579dbed73cbSSangeeta Misra 	ilb_status_t		rclib = ILB_STATUS_OK;
580dbed73cbSSangeeta Misra 	int			i;
581dbed73cbSSangeeta Misra 
582dbed73cbSSangeeta Misra 	if (argc < 2) {
583dbed73cbSSangeeta Misra 		ilbadm_err(gettext("missing required argument"
584dbed73cbSSangeeta Misra 		    " (server specification)"));
585dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
586dbed73cbSSangeeta Misra 		goto out;
587dbed73cbSSangeeta Misra 	}
588dbed73cbSSangeeta Misra 
589dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
590dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
591dbed73cbSSangeeta Misra 		goto out;
592dbed73cbSSangeeta Misra 
593dbed73cbSSangeeta Misra 	/* enable-server and disable-server only accepts serverids */
594dbed73cbSSangeeta Misra 	for (i = 1; i < argc && rclib == ILB_STATUS_OK; i++) {
595dbed73cbSSangeeta Misra 		ilb_server_data_t	srv;
596dbed73cbSSangeeta Misra 
597dbed73cbSSangeeta Misra 		if (argv[i][0] != ILB_SRVID_PREFIX) {
598dbed73cbSSangeeta Misra 			rc = ILBADM_INVAL_SRVID;
599dbed73cbSSangeeta Misra 			goto out;
600dbed73cbSSangeeta Misra 		}
601dbed73cbSSangeeta Misra 
602dbed73cbSSangeeta Misra 		bzero(&srv, sizeof (srv));
603dbed73cbSSangeeta Misra 		/* to do: check length */
604dbed73cbSSangeeta Misra 		(void) strlcpy(srv.sd_srvID, argv[i], sizeof (srv.sd_srvID));
605dbed73cbSSangeeta Misra 		switch (cmd) {
606dbed73cbSSangeeta Misra 		case cmd_enable_server:
607dbed73cbSSangeeta Misra 			rclib = ilb_enable_server(h, &srv, NULL);
608dbed73cbSSangeeta Misra 			break;
609dbed73cbSSangeeta Misra 		case cmd_disable_server:
610dbed73cbSSangeeta Misra 			rclib = ilb_disable_server(h, &srv, NULL);
611dbed73cbSSangeeta Misra 			break;
612dbed73cbSSangeeta Misra 		}
613dbed73cbSSangeeta Misra 
614dbed73cbSSangeeta Misra 		/* if we can't find a given server ID, just plough on */
615dbed73cbSSangeeta Misra 		if (rclib == ILB_STATUS_ENOENT) {
616dbed73cbSSangeeta Misra 			const char *msg = ilb_errstr(rclib);
617dbed73cbSSangeeta Misra 
618dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
619dbed73cbSSangeeta Misra 			ilbadm_err("%s: %s", msg, argv[i]);
620dbed73cbSSangeeta Misra 			rclib = ILB_STATUS_OK;
621dbed73cbSSangeeta Misra 			continue;
622dbed73cbSSangeeta Misra 		}
623dbed73cbSSangeeta Misra 		if (rclib != ILB_STATUS_OK)
624dbed73cbSSangeeta Misra 			break;
625dbed73cbSSangeeta Misra 	}
626dbed73cbSSangeeta Misra out:
627dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
628dbed73cbSSangeeta Misra 		(void) ilb_close(h);
629dbed73cbSSangeeta Misra 
630dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
631dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
632dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
633dbed73cbSSangeeta Misra 	}
634dbed73cbSSangeeta Misra 
635dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
636dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
637dbed73cbSSangeeta Misra 	return (rc);
638dbed73cbSSangeeta Misra }
639dbed73cbSSangeeta Misra 
640dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_disable_server(int argc,char * argv[])641dbed73cbSSangeeta Misra ilbadm_disable_server(int argc, char *argv[])
642dbed73cbSSangeeta Misra {
643dbed73cbSSangeeta Misra 	return (ilbadm_Xable_server(argc, argv, cmd_disable_server));
644dbed73cbSSangeeta Misra }
645dbed73cbSSangeeta Misra 
646dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_enable_server(int argc,char * argv[])647dbed73cbSSangeeta Misra ilbadm_enable_server(int argc, char *argv[])
648dbed73cbSSangeeta Misra {
649dbed73cbSSangeeta Misra 	return (ilbadm_Xable_server(argc, argv, cmd_enable_server));
650dbed73cbSSangeeta Misra }
651dbed73cbSSangeeta Misra 
652dbed73cbSSangeeta Misra /* ARGSUSED */
653dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_rem_server_from_group(int argc,char * argv[])654dbed73cbSSangeeta Misra ilbadm_rem_server_from_group(int argc, char *argv[])
655dbed73cbSSangeeta Misra {
656dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
657dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
658dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
659dbed73cbSSangeeta Misra 	ilbadm_sgroup_t	*sg;
660dbed73cbSSangeeta Misra 	int		c;
661dbed73cbSSangeeta Misra 
662dbed73cbSSangeeta Misra 	i_ilbadm_alloc_sgroup(&sg);
663dbed73cbSSangeeta Misra 
664dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":s:")) != -1) {
665dbed73cbSSangeeta Misra 		switch ((char)c) {
666dbed73cbSSangeeta Misra 		case 's':
667dbed73cbSSangeeta Misra 			rc = i_parse_serverIDs(optarg, sg);
668dbed73cbSSangeeta Misra 			break;
669dbed73cbSSangeeta Misra 		case ':':
670dbed73cbSSangeeta Misra 			ilbadm_err(gettext("missing option-argument for"
671dbed73cbSSangeeta Misra 			    " %c"), (char)optopt);
672dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
673dbed73cbSSangeeta Misra 			break;
674dbed73cbSSangeeta Misra 		case '?':
675dbed73cbSSangeeta Misra 		default: unknown_opt(argv, optind-1);
676dbed73cbSSangeeta Misra 			/* not reached */
677dbed73cbSSangeeta Misra 			break;
678dbed73cbSSangeeta Misra 		}
679dbed73cbSSangeeta Misra 		if (rc != ILBADM_OK)
680dbed73cbSSangeeta Misra 			goto out;
681dbed73cbSSangeeta Misra 	}
682dbed73cbSSangeeta Misra 
683dbed73cbSSangeeta Misra 	/* we need servergroup name and at least one serverID to remove */
684dbed73cbSSangeeta Misra 	if (optind >= argc || sg->sg_count == 0) {
685dbed73cbSSangeeta Misra 		rc = ILBADM_ENOOPTION;
686dbed73cbSSangeeta Misra 		goto out;
687dbed73cbSSangeeta Misra 	}
688dbed73cbSSangeeta Misra 
689dbed73cbSSangeeta Misra 	sg->sg_name = argv[optind];
690dbed73cbSSangeeta Misra 
691dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
692dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
693dbed73cbSSangeeta Misra 		goto out;
694dbed73cbSSangeeta Misra 
695dbed73cbSSangeeta Misra 	rc = i_mod_sg(h, sg, cmd_rem_srv, 0);
696dbed73cbSSangeeta Misra out:
697dbed73cbSSangeeta Misra 	i_ilbadm_free_sgroup(sg);
698dbed73cbSSangeeta Misra 
699dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
700dbed73cbSSangeeta Misra 		(void) ilb_close(h);
701dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
702dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
703dbed73cbSSangeeta Misra 	return (rc);
704dbed73cbSSangeeta Misra }
705dbed73cbSSangeeta Misra 
706dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_destroy_servergroup(int argc,char * argv[])707dbed73cbSSangeeta Misra ilbadm_destroy_servergroup(int argc, char *argv[])
708dbed73cbSSangeeta Misra {
709dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
710dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
711dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
712dbed73cbSSangeeta Misra 	char		*sgname;
713dbed73cbSSangeeta Misra 
714dbed73cbSSangeeta Misra 	if (argc != 2) {
715dbed73cbSSangeeta Misra 		ilbadm_err(gettext("usage:ilbadm"
716dbed73cbSSangeeta Misra 		    " delete-servergroup groupname"));
717dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
718dbed73cbSSangeeta Misra 		goto out;
719dbed73cbSSangeeta Misra 	}
720dbed73cbSSangeeta Misra 
721dbed73cbSSangeeta Misra 	sgname = argv[1];
722dbed73cbSSangeeta Misra 
723dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
724dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
725dbed73cbSSangeeta Misra 		goto out;
726dbed73cbSSangeeta Misra 
727dbed73cbSSangeeta Misra 	rclib = ilb_destroy_servergroup(h, sgname);
728dbed73cbSSangeeta Misra out:
729dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
730dbed73cbSSangeeta Misra 		(void) ilb_close(h);
731dbed73cbSSangeeta Misra 
732dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
733dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
734dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
735dbed73cbSSangeeta Misra 	}
736dbed73cbSSangeeta Misra 
737dbed73cbSSangeeta Misra 	return (rc);
738dbed73cbSSangeeta Misra }
739dbed73cbSSangeeta Misra 
740dbed73cbSSangeeta Misra #define	BUFSZ	1024
741dbed73cbSSangeeta Misra 
742dbed73cbSSangeeta Misra static int
export_srv_spec(ilb_server_data_t * srv,char * buf,const int bufsize)743dbed73cbSSangeeta Misra export_srv_spec(ilb_server_data_t *srv, char *buf, const int bufsize)
744dbed73cbSSangeeta Misra {
745dbed73cbSSangeeta Misra 	int	len = 0, bufsz = (int)bufsize;
746dbed73cbSSangeeta Misra 
747dbed73cbSSangeeta Misra 	ip2str(&srv->sd_addr, buf, bufsz, 0);
748dbed73cbSSangeeta Misra 
749dbed73cbSSangeeta Misra 	len += strlen(buf);
750dbed73cbSSangeeta Misra 	bufsz -= len;
751dbed73cbSSangeeta Misra 
752dbed73cbSSangeeta Misra 	if (srv->sd_minport != 0) {
753dbed73cbSSangeeta Misra 		in_port_t	h_min, h_max;
754dbed73cbSSangeeta Misra 		int		inc;
755dbed73cbSSangeeta Misra 
756dbed73cbSSangeeta Misra 		h_min = ntohs(srv->sd_minport);
757dbed73cbSSangeeta Misra 		h_max = ntohs(srv->sd_maxport);
758dbed73cbSSangeeta Misra 
759dbed73cbSSangeeta Misra 		/* to do: if service name was given, print that, not number */
760dbed73cbSSangeeta Misra 		if (h_max <= h_min)
761dbed73cbSSangeeta Misra 			inc = snprintf(buf+len, bufsz, ":%d", h_min);
762dbed73cbSSangeeta Misra 		else
763dbed73cbSSangeeta Misra 			inc = snprintf(buf+len, bufsz, ":%d-%d", h_min, h_max);
764dbed73cbSSangeeta Misra 
765dbed73cbSSangeeta Misra 		if (inc > bufsz) /* too little space */
766dbed73cbSSangeeta Misra 			return (-1);
767dbed73cbSSangeeta Misra 		len += inc;
768dbed73cbSSangeeta Misra 	}
769dbed73cbSSangeeta Misra 
770dbed73cbSSangeeta Misra 	return (len);
771dbed73cbSSangeeta Misra }
772dbed73cbSSangeeta Misra 
773dbed73cbSSangeeta Misra 
774dbed73cbSSangeeta Misra /*
775dbed73cbSSangeeta Misra  * this is called by ilb_walk_servers(), therefore we return ilb_status_t
776dbed73cbSSangeeta Misra  * not ilbadm_status, and retain an unused function argument
777dbed73cbSSangeeta Misra  */
778dbed73cbSSangeeta Misra /* ARGSUSED */
779dbed73cbSSangeeta Misra ilb_status_t
ilbadm_export_a_srv(ilb_handle_t h,ilb_server_data_t * srv,const char * sgname,void * arg)780dbed73cbSSangeeta Misra ilbadm_export_a_srv(ilb_handle_t h, ilb_server_data_t *srv, const char *sgname,
781dbed73cbSSangeeta Misra     void *arg)
782dbed73cbSSangeeta Misra {
783dbed73cbSSangeeta Misra 	sg_export_arg_t	*larg = (sg_export_arg_t *)arg;
784dbed73cbSSangeeta Misra 	FILE		*fp = larg->fp;
785dbed73cbSSangeeta Misra 	char		linebuf[BUFSZ]; /* XXXms make that dynamic */
786dbed73cbSSangeeta Misra 	int		sz = BUFSZ;
787dbed73cbSSangeeta Misra 
788dbed73cbSSangeeta Misra 	if (export_srv_spec(srv, linebuf, sz) == -1)
789dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
790dbed73cbSSangeeta Misra 
791dbed73cbSSangeeta Misra 	(void) fprintf(fp, "add-server -s server=");
792dbed73cbSSangeeta Misra 
793dbed73cbSSangeeta Misra 	(void) fprintf(fp, "%s %s\n", linebuf, sgname);
794dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
795dbed73cbSSangeeta Misra }
796dbed73cbSSangeeta Misra 
797dbed73cbSSangeeta Misra ilb_status_t
ilbadm_export_sg(ilb_handle_t h,ilb_sg_data_t * sg,void * arg)798dbed73cbSSangeeta Misra ilbadm_export_sg(ilb_handle_t h, ilb_sg_data_t *sg, void *arg)
799dbed73cbSSangeeta Misra {
800dbed73cbSSangeeta Misra 	ilb_status_t	rc = ILB_STATUS_OK;
801dbed73cbSSangeeta Misra 	sg_export_arg_t	*larg = (sg_export_arg_t *)arg;
802dbed73cbSSangeeta Misra 	FILE		*fp = larg->fp;
803dbed73cbSSangeeta Misra 
804dbed73cbSSangeeta Misra 	(void) fprintf(fp, "create-servergroup %s\n", sg->sgd_name);
805dbed73cbSSangeeta Misra 	if (sg->sgd_srvcount == 0)
806dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
807dbed73cbSSangeeta Misra 
808dbed73cbSSangeeta Misra 	rc = ilb_walk_servers(h, ilbadm_export_a_srv, sg->sgd_name, arg);
809dbed73cbSSangeeta Misra 	if (rc != ILB_STATUS_OK)
810dbed73cbSSangeeta Misra 		goto out;
811dbed73cbSSangeeta Misra 
812dbed73cbSSangeeta Misra 	if (fflush(fp) == EOF)
813dbed73cbSSangeeta Misra 		rc = ILB_STATUS_WRITE;
814dbed73cbSSangeeta Misra 
815dbed73cbSSangeeta Misra out:
816dbed73cbSSangeeta Misra 	return (rc);
817dbed73cbSSangeeta Misra }
818dbed73cbSSangeeta Misra 
819dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_export_servergroups(ilb_handle_t h,FILE * fp)820dbed73cbSSangeeta Misra ilbadm_export_servergroups(ilb_handle_t h, FILE *fp)
821dbed73cbSSangeeta Misra {
822dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
823dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
824dbed73cbSSangeeta Misra 	sg_export_arg_t	arg;
825dbed73cbSSangeeta Misra 
826dbed73cbSSangeeta Misra 	arg.fp = fp;
827dbed73cbSSangeeta Misra 	arg.sg = NULL;
828dbed73cbSSangeeta Misra 
829dbed73cbSSangeeta Misra 	rclib = ilb_walk_servergroups(h, ilbadm_export_sg, NULL, (void *)&arg);
830dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
831dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
832dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
833dbed73cbSSangeeta Misra 	}
834dbed73cbSSangeeta Misra 
835dbed73cbSSangeeta Misra 	return (rc);
836dbed73cbSSangeeta Misra }
837