Example #1
0
int
main(int argc, char **argv)
{
	int rc = 0;
	int errflg = 0;
	int opt;
	struct rlimit rlim;

	if ((command = strrchr(argv[0], '/')) != NULL)
		command++;
	else
		command = argv[0];

	/* options */
	while ((opt = getopt(argc, argv, "r")) != EOF) {
		switch (opt) {
		case 'r':		/* show registers */
			rflag = 1;
			break;
		default:
			errflg = 1;
			break;
		}
	}

	argc -= optind;
	argv += optind;

	if (errflg || argc <= 0) {
		(void) fprintf(stderr,
		    "usage:\t%s [-r] { pid | core }[/lwps] ...\n", command);
		(void) fprintf(stderr, "  (report process status flags)\n");
		(void) fprintf(stderr, "  -r : report registers\n");
		return (2);
	}

	/*
	 * Make sure we'll have enough file descriptors to handle a target
	 * that has many many mappings.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
		rlim.rlim_cur = rlim.rlim_max;
		(void) setrlimit(RLIMIT_NOFILE, &rlim);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	while (argc-- > 0)
		rc += look(*argv++);

	return (rc);
}
Example #2
0
int
Setrlimit()
{
	struct rlimit rlim;
	int fd_limit;
	if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
		Die(gettext("getrlimit failed"));
	fd_limit = rlim.rlim_cur;
	rlim.rlim_max = MIN(rlim.rlim_max, RLIMIT_NOFILE_MAX);
	rlim.rlim_cur = rlim.rlim_max;
	(void) enable_extended_FILE_stdio(-1, -1);
	if (setrlimit(RLIMIT_NOFILE, &rlim) == -1)
		return (fd_limit);
	else
		return (rlim.rlim_cur);
}
Example #3
0
int
main(int argc, char **argv)
{
    int rflag = 0, sflag = 0, xflag = 0, Fflag = 0;
    int errflg = 0, Sflag = 0;
    int rc = 0;
    int opt;
    const char *bar8 = "-------";
    const char *bar16 = "----------";
    const char *bar;
    struct rlimit rlim;
    struct stat64 statbuf;
    char buf[128];
    int mapfd;
    int prg_gflags = PGRAB_RDONLY;
    int prr_flags = 0;
    boolean_t use_agent_lwp = B_FALSE;

    if ((command = strrchr(argv[0], '/')) != NULL)
        command++;
    else
        command = argv[0];

    while ((opt = getopt(argc, argv, "arsxSlLFA:")) != EOF) {
        switch (opt) {
        case 'a':		/* include shared mappings in -[xS] */
            aflag = 1;
            break;
        case 'r':		/* show reserved mappings */
            rflag = 1;
            break;
        case 's':		/* show hardware page sizes */
            sflag = 1;
            break;
        case 'S':		/* show swap reservations */
            Sflag = 1;
            break;
        case 'x':		/* show extended mappings */
            xflag = 1;
            break;
        case 'l':		/* show unresolved link map names */
            lflag = 1;
            break;
        case 'L':		/* show lgroup information */
            Lflag = 1;
            use_agent_lwp = B_TRUE;
            break;
        case 'F':		/* force grabbing (no O_EXCL) */
            Fflag = PGRAB_FORCE;
            break;
        case 'A':
            if (parse_addr_range(optarg, &start_addr, &end_addr)
                    != 0)
                errflg++;
            break;
        default:
            errflg = 1;
            break;
        }
    }

    argc -= optind;
    argv += optind;

    if ((Sflag && (xflag || rflag || sflag)) || (xflag && rflag) ||
            (aflag && (!xflag && !Sflag)) ||
            (Lflag && (xflag || Sflag))) {
        errflg = 1;
    }

    if (errflg || argc <= 0) {
        (void) fprintf(stderr,
                       "usage:\t%s [-rslF] [-A start[,end]] { pid | core } ...\n",
                       command);
        (void) fprintf(stderr,
                       "\t\t(report process address maps)\n");
        (void) fprintf(stderr,
                       "\t%s -L [-rslF] [-A start[,end]] pid ...\n", command);
        (void) fprintf(stderr,
                       "\t\t(report process address maps lgroups mappings)\n");
        (void) fprintf(stderr,
                       "\t%s -x [-aslF] [-A start[,end]] pid ...\n", command);
        (void) fprintf(stderr,
                       "\t\t(show resident/anon/locked mapping details)\n");
        (void) fprintf(stderr,
                       "\t%s -S [-alF] [-A start[,end]] { pid | core } ...\n",
                       command);
        (void) fprintf(stderr,
                       "\t\t(show swap reservations)\n\n");
        (void) fprintf(stderr,
                       "\t-a: include shared mappings in -[xS] summary\n");
        (void) fprintf(stderr,
                       "\t-r: show reserved address maps\n");
        (void) fprintf(stderr,
                       "\t-s: show hardware page sizes\n");
        (void) fprintf(stderr,
                       "\t-l: show unresolved dynamic linker map names\n");
        (void) fprintf(stderr,
                       "\t-F: force grabbing of the target process\n");
        (void) fprintf(stderr,
                       "\t-L: show lgroup mappings\n");
        (void) fprintf(stderr,
                       "\t-A start,end: limit output to the specified range\n");
        return (2);
    }

    /*
     * Make sure we'll have enough file descriptors to handle a target
     * that has many many mappings.
     */
    if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
        rlim.rlim_cur = rlim.rlim_max;
        (void) setrlimit(RLIMIT_NOFILE, &rlim);
        (void) enable_extended_FILE_stdio(-1, -1);
    }

    /*
     * The implementation of -L option creates an agent LWP in the target
     * process address space. The agent LWP issues meminfo(2) system calls
     * on behalf of the target process. If we are interrupted prematurely,
     * the target process remains in the stopped state with the agent still
     * attached to it. To prevent such situation we catch signals from
     * terminal and terminate gracefully.
     */
    if (use_agent_lwp) {
        /*
         * Buffer output to stdout, stderr while process is grabbed.
         * Prevents infamous deadlocks due to pmap `pgrep xterm` and
         * other variants.
         */
        (void) proc_initstdio();

        prg_gflags = PGRAB_RETAIN | Fflag;
        prr_flags = PRELEASE_RETAIN;

        if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGHUP, intr);
        if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGINT, intr);
        if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
            (void) sigset(SIGQUIT, intr);
        (void) sigset(SIGPIPE, intr);
        (void) sigset(SIGTERM, intr);
    }

    while (argc-- > 0) {
        char *arg;
        int gcode;
        psinfo_t psinfo;
        int tries = 0;

        if (use_agent_lwp)
            (void) proc_flushstdio();

        if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
                                prg_gflags, &gcode)) == NULL) {
            (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
                           command, arg, Pgrab_error(gcode));
            rc++;
            continue;
        }

        procname = arg;		/* for perr() */

        addr_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 16 : 8;
        size_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 11 : 8;
        bar = addr_width == 8 ? bar8 : bar16;
        (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
        proc_unctrl_psinfo(&psinfo);

        if (Pstate(Pr) != PS_DEAD) {
            (void) snprintf(buf, sizeof (buf),
                            "/proc/%d/map", (int)psinfo.pr_pid);
            if ((mapfd = open(buf, O_RDONLY)) < 0) {
                (void) fprintf(stderr, "%s: cannot "
                               "examine %s: lost control of "
                               "process\n", command, arg);
                rc++;
                Prelease(Pr, prr_flags);
                continue;
            }
        } else {
            mapfd = -1;
        }

again:
        map_count = 0;

        if (Pstate(Pr) == PS_DEAD) {
            (void) printf("core '%s' of %d:\t%.70s\n",
                          arg, (int)psinfo.pr_pid, psinfo.pr_psargs);

            if (rflag || sflag || xflag || Sflag || Lflag) {
                (void) printf("  -%c option is not compatible "
                              "with core files\n", xflag ? 'x' :
                              sflag ? 's' : rflag ? 'r' :
                              Lflag ? 'L' : 'S');
                Prelease(Pr, prr_flags);
                rc++;
                continue;
            }

        } else {
            (void) printf("%d:\t%.70s\n",
                          (int)psinfo.pr_pid, psinfo.pr_psargs);
        }

        if (!(Pstatus(Pr)->pr_flags & PR_ISSYS)) {
            struct totals t;

            /*
             * Since we're grabbing the process readonly, we need
             * to make sure the address space doesn't change during
             * execution.
             */
            if (Pstate(Pr) != PS_DEAD) {
                if (tries++ == MAX_TRIES) {
                    Prelease(Pr, prr_flags);
                    (void) close(mapfd);
                    (void) fprintf(stderr, "%s: cannot "
                                   "examine %s: address space is "
                                   "changing\n", command, arg);
                    continue;
                }

                if (fstat64(mapfd, &statbuf) != 0) {
                    Prelease(Pr, prr_flags);
                    (void) close(mapfd);
                    (void) fprintf(stderr, "%s: cannot "
                                   "examine %s: lost control of "
                                   "process\n", command, arg);
                    continue;
                }
            }

            nstacks = psinfo.pr_nlwp * 2;
            stacks = calloc(nstacks, sizeof (stacks[0]));
            if (stacks != NULL) {
                int n = 0;
                (void) Plwp_iter(Pr, getstack, &n);
                qsort(stacks, nstacks, sizeof (stacks[0]),
                      cmpstacks);
            }

            (void) memset(&t, 0, sizeof (t));

            if (Pgetauxval(Pr, AT_BASE) != -1L &&
                    Prd_agent(Pr) == NULL) {
                (void) fprintf(stderr, "%s: warning: "
                               "librtld_db failed to initialize; "
                               "shared library information will not be "
                               "available\n", command);
            }

            /*
             * Gather data
             */
            if (xflag)
                rc += xmapping_iter(Pr, gather_xmap, NULL, 0);
            else if (Sflag)
                rc += xmapping_iter(Pr, gather_xmap, NULL, 1);
            else {
                if (rflag)
                    rc += rmapping_iter(Pr, gather_map,
                                        NULL);
                else if (sflag)
                    rc += xmapping_iter(Pr, gather_xmap,
                                        NULL, 0);
                else if (lflag)
                    rc += Pmapping_iter(Pr,
                                        gather_map, NULL);
                else
                    rc += Pmapping_iter_resolved(Pr,
                                                 gather_map, NULL);
            }

            /*
             * Ensure mappings are consistent.
             */
            if (Pstate(Pr) != PS_DEAD) {
                struct stat64 newbuf;

                if (fstat64(mapfd, &newbuf) != 0 ||
                        memcmp(&newbuf.st_mtim, &statbuf.st_mtim,
                               sizeof (newbuf.st_mtim)) != 0) {
                    if (stacks != NULL) {
                        free(stacks);
                        stacks = NULL;
                    }
                    goto again;
                }
            }

            /*
             * Display data.
             */
            if (xflag) {
                (void) printf("%*s%*s%*s%*s%*s "
                              "%sMode   Mapped File\n",
                              addr_width, "Address",
                              size_width, "Kbytes",
                              size_width, "RSS",
                              size_width, "Anon",
                              size_width, "Locked",
                              sflag ? "Pgsz " : "");

                rc += iter_xmap(sflag ?  look_xmap :
                                look_xmap_nopgsz, &t);

                (void) printf("%s%s %s %s %s %s\n",
                              addr_width == 8 ? "-" : "------",
                              bar, bar, bar, bar, bar);

                (void) printf("%stotal Kb", addr_width == 16 ?
                              "        " : "");

                printK(t.total_size, size_width);
                printK(t.total_rss, size_width);
                printK(t.total_anon, size_width);
                printK(t.total_locked, size_width);

                (void) printf("\n");

            } else if (Sflag) {
                (void) printf("%*s%*s%*s Mode"
                              " Mapped File\n",
                              addr_width, "Address",
                              size_width, "Kbytes",
                              size_width, "Swap");

                rc += iter_xmap(look_xmap_nopgsz, &t);

                (void) printf("%s%s %s %s\n",
                              addr_width == 8 ? "-" : "------",
                              bar, bar, bar);

                (void) printf("%stotal Kb", addr_width == 16 ?
                              "        " : "");

                printK(t.total_size, size_width);
                printK(t.total_swap, size_width);

                (void) printf("\n");

            } else {

                if (rflag) {
                    rc += iter_map(look_map, &t);
                } else if (sflag) {
                    if (Lflag) {
                        (void) printf("%*s %*s %4s"
                                      " %-6s %s %s\n",
                                      addr_width, "Address",
                                      size_width,
                                      "Bytes", "Pgsz", "Mode ",
                                      "Lgrp", "Mapped File");
                        rc += iter_xmap(look_smap, &t);
                    } else {
                        (void) printf("%*s %*s %4s"
                                      " %-6s %s\n",
                                      addr_width, "Address",
                                      size_width,
                                      "Bytes", "Pgsz", "Mode ",
                                      "Mapped File");
                        rc += iter_xmap(look_smap, &t);
                    }
                } else {
                    rc += iter_map(look_map, &t);
                }

                (void) printf(" %stotal  %*luK\n",
                              addr_width == 16 ?
                              "        " : "",
                              size_width, t.total_size);
            }

            if (stacks != NULL) {
                free(stacks);
                stacks = NULL;
            }

        }

        Prelease(Pr, prr_flags);
        if (mapfd != -1)
            (void) close(mapfd);
    }

    if (use_agent_lwp)
        (void) proc_finistdio();

    return (rc);
}
Example #4
0
int
main(int argc, char **argv)
{
	int rc = 0;
	int c;
	struct rlimit rlim;

	if ((command = strrchr(argv[0], '/')) != NULL)
		command++;
	else
		command = argv[0];

	if ((ngroups_max = sysconf(_SC_NGROUPS_MAX)) < 0)
		return (perr("sysconf(_SC_NGROUPS_MAX)"));

	opterr = 0;

	while ((c = getopt(argc, argv, "au:g:l:G:")) != EOF) {
		switch (c) {
		case 'a':
			all = B_TRUE;
			break;
		case 'u':
			user = optarg;
			doset = B_TRUE;
			break;
		case 'g':
			group = optarg;
			doset = B_TRUE;
			break;
		case 'G':
			grplst = optarg;
			doset = B_TRUE;
			break;
		case 'l':
			login = optarg;
			doset = B_TRUE;
			break;
		default:
			usage();
			/*NOTREACHED*/
		}
	}
	if (login != NULL && (user != NULL || group != NULL || grplst != NULL))
		usage();

	if (all && doset)
		usage();

	argc -= optind;
	argv += optind;

	if (argc == 0)
		usage();

	if (doset)
		initcred();

	/*
	 * Make sure we'll have enough file descriptors to handle a target
	 * that has many many mappings.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
		rlim.rlim_cur = rlim.rlim_max;
		(void) setrlimit(RLIMIT_NOFILE, &rlim);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	while (argc-- > 0)
		rc += look(*argv++);

	return (rc > 255 ? 255 : rc);
}
Example #5
0
int
main(int ac, char *av[])
{
	char *dir = "/";
	int allflag = 0;
	int df_allflag = 0;
	int opt_cnt = 0;
	int maxservers = 1;	/* zero allows inifinte number of threads */
	int maxservers_set = 0;
	int logmaxservers = 0;
	int pid;
	int i;
	char *provider = (char *)NULL;
	char *df_provider = (char *)NULL;
	struct protob *protobp0, *protobp;
	NETSELDECL(proto) = NULL;
	NETSELDECL(df_proto) = NULL;
	NETSELPDECL(providerp);
	char *defval;
	boolean_t can_do_mlp;
	uint_t dss_npaths = 0;
	char **dss_pathnames = NULL;
	sigset_t sgset;
	char name[PATH_MAX], value[PATH_MAX];
	int ret, bufsz;

	int pipe_fd = -1;

	MyName = *av;

	/*
	 * Initializations that require more privileges than we need to run.
	 */
	(void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID);
	svcsetprio();

	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS,
	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
		(void) fprintf(stderr, "%s should be run with"
		    " sufficient privileges\n", av[0]);
		exit(1);
	}

	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * Read in the values from SMF first before we check
	 * command line options so the options override SMF values.
	 */
	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("max_connections", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		max_conns_allowed = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			max_conns_allowed = -1;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("listen_backlog", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		listen_backlog = strtol(value, (char **)NULL, 10);
		if (errno != 0) {
			listen_backlog = 32;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("protocol", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_proto = strdup(value);
		opt_cnt++;
		if (strncasecmp("ALL", value, 3) == 0) {
			free(df_proto);
			df_proto = NULL;
			df_allflag = 1;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("device", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_provider = strdup(value);
		opt_cnt++;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("servers", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		maxservers = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			maxservers = 1;
		else
			maxservers_set = 1;
	}

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmin", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_min = strtol(value, (char **)NULL, 10);

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmax", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_max = strtol(value, (char **)NULL, 10);

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("server_delegation", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if (ret == SA_OK)
		if (strncasecmp(value, "off", 3) == 0)
			nfs_server_delegation = FALSE;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "in SMF:\n"
		    "\tprotocol=ALL\n"
		    "\tprotocol=protocol\n"
		    "\tdevice=devicename\n\n");
		usage();
	}
	opt_cnt = 0;

	while ((i = getopt(ac, av, "ac:p:s:t:l:")) != EOF) {
		switch (i) {
		case 'a':
			free(df_proto);
			df_proto = NULL;
			free(df_provider);
			df_provider = NULL;

			allflag = 1;
			opt_cnt++;
			break;

		case 'c':
			max_conns_allowed = atoi(optarg);
			break;

		case 'p':
			proto = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		/*
		 * DSS: NFSv4 distributed stable storage.
		 *
		 * This is a Contracted Project Private interface, for
		 * the sole use of Sun Cluster HA-NFS. See PSARC/2006/313.
		 */
		case 's':
			if (strlen(optarg) < MAXPATHLEN) {
				/* first "-s" option encountered? */
				if (dss_pathnames == NULL) {
					/*
					 * Allocate maximum possible space
					 * required given cmdline arg count;
					 * "-s <path>" consumes two args.
					 */
					size_t sz = (ac / 2) * sizeof (char *);
					dss_pathnames = (char **)malloc(sz);
					if (dss_pathnames == NULL) {
						(void) fprintf(stderr, "%s: "
						    "dss paths malloc failed\n",
						    av[0]);
						exit(1);
					}
					(void) memset(dss_pathnames, 0, sz);
				}
				dss_pathnames[dss_npaths] = optarg;
				dss_npaths++;
			} else {
				(void) fprintf(stderr,
				    "%s: -s pathname too long.\n", av[0]);
			}
			break;

		case 't':
			provider = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		case 'l':
			listen_backlog = atoi(optarg);
			break;

		case '?':
			usage();
			/* NOTREACHED */
		}
	}

	allflag = df_allflag;
	if (proto == NULL)
		proto = df_proto;
	if (provider == NULL)
		provider = df_provider;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "on the command line:\n"
		    "\t-a\n"
		    "\t-p protocol\n"
		    "\t-t transport\n\n");
		usage();
	}

	if (proto != NULL &&
	    strncasecmp(proto, NC_UDP, strlen(NC_UDP)) == 0) {
		if (nfs_server_vers_max == NFS_V4) {
			if (nfs_server_vers_min == NFS_V4) {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.  Exiting\n");
				exit(3);
			} else {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.\n");
			}
		}
	}

	/*
	 * If there is exactly one more argument, it is the number of
	 * servers.
	 */
	if (optind == ac - 1) {
		maxservers = atoi(av[optind]);
		maxservers_set = 1;
	}
	/*
	 * If there are two or more arguments, then this is a usage error.
	 */
	else if (optind < ac - 1)
		usage();
	/*
	 * Check the ranges for min/max version specified
	 */
	else if ((nfs_server_vers_min > nfs_server_vers_max) ||
	    (nfs_server_vers_min < NFS_VERSMIN) ||
	    (nfs_server_vers_max > NFS_VERSMAX))
		usage();
	/*
	 * There are no additional arguments, and we haven't set maxservers
	 * explicitly via the config file, we use a default number of
	 * servers.  We will log this.
	 */
	else if (maxservers_set == 0)
		logmaxservers = 1;

	/*
	 * Basic Sanity checks on options
	 *
	 * max_conns_allowed must be positive, except for the special
	 * value of -1 which is used internally to mean unlimited, -1 isn't
	 * documented but we allow it anyway.
	 *
	 * maxservers must be positive
	 * listen_backlog must be positive or zero
	 */
	if (((max_conns_allowed != -1) && (max_conns_allowed <= 0)) ||
	    (listen_backlog < 0) || (maxservers <= 0)) {
		usage();
	}

	/*
	 * Set current dir to server root
	 */
	if (chdir(dir) < 0) {
		(void) fprintf(stderr, "%s:  ", MyName);
		perror(dir);
		exit(1);
	}

#ifndef DEBUG
	pipe_fd = daemonize_init();
#endif

	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	/*
	 * establish our lock on the lock file and write our pid to it.
	 * exit if some other process holds the lock, or if there's any
	 * error in writing/locking the file.
	 */
	pid = _enter_daemon_lock(NFSD);
	switch (pid) {
	case 0:
		break;
	case -1:
		fprintf(stderr, "error locking for %s: %s\n", NFSD,
		    strerror(errno));
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	/*
	 * If we've been given a list of paths to be used for distributed
	 * stable storage, and provided we're going to run a version
	 * that supports it, setup the DSS paths.
	 */
	if (dss_pathnames != NULL && nfs_server_vers_max >= DSS_VERSMIN) {
		if (dss_init(dss_npaths, dss_pathnames) != 0) {
			fprintf(stderr, "%s", "dss_init failed. Exiting.\n");
			exit(1);
		}
	}

	/*
	 * Block all signals till we spawn other
	 * threads.
	 */
	(void) sigfillset(&sgset);
	(void) thr_sigsetmask(SIG_BLOCK, &sgset, NULL);

	if (logmaxservers) {
		fprintf(stderr,
		    "Number of servers not specified. Using default of %d.\n",
		    maxservers);
	}

	/*
	 * Make sure to unregister any previous versions in case the
	 * user is reconfiguring the server in interesting ways.
	 */
	svc_unreg(NFS_PROGRAM, NFS_VERSION);
	svc_unreg(NFS_PROGRAM, NFS_V3);
	svc_unreg(NFS_PROGRAM, NFS_V4);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V2);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V3);

	/*
	 * Set up kernel RPC thread pool for the NFS server.
	 */
	if (nfssvcpool(maxservers)) {
		fprintf(stderr, "Can't set up kernel NFS service: %s. "
		    "Exiting.\n", strerror(errno));
		exit(1);
	}

	/*
	 * Set up blocked thread to do LWP creation on behalf of the kernel.
	 */
	if (svcwait(NFS_SVCPOOL_ID)) {
		fprintf(stderr, "Can't set up NFS pool creator: %s. Exiting.\n",
		    strerror(errno));
		exit(1);
	}

	/*
	 * RDMA start and stop thread.
	 * Per pool RDMA listener creation and
	 * destructor thread.
	 *
	 * start rdma services and block in the kernel.
	 * (only if proto or provider is not set to TCP or UDP)
	 */
	if ((proto == NULL) && (provider == NULL)) {
		if (svcrdma(NFS_SVCPOOL_ID, nfs_server_vers_min,
		    nfs_server_vers_max, nfs_server_delegation)) {
			fprintf(stderr,
			    "Can't set up RDMA creator thread : %s\n",
			    strerror(errno));
		}
	}

	/*
	 * Now open up for signal delivery
	 */

	(void) thr_sigsetmask(SIG_UNBLOCK, &sgset, NULL);
	sigset(SIGTERM, sigflush);
	sigset(SIGUSR1, quiesce);

	/*
	 * Build a protocol block list for registration.
	 */
	protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob));
	protobp->serv = "NFS";
	protobp->versmin = nfs_server_vers_min;
	protobp->versmax = nfs_server_vers_max;
	protobp->program = NFS_PROGRAM;

	protobp->next = (struct protob *)malloc(sizeof (struct protob));
	protobp = protobp->next;
	protobp->serv = "NFS_ACL";		/* not used */
	protobp->versmin = nfs_server_vers_min;
	/* XXX - this needs work to get the version just right */
	protobp->versmax = (nfs_server_vers_max > NFS_ACL_V3) ?
	    NFS_ACL_V3 : nfs_server_vers_max;
	protobp->program = NFS_ACL_PROGRAM;
	protobp->next = (struct protob *)NULL;

	if (allflag) {
		if (do_all(protobp0, nfssvc) == -1) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			exit(1);
		}
	} else if (proto) {
		/* there's more than one match for the same protocol */
		struct netconfig *nconf;
		NCONF_HANDLE *nc;
		bool_t	protoFound = FALSE;
		if ((nc = setnetconfig()) == (NCONF_HANDLE *) NULL) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			goto done;
		}
		while (nconf = getnetconfig(nc)) {
			if (strcmp(nconf->nc_proto, proto) == 0) {
				protoFound = TRUE;
				do_one(nconf->nc_device, NULL,
				    protobp0, nfssvc);
			}
		}
		(void) endnetconfig(nc);
		if (protoFound == FALSE) {
			fprintf(stderr,
			    "couldn't find netconfig entry for protocol %s\n",
			    proto);
		}
	} else if (provider)
		do_one(provider, proto, protobp0, nfssvc);
	else {
		for (providerp = defaultproviders;
		    *providerp != NULL; providerp++) {
			provider = *providerp;
			do_one(provider, NULL, protobp0, nfssvc);
		}
	}
