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
ilbadm_noimport(int argc,char * argv[])180 ilbadm_noimport(int argc, char *argv[])
181 {
182 ilbadm_err(ilbadm_errstr(ILBADM_NORECURSIVE));
183 return (ILBADM_LIBERR);
184 }
185
186 static void
print_cmd_short(char * name,FILE * fp,ilbadm_cmd_desc_t * cmd)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
print_cmdlist_short(char * name,FILE * fp)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
match_cmd(char * name,ilbadm_cmd_desc_t * cmds,cmdfunc_t * action,int flags)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
ilb_import_cmdline(int argc,char * argv[],int flags)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
i_getln_to_argv(FILE * fp,arg_t ** ap)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
ilb_import_file(int fd,int flags)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
ilbadm_import(int fd,int argc,char * argv[],int flags)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
ilbadm_export(int argc,char * argv[])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