Пример #1
0
/* Initializes 'buffer' with 'n' bytes of high-quality random numbers.  Returns
 * 0 if successful, otherwise a positive errno value or EOF on error. */
int
get_entropy(void *buffer, size_t n)
{
#ifndef _WIN32
    size_t bytes_read;
    int error;
    int fd;

    fd = open(urandom, O_RDONLY);
    if (fd < 0) {
        VLOG_ERR("%s: open failed (%s)", urandom, ovs_strerror(errno));
        return errno ? errno : EINVAL;
    }

    error = read_fully(fd, buffer, n, &bytes_read);
    close(fd);

    if (error) {
        VLOG_ERR("%s: read error (%s)", urandom, ovs_retval_to_string(error));
    }
#else
    int error = 0;
    HCRYPTPROV   crypt_prov = 0;

    CryptAcquireContext(&crypt_prov, NULL, NULL,
                        PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!CryptGenRandom(crypt_prov, n, buffer)) {
        VLOG_ERR("CryptGenRandom: read error (%s)", ovs_lasterror_to_string());
        error = EINVAL;
    }

    CryptReleaseContext(crypt_prov, 0);
#endif
    return error;
}
/* In case of an unexpected termination, configure the action to be
 * taken. */
static void
set_config_failure_actions()
{
    /* In case of a failure, restart the process the first two times
     * After 'dwResetPeriod', the failure count is reset. */
    SC_ACTION fail_action[3] = {
        {SC_ACTION_RESTART, 0},
        {SC_ACTION_RESTART, 0},
        {SC_ACTION_NONE, 0}
    };
    SERVICE_FAILURE_ACTIONS service_fail_action;

    /* Reset failure count after (in seconds). */
    service_fail_action.dwResetPeriod = 10;

    /* Reboot message. */
    service_fail_action.lpRebootMsg = NULL;

    /* The command line of the process. */
    service_fail_action.lpCommand = NULL;

    /* Number of elements in 'fail_actions'. */
    service_fail_action.cActions = sizeof(fail_action)/sizeof(fail_action[0]);

    /* A pointer to an array of SC_ACTION structures. */
    service_fail_action.lpsaActions = fail_action;

    if (!ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS,
                              &service_fail_action)) {
        char *msg_buf = ovs_lasterror_to_string();
        VLOG_FATAL("Failed to configure service fail actions (%s).", msg_buf);
    }
}
/* Check whether 'program_name' has been created as a service. */
static void
check_service()
{
    /* Establish a connection to the local service control manager. */
    manager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
    if (!manager) {
        char *msg_buf = ovs_lasterror_to_string();
        VLOG_FATAL("Failed to open the service control manager (%s).",
                   msg_buf);
    }

    service = OpenService(manager, program_name, SERVICE_ALL_ACCESS);
    if (!service) {
        char *msg_buf = ovs_lasterror_to_string();
        VLOG_FATAL("Failed to open service (%s).", msg_buf);
    }
}
Пример #4
0
int
getrusage(int who, struct rusage *usage)
{
    FILETIME creation_time, exit_time, kernel_time, user_time;
    PROCESS_MEMORY_COUNTERS pmc;

    memset(usage, 0, sizeof(struct rusage));

    if (who == RUSAGE_SELF) {
        if (!GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
                             &kernel_time, &user_time)) {
            VLOG_ERR("failed at GetProcessTimes: %s",
                      ovs_lasterror_to_string());
            return -1;
        }

        if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
            VLOG_ERR("failed at GetProcessMemoryInfo: %s",
                      ovs_lasterror_to_string());
            return -1;
        }

        usage_to_timeval(&kernel_time, &usage->ru_stime);
        usage_to_timeval(&user_time, &usage->ru_utime);
        usage->ru_majflt = pmc.PageFaultCount;
        usage->ru_maxrss = pmc.PeakWorkingSetSize / 1024;
        return 0;
    } else if (who == RUSAGE_THREAD) {
        if (!GetThreadTimes(GetCurrentThread(), &creation_time, &exit_time,
                            &kernel_time, &user_time)) {
            VLOG_ERR("failed at GetThreadTimes: %s",
                      ovs_lasterror_to_string());
            return -1;
        }
        usage_to_timeval(&kernel_time, &usage->ru_stime);
        usage_to_timeval(&user_time, &usage->ru_utime);
        return 0;
    } else {
        return -1;
    }
}
Пример #5
0
/* Initializes the fatal signal handling module.  Calling this function is
 * optional, because calling any other function in the module will also
 * initialize it.  However, in a multithreaded program, the module must be
 * initialized while the process is still single-threaded. */
void
fatal_signal_init(void)
{
    static bool inited = false;

    if (!inited) {
        size_t i;

        assert_single_threaded();
        inited = true;

        ovs_mutex_init_recursive(&mutex);
#ifndef _WIN32
        xpipe_nonblocking(signal_fds);
#else
        wevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!wevent) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to create a event (%s).", msg_buf);
        }

        /* Register a function to handle Ctrl+C. */
        SetConsoleCtrlHandler(ConsoleHandlerRoutine, true);
#endif

        for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
            int sig_nr = fatal_signals[i];
