コード例 #1
0
ファイル: cf-serverd-functions.c プロジェクト: cf-gary/core
int InitServer(size_t queue_size)
{
    int sd = -1;

    if ((sd = OpenReceiverChannel()) == -1)
    {
        CfOut(cf_error, "", "Unable to start server");
        exit(1);
    }

    if (listen(sd, queue_size) == -1)
    {
        CfOut(cf_error, "listen", "listen failed");
        exit(1);
    }

    return sd;
}
コード例 #2
0
static int OpenReceiverChannel(void)
{
    struct addrinfo *response = NULL, *ap;
    struct addrinfo query = {
        .ai_flags = AI_PASSIVE,
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
    };

    /* Listen to INADDR(6)_ANY if BINDINTERFACE unset. */
    char *ptr = NULL;
    if (BINDINTERFACE[0] != '\0')
    {
        ptr = BINDINTERFACE;
    }

    char servname[PRINTSIZE(CFENGINE_PORT)];
    xsnprintf(servname, sizeof(servname), "%d", CFENGINE_PORT);

    /* Resolve listening interface. */
    int gres;
    if ((gres = getaddrinfo(ptr, servname, &query, &response)) != 0)
    {
        Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)",
            gai_strerror(gres));
        if (response)
        {
            freeaddrinfo(response);
        }
        return -1;
    }

    int sd = -1;
    for (ap = response; ap != NULL; ap = ap->ai_next)
    {
        sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
        if (sd == -1)
        {
            continue;
        }

       #ifdef IPV6_V6ONLY
        /* Properly implemented getaddrinfo(AI_PASSIVE) should return the IPV6
           loopback address first. Some platforms (notably Windows) don't
           listen to both address families when binding to it and need this
           flag. Some other platforms won't even honour this flag
           (openbsd). */
        if (BINDINTERFACE[0] == '\0' && ap->ai_family == AF_INET6)
        {
            int no = 0;
            if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY,
                           &no, sizeof(no)) == -1)
            {
                Log(LOG_LEVEL_VERBOSE,
                    "Failed to clear IPv6-only flag on listening socket"
                    " (setsockopt: %s)",
                    GetErrorStr());
            }
        }
        #endif

        int yes = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
                       &yes, sizeof(yes)) == -1)
        {
            Log(LOG_LEVEL_VERBOSE,
                "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)",
                GetErrorStr());
        }

        struct linger cflinger = {
            .l_onoff = 1,
            .l_linger = 60
        };
        if (setsockopt(sd, SOL_SOCKET, SO_LINGER,
                       &cflinger, sizeof(cflinger)) == -1)
        {
            Log(LOG_LEVEL_INFO,
                "Socket option SO_LINGER was not accepted. (setsockopt: %s)",
                GetErrorStr());
        }

        if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1)
        {
            if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
            {
                /* Convert IP address to string, no DNS lookup performed. */
                char txtaddr[CF_MAX_IP_LEN] = "";
                getnameinfo(ap->ai_addr, ap->ai_addrlen,
                            txtaddr, sizeof(txtaddr),
                            NULL, 0, NI_NUMERICHOST);
                Log(LOG_LEVEL_DEBUG, "Bound to address '%s' on '%s' = %d", txtaddr,
                    CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS);
            }
            break;
        }
        Log(LOG_LEVEL_INFO,
            "Could not bind server address. (bind: %s)",
            GetErrorStr());
        cf_closesocket(sd);
        sd = -1;
    }

    assert(response != NULL);               /* getaddrinfo() was successful */
    freeaddrinfo(response);
    return sd;
}

static int InitServer(size_t queue_size)
{
    int sd = OpenReceiverChannel();

    if (sd == -1)
    {
        Log(LOG_LEVEL_ERR, "Unable to start server");
    }
    else if (listen(sd, queue_size) == -1)
    {
        Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr());
        cf_closesocket(sd);
    }
    else
    {
        return sd;
    }

    exit(EXIT_FAILURE);
}
コード例 #3
0
ファイル: cf-serverd-functions.c プロジェクト: tzz/core
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;
}
コード例 #4
0
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config)
{
    int sd = -1, sd_reply;
    fd_set rset;
    struct timeval timeout;
    int ret_val;
    CfLock thislock;
    time_t starttime = time(NULL), last_collect = 0;

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

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

    sd = SetServerListenState(ctx, QUEUESIZE);

    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;
    }

    Log(LOG_LEVEL_INFO, "cf-serverd starting %.24s", ctime(&starttime));

    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(0);
    }

    if (!NO_FORK)
    {
        ActAsDaemon(sd);
    }

#endif /* !__MINGW32__ */

    WritePID("cf-serverd.pid");

/* Andrew Stribblehill <*****@*****.**> -- close sd on exec */
#ifndef __MINGW32__
    fcntl(sd, F_SETFD, FD_CLOEXEC);
#endif

    while (!IsPendingTermination())
    {
        time_t now = time(NULL);

        /* 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);
            }
            ThreadUnlock(cft_server_children);
        }

        // Check whether we should try to establish peering with a hub

        if ((COLLECT_INTERVAL > 0) && ((now - last_collect) > COLLECT_INTERVAL))
        {
            TryCollectCall();
            last_collect = now;
            continue;
        }

        /* check if listening is working */
        if (sd != -1)
        {
            // Look for normal incoming service requests

            FD_ZERO(&rset);
            FD_SET(sd, &rset);

            /* Set 1 second timeout for select, so that signals are handled in
             * a timely manner */
            timeout.tv_sec = 1;
            timeout.tv_usec = 0;

            Log(LOG_LEVEL_DEBUG, "Waiting at incoming select...");

            ret_val = select((sd + 1), &rset, NULL, NULL, &timeout);

            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;
            }

            Log(LOG_LEVEL_VERBOSE, "Accepting a connection");

            if ((sd_reply = accept(sd, (struct sockaddr *) &cin, &addrlen)) != -1)
            {
                /* 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);

                ServerEntryPoint(ctx, sd_reply, ipaddr);
            }
        }
    }

    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(1);
    }

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

    return sd;
}