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