done:

	free(protobp);
	free(protobp0);

	if (num_fds == 0) {
		fprintf(stderr, "Could not start NFS service for any protocol."
		    " Exiting.\n");
		exit(1);
	}

	end_listen_fds = num_fds;

	/*
	 * nfsd is up and running as far as we are concerned.
	 */
	daemonize_fini(pipe_fd);

	/*
	 * Get rid of unneeded privileges.
	 */
	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);

	/*
	 * Poll for non-data control events on the transport descriptors.
	 */
	poll_for_action();

	/*
	 * If we get here, something failed in poll_for_action().
	 */
	return (1);
}
Example #6
0
int
main(int argc, char **argv)
{
	boolean_t	is_daemon  = B_TRUE;
	boolean_t	is_verbose = B_FALSE;
	int		ipc_fd;
	int		c;
	struct rlimit	rl;

	/*
	 * -l is ignored for compatibility with old agent.
	 */

	while ((c = getopt(argc, argv, "vd:l:fa")) != EOF) {

		switch (c) {

		case 'a':
			do_adopt = B_TRUE;
			grandparent = getpid();
			break;

		case 'd':
			debug_level = strtoul(optarg, NULL, 0);
			break;

		case 'f':
			is_daemon = B_FALSE;
			break;

		case 'v':
			is_verbose = B_TRUE;
			break;

		case '?':
			(void) fprintf(stderr, "usage: %s [-a] [-d n] [-f] [-v]"
			    "\n", argv[0]);
			return (EXIT_FAILURE);

		default:
			break;
		}
	}

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	if (geteuid() != 0) {
		dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERROR, "must be super-user");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	if (is_daemon && daemonize() == 0) {
		dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERR, "cannot become daemon, exiting");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	dhcpmsg_init(argv[0], is_daemon, is_verbose, debug_level);
	(void) atexit(dhcpmsg_fini);

	tq = iu_tq_create();
	eh = iu_eh_create();

	if (eh == NULL || tq == NULL) {
		errno = ENOMEM;
		dhcpmsg(MSG_ERR, "cannot create timer queue or event handler");
		return (EXIT_FAILURE);
	}

	/*
	 * ignore most signals that could be reasonably generated.
	 */

	(void) signal(SIGTERM, graceful_shutdown);
	(void) signal(SIGQUIT, graceful_shutdown);
	(void) signal(SIGPIPE, SIG_IGN);
	(void) signal(SIGUSR1, SIG_IGN);
	(void) signal(SIGUSR2, SIG_IGN);
	(void) signal(SIGINT,  SIG_IGN);
	(void) signal(SIGHUP,  SIG_IGN);
	(void) signal(SIGCHLD, SIG_IGN);

	/*
	 * upon SIGTHAW we need to refresh any non-infinite leases.
	 */

	(void) iu_eh_register_signal(eh, SIGTHAW, refresh_ifslist, NULL);

	class_id = get_class_id();
	if (class_id != NULL)
		class_id_len = strlen(class_id);
	else
		dhcpmsg(MSG_WARNING, "get_class_id failed, continuing "
		    "with no vendor class id");

	/*
	 * the inactivity timer is enabled any time there are no
	 * interfaces under DHCP control.  if DHCP_INACTIVITY_WAIT
	 * seconds transpire without an interface under DHCP control,
	 * the agent shuts down.
	 */

	inactivity_id = iu_schedule_timer(tq, DHCP_INACTIVITY_WAIT,
	    inactivity_shutdown, NULL);

	/*
	 * max out the number available descriptors, just in case..
	 */

	rl.rlim_cur = RLIM_INFINITY;
	rl.rlim_max = RLIM_INFINITY;
	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
		dhcpmsg(MSG_ERR, "setrlimit failed");

	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * create the ipc channel that the agent will listen for
	 * requests on, and register it with the event handler so that
	 * `accept_event' will be called back.
	 */

	switch (dhcp_ipc_init(&ipc_fd)) {

	case 0:
		break;

	case DHCP_IPC_E_BIND:
		dhcpmsg(MSG_ERROR, "dhcp_ipc_init: cannot bind to port "
		    "%i (agent already running?)", IPPORT_DHCPAGENT);
		return (EXIT_FAILURE);

	default:
		dhcpmsg(MSG_ERROR, "dhcp_ipc_init failed");
		return (EXIT_FAILURE);
	}

	if (iu_register_event(eh, ipc_fd, POLLIN, accept_event, 0) == -1) {
		dhcpmsg(MSG_ERR, "cannot register ipc fd for messages");
		return (EXIT_FAILURE);
	}

	/*
	 * Create the global routing socket.  This is used for monitoring
	 * interface transitions, so that we learn about the kernel's Duplicate
	 * Address Detection status, and for inserting and removing default
	 * routes as learned from DHCP servers.
	 */
	rtsock_fd = socket(PF_ROUTE, SOCK_RAW, AF_INET);
	if (rtsock_fd == -1) {
		dhcpmsg(MSG_ERR, "cannot open routing socket");
		return (EXIT_FAILURE);
	}
	if (iu_register_event(eh, rtsock_fd, POLLIN, rtsock_event, 0) == -1) {
		dhcpmsg(MSG_ERR, "cannot register routing socket for messages");
		return (EXIT_FAILURE);
	}

	/*
	 * if the -a (adopt) option was specified, try to adopt the
	 * kernel-managed interface before we start.
	 */

	if (do_adopt && dhcp_adopt() == 0)
		return (EXIT_FAILURE);

	/*
	 * enter the main event loop; this is where all the real work
	 * takes place (through registering events and scheduling timers).
	 * this function only returns when the agent is shutting down.
	 */

	switch (iu_handle_events(eh, tq)) {

	case -1:
		dhcpmsg(MSG_WARNING, "iu_handle_events exited abnormally");
		break;

	case DHCP_REASON_INACTIVITY:
		dhcpmsg(MSG_INFO, "no interfaces to manage, shutting down...");
		break;

	case DHCP_REASON_TERMINATE:
		dhcpmsg(MSG_INFO, "received SIGTERM, shutting down...");
		break;

	case DHCP_REASON_SIGNAL:
		dhcpmsg(MSG_WARNING, "received unexpected signal, shutting "
		    "down...");
		break;
	}

	(void) iu_eh_unregister_signal(eh, SIGTHAW, NULL);

	iu_eh_destroy(eh);
	iu_tq_destroy(tq);

	return (EXIT_SUCCESS);
}
Example #7
0
int
parmount(char **mntlist, int count, char *fstype)
{
	int 		maxfd =	OPEN_MAX;
	struct 		rlimit rl;
	vfsent_t	**vl, *vp;

	/*
	 * Process scaling.  After running a series
	 * of tests based on the number of simultaneous processes and
	 * processors available, optimum performance was achieved near or
	 * at (PROCN * 2).
	 */
	if ((maxrun = sysconf(_SC_NPROCESSORS_ONLN)) == -1)
		maxrun = 4;
	else
		maxrun = maxrun * 2 + 1;

	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		rl.rlim_cur = rl.rlim_max;
		if (setrlimit(RLIMIT_NOFILE, &rl) == 0)
			maxfd = (int)rl.rlim_cur;
	}
	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * The parent needs to maintain 3 of its own fd's, plus 2 for
	 * each child (the stdout and stderr pipes).
	 */
	maxfd = (maxfd / 2) - 6;	/* 6 takes care of temporary  */
					/* periods of open fds */
	if (maxfd < maxrun)
		maxrun = maxfd;
	if (maxrun < 4)
		maxrun = 4;		/* sanity check */

	if (count == 0)
		mntlist = NULL;		/* used as a flag later */
	else
		fstype = NULL;		/* mount points supplied: */
					/* ignore fstype */
	/*
	 * Read the whole vfstab into a linked list for quick processing.
	 * On average, this is the most efficient way to collect and
	 * manipulate the vfstab data.
	 */
	vfsll = getvfsall(fstype, mntlist == NULL);

	/*
	 * Make an array out of the vfs linked list for sorting purposes.
	 */
	if (vfsll == NULL ||
	    (vfsarray = make_vfsarray(mntlist, count)) == NULL) {
		if (mntlist == NULL)	/* not an error - just none found */
			return (0);

		fprintf(stderr, gettext("%s: No valid entries found in %s\n"),
		    myname, vfstab);
		return (1);
	}

	/*
	 * Sort the entries based on their resolved path names
	 *
	 * If an lofs is encountered, then the original order of the vfstab
	 * file needs to be maintained until we are done mounting lofs's.
	 */
	if (!lofscnt)
		qsort((void *)vfsarray, vfsarraysize, sizeof (vfsent_t *),
		    mlevelcmp);

	/*
	 * Shrink the vfsll linked list down to the new list.  This will
	 * speed up the pid search in cleanupkid() later.
	 */
	vfsll = vfsarray[0];
	for (vl = vfsarray; vp = *vl; )
		vp->next = *++vl;

	/*
	 * Try to handle interrupts in a reasonable way.
	 */
	sigset(SIGHUP, cleanup);
	sigset(SIGQUIT, cleanup);
	sigset(SIGINT, cleanup);

	do_mounts();		/* do the mounts */

	if (failcnt > 0 && failcnt == lofsfail)
		return (ALL_LOFS_FAILURES);

	return (exitcode);
}
Example #8
0
int
main(int argc, char **argv)
{
	struct ps_prochandle *P;
	int gerr;
	char *prefix = NULL;
	int opt;
	int opt_p = 0, opt_g = 0, opt_c = 0;
	int oflags = 0;
	int i;
	char fname[MAXPATHLEN];
	char path[MAXPATHLEN];
	int err = 0;
	core_content_t content = CC_CONTENT_DEFAULT;
	struct rlimit rlim;

	if ((pname = strrchr(argv[0], '/')) == NULL)
		pname = argv[0];
	else
		argv[0] = ++pname;		/* for getopt() */

	while ((opt = getopt(argc, argv, "o:Fgpc:")) != EOF) {
		switch (opt) {
		case 'o':
			prefix = optarg;
			break;
		case 'c':
			if (proc_str2content(optarg, &content) != 0) {
				(void) fprintf(stderr, "%s: invalid "
				    "content string '%s'\n", pname, optarg);
				goto usage;
			}
			opt_c = 1;
			break;
		case 'F':
			oflags |= PGRAB_FORCE;
			break;
		case 'p':
			opt_p = 1;
			break;
		case 'g':
			opt_g = 1;
			break;
		default:
			goto usage;
		}
	}

	if ((opt_p | opt_g) == 0) {
		if (prefix == NULL)
			prefix = "core";
	} else {
		int options;

		if ((options = core_get_options()) == -1) {
			perror("core_get_options()");
			return (1);
		}

		if (opt_p && !(options & CC_PROCESS_PATH)) {
			(void) fprintf(stderr, "%s: per-process core dumps "
			    "are disabled (ignoring -p)\n", pname);
			opt_p = 0;
		}

		if (opt_g && !(options & CC_GLOBAL_PATH)) {
			(void) fprintf(stderr, "%s: global core dumps "
			    "are disabled (ignoring -g)\n", pname);
			opt_g = 0;
		}

		if ((opt_p | opt_g) == 0 && prefix == NULL)
			return (1);
	}

	argc -= optind;
	argv += optind;

	if (argc == 0)
		goto usage;

	/*
	 * Make sure we'll have enough file descriptors to handle a target
	 * that has many many mappings.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
		rlim.rlim_cur = rlim.rlim_max;
		(void) setrlimit(RLIMIT_NOFILE, &rlim);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	for (i = 0; i < argc; i++) {
		P = proc_arg_grab(argv[i], PR_ARG_PIDS, oflags, &gerr);
		if (P == NULL) {
			(void) fprintf(stderr, "%s: cannot grab %s: %s\n",
			    pname, argv[i], Pgrab_error(gerr));
			err++;
			continue;
		}

		if (prefix != NULL) {
			(void) snprintf(path, sizeof (path), "%s.%%p", prefix);
			convert_path(path, fname, sizeof (fname), P);

			gcore(P, fname, content, &err);
		}

		if (opt_p) {
			pid_t pid = Pstatus(P)->pr_pid;
			(void) core_get_process_path(path, sizeof (path), pid);
			convert_path(path, fname, sizeof (fname), P);
			if (!opt_c)
				(void) core_get_process_content(&content, pid);

			gcore(P, fname, content, &err);
		}

		if (opt_g) {
			/*
			 * Global core files are always just readable and
			 * writable by their owner so we temporarily change
			 * the umask.
			 */
			mode_t oldmode = umask(S_IXUSR | S_IRWXG | S_IRWXO);

			(void) core_get_global_path(path, sizeof (path));
			convert_path(path, fname, sizeof (fname), P);
			if (!opt_c)
				(void) core_get_global_content(&content);

			gcore(P, fname, content, &err);

			(void) umask(oldmode);
		}

		Prelease(P, 0);
	}

	return (err != 0);

usage:
	(void) fprintf(stderr, "usage: %s "
	    "[ -pgF ] [ -o filename ] [ -c content ] pid ...\n", pname);
	return (2);
}
Example #9
0
int
main(int argc, char *argv[])
{
	int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0;
	char *options, *value;
	extern char *optarg;
	extern int optind;
	int c, d;
	struct rlimit rl;
	int mode = RPC_SVC_MT_AUTO;
	int maxrecsz = RPC_MAXDATASIZE;

	void detachfromtty(void);
	int setmodulus();
	int pk_nodefaultkeys();
	int svc_create_local_service();

	char domainname[MAXNETNAMELEN + 1];

	/*
	 * Set our allowed number of file descriptors to the max
	 * of what the system will allow, limited by FD_SETSIZE.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		rlim_t limit;

		if ((limit = rl.rlim_max) > FD_SETSIZE)
			limit = FD_SETSIZE;
		rl.rlim_cur = limit;
		(void) setrlimit(RLIMIT_NOFILE, &rl);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	__key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc;
	__key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc;
	__key_gendes_LOCAL = &__key_gen_1_svc;

	/*
	 * Pre-option initialisation
	 */
	(void) umask(066);	/* paranoia */
	if (geteuid() != 0) {
		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
		exit(1);
	}
	setmodulus(HEXMODULUS);
	openlog("keyserv", LOG_PID, LOG_DAEMON);

	/*
	 * keyserv will not work with a null domainname.
	 */
	if (getdomainname(domainname, MAXNETNAMELEN+1) ||
	    (domainname[0] == '\0')) {
		syslog(LOG_ERR, "could not get a valid domainname.\n");
		exit(SMF_EXIT_ERR_CONFIG);
	}

	/*
	 * Initialise security mechanisms
	 */
	cache_size = NULL;
	cache_options = NULL;
	if (init_mechs() == -1) {
		disk_caching = 0;
	}

	defaults();

	while ((c = getopt(argc, argv, "ndDet:cs:")) != -1)
		switch (c) {
		case 'n':
			nflag++;
			break;
		case 'd':
			dflag++;
			use_nobody_keys = FALSE;
			break;
		case 'e':
			eflag++;
			use_nobody_keys = TRUE;
			break;
		case 'D':
			debugging = 1;
			break;
		case 't':
			nthreads = atoi(optarg);
			break;
		case 'c':
			disk_caching = 0;
			break;
		case 's':
			if (!disk_caching) {
				fprintf(stderr, "missing configuration file");
				fprintf(stderr, " or -c option specified\n");
				usage();
			}
			sflag++;
			/*
			 * Which version of [-s] do we have...?
			 */
			if (strchr((const char *) optarg, '=') == NULL) {
				/*
				 * -s <size>
				 */
				if (s1flag) {
					fprintf(stderr, "duplicate"
					    " [-s <size>]\n");
					usage();
				}
				s1flag++;
				default_cache = get_cache_size(optarg);
				break;
			}
			/*
			 * -s <mechtype>=<size>[,...]
			 */
			s2flag++;
			options = optarg;
			while (*options != '\0') {
				d = getsubopt(&options, cache_options, &value);
				if (d == -1) {
					/* Ignore unknown mechtype */
					continue;
				}
				if (value == NULL) {
					fprintf(stderr,
					    "missing cache size for "
					    "mechtype %s\n", cache_options[d]);
					usage();
				}
				cache_size[d] = get_cache_size(value);
			}
			break;
		default:
			usage();
			break;
		}


	if (dflag && eflag) {
		(void) fprintf(stderr, "specify only one of -d and -e\n");
		usage();
	}

	if (use_nobody_keys == FALSE) {
		pk_nodefaultkeys();
	}

	if (optind != argc) {
		usage();
	}

	if (!disk_caching && sflag) {
		fprintf(stderr, "missing configuration file");
		fprintf(stderr, " or -c option specified\n");
		usage();
	}

	if (debugging) {
		if (disk_caching) {
			char **cpp = cache_options;
			int *ip = cache_size;
			(void) fprintf(stderr, "default disk cache size: ");
			if (default_cache < 0) {
				(void) fprintf(stderr, "%d entries\n",
				    abs(default_cache));
			} else {
				(void) fprintf(stderr, "%dMB\n", default_cache);
			}

			(void) fprintf(stderr, "supported mechanisms:\n");
			(void) fprintf(stderr, "\talias\t\tdisk cache size\n");
			(void) fprintf(stderr, "\t=====\t\t===============\n");
			while (*cpp != NULL) {
				(void) fprintf(stderr, "\t%s\t\t", *cpp++);
				if (*ip < 0) {
					(void) fprintf(stderr, "%d entries\n",
					    abs(*ip));
				} else {
					(void) fprintf(stderr, "%dMB\n", *ip);
				}
				ip++;
			}
		} else {
			(void) fprintf(stderr,
			    "common key disk caching disabled\n");
		}
	}
	/*
	 * Post-option initialisation
	 */
	if (disk_caching) {
		int i;
		for (i = 0; mechs[i]; i++) {
			if ((AUTH_DES_COMPAT_CHK(mechs[i])) ||
			    (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0))
				continue;
			create_cache_file(mechs[i]->keylen, mechs[i]->algtype,
			    cache_size[i] ? cache_size[i] : default_cache);
		}
	}
	getrootkey(&masterkey, nflag);

	/*
	 * Set MT mode
	 */
	if (nthreads > 0) {
		(void) rpc_control(RPC_SVC_MTMODE_SET, &mode);
		(void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads);
	}

	/*
	 * Enable non-blocking mode and maximum record size checks for
	 * connection oriented transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
		syslog(LOG_INFO, "unable to set max RPC record size");
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	if (!debugging) {
		detachfromtty();
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	svc_run();
	abort();
	/* NOTREACHED */
	return (0);
}
Example #10
0
int
main(int argc, char **argv)
{
	dsvcd_datastore_t	**ds_table;
	dsvc_datastore_t	dd;
	dsvc_synchtype_t	synchtype;
	char			**modules;
	unsigned int		i, j;
	int			debug_level = 0;
	boolean_t		is_daemon = B_TRUE;
	boolean_t		is_verbose = B_FALSE;
	int			sig, nmodules, nsynchmods, c;
	sigset_t		sigset;
	char			signame[SIG2STR_MAX];
	char			*progname;
	void			*stackbase;
	unsigned int		stacksize = 16 * 1024;
	struct rlimit		rl;

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	/*
	 * Mask all signals except SIGABRT; doing this here ensures that
	 * all threads created through door_create() have them masked too.
	 */
	(void) sigfillset(&sigset);
	(void) sigdelset(&sigset, SIGABRT);
	(void) thr_sigsetmask(SIG_BLOCK, &sigset, NULL);

	/*
	 * Figure out our program name; just keep the final piece so that
	 * our dhcpmsg() messages don't get too long.
	 */
	progname = strrchr(argv[0], '/');
	if (progname != NULL)
		progname++;
	else
		progname = argv[0];

	/*
	 * Set the door thread creation procedure so that all of our
	 * threads are created with thread stacks with backing store.
	 */
	(void) door_server_create(doorserv_create);

	while ((c = getopt(argc, argv, "d:fv")) != EOF) {
		switch (c) {

		case 'd':
			debug_level = atoi(optarg);
			break;

		case 'f':
			is_daemon = B_FALSE;
			break;

		case 'v':
			is_verbose = B_TRUE;
			break;

		case '?':
			(void) fprintf(stderr,
			    gettext("usage: %s [-dn] [-f] [-v]\n"), progname);
			return (EXIT_FAILURE);

		default:
			break;
		}
	}

	if (geteuid() != 0) {
		dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERROR, "must be super-user");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	if (is_daemon && daemonize() == 0) {
		dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERROR, "cannot become daemon, exiting");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	dhcpmsg_init(progname, is_daemon, is_verbose, debug_level);
	(void) atexit(dhcpmsg_fini);

	/*
	 * Max out the number available descriptors since we need to
	 * allocate two per held lock.
	 */
	rl.rlim_cur = RLIM_INFINITY;
	rl.rlim_max = RLIM_INFINITY;
	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
		dhcpmsg(MSG_ERR, "setrlimit failed");

	(void) enable_extended_FILE_stdio(-1, -1);

	if (enumerate_dd(&modules, &nmodules) != DSVC_SUCCESS) {
		dhcpmsg(MSG_ERROR, "cannot enumerate public modules, exiting");
		return (EXIT_FAILURE);
	}

	/*
	 * NOTE: this code assumes that a module that needs dsvclockd will
	 * always need it (even as the container version is ramped).  If
	 * this becomes bogus in a future release, we'll have to make this
	 * logic more sophisticated.
	 */
	nsynchmods = nmodules;
	for (i = 0; i < nmodules; i++) {
		dd.d_resource = modules[i];
		dd.d_conver = DSVC_CUR_CONVER;
		dd.d_location = "";
		if (module_synchtype(&dd, &synchtype) != DSVC_SUCCESS) {
			dhcpmsg(MSG_WARNING, "cannot determine synchronization "
			    "type for `%s', skipping", modules[i]);
			free(modules[i]);
			modules[i] = NULL;
			nsynchmods--;
			continue;
		}
		if ((synchtype & DSVC_SYNCH_STRATMASK) != DSVC_SYNCH_DSVCD) {
			free(modules[i]);
			modules[i] = NULL;
			nsynchmods--;
		}
	}

	if (nsynchmods == 0) {
		dhcpmsg(MSG_INFO, "no public modules need synchronization");
		return (EXIT_SUCCESS);
	}

	/*
	 * Allocate the datastore table; include one extra entry so that
	 * the table is NULL-terminated.
	 */
	ds_table = calloc(nsynchmods + 1, sizeof (dsvcd_datastore_t *));
	if (ds_table == NULL) {
		dhcpmsg(MSG_ERR, "cannot allocate datastore table, exiting");
		return (EXIT_FAILURE);
	}
	ds_table[nsynchmods] = NULL;

	/*
	 * Create the datastores (which implicitly creates the doors).
	 * then sit around and wait for requests to come in on the doors.
	 */
	for (i = 0, j = 0; i < nmodules; i++) {
		if (modules[i] != NULL) {
			ds_table[j] = ds_create(modules[i], svc_lock);
			if (ds_table[j] == NULL) {
				while (j-- > 0)
					ds_destroy(ds_table[j]);
				return (EXIT_FAILURE);
			}
			free(modules[i]);
			j++;
		}
	}
	free(modules);

	stackbase = stack_create(&stacksize);
	if (stackbase == NULL)
		dhcpmsg(MSG_ERR, "cannot create reaper stack; containers "
		    "will not be reaped");
	else {
		errno = thr_create(stackbase, stacksize, reaper, ds_table,
		    THR_DAEMON, NULL);
		if (errno != 0) {
			dhcpmsg(MSG_ERR, "cannot create reaper thread; "
			    "containers will not be reaped");
			stack_destroy(stackbase, stacksize);
		}
	}

	/*
	 * Synchronously wait for a QUIT, TERM, or INT, then shutdown.
	 */
	(void) sigemptyset(&sigset);
	(void) sigaddset(&sigset, SIGQUIT);
	(void) sigaddset(&sigset, SIGTERM);
	(void) sigaddset(&sigset, SIGINT);

	(void) sigwait(&sigset, &sig);
	if (sig != SIGTERM && sig != SIGQUIT && sig != SIGINT)
		dhcpmsg(MSG_WARNING, "received unexpected signal");

	if (sig2str(sig, signame) == -1)
		(void) strlcpy(signame, "???", sizeof (signame));

	dhcpmsg(MSG_INFO, "shutting down via SIG%s", signame);

	for (i = 0; i < nsynchmods; i++)
		ds_destroy(ds_table[i]);

	return (EXIT_SUCCESS);
}
Example #11
0
int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts)
{
	int max_threads, max_queue, readtimeout, ret = 0;
	unsigned int options = 0;
	char timestr[32];
#ifndef	_WIN32
	struct sigaction sigact;
	sigset_t sigset;
	struct rlimit rlim;
#endif
	mode_t old_umask;
	const struct optstruct *opt;
	char buff[BUFFSIZE + 1];
	pid_t mainpid;
	int idletimeout;
	unsigned long long val;
	size_t i, j, rr_last = 0;
	pthread_t accept_th;
	pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_t recvfds_mutex = PTHREAD_MUTEX_INITIALIZER;
	struct acceptdata acceptdata = ACCEPTDATA_INIT(&fds_mutex, &recvfds_mutex);
	struct fd_data *fds = &acceptdata.recv_fds;
	time_t start_time, current_time;
	unsigned int selfchk;
	threadpool_t *thr_pool;

#if defined(FANOTIFY) || defined(CLAMAUTH)
	pthread_t fan_pid;
	pthread_attr_t fan_attr;
	struct thrarg *tharg = NULL; /* shut up gcc */
#endif

#ifndef	_WIN32
	memset(&sigact, 0, sizeof(struct sigaction));
#endif

    /* set up limits */
    if((opt = optget(opts, "MaxScanSize"))->active) {
	if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) {
	    logg("!cl_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
	    cl_engine_free(engine);
	    return 1;
	}
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL);
    if(val)
    	logg("Limits: Global size limit set to %llu bytes.\n", val);
    else
    	logg("^Limits: Global size limit protection disabled.\n");

    if((opt = optget(opts, "MaxFileSize"))->active) {
	if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) {
	    logg("!cl_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
	    cl_engine_free(engine);
	    return 1;
	}
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL);
    if(val)
    	logg("Limits: File size limit set to %llu bytes.\n", val);
    else
    	logg("^Limits: File size limit protection disabled.\n");

#ifndef _WIN32
    if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
	if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL))
	    logg("^System limit for file size is lower than engine->maxfilesize\n");
	if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL))
	    logg("^System limit for file size is lower than engine->maxscansize\n");
    } else {
	logg("^Cannot obtain resource limits for file size\n");
    }
