Пример #1
0
/* Set up standard signal-handling. */
static void InitSignals()
{
    MakeSignalPipe();

    signal(SIGINT, HandleSignalsForDaemon);
    signal(SIGTERM, HandleSignalsForDaemon);
    signal(SIGHUP, HandleSignalsForDaemon);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGUSR1, HandleSignalsForDaemon);
    signal(SIGUSR2, HandleSignalsForDaemon);
}
Пример #2
0
int main(int argc, char *argv[])
{
    signal(SIGINT, HandleSignal);
    signal(SIGTERM, HandleSignal);

    Log(LOG_LEVEL_VERBOSE, "Starting cf-testd");
    cfnet_init(NULL, NULL);
    MakeSignalPipe();

    long n_threads = 1;
    CFTestD_Config *config = CFTestD_CheckOpts(argc, argv, &n_threads);
    if (config->address == NULL)
    {
        /* default to localhost */
        config->address = xstrdup("127.0.0.1");
    }

    CFTestD_Config **thread_configs = (CFTestD_Config**) xcalloc(n_threads, sizeof(CFTestD_Config*));
    for (int i = 0; i < n_threads; i++)
    {
        thread_configs[i] = (CFTestD_Config*) xmalloc(sizeof(CFTestD_Config));

        if (config->report_file != NULL && strstr(config->report_file, "%d") != NULL)
        {
            /* replace the '%d' with the thread number */
            asprintf(&(thread_configs[i]->report_file), config->report_file, i);
        }
        else
        {
            thread_configs[i]->report_file = SafeStringDuplicate(config->report_file);
        }

        if (config->key_file != NULL && strstr(config->key_file, "%d") != NULL)
        {
            /* replace the '%d' with the thread number */
            asprintf(&(thread_configs[i]->key_file), config->key_file, i);
        }
        else
        {
            thread_configs[i]->key_file = SafeStringDuplicate(config->key_file);
        }

        if (i == 0)
        {
            thread_configs[i]->address = xstrdup(config->address);
        }
        else
        {
            thread_configs[i]->address = IncrementIPaddress(thread_configs[i-1]->address);
        }
    }

    CFTestD_ConfigDestroy(config);

    bool failure = false;
    for (int i = 0; !failure && (i < n_threads); i++)
    {
        int ret = pthread_create(&(thread_configs[i]->t_id), NULL, CFTestD_ServeReport, thread_configs[i]);
        if (ret != 0)
        {
            Log(LOG_LEVEL_ERR, "Failed to create a new thread nr. %d: %s\n", i, strerror(ret));
            failure = true;
        }
    }

    if (failure)
    {
        return EXIT_FAILURE;
    }

    for (int i = 0; i < n_threads; i++)
    {
        int ret = pthread_join(thread_configs[i]->t_id, NULL);
        if (ret != 0)
        {
            Log(LOG_LEVEL_ERR, "Failed to join the thread nr. %d: %s\n", i, strerror(ret));
        }
        else
        {
            failure = failure && (thread_configs[i]->ret != 0);
        }
        CFTestD_ConfigDestroy(thread_configs[i]);
    }

    return failure ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #3
0
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config)
{
    int sd = -1;
    fd_set rset;
    int ret_val;
    CfLock thislock;
    time_t last_policy_reload = 0;
    extern int COLLECT_WINDOW;

    struct sockaddr_storage cin;
    socklen_t addrlen = sizeof(cin);

    MakeSignalPipe();

    signal(SIGINT, HandleSignalsForDaemon);
    signal(SIGTERM, HandleSignalsForDaemon);
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGUSR1, HandleSignalsForDaemon);
    signal(SIGUSR2, HandleSignalsForDaemon);

    ServerTLSInitialize();

    sd = SetServerListenState(ctx, QUEUESIZE, SERVER_LISTEN, &InitServer);

    TransactionContext tc = {
        .ifelapsed = 0,
        .expireafter = 1,
    };

    Policy *server_cfengine_policy = PolicyNew();
    Promise *pp = NULL;
    {
        Bundle *bp = PolicyAppendBundle(server_cfengine_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL);
        PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine");

        pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL);
    }
    assert(pp);

    thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false);

    if (thislock.lock == NULL)
    {
        PolicyDestroy(server_cfengine_policy);
        return;
    }

    if (sd != -1)
    {
        Log(LOG_LEVEL_VERBOSE, "Listening for connections ...");
    }

