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