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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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