#ifdef __MINGW32__

    if (!NO_FORK)
    {
        Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground");
    }

#else /* !__MINGW32__ */

    if ((!NO_FORK) && (fork() != 0))
    {
        _exit(EXIT_SUCCESS);
    }

    if (!NO_FORK)
    {
        ActAsDaemon();
    }

#endif /* !__MINGW32__ */

    WritePID("cf-serverd.pid");

/* Andrew Stribblehill <*****@*****.**> -- close sd on exec */
#ifndef __MINGW32__
    fcntl(sd, F_SETFD, FD_CLOEXEC);
#endif
    CollectCallStart(COLLECT_INTERVAL);
    while (!IsPendingTermination())
    {
        /* Note that this loop logic is single threaded, but ACTIVE_THREADS
           might still change in threads pertaining to service handling */

        if (ThreadLock(cft_server_children))
        {
            if (ACTIVE_THREADS == 0)
            {
                CheckFileChanges(ctx, policy, config, &last_policy_reload);
            }
            ThreadUnlock(cft_server_children);
        }

        // Check whether we have established peering with a hub
        if (CollectCallHasPending())
        {
            int waiting_queue = 0;
            int new_client = CollectCallGetPending(&waiting_queue);
            if (waiting_queue > COLLECT_WINDOW)
            {
                Log(LOG_LEVEL_INFO, "Closing collect call because it would take"
                                    "longer than the allocated window [%d]", COLLECT_WINDOW);
            }
            ConnectionInfo *info = ConnectionInfoNew();
            if (info)
            {
                ConnectionInfoSetSocket(info, new_client);
                ServerEntryPoint(ctx, POLICY_SERVER, info);
                CollectCallMarkProcessed();
            }
        }
        else
        {
            /* check if listening is working */
            if (sd != -1)
            {
                // Look for normal incoming service requests
                int signal_pipe = GetSignalPipe();
                FD_ZERO(&rset);
                FD_SET(sd, &rset);
                FD_SET(signal_pipe, &rset);

                Log(LOG_LEVEL_DEBUG, "Waiting at incoming select...");
                struct timeval timeout = {
                    .tv_sec = 60,
                    .tv_usec = 0
                };
                int max_fd = (sd > signal_pipe) ? (sd + 1) : (signal_pipe + 1);
                ret_val = select(max_fd, &rset, NULL, NULL, &timeout);

                // Empty the signal pipe. We don't need the values.
                unsigned char buf;
                while (recv(signal_pipe, &buf, 1, 0) > 0) {}

                if (ret_val == -1)      /* Error received from call to select */
                {
                    if (errno == EINTR)
                    {
                        continue;
                    }
                    else
                    {
                        Log(LOG_LEVEL_ERR, "select failed. (select: %s)", GetErrorStr());
                        exit(1);
                    }
                }
                else if (!ret_val) /* No data waiting, we must have timed out! */
                {
                    continue;
                }

                if (FD_ISSET(sd, &rset))
                {
                    int new_client = accept(sd, (struct sockaddr *)&cin, &addrlen);
                    if (new_client == -1)
                    {
                        continue;
                    }
                    /* Just convert IP address to string, no DNS lookup. */
                    char ipaddr[CF_MAX_IP_LEN] = "";
                    getnameinfo((struct sockaddr *) &cin, addrlen,
                                ipaddr, sizeof(ipaddr),
                                NULL, 0, NI_NUMERICHOST);

                    ConnectionInfo *info = ConnectionInfoNew();
                    if (info)
                    {
                        ConnectionInfoSetSocket(info, new_client);
                        ServerEntryPoint(ctx, ipaddr, info);
                    }
                }
            }
        }
    }
    CollectCallStop();
    PolicyDestroy(server_cfengine_policy);
}

/*********************************************************************/
/* Level 2                                                           */
/*********************************************************************/

int InitServer(size_t queue_size)
{
    int sd = -1;

    if ((sd = OpenReceiverChannel()) == -1)
    {
        Log(LOG_LEVEL_ERR, "Unable to start server");
        exit(EXIT_FAILURE);
    }

    if (listen(sd, queue_size) == -1)
    {
        Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr());
        exit(EXIT_FAILURE);
    }

    return sd;
}