#endif

    if((opt = optget(opts, "MaxRecursion"))->active) {
	if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) {
	    logg("!cl_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
	    cl_engine_free(engine);
	    return 1;
	}
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_RECURSION, NULL);
    if(val)
    	logg("Limits: Recursion level limit set to %u.\n", (unsigned int) val);
    else
    	logg("^Limits: Recursion level limit protection disabled.\n");

    if((opt = optget(opts, "MaxFiles"))->active) {
	if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) {
	    logg("!cl_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
	    cl_engine_free(engine);
	    return 1;
	}
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILES, NULL);
    if(val)
    	logg("Limits: Files limit set to %u.\n", (unsigned int) val);
    else
    	logg("^Limits: Files limit protection disabled.\n");

#ifndef _WIN32
    if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
	logg("*Limits: Core-dump limit is %lu.\n", (unsigned long)rlim.rlim_cur);
    }
#endif

    /* Engine max sizes */

    if((opt = optget(opts, "MaxEmbeddedPE"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_EMBEDDEDPE) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, NULL);
    logg("Limits: MaxEmbeddedPE limit set to %llu bytes.\n", val);

    if((opt = optget(opts, "MaxHTMLNormalize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNORMALIZE) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, NULL);
    logg("Limits: MaxHTMLNormalize limit set to %llu bytes.\n", val);

    if((opt = optget(opts, "MaxHTMLNoTags"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNOTAGS) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, NULL);
    logg("Limits: MaxHTMLNoTags limit set to %llu bytes.\n", val);

    if((opt = optget(opts, "MaxScriptNormalize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_SCRIPTNORMALIZE) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, NULL);
    logg("Limits: MaxScriptNormalize limit set to %llu bytes.\n", val);

    if((opt = optget(opts, "MaxZipTypeRcg"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) {
            logg("!cli_engine_set_num(CL_ENGINE_MAX_ZIPTYPERCG) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, NULL);
    logg("Limits: MaxZipTypeRcg limit set to %llu bytes.\n", val);

    if((opt = optget(opts, "MaxPartitions"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) {
            logg("!cli_engine_set_num(MaxPartitions) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_PARTITIONS, NULL);
    logg("Limits: MaxPartitions limit set to %llu.\n", val);

    if((opt = optget(opts, "MaxIconsPE"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) {
            logg("!cli_engine_set_num(MaxIconsPE) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_MAX_ICONSPE, NULL);
    logg("Limits: MaxIconsPE limit set to %llu.\n", val);

    if((opt = optget(opts, "PCREMatchLimit"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) {
            logg("!cli_engine_set_num(PCREMatchLimit) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, NULL);
    logg("Limits: PCREMatchLimit limit set to %llu.\n", val);

    if((opt = optget(opts, "PCRERecMatchLimit"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) {
            logg("!cli_engine_set_num(PCRERecMatchLimit) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, NULL);
    logg("Limits: PCRERecMatchLimit limit set to %llu.\n", val);

    if((opt = optget(opts, "PCREMaxFileSize"))->active) {
        if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, opt->numarg))) {
            logg("!cli_engine_set_num(PCREMaxFileSize) failed: %s\n", cl_strerror(ret));
            cl_engine_free(engine);
            return 1;
        }
    }
    val = cl_engine_get_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, NULL);
    logg("Limits: PCREMaxFileSize limit set to %llu.\n", val);

    if(optget(opts, "ScanArchive")->enabled) {
	logg("Archive support enabled.\n");
	options |= CL_SCAN_ARCHIVE;

	if(optget(opts, "ArchiveBlockEncrypted")->enabled) {
	    logg("Archive: Blocking encrypted archives.\n");
	    options |= CL_SCAN_BLOCKENCRYPTED;
	}

    } else {
	logg("Archive support disabled.\n");
    }

    if(optget(opts, "AlgorithmicDetection")->enabled) {
	logg("Algorithmic detection enabled.\n");
	options |= CL_SCAN_ALGORITHMIC;
    } else {
	logg("Algorithmic detection disabled.\n");
    }

    if(optget(opts, "ScanPE")->enabled) {
	logg("Portable Executable support enabled.\n");
	options |= CL_SCAN_PE;
    } else {
	logg("Portable Executable support disabled.\n");
    }

    if(optget(opts, "ScanELF")->enabled) {
	logg("ELF support enabled.\n");
	options |= CL_SCAN_ELF;
    } else {
	logg("ELF support disabled.\n");
    }

    if(optget(opts, "ScanPE")->enabled || optget(opts, "ScanELF")->enabled) {
	if(optget(opts, "DetectBrokenExecutables")->enabled) {
	    logg("Detection of broken executables enabled.\n");
	    options |= CL_SCAN_BLOCKBROKEN;
	}
    }

    if(optget(opts, "ScanMail")->enabled) {
	logg("Mail files support enabled.\n");
	options |= CL_SCAN_MAIL;

	if(optget(opts, "ScanPartialMessages")->enabled) {
	    logg("Mail: RFC1341 handling enabled.\n");
	    options |= CL_SCAN_PARTIAL_MESSAGE;
	}

    } else {
	logg("Mail files support disabled.\n");
    }

    if(optget(opts, "ScanOLE2")->enabled) {
	logg("OLE2 support enabled.\n");
	options |= CL_SCAN_OLE2;
	if(optget(opts, "OLE2BlockMacros")->enabled) {
	    logg("OLE2: Blocking all VBA macros.\n");
	    options |= CL_SCAN_BLOCKMACROS;
	}
    } else {
	logg("OLE2 support disabled.\n");
    }

    if(optget(opts, "ScanPDF")->enabled) {
	logg("PDF support enabled.\n");
	options |= CL_SCAN_PDF;
    } else {
	logg("PDF support disabled.\n");
    }

    if(optget(opts, "ScanSWF")->enabled) {
	logg("SWF support enabled.\n");
	options |= CL_SCAN_SWF;
    } else {
	logg("SWF support disabled.\n");
    }

    if(optget(opts, "ScanHTML")->enabled) {
	logg("HTML support enabled.\n");
	options |= CL_SCAN_HTML;
    } else {
	logg("HTML support disabled.\n");
    }

    if(optget(opts,"PhishingScanURLs")->enabled) {

	if(optget(opts,"PhishingAlwaysBlockCloak")->enabled) {
	    options |= CL_SCAN_PHISHING_BLOCKCLOAK; 
	    logg("Phishing: Always checking for cloaked urls\n");
	}

	if(optget(opts,"PhishingAlwaysBlockSSLMismatch")->enabled) {
	    options |= CL_SCAN_PHISHING_BLOCKSSL;
	    logg("Phishing: Always checking for ssl mismatches\n");
	}
    }

    if(optget(opts,"PartitionIntersection")->enabled) {
        options |= CL_SCAN_PARTITION_INTXN;
        logg("Raw DMG: Always checking for partitons intersections\n");
    }

    if(optget(opts,"HeuristicScanPrecedence")->enabled) {
	    options |= CL_SCAN_HEURISTIC_PRECEDENCE;
	    logg("Heuristic: precedence enabled\n");
    }

    if(optget(opts, "StructuredDataDetection")->enabled) {
        options |= CL_SCAN_STRUCTURED;

	if((opt = optget(opts, "StructuredMinCreditCardCount"))->enabled) {
	    if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) {
		logg("!cl_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
		cl_engine_free(engine);
		return 1;
	    }
	}
	val = cl_engine_get_num(engine, CL_ENGINE_MIN_CC_COUNT, NULL);
	logg("Structured: Minimum Credit Card Number Count set to %u\n", (unsigned int) val);

	if((opt = optget(opts, "StructuredMinSSNCount"))->enabled) {
	    if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) {
		logg("!cl_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
		cl_engine_free(engine);
		return 1;
	    }
	}
	val = cl_engine_get_num(engine, CL_ENGINE_MIN_SSN_COUNT, NULL);
        logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int) val);

        if(optget(opts, "StructuredSSNFormatNormal")->enabled)
            options |= CL_SCAN_STRUCTURED_SSN_NORMAL;

        if(optget(opts, "StructuredSSNFormatStripped")->enabled)
	    options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;
    }

#ifdef HAVE__INTERNAL__SHA_COLLECT
    if(optget(opts, "DevCollectHashes")->enabled)
	options |= CL_SCAN_INTERNAL_COLLECT_SHA;
#endif

    selfchk = optget(opts, "SelfCheck")->numarg;
    if(!selfchk) {
	logg("Self checking disabled.\n");
    } else {
	logg("Self checking every %u seconds.\n", selfchk);
    }

    /* save the PID */
    mainpid = getpid();
    if((opt = optget(opts, "PidFile"))->enabled) {
	    FILE *fd;
	old_umask = umask(0002);
	if((fd = fopen(opt->strarg, "w")) == NULL) {
	    logg("!Can't save PID in file %s\n", opt->strarg);
	} else {
	    if (fprintf(fd, "%u\n", (unsigned int) mainpid)<0) {
	    	logg("!Can't save PID in file %s\n", opt->strarg);
	    }
	    fclose(fd);
	}
	umask(old_umask);
    }

    logg("*Listening daemon: PID: %u\n", (unsigned int) mainpid);
    max_threads = optget(opts, "MaxThreads")->numarg;
    max_queue = optget(opts, "MaxQueue")->numarg;
    acceptdata.commandtimeout = optget(opts, "CommandReadTimeout")->numarg;
    readtimeout = optget(opts, "ReadTimeout")->numarg;

#if !defined(_WIN32) && defined(RLIMIT_NOFILE)
    if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
	/* don't warn if default value is too high, silently fix it */
	unsigned maxrec;
	int max_max_queue;
	unsigned warn = optget(opts, "MaxQueue")->active;
	const unsigned clamdfiles = 6;
	/* Condition to not run out of file descriptors:
	 * MaxThreads * MaxRecursion + (MaxQueue - MaxThreads) + CLAMDFILES < RLIMIT_NOFILE 
	 * CLAMDFILES is 6: 3 standard FD + logfile + 2 FD for reloading the DB
	 * */
#ifdef C_SOLARIS
#ifdef HAVE_ENABLE_EXTENDED_FILE_STDIO
	if (enable_extended_FILE_stdio(-1, -1) == -1) {
	    logg("^Unable to set extended FILE stdio, clamd will be limited to max 256 open files\n");
	    rlim.rlim_cur = rlim.rlim_cur > 255 ? 255 : rlim.rlim_cur;
	}
#elif !defined(_LP64)
	if (rlim.rlim_cur > 255) {
	    rlim.rlim_cur = 255;
	    logg("^Solaris only supports 256 open files for 32-bit processes, you need at least Solaris 10u4, or compile as 64-bit to support more!\n");
	}
#endif
#endif
	opt = optget(opts,"MaxRecursion");
	maxrec = opt->numarg;
	max_max_queue = rlim.rlim_cur - maxrec * max_threads - clamdfiles + max_threads;
	if (max_queue < max_threads) {
	    max_queue = max_threads;
	    if (warn)
		logg("^MaxQueue value too low, increasing to: %d\n", max_queue);
	}
	if (max_max_queue < max_threads) {
	    logg("^MaxThreads * MaxRecursion is too high: %d, open file descriptor limit is: %lu\n",
		 maxrec*max_threads, (unsigned long)rlim.rlim_cur);
	    max_max_queue = max_threads;
	}
	if (max_queue > max_max_queue) {
	    max_queue = max_max_queue;
	    if (warn)
		logg("^MaxQueue value too high, lowering to: %d\n", max_queue);
	} else if (max_queue < 2*max_threads && max_queue < max_max_queue) {
	    max_queue = 2*max_threads;
	    if (max_queue > max_max_queue)
		max_queue = max_max_queue;
	    /* always warn here */
	    logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue);
	}
    }
#endif
    logg("*MaxQueue set to: %d\n", max_queue);
    acceptdata.max_queue = max_queue;

    if(optget(opts, "ScanOnAccess")->enabled)

#if defined(FANOTIFY) || defined(CLAMAUTH)
    {
        do {
	    if(pthread_attr_init(&fan_attr)) break;
	    pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE);
	    if(!(tharg = (struct thrarg *) malloc(sizeof(struct thrarg)))) break;
	    tharg->opts = opts;
	    tharg->engine = engine;
	    tharg->options = options;
	    if(!pthread_create(&fan_pid, &fan_attr, onas_fan_th, tharg)) break;
	    free(tharg);
	    tharg=NULL;
	} while(0);
	if (!tharg) logg("!Unable to start on-access scan\n");
    }
#else
	logg("!On-access scan is not available\n");
#endif


#ifndef	_WIN32
    /* set up signal handling */
    sigfillset(&sigset);
    sigdelset(&sigset, SIGINT);
    sigdelset(&sigset, SIGTERM);
    sigdelset(&sigset, SIGSEGV);
    sigdelset(&sigset, SIGHUP);
    sigdelset(&sigset, SIGPIPE);
    sigdelset(&sigset, SIGUSR2);
    /* The behavior of a process is undefined after it ignores a 
     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
    sigdelset(&sigset, SIGFPE);
    sigdelset(&sigset, SIGILL);
    sigdelset(&sigset, SIGSEGV);
#ifdef SIGBUS    
    sigdelset(&sigset, SIGBUS);
#endif
    sigdelset(&sigset, SIGTSTP);
    sigdelset(&sigset, SIGCONT);
    sigprocmask(SIG_SETMASK, &sigset, NULL);

    /* SIGINT, SIGTERM, SIGSEGV */
    sigact.sa_handler = sighandler_th;
    sigemptyset(&sigact.sa_mask);
    sigaddset(&sigact.sa_mask, SIGINT);
    sigaddset(&sigact.sa_mask, SIGTERM);
    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaddset(&sigact.sa_mask, SIGPIPE);
    sigaddset(&sigact.sa_mask, SIGUSR2);
    sigaction(SIGINT, &sigact, NULL);
    sigaction(SIGTERM, &sigact, NULL);
    sigaction(SIGHUP, &sigact, NULL);
    sigaction(SIGPIPE, &sigact, NULL);
    sigaction(SIGUSR2, &sigact, NULL);
#endif

    idletimeout = optget(opts, "IdleTimeout")->numarg;

    for (i=0;i < nsockets;i++)
	if (fds_add(&acceptdata.fds, socketds[i], 1, 0) == -1) {
	    logg("!fds_add failed\n");
	    cl_engine_free(engine);
	    return 1;
	}
#ifdef _WIN32
	event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL);
	event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL);
#else
    if (pipe(acceptdata.syncpipe_wake_recv) == -1 ||
	(pipe(acceptdata.syncpipe_wake_accept) == -1)) {

	logg("!pipe failed\n");
	exit(-1);
    }
    syncpipe_wake_recv_w = acceptdata.syncpipe_wake_recv[1];

    if (fds_add(fds, acceptdata.syncpipe_wake_recv[0], 1, 0) == -1 ||
	fds_add(&acceptdata.fds, acceptdata.syncpipe_wake_accept[0], 1, 0)) {
	logg("!failed to add pipe fd\n");
	exit(-1);
    }
#endif

    if ((thr_pool = thrmgr_new(max_threads, idletimeout, max_queue, scanner_thread)) == NULL) {
	logg("!thrmgr_new failed\n");
	exit(-1);
    }

    if (pthread_create(&accept_th, NULL, acceptloop_th, &acceptdata)) {
	logg("!pthread_create failed\n");
	exit(-1);
    }

    time(&start_time);
    for(;;) {
	int new_sd;

	/* Block waiting for connection on any of the sockets */
	pthread_mutex_lock(fds->buf_mutex);
	fds_cleanup(fds);
	/* signal that we can accept more connections */
	if (fds->nfds <= (unsigned)max_queue)
	    pthread_cond_signal(&acceptdata.cond_nfds);
	new_sd = fds_poll_recv(fds, selfchk ? (int)selfchk : -1, 1, event_wake_recv);
#ifdef _WIN32
	ResetEvent(event_wake_recv);
#else
	if (!fds->nfds) {
	    /* at least the dummy/sync pipe should have remained */
	    logg("!All recv() descriptors gone: fatal\n");
	    pthread_mutex_lock(&exit_mutex);
	    progexit = 1;
	    pthread_mutex_unlock(&exit_mutex);
	    pthread_mutex_unlock(fds->buf_mutex);
	    break;
	}
#endif
	if (new_sd == -1 && errno != EINTR) {
	    logg("!Failed to poll sockets, fatal\n");
	    pthread_mutex_lock(&exit_mutex);
	    progexit = 1;
	    pthread_mutex_unlock(&exit_mutex);
	}


	if(fds->nfds) i = (rr_last + 1) % fds->nfds;
	for (j = 0;  j < fds->nfds && new_sd >= 0; j++, i = (i+1) % fds->nfds) {
	    size_t pos = 0;
	    int error = 0;
	    struct fd_buf *buf = &fds->buf[i];
	    if (!buf->got_newdata)
		continue;

#ifndef _WIN32
	    if (buf->fd == acceptdata.syncpipe_wake_recv[0]) {
		/* dummy sync pipe, just to wake us */
		if (read(buf->fd, buff, sizeof(buff)) < 0) {
		    logg("^Syncpipe read failed\n");
		}
		continue;
	    }
#endif
	    if (buf->got_newdata == -1) {
		if (buf->mode == MODE_WAITREPLY) {
		    logg("$mode WAIT_REPLY -> closed\n");
		    buf->fd = -1;
		    thrmgr_group_terminate(buf->group);
		    thrmgr_group_finished(buf->group, EXIT_ERROR);
		    continue;
		} else {
		    logg("$client read error or EOF on read\n");
		    error = 1;
		}
	    }

	    if (buf->fd != -1 && buf->got_newdata == -2) {
		logg("$Client read timed out\n");
		mdprintf(buf->fd, "COMMAND READ TIMED OUT\n");
		error = 1;
	    }

	    rr_last = i;
	    if (buf->mode == MODE_WAITANCILL) {
		buf->mode = MODE_COMMAND;
		logg("$mode -> MODE_COMMAND\n");
	    }
	    while (!error && buf->fd != -1 && buf->buffer && pos < buf->off &&
		   buf->mode != MODE_WAITANCILL) {
		client_conn_t conn;
		const char *cmd = NULL;
		int rc;
		/* New data available to read on socket. */

		memset(&conn, 0, sizeof(conn));
		conn.scanfd = buf->recvfd;
		buf->recvfd = -1;
		conn.sd = buf->fd;
		conn.options = options;
		conn.opts = opts;
		conn.thrpool = thr_pool;
		conn.engine = engine;
		conn.group = buf->group;
		conn.id = buf->id;
		conn.quota = buf->quota;
		conn.filename = buf->dumpname;
		conn.mode = buf->mode;
		conn.term = buf->term;

		/* Parse & dispatch command */
		cmd = parse_dispatch_cmd(&conn, buf, &pos, &error, opts, readtimeout);

		if (conn.mode == MODE_COMMAND && !cmd)
		    break;
		if (!error) {
		    if (buf->mode == MODE_WAITREPLY && buf->off) {
			/* Client is not supposed to send anything more */
			logg("^Client sent garbage after last command: %lu bytes\n", (unsigned long)buf->off);
			buf->buffer[buf->off] = '\0';
			logg("$Garbage: %s\n", buf->buffer);
			error = 1;
		    } else if (buf->mode == MODE_STREAM) {
			rc = handle_stream(&conn, buf, opts, &error, &pos, readtimeout);
			if (rc == -1)
			    break;
			else
			    continue;
		    }
		}
		if (error && error != CL_ETIMEOUT) {
		    conn_reply_error(&conn, "Error processing command.");
		}
	    }
	    if (error) {
		if (buf->dumpfd != -1) {
		    close(buf->dumpfd);
		    if (buf->dumpname) {
			cli_unlink(buf->dumpname);
			free(buf->dumpname);
		    }
		    buf->dumpfd = -1;
		}
		thrmgr_group_terminate(buf->group);
		if (thrmgr_group_finished(buf->group, EXIT_ERROR)) {
		    if (buf->fd < 0) {
			logg("$Skipping shutdown of bad socket after error (FD %d)\n", buf->fd);
		    }
		    else {
			logg("$Shutting down socket after error (FD %d)\n", buf->fd);
			shutdown(buf->fd, 2);
			closesocket(buf->fd);
		    }
		} else
		    logg("$Socket not shut down due to active tasks\n");
		buf->fd = -1;
	    }
	}
	pthread_mutex_unlock(fds->buf_mutex);

	/* handle progexit */
	pthread_mutex_lock(&exit_mutex);
	if (progexit) {
	    pthread_mutex_unlock(&exit_mutex);
	    pthread_mutex_lock(fds->buf_mutex);
	    for (i=0;i < fds->nfds; i++) {
		if (fds->buf[i].fd == -1)
		    continue;
		thrmgr_group_terminate(fds->buf[i].group);
		if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR)) {
		    logg("$Shutdown closed fd %d\n", fds->buf[i].fd);
		    shutdown(fds->buf[i].fd, 2);
		    closesocket(fds->buf[i].fd);
		    fds->buf[i].fd = -1;
		}
	    }
	    pthread_mutex_unlock(fds->buf_mutex);
	    break;
	}
	pthread_mutex_unlock(&exit_mutex);

	/* SIGHUP */
	if (sighup) {
	    logg("SIGHUP caught: re-opening log file.\n");
	    logg_close();
	    sighup = 0;
	    if(!logg_file && (opt = optget(opts, "LogFile"))->enabled)
		logg_file = opt->strarg;
	}

	/* SelfCheck */
	if(selfchk) {
	    time(&current_time);
	    if((current_time - start_time) >= (time_t)selfchk) {
		if(reload_db(engine, dboptions, opts, TRUE, &ret)) {
		    pthread_mutex_lock(&reload_mutex);
		    reload = 1;
		    pthread_mutex_unlock(&reload_mutex);
		}
		time(&start_time);
	    }
	}

	/* DB reload */
	pthread_mutex_lock(&reload_mutex);
	if(reload) {
	    pthread_mutex_unlock(&reload_mutex);

	    engine = reload_db(engine, dboptions, opts, FALSE, &ret);
	    if(ret) {
		logg("Terminating because of a fatal error.\n");
		if(new_sd >= 0)
		    closesocket(new_sd);
		break;
	    }

	    pthread_mutex_lock(&reload_mutex);
	    reload = 0;
	    time(&reloaded_time);
	    pthread_mutex_unlock(&reload_mutex);

#if defined(FANOTIFY) || defined(CLAMAUTH)
	    if(optget(opts, "ScanOnAccess")->enabled && tharg) {
		tharg->engine = engine;
	    }
#endif
	    time(&start_time);
	} else {
	    pthread_mutex_unlock(&reload_mutex);
	}
    }

    pthread_mutex_lock(&exit_mutex);
    progexit = 1;
    pthread_mutex_unlock(&exit_mutex);
#ifdef _WIN32
    SetEvent(event_wake_accept);
#else
    if (write(acceptdata.syncpipe_wake_accept[1], "", 1) < 0) {
	logg("^Write to syncpipe failed\n");
    }
#endif
    /* Destroy the thread manager.
     * This waits for all current tasks to end
     */
    logg("*Waiting for all threads to finish\n");
    thrmgr_destroy(thr_pool);
#if defined(FANOTIFY) || defined(CLAMAUTH)
    if(optget(opts, "ScanOnAccess")->enabled && tharg) {
	logg("Stopping on-access scan\n");
	pthread_mutex_lock(&logg_mutex);
	pthread_kill(fan_pid, SIGUSR1);
	pthread_mutex_unlock(&logg_mutex);
	pthread_join(fan_pid, NULL);
    free(tharg);
    }
#endif
    if(engine) {
	thrmgr_setactiveengine(NULL);
	cl_engine_free(engine);
    }

    pthread_join(accept_th, NULL);
    fds_free(fds);
    pthread_mutex_destroy(fds->buf_mutex);
    pthread_cond_destroy(&acceptdata.cond_nfds);
#ifdef _WIN32
    CloseHandle(event_wake_accept);
    CloseHandle(event_wake_recv);
#else
    close(acceptdata.syncpipe_wake_accept[1]);
    close(acceptdata.syncpipe_wake_recv[1]);
#endif
    if(dbstat.entries)
	cl_statfree(&dbstat);
    logg("*Shutting down the main socket%s.\n", (nsockets > 1) ? "s" : "");
    for (i = 0; i < nsockets; i++)
	shutdown(socketds[i], 2);

    if((opt = optget(opts, "PidFile"))->enabled) {
	if(unlink(opt->strarg) == -1)
	    logg("!Can't unlink the pid file %s\n", opt->strarg);
	else
	    logg("Pid file removed.\n");
    }

    time(&current_time);
    logg("--- Stopped at %s", cli_ctime(&current_time, timestr, sizeof(timestr)));

    return ret;
} 
Example #12
0
int
main(int argc, char *argv[])
{
	int msize;
	char buf[BUFSIZ+1];
	int i;
	char hostname[256];
	int hflag;
	struct rlimit rl;

	if (argc < 2)
		usage();

	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		rl.rlim_cur = (rl.rlim_max < MAX_THREADS ?
		    rl.rlim_max : MAX_THREADS);
		(void) setrlimit(RLIMIT_NOFILE, &rl);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	(void) gethostname(hostname, sizeof (hostname));

	init_who();

	msize = snprintf(buf, sizeof (buf), "From %s@%s:  ", who, hostname);
	while ((i = getchar()) != EOF) {
		if (msize >= (sizeof (buf) - 1)) {
			(void) fprintf(stderr, "Message too long\n");
			exit(1);
		}
		buf[msize++] = i;
	}
	buf[msize] = '\0';
	path = buf;
	hflag = 1;
	while (argc > 1) {
		if (argv[1][0] == '-') {
			switch (argv[1][1]) {
				case 'h':
					hflag = 1;
					break;
				case 'n':
					hflag = 0;
					break;
				case 'q':
					qflag = 1;
					break;
				default:
					usage();
					break;
			}
			argc--;
			argv++;
			continue;
		}
		if (hflag) {
			doit(argv[1]);
		} else {
			char *machine, *user, *domain;

			(void) setnetgrent(argv[1]);
			while (getnetgrent(&machine, &user, &domain)) {
				if (machine)
					doit(machine);
				else
					doall();
			}
			(void) endnetgrent();
		}
		argc--;
		argv++;
	}
	thr_exit(NULL);
	return (0);
}
Example #13
0
int
main(int argc, char **argv)
{
	int c;
	pid_t pid;
	extern char *optarg;
	sigset_t mask;
	struct sigaction act;

	(void) setlocale(LC_ALL, "");
#ifndef	TEXT_DOMAIN
#define	TEXT_DOMAIN	"SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	if ((prog = strrchr(argv[0], '/')) == NULL) {
		prog = argv[0];
	} else {
		prog++;
	}

	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * process arguments
	 */
	if (argc > 3) {
		usage();
	}
	while ((c = getopt(argc, argv, "d:t:")) != EOF) {
		switch (c) {
		case 'd':
			debug_level = atoi(optarg);
			break;
		case 't':
			idle_timeout = atoi(optarg);
			break;
		case '?':
		default:
			usage();
			/*NOTREACHED*/
		}
	}

	/*
	 * Check permission
	 */
	if (getuid() != 0) {
		(void) fprintf(stderr, gettext("Must be root to run %s\n"),
		    prog);
		exit(EPERM);
	}

	/*
	 * When rcm_daemon is started by a call to librcm, it inherits file
	 * descriptors from the DR initiator making a call. The file
	 * descriptors may correspond to devices that can be removed by DR.
	 * Since keeping them remain opened is problematic, close everything
	 * but stdin/stdout/stderr.
	 */
	closefrom(3);

	/*
	 * When rcm_daemon is started by the caller, it will inherit the
	 * signal block mask.  We unblock all signals to make sure the
	 * signal handling will work normally.
	 */
	(void) sigfillset(&mask);
	(void) thr_sigsetmask(SIG_UNBLOCK, &mask, NULL);

	/*
	 * block SIGUSR1, use it for killing specific threads
	 */
	(void) sigemptyset(&mask);
	(void) sigaddset(&mask, SIGUSR1);
	(void) thr_sigsetmask(SIG_BLOCK, &mask, NULL);

	/*
	 * Setup signal handlers for SIGHUP and SIGUSR1
	 * SIGHUP - causes a "delayed" daemon exit, effectively the same
	 *	as a daemon restart.
	 * SIGUSR1 - causes a thr_exit(). Unblocked in selected threads.
	 */
	act.sa_flags = 0;
	act.sa_handler = catch_sighup;
	(void) sigaction(SIGHUP, &act, NULL);
	act.sa_handler = catch_sigusr1;
	(void) sigaction(SIGUSR1, &act, NULL);

	/*
	 * ignore SIGPIPE so that the rcm daemon does not exit when it
	 * attempts to read or write from a pipe whose corresponding
	 * rcm script process exited.
	 */
	act.sa_handler = SIG_IGN;
	(void) sigaction(SIGPIPE, &act, NULL);

	/*
	 * run in daemon mode
	 */
	if (debug_level < DEBUG_LEVEL_FORK) {
		if (fork()) {
			exit(0);
		}
		detachfromtty();
	}

	/* only one daemon can run at a time */
	if ((pid = enter_daemon_lock()) != getpid()) {
		rcm_log_message(RCM_DEBUG, "%s pid %d already running\n",
		    prog, pid);
		exit(EDEADLK);
	}

	rcm_log_message(RCM_TRACE1, "%s started, debug level = %d\n",
	    prog, debug_level);

	/*
	 * Set daemon state to block RCM requests before rcm_daemon is
	 * fully initialized. See rcmd_thr_incr().
	 */
	rcmd_set_state(RCMD_INIT);

	/*
	 * create rcm_daemon door and set permission to 0400
	 */
	if (create_event_service(RCM_SERVICE_DOOR, event_service) == -1) {
		rcm_log_message(RCM_ERROR,
		    gettext("cannot create door service: %s\n"),
		    strerror(errno));
		rcmd_exit(errno);
	}
	(void) chmod(RCM_SERVICE_DOOR, S_IRUSR);

	init_poll_thread(); /* initialize poll thread related data */

	/*
	 * Initialize database by asking modules to register.
	 */
	rcmd_db_init();

	/*
	 * Initialize locking, including lock recovery in the event of
	 * unexpected daemon failure.
	 */
	rcmd_lock_init();

	/*
	 * Start accepting normal requests
	 */
	rcmd_set_state(RCMD_NORMAL);

	/*
	 * Start cleanup thread
	 */
	rcmd_db_clean();

	/*
	 * Loop within daemon and return after a period of inactivity.
	 */
	rcmd_start_timer(idle_timeout);

	rcmd_cleanup(0);
	return (0);
}
Example #14
0
int
main(int argc, char *argv[])
{
	pid_t pid;
	int c, error;
	struct rlimit rlset;
	char *defval;

	/*
	 * There is no check for non-global zone and Trusted Extensions.
	 * Reparsed works in both of these environments as long as the
	 * services that use reparsed are supported.
	 */

	MyName = argv[0];
	if (geteuid() != 0) {
		syslog(LOG_ERR, "%s must be run as root", MyName);
		exit(1);
	}

	while ((c = getopt(argc, argv, REPARSED_CMD_OPTS)) != EOF) {
		switch (c) {
		case 'v':
			verbose++;
			break;
		default:
			usage();
		}
	}

	daemonize();
	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	(void) _create_daemon_lock(REPARSED, DAEMON_UID, DAEMON_GID);
	(void) enable_extended_FILE_stdio(-1, -1);
	switch (_enter_daemon_lock(REPARSED)) {
	case 0:
		break;
	case -1:
		syslog(LOG_ERR, "Error locking for %s", REPARSED);
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	(void) signal(SIGHUP, warn_hup);

	/*
	 * Make the process a privilege aware daemon.
	 * Only "basic" privileges are required.
	 *
	 */
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
	    (char *)NULL) == -1) {
		syslog(LOG_ERR, "should be run with sufficient privileges");
		exit(3);
	}

	/*
	 * Clear basic privileges not required by reparsed.
	 */
	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);

	return (start_reparsed_svcs());
}
Example #15
0
int
main(int argc, char **argv)
{
	int rc = 0;
	int opt;
	struct rlimit rlim;

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	if ((command = strrchr(argv[0], '/')) != NULL)
		command++;
	else
		command = argv[0];

	while ((opt = getopt(argc, argv, "lDMNPevs:xS")) != EOF) {
		switch (opt) {
		case 'l':
			list = B_TRUE;
			break;
		case 'D':
			set = B_TRUE;
			Don = B_TRUE;
			break;
		case 'M':
			mac_aware = B_TRUE;
			break;
		case 'N':
			set = B_TRUE;
			Doff = B_TRUE;
			break;
		case 'P':
			set = B_TRUE;
			pfexec = B_TRUE;
			break;
		case 'e':
			exec = B_TRUE;
			break;
		case 'S':
			mode = PRIV_STR_SHORT;
			break;
		case 'v':
			verb = B_TRUE;
			mode = PRIV_STR_LIT;
			break;
		case 's':
			set = B_TRUE;
			if ((rc = parsespec(optarg)) != 0)
				return (rc);
			break;
		case 'x':
			set = B_TRUE;
			xpol = B_TRUE;
			break;
		default:
			usage();
			/*NOTREACHED*/
		}
	}

	argc -= optind;
	argv += optind;

	if ((argc < 1 && !list) || Doff && Don || list && (set || exec) ||
	    (mac_aware && !exec))
		usage();

	/*
	 * Make sure we'll have enough file descriptors to handle a target
	 * that has many many mappings.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
		rlim.rlim_cur = rlim.rlim_max;
		(void) setrlimit(RLIMIT_NOFILE, &rlim);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	if (exec) {
		privupdate_self();
		rc = execvp(argv[0], &argv[0]);
		(void) fprintf(stderr, "%s: %s: %s\n", command, argv[0],
		    strerror(errno));
	} else if (list) {
		rc = dumppriv(argv);
	} else {
		while (argc-- > 0)
			rc += look(*argv++);
	}

	return (rc);
}