#ifndef _WIN32
            struct sigaction old_sa;

            xsigaction(sig_nr, NULL, &old_sa);
            if (old_sa.sa_handler == SIG_DFL
                && signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#else
            if (signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#endif
        }
        atexit(fatal_signal_atexit_handler);
    }
}
Пример #6
0
void
daemonize_complete(void)
{
    /* If running as a child because '--detach' option was specified,
     * communicate with the parent to inform that the child is ready. */
    if (detached) {
        int error;

        close_standard_fds();

        error = WriteFile(write_handle, "a", 1, NULL, NULL);
        if (!error) {
            VLOG_FATAL("Failed to communicate with the parent (%s)",
                       ovs_lasterror_to_string());
        }
    }

    service_complete();
}
/* Registers the call-back and configures the actions in case of a failure
 * with the Windows services manager. */
void
service_start(int *argcp, char **argvp[])
{
    int argc = *argcp;
    char **argv = *argvp;
    int i;
    SERVICE_TABLE_ENTRY service_table[] = {
        {(LPTSTR)program_name, (LPSERVICE_MAIN_FUNCTION)main},
        {NULL, NULL}
    };

    /* 'detached' is 'false' when service_start() is called the first time.
     * It is 'true', when it is called the second time by the Windows services
     * manager. */
    if (detached) {
        init_service_status();

        wevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!wevent) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to create a event (%s).", msg_buf);
        }

        poll_fd_wait_event(0, wevent, POLLIN);

        /* Register the control handler. This function is called by the service
         * manager to stop the service. */
        hstatus = RegisterServiceCtrlHandler(program_name,
                                         (LPHANDLER_FUNCTION)control_handler);
        if (!hstatus) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to register the service control handler (%s).",
                        msg_buf);
        }

        if (monitor) {
            set_config_failure_actions();
        }

        /* When the service control manager does the call back, it does not
         * send the same arguments as sent to the main function during the
         * service start. So, use the arguments passed over during the first
         * time. */
        *argcp = sargc;
        *argvp = *sargvp;

        /* XXX: Windows implementation cannot have a unixctl commands in the
        * traditional sense of unix domain sockets. If an implementation is
        * done that involves 'unixctl' vlog commands the following call is
        * needed to make sure that the unixctl commands for vlog get
        * registered in a daemon, even before the first log message. */
        vlog_init();

        return;
    }

    assert_single_threaded();

    /* A reference to arguments passed to the main function the first time.
     * We need it after the call-back from service control manager. */
    sargc = argc;
    sargvp = argvp;

    /* We are only interested in the '--service' and '--service-monitor'
     * options before the call-back from the service control manager. */
    for (i = 0; i < argc; i ++) {
        if (!strcmp(argv[i], "--service")) {
            detach = true;
        } else if (!strcmp(argv[i], "--service-monitor")) {
            monitor = true;
        }
    }

    /* If '--service' is not a command line option, run in foreground. */
    if (!detach) {
        return;
    }

    /* If we have been configured to run as a service, then that service
     * should already have been created either manually or through a start up
     * script. */
    check_service();

    detached = true;

    /* StartServiceCtrlDispatcher blocks and returns after the service is
     * stopped. */
    if (!StartServiceCtrlDispatcher(service_table)) {
        char *msg_buf = ovs_lasterror_to_string();
        VLOG_FATAL("Failed at StartServiceCtrlDispatcher (%s)", msg_buf);
    }
    exit(0);
}
Пример #8
0
/* If one of the command line option is "--detach", creates
 * a new process in case of parent, waits for child to start and exits.
 * In case of the child, returns. */
static bool
detach_process(int argc, char *argv[])
{
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    HANDLE read_pipe, write_pipe;
    char *buffer;
    int error, i;
    char ch;

    /* We are only interested in the '--detach' and '--pipe-handle'. */
    for (i = 0; i < argc; i ++) {
        if (!strcmp(argv[i], "--detach")) {
            detach = true;
        } else if (!strncmp(argv[i], "--pipe-handle", 13)) {
            /* If running as a child, return. */
            detached = true;
            return true;
        }
    }

    /* Nothing to do if the option --detach is not set. */
    if (!detach) {
        return false;
    }

    /* Set the security attribute such that a process created will
     * inherit the pipe handles. */
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    /* Create an anonymous pipe to communicate with the child. */
    error = CreatePipe(&read_pipe, &write_pipe, &sa, 0);
    if (!error) {
        VLOG_FATAL("CreatePipe failed (%s)", ovs_lasterror_to_string());
    }

    GetStartupInfo(&si);

    /* To the child, we pass an extra argument '--pipe-handle=write_pipe' */
    buffer = xasprintf("%s %s=%ld", GetCommandLine(), "--pipe-handle",
                       write_pipe);

    /* Create a detached child */
    error = CreateProcess(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS,
                          NULL, NULL, &si, &pi);
    if (!error) {
        VLOG_FATAL("CreateProcess failed (%s)", ovs_lasterror_to_string());
    }

    /* Close one end of the pipe in the parent. */
    CloseHandle(write_pipe);

    /* Block and wait for child to say it is ready. */
    error = ReadFile(read_pipe, &ch, 1, NULL, NULL);
    if (!error) {
        VLOG_FATAL("Failed to read from child (%s)",
                   ovs_lasterror_to_string());
    }
    /* The child has successfully started and is ready. */
    exit(0);
}