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