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