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 <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 #include <strings.h> 32 #include <errno.h> 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <libilb.h> 38 #include "ilbadm.h" 39 40 static ilbadm_cmd_help_t create_sg_help = { 41 "[-s server=hostspec[:portspec...]] groupname" 42 }; 43 44 static ilbadm_cmd_help_t create_rule_help = { 45 "[-e] [-p] -i vip=value,port=value[,protocol=value] \n" \ 46 " -m lbalg=value,type=value[,proxy-src=ip-range][,pmask=mask] \n"\ 47 " -h hc-name=value[,hc-port=value]] \n" \ 48 " [-t [conn-drain=N][,nat-timeout=N][,persist-timeout=N]] \n" \ 49 " -o servergroup=value name" 50 }; 51 52 static ilbadm_cmd_help_t destroy_rule_help = { 53 "-a | name ..." 54 }; 55 56 static ilbadm_cmd_help_t add_server_help = { 57 "-s server=value[,value ...] servergroup" 58 }; 59 60 static ilbadm_cmd_help_t remove_server_help = { 61 "-s server=value[,value ...] servergroup" 62 }; 63 64 65 static ilbadm_cmd_help_t disable_server_help = { 66 "server ... " 67 }; 68 69 static ilbadm_cmd_help_t enable_server_help = { 70 "server ..." 71 }; 72 73 static ilbadm_cmd_help_t enable_rule_help = { 74 "[name ... ]" 75 }; 76 77 static ilbadm_cmd_help_t disable_rule_help = { 78 "[name ... ]" 79 }; 80 81 static ilbadm_cmd_help_t show_server_help = { 82 "[[-p] -o field[,field...]] [rulename ... ]" 83 }; 84 85 static ilbadm_cmd_help_t showstats_help = { 86 "[-p] -o field[,...]] [-tdAvi]\n" \ 87 " [-r rulename|-s servername] [interval [count]]" 88 }; 89 90 static ilbadm_cmd_help_t show_nat_help = { 91 "[count]" 92 }; 93 94 static ilbadm_cmd_help_t show_persist_help = { 95 "[count]" 96 }; 97 98 static ilbadm_cmd_help_t show_hc_help = { 99 "[hc-name]" 100 }; 101 102 static ilbadm_cmd_help_t create_hc_help = { 103 "[-n] -h hc-test=value[,hc-timeout=value]\n" \ 104 " [,hc-count=value][,hc-interval=value] hcname" 105 }; 106 107 static ilbadm_cmd_help_t destroy_hc_help = { 108 "name ..." 109 }; 110 111 static ilbadm_cmd_help_t show_hc_result_help = { 112 "[rule-name]" 113 }; 114 115 static ilbadm_cmd_help_t show_rule_help = { 116 "[-e|-d] [-f |[-p] -o key[,key ...]] [name ...]" 117 }; 118 119 static ilbadm_cmd_help_t destroy_servergroup_help = { 120 "groupname" 121 }; 122 123 static ilbadm_cmd_help_t show_servergroup_help = { 124 "[[-p] -o field[,field]] [name]" 125 }; 126 127 static ilbadm_cmd_help_t export_config_help = { 128 "[filename]" 129 }; 130 131 static ilbadm_cmd_help_t import_config_help = { 132 "[-p] [filename]" 133 }; 134 static ilbadm_cmd_desc_t ilbadm_cmds[] = { 135 {"create-rule", "create-rl", ilbadm_create_rule, &create_rule_help}, 136 {"delete-rule", "delete-rl", ilbadm_destroy_rule, &destroy_rule_help}, 137 {"enable-rule", "enable-rl", ilbadm_enable_rule, &enable_rule_help}, 138 {"disable-rule", "disable-rl", ilbadm_disable_rule, 139 &disable_rule_help}, 140 {"show-rule", "show-rl", ilbadm_show_rules, &show_rule_help}, 141 142 {"create-servergroup", "create-sg", ilbadm_create_servergroup, 143 &create_sg_help}, 144 {"delete-servergroup", "delete-sg", ilbadm_destroy_servergroup, 145 &destroy_servergroup_help}, 146 {"show-servergroup", "show-sg", ilbadm_show_servergroups, 147 &show_servergroup_help}, 148 149 {"add-server", "add-srv", ilbadm_add_server_to_group, 150 &add_server_help}, 151 {"remove-server", "remove-srv", ilbadm_rem_server_from_group, 152 &remove_server_help}, 153 {"disable-server", "disable-srv", ilbadm_disable_server, 154 &disable_server_help}, 155 {"enable-server", "enable-srv", ilbadm_enable_server, 156 &enable_server_help}, 157 {"show-server", "show-srv", ilbadm_show_server, 158 &show_server_help}, 159 160 {"show-healthcheck", "show-hc", ilbadm_show_hc, &show_hc_help}, 161 {"create-healthcheck", "create-hc", ilbadm_create_hc, &create_hc_help}, 162 {"delete-healthcheck", "delete-hc", ilbadm_destroy_hc, 163 &destroy_hc_help}, 164 {"show-hc-result", "show-hc-res", ilbadm_show_hc_result, 165 &show_hc_result_help}, 166 167 {"export-config", "export-cf", ilbadm_export, &export_config_help}, 168 {"import-config", "import-cf", ilbadm_noimport, &import_config_help}, 169 170 {"show-statistics", "show-stats", ilbadm_show_stats, &showstats_help}, 171 {"show-nat", "show-nat", ilbadm_show_nat, &show_nat_help}, 172 {"show-persist", "show-pt", ilbadm_show_persist, 173 &show_persist_help}, 174 {"", "", NULL, NULL} 175 }; 176 177 178 /* ARGSUSED */ 179 ilbadm_status_t 180 ilbadm_noimport(int argc, char *argv[]) 181 { 182 ilbadm_err(ilbadm_errstr(ILBADM_NORECURSIVE)); 183 return (ILBADM_LIBERR); 184 } 185 186 static void 187 print_cmd_short(char *name, FILE *fp, ilbadm_cmd_desc_t *cmd) 188 { 189 char *h; 190 191 while (cmd->c_name[0] != '\0') { 192 if (cmd->c_help != NULL && 193 (h = cmd->c_help->h_help) != NULL) 194 (void) fprintf(fp, "%s %s|%s %s\n", name, 195 cmd->c_name, cmd->c_alias, h); 196 else 197 (void) fprintf(fp, "%s %s|%s\n", name, cmd->c_name, 198 cmd->c_alias); 199 cmd++; 200 } 201 } 202 203 void 204 print_cmdlist_short(char *name, FILE *fp) 205 { 206 print_cmd_short(name, fp, ilbadm_cmds); 207 } 208 209 #define IMPORT_FILE 0x1 210 211 static void 212 match_cmd(char *name, ilbadm_cmd_desc_t *cmds, cmdfunc_t *action, int flags) 213 { 214 ilbadm_cmd_desc_t *cmd; 215 216 if ((flags & IMPORT_FILE) == IMPORT_FILE) { 217 if (strcasecmp(name, "export-config") == 0 || 218 strcasecmp(name, "export-cf") == 0) { 219 ilbadm_err(gettext("export from import file" 220 " not allowed")); 221 exit(1); 222 } 223 } 224 225 for (cmd = &cmds[0]; cmd->c_name[0] != '\0'; cmd++) { 226 if (strncasecmp(cmd->c_name, name, sizeof (cmd->c_name)) == 0 || 227 strncasecmp(cmd->c_alias, name, sizeof (cmd->c_alias)) == 0) 228 break; 229 } 230 *action = cmd->c_action; 231 } 232 233 /* 234 * read and parse commandline 235 */ 236 static ilbadm_status_t 237 ilb_import_cmdline(int argc, char *argv[], int flags) 238 { 239 ilbadm_status_t rc = ILBADM_OK; 240 cmdfunc_t cmd; 241 242 match_cmd(argv[0], ilbadm_cmds, &cmd, flags); 243 244 if (*cmd != NULL) { 245 rc = cmd(argc, argv); 246 } else { 247 rc = ILBADM_INVAL_COMMAND; 248 ilbadm_err(ilbadm_errstr(rc)); 249 } 250 251 return (rc); 252 } 253 254 #define CHUNK 10 255 #define LINESZ 1024 256 257 typedef struct { 258 int listsz; 259 char *arglist[1]; 260 } arg_t; 261 262 static int 263 i_getln_to_argv(FILE *fp, arg_t **ap) 264 { 265 static char *linebuf = NULL; 266 char *stringp, *currp; 267 char delim[] = " \t\n"; 268 int i; 269 arg_t *a = *ap; 270 271 #define STR_DIFF(s1, s2) (int)((char *)s2 - (char *)s1) 272 #define STR_ADJ_SZ(sz, buf, s) (sz - STR_DIFF(buf, s)) 273 274 if (linebuf == NULL) 275 if ((linebuf = (char *)malloc(LINESZ)) == NULL) 276 return (0); 277 278 stringp = currp = linebuf; 279 i = 0; 280 read_next: 281 if (fgets(currp, STR_ADJ_SZ(LINESZ, linebuf, currp), fp) == NULL) 282 return (i); 283 284 /* ignore lines starting with a # character */ 285 if (*currp == '#') 286 goto read_next; 287 288 for (; stringp != NULL && currp != NULL; i++) { 289 currp = strsep(&stringp, delim); 290 /* 291 * if there's more than one adjacent delimiters ... 292 */ 293 if (*currp == '\0') { 294 i--; 295 continue; 296 } 297 /* 298 * if we find a '\' at the end of a line, treat 299 * it as a continuation character. 300 */ 301 if (*currp == '\\' && stringp == NULL) { 302 stringp = currp; 303 goto read_next; 304 } 305 if (a == NULL) { 306 a = (arg_t *)malloc(sizeof (*a)); 307 bzero(a, sizeof (*a)); 308 } 309 if (a->listsz <= i) { 310 int sz; 311 312 a->listsz += CHUNK; 313 sz = sizeof (*a) + 314 ((a->listsz - 1) * sizeof (a->arglist)); 315 a = (arg_t *)realloc(a, sz); 316 *ap = a; 317 } 318 a->arglist[i] = currp; 319 } 320 return (i); 321 } 322 323 static ilbadm_status_t 324 ilb_import_file(int fd, int flags) 325 { 326 FILE *fp; 327 arg_t *a = NULL; 328 int argcount; 329 ilbadm_status_t rc = ILBADM_OK; 330 331 if ((fp = fdopen(fd, "r")) == NULL) { 332 ilbadm_err(gettext("cannot import file for reading")); 333 exit(1); 334 } 335 336 if ((flags & ILBADM_IMPORT_PRESERVE) == 0) { 337 ilb_handle_t h = ILB_INVALID_HANDLE; 338 ilb_status_t rclib; 339 340 rclib = ilb_open(&h); 341 if (rclib == ILB_STATUS_OK) 342 (void) ilb_reset_config(h); 343 if (h != ILB_INVALID_HANDLE) 344 (void) ilb_close(h); 345 } 346 347 while ((argcount = i_getln_to_argv(fp, &a)) > 0) { 348 optind = 1; 349 rc = ilb_import_cmdline(argcount, a->arglist, IMPORT_FILE); 350 if (rc != ILBADM_OK) 351 break; 352 } 353 354 return (rc); 355 } 356 357 /* 358 * this is the wrapper around everything to do with importing and 359 * parsing either commandline or persistent storage. 360 * if (fd == -1), parse commandline, otherwise use the given fd as input. 361 */ 362 /* ARGSUSED */ 363 ilbadm_status_t 364 ilbadm_import(int fd, int argc, char *argv[], int flags) 365 { 366 ilbadm_status_t rc; 367 368 if (fd == -1) 369 rc = ilb_import_cmdline(argc, argv, 0); 370 else 371 rc = ilb_import_file(fd, flags); 372 373 return (rc); 374 } 375 376 ilbadm_status_t 377 ilbadm_export(int argc, char *argv[]) 378 { 379 ilb_handle_t h = ILB_INVALID_HANDLE; 380 ilbadm_status_t rc = ILBADM_OK; 381 ilb_status_t rclib = ILB_STATUS_OK; 382 int fd; 383 FILE *fp; 384 char *fname = NULL; 385 char tmpfile[MAXPATHLEN]; 386 387 if (argc < 2) { 388 fd = 1; /* stdout */ 389 *tmpfile = '\0'; 390 } else { 391 fname = argv[1]; 392 (void) snprintf(tmpfile, sizeof (tmpfile), "%sXXXXXX", fname); 393 fd = mkstemp(tmpfile); 394 395 if (fd == -1) { 396 ilbadm_err(gettext("cannot create working file")); 397 exit(1); 398 } 399 } 400 fp = fdopen(fd, "w"); 401 if (fp == NULL) { 402 ilbadm_err(gettext("cannot open file for writing"), fd); 403 exit(1); 404 } 405 406 rclib = ilb_open(&h); 407 if (rclib != ILB_STATUS_OK) 408 goto out; 409 410 rc = ilbadm_export_servergroups(h, fp); 411 if (rc != ILBADM_OK) 412 goto out; 413 414 rc = ilbadm_export_hc(h, fp); 415 if (rc != ILBADM_OK) 416 goto out; 417 418 rc = ilbadm_export_rules(h, fp); 419 if (rc != ILBADM_OK) 420 goto out; 421 422 if (fname != NULL) { 423 if (rename(tmpfile, fname) == -1) { 424 ilbadm_err(gettext("cannot create %s: %s"), fname, 425 strerror(errno)); 426 exit(1); 427 } 428 *tmpfile = '\0'; 429 } 430 431 out: 432 if (h != ILB_INVALID_HANDLE) 433 (void) ilb_close(h); 434 435 if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR)) 436 ilbadm_err(ilbadm_errstr(rc)); 437 (void) fclose(fp); 438 if (*tmpfile != '\0') 439 (void) unlink(tmpfile); 440 return (rc); 441 } 442