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