void StartServer(Policy *policy, GenericAgentConfig *config, const ReportContext *report_context) { int sd = -1, sd_reply; fd_set rset; struct timeval timeout; int ret_val; Promise *pp = NewPromise("server_cfengine", config->input_file); Attributes dummyattr = { {0} }; CfLock thislock; time_t starttime = time(NULL), last_collect = 0; #if defined(HAVE_GETADDRINFO) socklen_t addrlen = sizeof(struct sockaddr_in6); struct sockaddr_in6 cin; #else socklen_t addrlen = sizeof(struct sockaddr_in); struct sockaddr_in cin; #endif memset(&dummyattr, 0, sizeof(dummyattr)); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); sd = SetServerListenState(QUEUESIZE); dummyattr.transaction.ifelapsed = 0; dummyattr.transaction.expireafter = 1; thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false); if (thislock.lock == NULL) { return; } CfOut(cf_inform, "", "cf-serverd starting %.24s\n", cf_ctime(&starttime)); if (sd != -1) { CfOut(cf_verbose, "", "Listening for connections ...\n"); } #ifdef __MINGW32__ if (!NO_FORK) { CfOut(cf_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(&policy, config, report_context); } 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); timeout.tv_sec = 10; /* Set a 10 second timeout for select */ timeout.tv_usec = 0; CfDebug(" -> Waiting at incoming select...\n"); ret_val = select((sd + 1), &rset, NULL, NULL, &timeout); if (ret_val == -1) /* Error received from call to select */ { if (errno == EINTR) { continue; } else { CfOut(cf_error, "select", "select failed"); exit(1); } } else if (!ret_val) /* No data waiting, we must have timed out! */ { continue; } CfOut(cf_verbose, "", " -> Accepting a connection\n"); if ((sd_reply = accept(sd, (struct sockaddr *) &cin, &addrlen)) != -1) { char ipaddr[CF_MAXVARSIZE]; memset(ipaddr, 0, CF_MAXVARSIZE); ThreadLock(cft_getaddr); snprintf(ipaddr, CF_MAXVARSIZE - 1, "%s", sockaddr_ntop((struct sockaddr *) &cin)); ThreadUnlock(cft_getaddr); ServerEntryPoint(sd_reply, ipaddr, SV); } } } }
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; }