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