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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * vscand Daemon Program 28 */ 29 30 #include <stdio.h> 31 #include <sys/stat.h> 32 #include <sys/filio.h> 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <sys/ioctl.h> 36 #include <sys/param.h> 37 #include <zone.h> 38 #include <tsol/label.h> 39 #include <string.h> 40 #include <stdlib.h> 41 #include <fcntl.h> 42 #include <wait.h> 43 #include <unistd.h> 44 #include <getopt.h> 45 #include <stdarg.h> 46 #include <libscf.h> 47 #include <signal.h> 48 #include <atomic.h> 49 #include <libintl.h> 50 #include <netinet/in.h> 51 #include <arpa/inet.h> 52 #include <ctype.h> 53 #include <pthread.h> 54 #include <syslog.h> 55 #include <locale.h> 56 #include <pwd.h> 57 #include <grp.h> 58 #include <priv_utils.h> 59 #include <rctl.h> 60 #include "vs_incl.h" 61 62 #define VS_FILE_DESCRIPTORS 512 63 64 static int vscand_fg = 0; /* daemon by default */ 65 static vs_daemon_state_t vscand_state = VS_STATE_INIT; 66 static volatile uint_t vscand_sigval = 0; 67 static volatile uint_t vscand_n_refresh = 0; 68 static int vscand_kdrv_fd = -1; 69 static pthread_mutex_t vscand_cfg_mutex = PTHREAD_MUTEX_INITIALIZER; 70 static pthread_cond_t vscand_cfg_cv; 71 static pthread_t vscand_cfg_tid = 0; 72 73 /* virus log path */ 74 static char vscand_vlog[MAXPATHLEN]; 75 76 /* user and group ids - default to 0 */ 77 static uid_t root_uid = 0, daemon_uid = 0; 78 static gid_t sys_gid = 0; 79 80 81 /* local function prototypes */ 82 static void vscand_sig_handler(int); 83 static int vscand_parse_args(int, char **); 84 static void vscand_get_uid_gid(); 85 static int vscand_init_file(char *, uid_t, gid_t, mode_t); 86 static void vscand_usage(char *); 87 static int vscand_daemonize_init(void); 88 static void vscand_daemonize_fini(int, int); 89 static int vscand_init(void); 90 static void vscand_fini(void); 91 static int vscand_cfg_init(void); 92 static void vscand_cfg_fini(void); 93 static void *vscand_cfg_handler(void *); 94 static int vscand_configure(void); 95 static void vscand_dtrace_cfg(vs_props_all_t *); 96 static int vscand_kernel_bind(void); 97 static void vscand_kernel_unbind(void); 98 static int vscand_kernel_enable(int); 99 static void vscand_kernel_disable(void); 100 static int vscand_kernel_config(vs_config_t *); 101 static int vscand_kernel_max_req(uint32_t *); 102 static void vscand_error(const char *); 103 static int vscand_get_viruslog(void); 104 static int vscand_set_resource_limits(void); 105 106 107 /* 108 * Enable libumem debugging by default on DEBUG builds. 109 */ 110 #ifdef DEBUG 111 const char * 112 _umem_debug_init(void) 113 { 114 return ("default,verbose"); /* $UMEM_DEBUG setting */ 115 } 116 117 const char * 118 _umem_logging_init(void) 119 { 120 return ("fail,contents"); /* $UMEM_LOGGING setting */ 121 } 122 #endif 123 124 125 /* 126 * vscand_sig_handler 127 */ 128 static void 129 vscand_sig_handler(int sig) 130 { 131 if (vscand_sigval == 0) 132 (void) atomic_swap_uint(&vscand_sigval, sig); 133 134 if (sig == SIGHUP) 135 atomic_inc_uint(&vscand_n_refresh); 136 } 137 138 139 /* 140 * main 141 * 142 * main must return SMF return code (see smf_method(7)) if vscand 143 * is invoked directly by smf (see manifest: vscan.xml) 144 * Exit codes: SMF_EXIT_ERR_CONFIG - error 145 * SMF_EXIT_ERR_FATAL - fatal error 146 * SMF_EXIT_OK - success 147 */ 148 int 149 main(int argc, char **argv) 150 { 151 int err_stat = 0, pfd = -1; 152 sigset_t set; 153 struct sigaction act; 154 int sigval; 155 156 mode_t log_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 157 mode_t door_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 158 159 (void) setlocale(LC_ALL, ""); 160 openlog("vscand", 0, LOG_DAEMON); 161 162 /* check if running in global zone; other zones not supported */ 163 if (getzoneid() != GLOBAL_ZONEID) { 164 vscand_error(gettext("non-global zone not supported")); 165 exit(SMF_EXIT_ERR_FATAL); 166 } 167 168 /* check for a Trusted Solaris environment; not supported */ 169 if (is_system_labeled()) { 170 vscand_error(gettext("Trusted Extensions not supported")); 171 exit(SMF_EXIT_ERR_FATAL); 172 } 173 174 /* Parse arguments */ 175 if (vscand_parse_args(argc, argv) != 0) 176 exit(SMF_EXIT_ERR_CONFIG); 177 178 vscand_get_uid_gid(); 179 180 /* 181 * Initializetion of virus log and statistic door file 182 * MUST be done BEFORE vscand_daemonize_init resets uid/gid. 183 * Only root can create the files in /var/log and /var/run. 184 */ 185 if ((vscand_get_viruslog() != 0) || 186 (vscand_vlog[0] == '\0') || 187 (vscand_init_file(vscand_vlog, root_uid, sys_gid, log_mode) != 0)) { 188 *vscand_vlog = 0; 189 } 190 191 (void) vscand_init_file(VS_STATS_DOOR_NAME, 192 daemon_uid, sys_gid, door_mode); 193 194 /* 195 * Once we're done setting our global state up, set up signal handlers 196 * for ensuring orderly termination on SIGTERM. 197 */ 198 (void) sigfillset(&set); 199 (void) sigdelset(&set, SIGABRT); /* always unblocked for ASSERT() */ 200 201 (void) sigfillset(&act.sa_mask); 202 act.sa_handler = vscand_sig_handler; 203 act.sa_flags = 0; 204 205 (void) sigaction(SIGTERM, &act, NULL); 206 (void) sigaction(SIGHUP, &act, NULL); /* Refresh config */ 207 (void) sigaction(SIGINT, &act, NULL); 208 (void) sigaction(SIGPIPE, &act, NULL); 209 (void) sigdelset(&set, SIGTERM); 210 (void) sigdelset(&set, SIGHUP); 211 (void) sigdelset(&set, SIGINT); 212 (void) sigdelset(&set, SIGPIPE); 213 214 if (vscand_fg) { 215 (void) sigdelset(&set, SIGTSTP); 216 (void) sigdelset(&set, SIGTTIN); 217 (void) sigdelset(&set, SIGTTOU); 218 219 if (vscand_init() != 0) { 220 vscand_error(gettext("failed to initialize service")); 221 exit(SMF_EXIT_ERR_CONFIG); 222 } 223 } else { 224 /* 225 * "pfd" is a pipe descriptor -- any fatal errors 226 * during subsequent initialization of the child 227 * process should be written to this pipe and the 228 * parent will report this error as the exit status. 229 */ 230 pfd = vscand_daemonize_init(); 231 232 if (vscand_init() != 0) { 233 vscand_error(gettext("failed to initialize service")); 234 exit(SMF_EXIT_ERR_CONFIG); 235 } 236 237 vscand_daemonize_fini(pfd, err_stat); 238 } 239 240 vscand_state = VS_STATE_RUNNING; 241 242 /* Wait here until shutdown */ 243 while (vscand_state == VS_STATE_RUNNING) { 244 if (vscand_sigval == 0 && vscand_n_refresh == 0) 245 (void) sigsuspend(&set); 246 247 sigval = atomic_swap_uint(&vscand_sigval, 0); 248 249 switch (sigval) { 250 case 0: 251 case SIGPIPE: 252 case SIGHUP: 253 break; 254 default: 255 vscand_state = VS_STATE_SHUTDOWN; 256 break; 257 } 258 259 if (atomic_swap_uint(&vscand_n_refresh, 0) != 0) 260 (void) pthread_cond_signal(&vscand_cfg_cv); 261 } 262 263 vscand_fini(); 264 return (SMF_EXIT_OK); 265 } 266 267 268 /* 269 * vscand_parse_args 270 * Routine to parse the arguments to the daemon program 271 * 'f' argument runs process in the foreground instead of as a daemon 272 */ 273 int 274 vscand_parse_args(int argc, char **argv) 275 { 276 int optchar; 277 278 while ((optchar = getopt(argc, argv, "f?")) != EOF) { 279 switch (optchar) { 280 case 'f': 281 vscand_fg = 1; 282 break; 283 default: 284 vscand_usage(argv[0]); 285 return (-1); 286 } 287 } 288 return (0); 289 } 290 291 292 /* 293 * vscand_usage 294 */ 295 static void 296 vscand_usage(char *progname) 297 { 298 char buf[128]; 299 300 (void) snprintf(buf, sizeof (buf), "%s %s [-f]", 301 gettext("Usage"), progname); 302 vscand_error(buf); 303 304 (void) snprintf(buf, sizeof (buf), "\t-f %s\n", 305 gettext("run program in foreground")); 306 vscand_error(buf); 307 } 308 309 310 /* 311 * vscand_get_uid_gid 312 * 313 * failure to access a uid/gid results in the default (0) being used. 314 */ 315 static void 316 vscand_get_uid_gid() 317 { 318 struct passwd *pwd; 319 struct group *grp; 320 321 if ((pwd = getpwnam("root")) != NULL) 322 root_uid = pwd->pw_uid; 323 324 if ((pwd = getpwnam("daemon")) != NULL) 325 daemon_uid = pwd->pw_uid; 326 327 if ((grp = getgrnam("sys")) != NULL) 328 sys_gid = grp->gr_gid; 329 } 330 331 332 /* 333 * vscand_daemonize_init 334 * 335 * This function will fork off a child process, from which 336 * only the child will return. 337 */ 338 static int 339 vscand_daemonize_init(void) 340 { 341 int status, pfds[2]; 342 sigset_t set, oset; 343 pid_t pid; 344 345 /* 346 * Reset process owner/group to daemon/sys. Root ownership is only 347 * required to initialize virus log file in /var/log 348 */ 349 if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS, 350 daemon_uid, sys_gid, 351 PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_READ, 352 PRIV_FILE_FLAG_SET, NULL) != 0) { 353 vscand_error(gettext("failed to initialize privileges")); 354 _exit(SMF_EXIT_ERR_FATAL); 355 } 356 357 /* 358 * Block all signals prior to the fork and leave them blocked in the 359 * parent so we don't get in a situation where the parent gets SIGINT 360 * and returns non-zero exit status and the child is actually running. 361 * In the child, restore the signal mask once we've done our setsid(). 362 */ 363 (void) sigfillset(&set); 364 (void) sigdelset(&set, SIGABRT); 365 (void) sigprocmask(SIG_BLOCK, &set, &oset); 366 367 if (pipe(pfds) == -1) { 368 vscand_error(gettext("failed to create pipe for daemonize")); 369 _exit(SMF_EXIT_ERR_FATAL); 370 } 371 372 if ((pid = fork()) == -1) { 373 vscand_error(gettext("failed to fork for daemonize")); 374 _exit(SMF_EXIT_ERR_FATAL); 375 } 376 377 /* 378 * If we're the parent process, wait for either the child to send us 379 * the appropriate exit status over the pipe or for the read to fail 380 * (presumably with 0 for EOF if our child terminated abnormally). 381 * If the read fails, exit with either the child's exit status if it 382 * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal. 383 */ 384 if (pid != 0) { 385 (void) close(pfds[1]); 386 387 if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 388 _exit(status); 389 390 if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 391 _exit(WEXITSTATUS(status)); 392 393 vscand_error(gettext("failed to daemonize")); 394 _exit(SMF_EXIT_ERR_FATAL); 395 } 396 397 398 (void) setsid(); 399 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 400 (void) chdir("/"); 401 (void) umask(022); 402 (void) close(pfds[0]); 403 404 return (pfds[1]); 405 } 406 407 408 /* 409 * vscand_daemonize_fini 410 * Now that we're running, if a pipe fd was specified, write an exit 411 * status to it to indicate that our parent process can safely detach. 412 */ 413 static void 414 vscand_daemonize_fini(int fd, int err_status) 415 { 416 if (fd >= 0) 417 (void) write(fd, &err_status, sizeof (err_status)); 418 419 (void) close(fd); 420 421 /* Restore standard file descriptors */ 422 if ((fd = open("/dev/null", O_RDWR)) >= 0) { 423 (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 424 (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 425 (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 426 (void) close(fd); 427 } 428 429 /* clear basic privileges not required by vscand */ 430 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 431 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 432 } 433 434 435 /* 436 * vscand_init_file 437 * 438 * create specified file and set its uid, gid and mode 439 */ 440 static int 441 vscand_init_file(char *filepath, uid_t uid, gid_t gid, mode_t access_mode) 442 { 443 int fd, rc = 0; 444 struct stat stat_buf; 445 char buf[MAXPATHLEN]; 446 447 if ((fd = open(filepath, O_RDONLY | O_CREAT, access_mode)) == -1) { 448 rc = -1; 449 } else { 450 if (fstat(fd, &stat_buf) != 0) { 451 rc = -1; 452 } else { 453 if ((stat_buf.st_mode & S_IAMB) != access_mode) { 454 if (fchmod(fd, access_mode) != 0) 455 rc = -1; 456 } 457 458 if ((stat_buf.st_uid != uid) || 459 (stat_buf.st_gid != gid)) { 460 if (fchown(fd, uid, gid) != 0) 461 rc = -1; 462 } 463 } 464 465 (void) close(fd); 466 } 467 468 if (rc == -1) { 469 (void) snprintf(buf, MAXPATHLEN, "%s %s", 470 gettext("Failed to initialize"), filepath); 471 vscand_error(buf); 472 } 473 474 return (rc); 475 } 476 477 478 /* 479 * vscand_init 480 * 481 * There are some requirements on the order in which the daemon 482 * initialization functions are called. 483 * 484 * - vscand_kernel_bind - bind to kernel module 485 * - vs_eng_init populates vs_icap data and thus vs_icap_init MUST be 486 * called before vs_eng_init 487 * - vscand_configure - load the configuration 488 * - vs_door_init - start vscan door server 489 * - vscand_kernel_enable - enable scan requests from kernel 490 */ 491 static int 492 vscand_init(void) 493 { 494 int door_fd = -1; 495 uint32_t max_req; 496 497 if (vscand_kernel_bind() < 0) 498 return (-1); 499 500 if (vscand_kernel_max_req(&max_req) == -1) 501 return (-1); 502 503 if (vs_svc_init(max_req) != 0) 504 return (-1); 505 506 if (vs_stats_init() != 0) 507 vscand_error( 508 gettext("failed to initialize statistics interface")); 509 510 vs_icap_init(); 511 vs_eng_init(); 512 513 /* initialize configuration and handler thread */ 514 if (vscand_cfg_init() != 0) { 515 vscand_error(gettext("failed to initialize configuration")); 516 vscand_fini(); 517 return (-1); 518 } 519 520 (void) vscand_set_resource_limits(); 521 522 if (((door_fd = vs_door_init()) < 0) || 523 (vscand_kernel_enable(door_fd) < 0)) { 524 vscand_fini(); 525 return (-1); 526 } 527 528 return (0); 529 } 530 531 532 /* 533 * vscand_fini 534 * 535 * vscand_kernel_disable - should be called first to ensure that no 536 * more scan requests are initiated from the kernel module 537 * vs_svc_terminate - terminate requests and wait for thread completion 538 * vs_xxx_fini - module cleanup routines 539 * vscand_kernel_unbind - should be called last to tell the kernel module 540 * that vscand is shutdown. 541 */ 542 static void 543 vscand_fini(void) 544 { 545 vscand_kernel_disable(); 546 547 /* terminate reconfiguration handler thread */ 548 vscand_cfg_fini(); 549 550 /* terminate requests and wait for completion */ 551 vs_svc_terminate(); 552 553 /* clean up */ 554 vs_svc_fini(); 555 vs_eng_fini(); 556 vs_icap_fini(); 557 vs_door_fini(); 558 vs_stats_fini(); 559 560 vscand_kernel_unbind(); 561 } 562 563 564 /* 565 * vscand_cfg_init 566 * 567 * initialize configuration and reconfiguration handler thread 568 */ 569 static int 570 vscand_cfg_init(void) 571 { 572 int rc; 573 574 (void) pthread_cond_init(&vscand_cfg_cv, NULL); 575 576 (void) pthread_mutex_lock(&vscand_cfg_mutex); 577 rc = vscand_configure(); 578 (void) pthread_mutex_unlock(&vscand_cfg_mutex); 579 580 if (rc != 0) 581 return (-1); 582 583 if (pthread_create(&vscand_cfg_tid, NULL, vscand_cfg_handler, 0) != 0) { 584 vscand_cfg_tid = 0; 585 return (-1); 586 } 587 588 return (0); 589 } 590 591 592 /* 593 * vscand_cfg_fini 594 * 595 * terminate reconfiguration handler thread 596 */ 597 static void 598 vscand_cfg_fini() 599 { 600 if (vscand_cfg_tid != 0) { 601 (void) pthread_cond_signal(&vscand_cfg_cv); 602 (void) pthread_join(vscand_cfg_tid, NULL); 603 vscand_cfg_tid = 0; 604 } 605 (void) pthread_cond_destroy(&vscand_cfg_cv); 606 } 607 608 609 /* 610 * vscand_cfg_handler 611 * wait for reconfiguration event and reload configuration 612 * exit on VS_STATE_SHUTDOWN 613 */ 614 /*ARGSUSED*/ 615 static void * 616 vscand_cfg_handler(void *arg) 617 { 618 (void) pthread_mutex_lock(&vscand_cfg_mutex); 619 620 while (pthread_cond_wait(&vscand_cfg_cv, &vscand_cfg_mutex) == 0) { 621 if (vscand_state == VS_STATE_SHUTDOWN) 622 break; 623 624 (void) vscand_configure(); 625 } 626 627 (void) pthread_mutex_unlock(&vscand_cfg_mutex); 628 629 return (NULL); 630 } 631 632 633 /* 634 * vscand_configure 635 */ 636 static int 637 vscand_configure(void) 638 { 639 uint32_t len; 640 vs_config_t kconfig; 641 vs_props_all_t config; 642 643 (void) memset(&config, 0, sizeof (vs_props_all_t)); 644 if (vs_props_get_all(&config) != VS_ERR_NONE) { 645 vscand_error(gettext("configuration data error")); 646 return (-1); 647 } 648 649 (void) memset(&kconfig, 0, sizeof (vs_config_t)); 650 len = sizeof (kconfig.vsc_types); 651 if (vs_parse_types(config.va_props.vp_types, 652 kconfig.vsc_types, &len) != 0) { 653 vscand_error(gettext("configuration data error - types")); 654 return (-1); 655 } 656 kconfig.vsc_types_len = len; 657 658 /* Convert the maxfsize string from the configuration into bytes */ 659 if (vs_strtonum(config.va_props.vp_maxsize, 660 &kconfig.vsc_max_size) != 0) { 661 vscand_error(gettext("configuration data error - max-size")); 662 return (-1); 663 } 664 kconfig.vsc_allow = config.va_props.vp_maxsize_action ? 1LL : 0LL; 665 666 /* Send configuration update to kernel */ 667 if (vscand_kernel_config(&kconfig) != 0) { 668 return (-1); 669 } 670 671 /* dtrace the configuration data */ 672 vscand_dtrace_cfg(&config); 673 674 /* propagate configuration changes */ 675 vs_eng_config(&config); 676 vs_stats_config(&config); 677 678 return (0); 679 } 680 681 682 /* 683 * vscand_get_state 684 */ 685 vs_daemon_state_t 686 vscand_get_state(void) 687 { 688 return (vscand_state); 689 } 690 691 692 /* 693 * vscand_get_viruslog 694 */ 695 static int 696 vscand_get_viruslog() 697 { 698 vs_props_t props; 699 uint64_t propids; 700 int rc; 701 702 propids = VS_PROPID_VLOG; 703 if ((rc = vs_props_get(&props, propids)) != VS_ERR_NONE) { 704 vscand_error(vs_strerror(rc)); 705 return (-1); 706 } 707 708 (void) strlcpy(vscand_vlog, props.vp_vlog, sizeof (vscand_vlog)); 709 return (0); 710 } 711 712 713 /* 714 * vscand_viruslog 715 */ 716 char * 717 vscand_viruslog(void) 718 { 719 if (vscand_vlog[0] == '\0') 720 return (NULL); 721 722 return (vscand_vlog); 723 } 724 725 726 /* 727 * vscand_kernel_bind 728 */ 729 static int 730 vscand_kernel_bind(void) 731 { 732 char devname[MAXPATHLEN]; 733 int inst = 0; 734 735 (void) snprintf(devname, MAXPATHLEN, "%s%d", VS_DRV_PATH, inst); 736 737 if ((vscand_kdrv_fd = open(devname, O_RDONLY)) < 0) { 738 vscand_error(gettext("failed to bind to kernel")); 739 return (-1); 740 } 741 742 return (0); 743 } 744 745 746 /* 747 * vscand_kernel_unbind 748 */ 749 static void 750 vscand_kernel_unbind(void) 751 { 752 if (vscand_kdrv_fd >= 0) 753 (void) close(vscand_kdrv_fd); 754 } 755 756 757 /* 758 * vscand_kernel_enable 759 */ 760 static int 761 vscand_kernel_enable(int door_fd) 762 { 763 if (ioctl(vscand_kdrv_fd, VS_IOCTL_ENABLE, door_fd) < 0) { 764 vscand_error(gettext("failed to bind to kernel")); 765 (void) close(vscand_kdrv_fd); 766 vscand_kdrv_fd = -1; 767 return (-1); 768 } 769 return (0); 770 } 771 772 773 /* 774 * vscand_kernel_disable 775 */ 776 static void 777 vscand_kernel_disable() 778 { 779 if (vscand_kdrv_fd >= 0) 780 (void) ioctl(vscand_kdrv_fd, VS_IOCTL_DISABLE); 781 } 782 783 784 /* 785 * vscand_kernel_config 786 */ 787 int 788 vscand_kernel_config(vs_config_t *conf) 789 { 790 if ((vscand_kdrv_fd < 0) || 791 (ioctl(vscand_kdrv_fd, VS_IOCTL_CONFIG, conf) < 0)) { 792 vscand_error(gettext("failed to send config to kernel")); 793 return (-1); 794 } 795 796 return (0); 797 } 798 799 800 /* 801 * vscand_kernel_result 802 */ 803 int 804 vscand_kernel_result(vs_scan_rsp_t *scan_rsp) 805 { 806 if ((vscand_kdrv_fd < 0) || 807 (ioctl(vscand_kdrv_fd, VS_IOCTL_RESULT, scan_rsp) < 0)) { 808 vscand_error(gettext("failed to send result to kernel")); 809 return (-1); 810 } 811 812 return (0); 813 } 814 815 816 /* 817 * vscand_kernel_max_req 818 */ 819 int 820 vscand_kernel_max_req(uint32_t *max_req) 821 { 822 if ((vscand_kdrv_fd < 0) || 823 (ioctl(vscand_kdrv_fd, VS_IOCTL_MAX_REQ, max_req) < 0)) { 824 vscand_error(gettext("failed to get config data from kernel")); 825 return (-1); 826 } 827 828 return (0); 829 } 830 831 832 /* 833 * vscand_set_resource_limits 834 * 835 * If the process's max file descriptor limit is less than 836 * VS_FILE_DESCRIPTORS, increae it to VS_FILE_DESCRIPTORS. 837 */ 838 static int 839 vscand_set_resource_limits(void) 840 { 841 int rc = -1; 842 rctlblk_t *rblk; 843 char *limit = "process.max-file-descriptor"; 844 845 rblk = (rctlblk_t *)malloc(rctlblk_size()); 846 847 if (rblk != NULL) { 848 rc = getrctl(limit, NULL, rblk, 0); 849 if ((rc == 0) && 850 (rctlblk_get_value(rblk) < VS_FILE_DESCRIPTORS)) { 851 rctlblk_set_value(rblk, VS_FILE_DESCRIPTORS); 852 rc = setrctl(limit, NULL, rblk, 0); 853 } 854 (void) free(rblk); 855 } 856 857 return (rc); 858 } 859 860 861 /* 862 * vscand_error 863 */ 864 static void 865 vscand_error(const char *errmsg) 866 { 867 (void) fprintf(stderr, "vscand: %s", errmsg); 868 syslog(LOG_ERR, "%s\n", errmsg); 869 } 870 871 872 /* 873 * vscand_dtrace_cfg 874 * vscand_dtrace_gen 875 * vscand_dtrace_eng 876 * 877 * Support for dtracing vscand configuration when processing 878 * a reconfiguration event (SIGHUP) 879 */ 880 /*ARGSUSED*/ 881 static void 882 vscand_dtrace_eng(char *id, boolean_t enable, char *host, int port, int conn) 883 { 884 } 885 /*ARGSUSED*/ 886 static void 887 vscand_dtrace_gen(char *size, boolean_t action, char *types, char *log) 888 { 889 } 890 static void 891 vscand_dtrace_cfg(vs_props_all_t *config) 892 { 893 int i; 894 895 vscand_dtrace_gen(config->va_props.vp_maxsize, 896 config->va_props.vp_maxsize_action, 897 config->va_props.vp_types, 898 config->va_props.vp_vlog); 899 900 for (i = 0; i < VS_SE_MAX; i++) { 901 if (config->va_se[i].vep_engid[0] != 0) 902 vscand_dtrace_eng(config->va_se[i].vep_engid, 903 config->va_se[i].vep_enable, 904 config->va_se[i].vep_host, 905 config->va_se[i].vep_port, 906 config->va_se[i].vep_maxconn); 907 } 908 } 909