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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #include <stdio.h>
28 #include <strings.h>
29 #include <limits.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <arpa/inet.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <libintl.h>
40 #include <locale.h>
41 #include <libvscan.h>
42
43 #if !defined(TEXT_DOMAIN)
44 #define TEXT_DOMAIN "SYS_TEST"
45 #endif
46
47
48 /* Property Names */
49 #define VS_ADM_MAXSIZE "max-size"
50 #define VS_ADM_MAXSIZE_ACTION "max-size-action"
51 #define VS_ADM_TYPES "types"
52
53 /* Scan Engine Property Names */
54 #define VS_ADM_SE_ENABLE "enable"
55 #define VS_ADM_SE_HOST "host"
56 #define VS_ADM_SE_PORT "port"
57 #define VS_ADM_SE_MAXCONN "max-connection"
58
59 /* Property Values */
60 #define VS_ADM_ON "on"
61 #define VS_ADM_OFF "off"
62 #define VS_ADM_ALLOW "allow"
63 #define VS_ADM_DENY "deny"
64
65
66 /*
67 * Print buffer length: used for sizing buffers that are filled with
68 * user-readable strings for property values. Define a number that
69 * accounts for some pre-value information, and won't (likely)
70 * wrap an 80-column display
71 */
72 #define VS_ADM_PRINT_BUF_LEN 4096
73
74 /* Program exit codes */
75 #define VS_ADM_EXIT_SUCCESS 0
76 #define VS_ADM_EXIT_ERROR 1
77 #define VS_ADM_EXIT_USAGE 2
78
79
80 /*
81 * vscanadm property definition. Maps the property ids to a
82 * property name, and includes functions to convert to and from
83 * input strings and native data.
84 */
85 typedef struct vs_adm_property {
86 const char *vap_name;
87 uint64_t vap_id;
88 int (*vap_parse)(const char *, void *);
89 int (*vap_unparse)(const void *, char *, size_t);
90 } vs_adm_property_t;
91
92
93 /* usage/help information for subcommnds */
94 #define VS_ADM_HELP_GET ("[-p property]...\n" \
95 "\tdisplay vscan properties")
96 #define VS_ADM_HELP_SET ("-p property=value [-p property=value]...\n" \
97 "\tset values of vscan properties")
98 #define VS_ADM_HELP_GET_ENG ("[-p property] [engine_id]\n" \
99 "\tdisplay values of scan engine properties")
100 #define VS_ADM_HELP_ADD_ENG ("[-p property=value]... engine_id\n" \
101 "\tadd scan engine")
102 #define VS_ADM_HELP_SET_ENG ("-p property=value [-p property=value]" \
103 "... engine_id\n\tset values of scan engine properties")
104 #define VS_ADM_HELP_REM_ENG ("engine_id\n" \
105 "\tremove scan engine")
106 #define VS_ADM_HELP_SHOW ("\n\tdisplay the values of all vscan " \
107 "service and scan engine properties")
108 #define VS_ADM_HELP_STATS ("[-z]\n\tdisplay vscan service statistics")
109 #define VS_ADM_HELP_IMPORT ("-p property filename\n" \
110 "\timport property from file")
111 #define VS_ADM_HELP_EXPORT ("-p property filename\n" \
112 "\texport property to file")
113 #define VS_ADM_HELP_VALIDATE ("-p property filename\n" \
114 "\tvalidate property in file")
115
116
117 /*
118 * vscanadm command structure. Encapsulates the vscanadm
119 * subcommand name, pointer to the subcommand implementation
120 * function, and a help id to get usage/help information.
121 */
122 typedef struct vs_adm_cmd {
123 int (*vac_func)(int, char *[]);
124 const char *vac_name;
125 char *vac_helpid;
126 }
127 vs_adm_cmd_t;
128
129
130 /* Subcommand implementation functions */
131 static int vs_adm_set(int, char **);
132 static int vs_adm_get(int, char **);
133 static int vs_adm_set_engine(int, char **);
134 static int vs_adm_get_engine(int, char **);
135 static int vs_adm_rem_engine(int, char **);
136 static int vs_adm_show(int, char **);
137 static int vs_adm_stats(int, char **);
138 static int vs_adm_import(int, char **);
139 static int vs_adm_export(int, char **);
140 static int vs_adm_validate(int, char **);
141
142
143 /*
144 * Parse routines to transform libvscan API data into user-readable strings
145 */
146 static int vs_adm_parse_maxsize(const char *, void *);
147 static int vs_adm_parse_maxsize_action(const char *, void *);
148 static int vs_adm_parse_types(const char *, void *);
149 static int vs_adm_parse_enable(const char *, void *);
150 static int vs_adm_parse_host(const char *, void *);
151 static int vs_adm_parse_port(const char *, void *);
152 static int vs_adm_parse_maxconn(const char *, void *);
153
154
155 /*
156 * Unparse routines to transform strings from the user input into
157 * API native data.
158 *
159 * While some value validation is performed in the course of unparsing
160 * string data, complete value validation is left to libvscan.
161 * Values that are in unacceptable form, out of range, or otherwise
162 * violate rules for a given property will be rejected
163 */
164 static int vs_adm_unparse_maxsize(const void *, char *, size_t);
165 static int vs_adm_unparse_maxsize_action(const void *, char *, size_t);
166 static int vs_adm_unparse_types(const void *, char *, size_t);
167 static int vs_adm_unparse_enable(const void *, char *, size_t);
168 static int vs_adm_unparse_host(const void *, char *, size_t);
169 static int vs_adm_unparse_port(const void *, char *, size_t);
170 static int vs_adm_unparse_maxconn(const void *, char *, size_t);
171
172
173 /*
174 * The properties table includes a vscanadm property entry, specifying
175 * the property nane, property id, parse amd inparse methods,
176 * for each vscanadm property.
177 */
178 static const vs_adm_property_t vs_adm_props_all[] = {
179 { VS_ADM_MAXSIZE, VS_PROPID_MAXSIZE,
180 vs_adm_parse_maxsize, vs_adm_unparse_maxsize },
181 { VS_ADM_MAXSIZE_ACTION, VS_PROPID_MAXSIZE_ACTION,
182 vs_adm_parse_maxsize_action, vs_adm_unparse_maxsize_action },
183 { VS_ADM_TYPES, VS_PROPID_TYPES,
184 vs_adm_parse_types, vs_adm_unparse_types },
185 { VS_ADM_SE_ENABLE, VS_PROPID_SE_ENABLE,
186 vs_adm_parse_enable, vs_adm_unparse_enable },
187 { VS_ADM_SE_HOST, VS_PROPID_SE_HOST,
188 vs_adm_parse_host, vs_adm_unparse_host },
189 { VS_ADM_SE_PORT, VS_PROPID_SE_PORT,
190 vs_adm_parse_port, vs_adm_unparse_port },
191 { VS_ADM_SE_MAXCONN, VS_PROPID_SE_MAXCONN,
192 vs_adm_parse_maxconn, vs_adm_unparse_maxconn },
193 { NULL, 0, NULL, NULL }
194 };
195
196
197 /*
198 * The subcommand table. Used to find the subcommand specified
199 * by the user and dispatch the processing for the subcommand.
200 * Also used to display usage information for each subcommand.
201 */
202 static const vs_adm_cmd_t vs_adm_cmds[] =
203 {
204 { vs_adm_get, "get", VS_ADM_HELP_GET },
205 { vs_adm_set, "set", VS_ADM_HELP_SET },
206 { vs_adm_get_engine, "get-engine", VS_ADM_HELP_GET_ENG },
207 { vs_adm_set_engine, "set-engine", VS_ADM_HELP_SET_ENG },
208 { vs_adm_set_engine, "add-engine", VS_ADM_HELP_ADD_ENG },
209 { vs_adm_rem_engine, "remove-engine", VS_ADM_HELP_REM_ENG },
210 { vs_adm_import, "import", VS_ADM_HELP_IMPORT },
211 { vs_adm_export, "export", VS_ADM_HELP_EXPORT },
212 { vs_adm_validate, "validate", VS_ADM_HELP_VALIDATE },
213 { vs_adm_show, "show", VS_ADM_HELP_SHOW },
214 { vs_adm_stats, "stats", VS_ADM_HELP_STATS },
215 { NULL, NULL, NULL }
216 };
217
218
219 static const char *vs_adm_cmd;
220 static const char *vs_adm_subcmd;
221
222 static int vs_adm_usage(FILE *);
223 static int vs_adm_props_from_input(int, char **, vs_props_t *, uint64_t *);
224 static void vs_adm_output_getcmd(uint64_t, const void *);
225 static void vs_adm_output_stats(vs_stats_t *);
226 static const vs_adm_property_t *vs_adm_prop_by_name(const char *);
227 static const vs_adm_property_t *vs_adm_prop_by_id(const uint64_t);
228 static int vs_adm_parse(const vs_adm_property_t *, const char *, void *);
229 static void vs_adm_unparse(const vs_adm_property_t *, const void *,
230 char *, size_t);
231
232 static int vs_adm_file_read(char *, char *, int);
233 static int vs_adm_file_write(char *, char *);
234 static int vs_adm_file_usage(int argc, char **argv);
235
236 /*
237 * main
238 */
239 int
main(int argc,char ** argv)240 main(int argc, char **argv)
241 {
242 const vs_adm_cmd_t *cp;
243 const char *p;
244 int i, err;
245
246 (void) setlocale(LC_ALL, "");
247 (void) textdomain(TEXT_DOMAIN);
248
249 /* executable and subcommand names */
250 if ((p = strrchr(argv[0], '/')) == NULL)
251 vs_adm_cmd = argv[0];
252 else
253 vs_adm_cmd = p + 1;
254
255 vs_adm_subcmd = argv[1];
256
257 /* require at least command and sub-command */
258 if (argc < 2)
259 return (vs_adm_usage(stdout));
260
261 /* Check for the "-?" help switch */
262 for (i = 1; i < argc; i++) {
263 if (strcmp(argv[i], "-?") == 0)
264 return (vs_adm_usage(stdout));
265 }
266
267 /* Locate the specified subcommand */
268 for (cp = vs_adm_cmds; cp->vac_name != NULL; cp++) {
269 if (strcmp(cp->vac_name, vs_adm_subcmd) == 0)
270 break;
271 }
272
273 if (cp->vac_name == NULL) {
274 (void) fprintf(stderr, "%s: %s -- %s\n",
275 gettext("invalid subcommand"),
276 vs_adm_cmd, vs_adm_subcmd);
277 return (vs_adm_usage(stderr));
278 }
279
280 /* invoke sub-command handler */
281 err = cp->vac_func(argc, argv);
282
283 return (err == VS_ADM_EXIT_USAGE ? vs_adm_usage(stderr) : err);
284 }
285
286
287 /*
288 * vs_adm_usage
289 */
290 static int
vs_adm_usage(FILE * fp)291 vs_adm_usage(FILE *fp)
292 {
293 const vs_adm_cmd_t *cp;
294
295 for (cp = vs_adm_cmds; cp->vac_name != NULL; cp++) {
296 (void) fprintf(fp, "%s %s", vs_adm_cmd, cp->vac_name);
297 if (cp->vac_helpid != NULL)
298 (void) fprintf(fp, " %s\n", cp->vac_helpid);
299 }
300
301 return (VS_ADM_EXIT_USAGE);
302 }
303
304
305 /*
306 * vs_adm_get
307 *
308 * Gets and displays general vscan service configuration properties.
309 */
310 static int
vs_adm_get(int argc,char ** argv)311 vs_adm_get(int argc, char **argv)
312 {
313 uint64_t propids;
314 int i, rc;
315 vs_props_t vp;
316 const vs_adm_property_t *vap;
317
318 (void) memset(&vp, 0, sizeof (vp));
319
320 if (argc <= 2) {
321 propids = VS_PROPID_GEN_ALL;
322 } else {
323 propids = 0LL;
324 for (i = 2; i < argc; i++) {
325 /* the "-p" specifier is optional */
326 if (strcmp(argv[i], "-p") == 0) {
327 if (++i >= argc)
328 return (VS_ADM_EXIT_USAGE);
329 }
330
331 if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
332 (void) fprintf(stderr, "%s '%s'\n",
333 gettext("invalid property"), argv[i]);
334 return (VS_ADM_EXIT_ERROR);
335 }
336
337 propids |= vap->vap_id;
338 }
339 }
340
341 rc = vs_props_get(&vp, propids);
342 if (rc != VS_ERR_NONE) {
343 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
344 return (VS_ADM_EXIT_ERROR);
345 }
346
347 vs_adm_output_getcmd(propids, &vp);
348
349 return (VS_ADM_EXIT_SUCCESS);
350 }
351
352
353 /*
354 * vs_adm_set
355 *
356 * Sets values for general vscan service configuration properties
357 *
358 * Calls a common function used by the set, add, and remove
359 * subcommands to modify general property values.
360 */
361 static int
vs_adm_set(int argc,char ** argv)362 vs_adm_set(int argc, char **argv)
363 {
364 vs_props_t vp;
365 uint64_t propids;
366 int rc;
367
368 if (argc < 3)
369 return (VS_ADM_EXIT_USAGE);
370
371 rc = vs_adm_props_from_input(argc, argv, &vp, &propids);
372 if (rc != VS_ADM_EXIT_SUCCESS)
373 return (rc);
374
375 rc = vs_props_set(&vp, propids);
376 if (rc != VS_ERR_NONE) {
377 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
378 return (VS_ADM_EXIT_ERROR);
379 }
380
381 return (VS_ADM_EXIT_SUCCESS);
382 }
383
384
385 /*
386 * vs_adm_get_engine
387 *
388 * Gets and displays scan engine configuration properties for
389 * one or more scan engines.
390 */
391 static int
vs_adm_get_engine(int argc,char ** argv)392 vs_adm_get_engine(int argc, char **argv)
393 {
394 int i, rc;
395 uint64_t propids;
396 char *engid = NULL;
397 const vs_adm_property_t *vap;
398 vs_props_all_t va;
399
400 propids = 0LL;
401 for (i = 2; i < argc; i++) {
402 /* if not preceded by -p, must be engine id and must be last */
403 if (strcmp(argv[i], "-p") != 0) {
404 if (i != (argc - 1))
405 return (VS_ADM_EXIT_USAGE);
406
407 engid = argv[i];
408 if (strlen(engid) > VS_SE_NAME_LEN) {
409 (void) fprintf(stderr, "%s\n",
410 gettext("invalid scan engine"));
411 return (VS_ADM_EXIT_ERROR);
412 }
413 } else {
414 /* property should follow the -p */
415 if (++i >= argc)
416 return (VS_ADM_EXIT_USAGE);
417
418 if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
419 (void) fprintf(stderr, "%s '%s'\n",
420 gettext("invalid property"), argv[i]);
421 return (VS_ADM_EXIT_ERROR);
422 }
423
424 propids |= vap->vap_id;
425 }
426 }
427
428 if (propids == 0LL)
429 propids = VS_PROPID_SE_ALL;
430
431 /* get properties for specified engine */
432 if (engid) {
433 rc = vs_props_se_get(engid, &va.va_se[0], propids);
434 if (rc != VS_ERR_NONE) {
435 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
436 return (VS_ADM_EXIT_ERROR);
437 }
438 vs_adm_output_getcmd(propids, &va.va_se[0]);
439 return (VS_ADM_EXIT_SUCCESS);
440 }
441
442 /* get properties for all engines */
443 if ((rc = vs_props_get_all(&va)) != VS_ERR_NONE) {
444 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
445 return (VS_ADM_EXIT_ERROR);
446 }
447
448 for (i = 0; i < VS_SE_MAX; i++) {
449 if (*(va.va_se[i].vep_engid) == 0)
450 break;
451 vs_adm_output_getcmd(propids, &va.va_se[i]);
452 }
453 if (i == 0) {
454 (void) fprintf(stdout, "%s\n",
455 gettext("no scan engines configured"));
456 }
457
458 return (VS_ADM_EXIT_SUCCESS);
459 }
460
461
462 /*
463 * vs_adm_set_engine
464 *
465 * Sets one or more scan engine configuration properties for a
466 * single scan engine.
467 */
468 static int
vs_adm_set_engine(int argc,char ** argv)469 vs_adm_set_engine(int argc, char **argv)
470 {
471 const vs_adm_property_t *vap;
472 vs_props_se_t sep;
473 char *val;
474 uint64_t propids;
475 int i, rc;
476 char *engid;
477 int add = (strcmp(vs_adm_subcmd, "add-engine") == 0) ? 1 : 0;
478
479
480 if ((argc < 3) || ((!add) && (argc < 4)))
481 return (VS_ADM_EXIT_USAGE);
482
483 /* Get the engine id */
484 engid = argv[argc - 1];
485 if (strchr(engid, '=') || strcmp(argv[argc - 2], "-p") == 0) {
486 return (VS_ADM_EXIT_USAGE);
487 }
488
489 if (strlen(engid) > VS_SE_NAME_LEN) {
490 (void) fprintf(stderr, "%s\n",
491 gettext("invalid scan engine"));
492 return (VS_ADM_EXIT_ERROR);
493 }
494
495 propids = 0LL;
496
497 for (i = 2; i < (argc - 1); i++) {
498 /* The "-p" is optional */
499 if (strcmp(argv[i], "-p") == 0) {
500 if (++i >= argc)
501 return (VS_ADM_EXIT_USAGE);
502 }
503
504 if ((val = strchr(argv[i], '=')) == NULL)
505 return (VS_ADM_EXIT_USAGE);
506
507 *val = 0;
508 val++;
509
510 /* Find the SE property pointer from the SE property name */
511 if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
512 (void) fprintf(stderr, "%s '%s'\n",
513 gettext("invalid property"), argv[i]);
514 return (VS_ADM_EXIT_ERROR);
515 }
516
517 propids |= vap->vap_id;
518
519 if ((vs_adm_parse(vap, val, &sep)) != 0) {
520 (void) fprintf(stderr, "%s '%s'\n",
521 gettext("invalid property value"), val);
522 return (VS_ADM_EXIT_ERROR);
523 }
524 }
525
526 if (add)
527 rc = vs_props_se_create(engid, &sep, propids);
528 else
529 rc = vs_props_se_set(engid, &sep, propids);
530
531 if (rc != VS_ERR_NONE) {
532 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
533 return (VS_ADM_EXIT_ERROR);
534 }
535
536 return (VS_ADM_EXIT_SUCCESS);
537 }
538
539
540 /*
541 * vs_adm_rem_engine
542 */
543 /* ARGSUSED */
544 static int
vs_adm_rem_engine(int argc,char ** argv)545 vs_adm_rem_engine(int argc, char **argv)
546 {
547 int rc;
548 char *engid;
549
550 if (argc != 3)
551 return (VS_ADM_EXIT_USAGE);
552
553 engid = argv[2];
554
555 if (strlen(engid) > VS_SE_NAME_LEN) {
556 (void) fprintf(stderr, "%s\n",
557 gettext("invalid scan engine"));
558 return (VS_ADM_EXIT_ERROR);
559 }
560
561 if ((rc = vs_props_se_delete(engid)) != VS_ERR_NONE) {
562 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
563 return (rc);
564 }
565
566 return (VS_ADM_EXIT_SUCCESS);
567 }
568
569
570 /*
571 * vs_adm_import
572 */
573 static int
vs_adm_import(int argc,char ** argv)574 vs_adm_import(int argc, char **argv)
575 {
576 int rc;
577 vs_props_t vp;
578 uint64_t propids;
579 char *filename;
580
581 if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
582 return (rc);
583
584 filename = argv[argc - 1];
585 rc = vs_adm_file_read(filename, vp.vp_types, sizeof (vp.vp_types));
586 if (rc != VS_ADM_EXIT_SUCCESS)
587 return (rc);
588
589 propids = VS_PROPID_TYPES;
590 rc = vs_props_set(&vp, propids);
591 if (rc != VS_ERR_NONE) {
592 (void) fprintf(stderr, "%s\n", vs_strerror(rc));
593 return (VS_ADM_EXIT_ERROR);
594 }
595
596 return (VS_ADM_EXIT_SUCCESS);
597 }
598
599
600 /*
601 * vs_adm_validate
602 */
603 static int
vs_adm_validate(int argc,char ** argv)604 vs_adm_validate(int argc, char **argv)
605 {
606 int rc;
607 vs_props_t vp;
608 char *filename;
609
610 if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
611 return (rc);
612
613 filename = argv[argc - 1];
614 rc = vs_adm_file_read(filename, vp.vp_types, sizeof (vp.vp_types));
615 if (rc != VS_ADM_EXIT_SUCCESS)
616 return (rc);
617
618 if (vs_props_validate(&vp, VS_PROPID_TYPES) != VS_ERR_NONE) {
619 (void) fprintf(stderr, "%s: %s\n", filename, vs_strerror(rc));
620 return (VS_ADM_EXIT_ERROR);
621 }
622
623 (void) fprintf(stdout, "%s: valid\n", filename);
624 return (VS_ADM_EXIT_SUCCESS);
625 }
626
627
628 /*
629 * vs_adm_export
630 */
631 static int
vs_adm_export(int argc,char ** argv)632 vs_adm_export(int argc, char **argv)
633 {
634 int rc;
635 vs_props_t vp;
636 uint64_t propids;
637 char *filename;
638
639 if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
640 return (rc);
641
642 filename = argv[argc - 1];
643 (void) memset(&vp, 0, sizeof (vs_props_t));
644 propids = VS_PROPID_TYPES;
645 if ((rc = vs_props_get(&vp, propids)) != VS_ERR_NONE) {
646 (void) fprintf(stderr, "%s: %s\n", filename, vs_strerror(rc));
647 return (VS_ADM_EXIT_ERROR);
648 }
649
650 rc = vs_adm_file_write(filename, vp.vp_types);
651 if (rc != VS_ADM_EXIT_SUCCESS)
652 return (rc);
653
654 return (VS_ADM_EXIT_SUCCESS);
655 }
656
657
658 /*
659 * vs_adm_file_usage
660 *
661 * import, export and validate - VS_PROPID_TYPES only
662 */
663 static int
vs_adm_file_usage(int argc,char ** argv)664 vs_adm_file_usage(int argc, char **argv)
665 {
666 const vs_adm_property_t *vap;
667 char *prop;
668
669 if (argc < 4)
670 return (VS_ADM_EXIT_USAGE);
671
672 /* -p optional */
673 if (strcmp(argv[2], "-p") == 0) {
674 if (argc != 5)
675 return (VS_ADM_EXIT_USAGE);
676 } else if (argc != 4)
677 return (VS_ADM_EXIT_USAGE);
678
679 /* only VS_PROPID_TYPES supported */
680 prop = argv[argc - 2];
681 vap = vs_adm_prop_by_name(prop);
682 if ((vap == NULL) || (vap->vap_id != VS_PROPID_TYPES)) {
683 (void) fprintf(stderr, "%s '%s'\n",
684 gettext("invalid property"), prop);
685 return (VS_ADM_EXIT_USAGE);
686 }
687
688 return (VS_ADM_EXIT_SUCCESS);
689 }
690
691
692 /*
693 * vs_adm_file_read
694 */
695 static int
vs_adm_file_read(char * filename,char * buf,int len)696 vs_adm_file_read(char *filename, char *buf, int len)
697 {
698 FILE *fp;
699
700 if ((fp = fopen(filename, "r")) == NULL) {
701 (void) fprintf(stderr, "%s: %s\n", filename,
702 vs_strerror(VS_ERR_SYS));
703 return (VS_ADM_EXIT_ERROR);
704 }
705
706 (void) memset(buf, 0, len);
707 if (fgets(buf, len, fp) == NULL) {
708 (void) fprintf(stderr, "%s: %s\n", filename,
709 gettext("invalid property value"));
710 (void) fclose(fp);
711 return (VS_ADM_EXIT_ERROR);
712 }
713
714 (void) fclose(fp);
715
716 /* remove newline */
717 if (buf[strlen(buf) - 1] == '\n')
718 buf[strlen(buf) - 1] = '\0';
719
720 return (VS_ADM_EXIT_SUCCESS);
721 }
722
723
724 /*
725 * vs_adm_file_write
726 */
727 static int
vs_adm_file_write(char * filename,char * buf)728 vs_adm_file_write(char *filename, char *buf)
729 {
730 FILE *fp;
731 int bytes;
732
733 if ((fp = fopen(filename, "w")) == NULL) {
734 (void) fprintf(stderr, "%s: %s\n", filename,
735 vs_strerror(VS_ERR_SYS));
736 return (VS_ADM_EXIT_ERROR);
737 }
738
739 bytes = fprintf(fp, "%s\n", buf);
740 if ((bytes < 0) || (bytes != strlen(buf) + 1)) {
741 (void) fprintf(stderr, "%s: %s\n", filename,
742 vs_strerror(VS_ERR_SYS));
743 (void) fclose(fp);
744 return (VS_ADM_EXIT_ERROR);
745 }
746
747 (void) fclose(fp);
748 return (VS_ADM_EXIT_SUCCESS);
749 }
750
751
752 /*
753 * vs_adm_show
754 *
755 * Gets and displays all general properties and all scan engine
756 * properties.
757 */
758 /* ARGSUSED */
759 static int
vs_adm_show(int argc,char ** argv)760 vs_adm_show(int argc, char **argv)
761 {
762 if (argc > 2)
763 return (VS_ADM_EXIT_USAGE);
764
765 (void) vs_adm_get(argc, argv);
766 (void) vs_adm_get_engine(argc, argv);
767
768 return (VS_ADM_EXIT_SUCCESS);
769 }
770
771
772 /*
773 * vs_adm_stats
774 *
775 * Gets and displays vscan service statistics.
776 */
777 /* ARGSUSED */
778 static int
vs_adm_stats(int argc,char ** argv)779 vs_adm_stats(int argc, char **argv)
780 {
781 int rc;
782 vs_stats_t stats;
783
784 /* get statistics */
785 if (argc == 2) {
786 if ((rc = vs_statistics(&stats)) == VS_ERR_NONE) {
787 vs_adm_output_stats(&stats);
788 return (VS_ADM_EXIT_SUCCESS);
789 } else {
790 (void) fprintf(stdout, "%s\n", vs_strerror(rc));
791 return (VS_ADM_EXIT_ERROR);
792 }
793 }
794
795 /* reset statistics */
796 if (argc == 3 && strcmp(argv[2], "-z") == 0) {
797 if ((rc = vs_statistics_reset()) == VS_ERR_NONE) {
798 return (VS_ADM_EXIT_SUCCESS);
799 } else {
800 (void) fprintf(stdout, "%s\n", vs_strerror(rc));
801 return (VS_ADM_EXIT_ERROR);
802 }
803 }
804
805 /* usage error */
806 return (vs_adm_usage(stdout));
807 }
808
809
810 /*
811 * vs_adm_output_stats
812 */
813 static void
vs_adm_output_stats(vs_stats_t * stats)814 vs_adm_output_stats(vs_stats_t *stats)
815 {
816 int i;
817 char *engid;
818
819 if (stats == NULL)
820 return;
821
822 (void) fprintf(stdout, "scanned=%lld\n", stats->vss_scanned);
823 (void) fprintf(stdout, "infected=%lld\n", stats->vss_infected);
824 if (stats->vss_cleaned > 0)
825 (void) printf("cleaned=%lld\n", stats->vss_cleaned);
826 (void) fprintf(stdout, "failed=%lld\n", stats->vss_failed);
827
828 for (i = 0; i < VS_SE_MAX; i++) {
829 engid = stats->vss_eng[i].vss_engid;
830 if (*engid == 0)
831 break;
832 (void) fprintf(stdout, "%s:errors=%lld\n", engid,
833 stats->vss_eng[i].vss_errors);
834 }
835 }
836
837
838 /*
839 * vs_adm_props_from_input
840 */
841 static int
vs_adm_props_from_input(int argc,char ** argv,vs_props_t * vsprops,uint64_t * propids)842 vs_adm_props_from_input(int argc, char **argv, vs_props_t *vsprops,
843 uint64_t *propids)
844 {
845 const vs_adm_property_t *vap;
846 char *val;
847 int i;
848
849 (void) memset(vsprops, 0, sizeof (vs_props_t));
850
851 *propids = 0LL;
852 for (i = 2; i < argc; i++) {
853 /* The "-p" is optional */
854 if (strcmp(argv[i], "-p") == 0) {
855 if (++i >= argc)
856 return (VS_ADM_EXIT_USAGE);
857 }
858
859 if ((val = strchr(argv[i], '=')) == NULL)
860 return (VS_ADM_EXIT_USAGE);
861
862 /* Find the vscanadm property pointer from the property name */
863 *val = '\0';
864 val++;
865 if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
866 (void) fprintf(stderr, "%s '%s'\n",
867 gettext("invalid property"), argv[i]);
868 return (VS_ADM_EXIT_ERROR);
869 }
870
871 /* Add in the property id and parse the property value */
872 *propids |= vap->vap_id;
873 if ((vs_adm_parse(vap, val, vsprops)) != 0) {
874 (void) fprintf(stderr, "%s '%s'\n",
875 gettext("invalid property value"), val);
876 return (VS_ADM_EXIT_ERROR);
877 }
878 }
879
880 return (VS_ADM_EXIT_SUCCESS);
881 }
882
883
884 /*
885 * vs_adm_output_getcmd
886 *
887 * Prints the results of a get command; both the get for general
888 * configuration properties as well as the get for an engine
889 * properties.
890 *
891 */
892 static void
vs_adm_output_getcmd(uint64_t propids,const void * props)893 vs_adm_output_getcmd(uint64_t propids, const void *props)
894 {
895 char value[VS_ADM_PRINT_BUF_LEN];
896 uint64_t propid;
897 const vs_adm_property_t *vap;
898 char *label = NULL;
899
900 if (VS_PROPID_IS_SE(propids))
901 label = ((vs_props_se_t *)props)->vep_engid;
902
903 /*
904 * Unparse values from the property structure into readable strings
905 * and print them.
906 */
907 for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) {
908 if ((propids & propid) == 0)
909 continue;
910
911 if ((vap = vs_adm_prop_by_id(propid)) == NULL)
912 continue;
913
914 *value = '\0';
915 vs_adm_unparse(vap, props, value, sizeof (value));
916
917 if (label)
918 (void) fprintf(stdout, "%s:", label);
919 (void) fprintf(stdout, "%s=%s\n", vap->vap_name, value);
920 }
921
922 (void) fprintf(stdout, "\n");
923 }
924
925
926 /*
927 * vs_adm_prop_by_name
928 *
929 * Finds and returns a pointer to a vscan property structure from the
930 * property table by property name.
931 */
932 static const vs_adm_property_t *
vs_adm_prop_by_name(const char * propname)933 vs_adm_prop_by_name(const char *propname)
934 {
935 const vs_adm_property_t *p;
936
937 for (p = vs_adm_props_all; p->vap_name != NULL; p++) {
938 if (strcmp(propname, p->vap_name) == 0)
939 return (p);
940 }
941
942 return (NULL);
943 }
944
945
946 /*
947 * vs_adm_prop_by_id
948 *
949 * Finds and returns a pointer to a vscan property structure from the
950 * property table by property name.
951 */
952 static const vs_adm_property_t *
vs_adm_prop_by_id(const uint64_t propid)953 vs_adm_prop_by_id(const uint64_t propid)
954 {
955 const vs_adm_property_t *p;
956
957 for (p = vs_adm_props_all; p->vap_id != 0; p++) {
958 if (propid == p->vap_id)
959 return (p);
960 }
961
962 return (NULL);
963 }
964
965
966 /*
967 * vs_adm_parse
968 *
969 * Entry point for parsing the user input strings into a data structure
970 * used for setting values. Dispatches the actual parsing to the parse
971 * routine for the specified vscanadm property.
972 *
973 * This function is used to dispatch parsing for values supplied by the
974 * user for all subcommands; both the general configuration as well as
975 * scan engine configuration. The structure pointer is therefore typed
976 * as a void pointer, and cast appropriately in the parse routine for
977 * the vscanadm property.
978 */
979 static int
vs_adm_parse(const vs_adm_property_t * vap,const char * valvap_name,void * vp)980 vs_adm_parse(const vs_adm_property_t *vap, const char *valvap_name,
981 void *vp)
982 {
983 return ((vap->vap_parse)(valvap_name, vp));
984 }
985
986
987 /*
988 * vs_adm_parse_maxsize
989 *
990 * Parses a user-supplied string into a maxsize (decimal) value for
991 * the general vscan configuration properties.
992 */
993 static int
vs_adm_parse_maxsize(const char * valstr,void * vp)994 vs_adm_parse_maxsize(const char *valstr, void *vp)
995 {
996 vs_props_t *svcp = vp;
997
998 uint64_t maxsize;
999 char *end;
1000
1001 errno = 0;
1002 maxsize = strtoll(valstr, &end, 10);
1003 if (errno != 0)
1004 return (-1);
1005 (void) snprintf(svcp->vp_maxsize, sizeof (svcp->vp_maxsize),
1006 "%llu%s", maxsize, end);
1007
1008 return (0);
1009 }
1010
1011
1012 /*
1013 * vs_adm_parse_maxsize_action
1014 *
1015 * Parses a user-supplied string into a maxsize action value for the
1016 * general vscan configuration properties.
1017 *
1018 * Returns: 0 success
1019 * -1 failure
1020 */
1021 static int
vs_adm_parse_maxsize_action(const char * valstr,void * vp)1022 vs_adm_parse_maxsize_action(const char *valstr, void *vp)
1023 {
1024 vs_props_t *svcp = vp;
1025
1026 if (strcmp(valstr, VS_ADM_ALLOW) == 0) {
1027 svcp->vp_maxsize_action = B_TRUE;
1028 return (0);
1029 }
1030
1031 if (strcmp(valstr, VS_ADM_DENY) == 0) {
1032 svcp->vp_maxsize_action = B_FALSE;
1033 return (0);
1034 }
1035
1036 return (-1);
1037 }
1038
1039
1040 /*
1041 * vs_adm_parse_types
1042 *
1043 * Returns: 0 success
1044 * -1 on failure.
1045 */
1046 static int
vs_adm_parse_types(const char * valstr,void * vp)1047 vs_adm_parse_types(const char *valstr, void *vp)
1048 {
1049 vs_props_t *svcp = vp;
1050
1051 if (strlen(valstr) >= sizeof (svcp->vp_types))
1052 return (-1);
1053
1054 if (strlcpy(svcp->vp_types, valstr, sizeof (svcp->vp_types))
1055 >= sizeof (svcp->vp_types))
1056 return (-1);
1057
1058 return (0);
1059 }
1060
1061
1062 /*
1063 * vs_adm_parse_enable
1064 *
1065 * Parses a user-supplied string into an enable value for the
1066 * properties of a scan engine.
1067 *
1068 * Returns: 0 success
1069 * -1 on failure.
1070 */
1071 static int
vs_adm_parse_enable(const char * valstr,void * vp)1072 vs_adm_parse_enable(const char *valstr, void *vp)
1073 {
1074 vs_props_se_t *sep = vp;
1075
1076 if (strcmp(valstr, VS_ADM_ON) == 0) {
1077 sep->vep_enable = B_TRUE;
1078 return (0);
1079 }
1080
1081 if (strcmp(valstr, VS_ADM_OFF) == 0) {
1082 sep->vep_enable = B_FALSE;
1083 return (0);
1084 }
1085
1086 return (-1);
1087 }
1088
1089
1090 /*
1091 * vs_adm_parse_host
1092 *
1093 * Parses a user-supplied string into an ip address value for the
1094 * properties of a scan engine.
1095 */
1096 static int
vs_adm_parse_host(const char * valstr,void * vp)1097 vs_adm_parse_host(const char *valstr, void *vp)
1098 {
1099 vs_props_se_t *sep = vp;
1100
1101 if (strlen(valstr) >= sizeof (sep->vep_host))
1102 return (-1);
1103
1104 if (strlcpy(sep->vep_host, valstr, sizeof (sep->vep_host)) >=
1105 sizeof (sep->vep_host))
1106 return (-1);
1107
1108 return (0);
1109 }
1110
1111
1112 /*
1113 * vs_adm_parse_port
1114 *
1115 * Parses a user-supplied string into a port value for the properties of
1116 * a scan engine. The port is an unsigned short int, but the conversion
1117 * must be done on a word-sized int. Casting the converted int into the
1118 * port member of the property structure can result in a valid but
1119 * unintended value, so the range is checked first for validity.
1120 *
1121 * Returns: 0 success
1122 * -1 on failure.
1123 */
1124 static int
vs_adm_parse_port(const char * valstr,void * vp)1125 vs_adm_parse_port(const char *valstr, void *vp)
1126 {
1127 vs_props_se_t *sep = vp;
1128 unsigned long port;
1129 char *end;
1130
1131 end = 0;
1132 port = strtoul(valstr, &end, 0);
1133 if (port > UINT16_MAX || (end < (valstr + strlen(valstr))))
1134 return (-1);
1135
1136 sep->vep_port = port;
1137
1138 return (0);
1139 }
1140
1141
1142 /*
1143 * vs_adm_parse_maxconn
1144 *
1145 * Parses a user-supplied string into a max connections (decimal) value
1146 * for the properties of a scan engine.
1147 *
1148 * Returns: 0 success
1149 * -1 on failure.
1150 */
1151 static int
vs_adm_parse_maxconn(const char * valstr,void * vp)1152 vs_adm_parse_maxconn(const char *valstr, void *vp)
1153 {
1154 vs_props_se_t *sep = vp;
1155 char *end;
1156
1157 sep->vep_maxconn = strtoll(valstr, &end, 10);
1158 if (end < valstr + strlen(valstr))
1159 return (-1);
1160
1161 return (0);
1162 }
1163
1164
1165 /*
1166 * vs_adm_unparse
1167 *
1168 * Entry point for unparsing native data into a readable string
1169 * used for display to the user. Dispatches the actual unparsing to
1170 * the unparse routine for the specified vscanadm property.
1171 *
1172 * This function is used to dispatch unparsing for all subcommands.
1173 * The structure pointer is therefore typed as a void pointer, and
1174 * cast appropriately in the unparse routine for the vscanadm property.
1175 */
1176 static void
vs_adm_unparse(const vs_adm_property_t * vap,const void * vp,char * buf,size_t len)1177 vs_adm_unparse(const vs_adm_property_t *vap, const void *vp,
1178 char *buf, size_t len)
1179 {
1180 if ((vap->vap_unparse)(vp, buf, len) != 0)
1181 (void) snprintf(buf, len, gettext(" (error) "));
1182 }
1183
1184
1185 /*
1186 * vs_adm_unparse_maxsize
1187 *
1188 * Unparses a max fsize value in native data form into a
1189 * user-readable string.
1190 */
1191 /* ARGSUSED */
1192 static int
vs_adm_unparse_maxsize(const void * vp,char * buf,size_t len)1193 vs_adm_unparse_maxsize(const void *vp, char *buf, size_t len)
1194 {
1195 const vs_props_t *svcp = vp;
1196
1197 (void) snprintf(buf, len, "%s", svcp->vp_maxsize);
1198
1199 return (0);
1200 }
1201
1202
1203 /*
1204 * vs_adm_unparse_maxsize_action
1205 *
1206 * Unparses a max fsize action value in native data form into a
1207 * user-readable string.
1208 */
1209 /* ARGSUSED */
1210 static int
vs_adm_unparse_maxsize_action(const void * vp,char * buf,size_t len)1211 vs_adm_unparse_maxsize_action(const void *vp, char *buf, size_t len)
1212 {
1213 const vs_props_t *svcp = vp;
1214
1215 (void) snprintf(buf, len, "%s",
1216 svcp->vp_maxsize_action ? VS_ADM_ALLOW : VS_ADM_DENY);
1217
1218 return (0);
1219 }
1220
1221
1222 /*
1223 * vs_adm_unparse_types
1224 *
1225 * Returns: 0 success
1226 * -1 on failure.
1227 */
1228 static int
vs_adm_unparse_types(const void * vp,char * buf,size_t len)1229 vs_adm_unparse_types(const void *vp, char *buf, size_t len)
1230 {
1231 const vs_props_t *svcp = vp;
1232
1233 (void) strlcpy(buf, svcp->vp_types, len);
1234
1235 return (0);
1236 }
1237
1238
1239 /*
1240 * vs_adm_unparse_enable
1241 *
1242 * Unparses the enable value for a scan engine in native data
1243 * form into a user-readable string.
1244 */
1245 /* ARGSUSED */
1246 static int
vs_adm_unparse_enable(const void * vp,char * buf,size_t len)1247 vs_adm_unparse_enable(const void *vp, char *buf, size_t len)
1248 {
1249 const vs_props_se_t *sep = vp;
1250
1251 (void) snprintf(buf, len, "%s",
1252 sep->vep_enable ? VS_ADM_ON : VS_ADM_OFF);
1253
1254 return (0);
1255 }
1256
1257
1258 /*
1259 * vs_adm_unparse_host
1260 *
1261 * Unparses an ip address for a scan engine in native data
1262 * form into a user-readable string.
1263 *
1264 * Returns: 0 success
1265 * -1 on failure.
1266 */
1267 /* ARGSUSED */
1268 static int
vs_adm_unparse_host(const void * vp,char * buf,size_t len)1269 vs_adm_unparse_host(const void *vp, char *buf, size_t len)
1270 {
1271 const vs_props_se_t *sep = vp;
1272
1273 (void) strlcpy(buf, sep->vep_host, len);
1274
1275 return (0);
1276 }
1277
1278
1279 /*
1280 * vs_adm_unparse_port
1281 *
1282 * Unparses a port value for a scan engine in native data
1283 * form into a user-readable string.
1284 */
1285 /* ARGSUSED */
1286 static int
vs_adm_unparse_port(const void * vp,char * buf,size_t len)1287 vs_adm_unparse_port(const void *vp, char *buf, size_t len)
1288 {
1289 const vs_props_se_t *sep = vp;
1290
1291 (void) snprintf(buf, len, "%hu", sep->vep_port);
1292
1293 return (0);
1294 }
1295
1296
1297 /*
1298 * vs_adm_unparse_maxconn
1299 *
1300 * Unparses a max connecctions for a scan engine in native data
1301 * form into a user-readable string.
1302 *
1303 */
1304 /* ARGSUSED */
1305 static int
vs_adm_unparse_maxconn(const void * vp,char * buf,size_t len)1306 vs_adm_unparse_maxconn(const void *vp, char *buf, size_t len)
1307 {
1308 const vs_props_se_t *sep = vp;
1309
1310 (void) snprintf(buf, len, "%lld", sep->vep_maxconn);
1311
1312 return (0);
1313 }
1314