void *sockaddr_pton(int af,void *src) { int err; #if defined(HAVE_GETADDRINFO) static struct sockaddr_in6 adr6; #endif static struct sockaddr_in adr; switch (af) { case AF_INET: memset(&adr,0,sizeof(adr)); adr.sin_family = AF_INET; adr.sin_addr.s_addr = inet_addr(src); Debug("Coded ipv4 %s\n",sockaddr_ntop((struct sockaddr *)&adr)); return (void *)&adr; #if defined(HAVE_GETADDRINFO) case AF_INET6: memset(&adr6,0,sizeof(adr6)); adr6.sin6_family = AF_INET6; err = inet_pton(AF_INET6,src,&(adr6.sin6_addr)); if (err > 0) { Debug("Coded ipv6 %s\n",sockaddr_ntop((struct sockaddr *)&adr6)); return (void *)&adr6; } else { return NULL; } break; #endif default: Debug("Address family was %d\n",af); FatalError("Software failure in sockaddr_pton\n"); } return NULL; }
const char *Hostname2IPString(const char *hostname) { static char ipbuffer[CF_SMALLBUF]; #if defined(HAVE_GETADDRINFO) int err; struct addrinfo query, *response, *ap; memset(&query, 0, sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; memset(ipbuffer, 0, CF_SMALLBUF - 1); if ((err = getaddrinfo(hostname, NULL, &query, &response)) != 0) { CfOut(cf_inform, "", "Unable to lookup hostname (%s) or cfengine service: %s", hostname, gai_strerror(err)); return hostname; } for (ap = response; ap != NULL; ap = ap->ai_next) { strncpy(ipbuffer, sockaddr_ntop(ap->ai_addr), 64); CfDebug("Found address (%s) for host %s\n", ipbuffer, hostname); if (strlen(ipbuffer) == 0) { snprintf(ipbuffer, CF_SMALLBUF - 1, "Empty IP result for %s", hostname); } freeaddrinfo(response); return ipbuffer; } #else struct hostent *hp; struct sockaddr_in cin; memset(&cin, 0, sizeof(cin)); memset(ipbuffer, 0, CF_SMALLBUF - 1); if ((hp = gethostbyname(hostname)) != NULL) { cin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; strncpy(ipbuffer, inet_ntoa(cin.sin_addr), CF_SMALLBUF - 1); CfOut(cf_verbose, "", "Found address (%s) for host %s\n", ipbuffer, hostname); return ipbuffer; } #endif snprintf(ipbuffer, CF_SMALLBUF - 1, "Unknown IP %s", hostname); return ipbuffer; }
char * Hostname2IPString(char *hostname) { static char ipbuffer[65]; int err; #if defined(HAVE_GETADDRINFO) && !defined(DARWIN) struct addrinfo query, *response, *ap; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; memset(ipbuffer,0,63); if ((err = getaddrinfo(hostname,NULL,&query,&response)) != 0) { snprintf(g_output,CF_BUFSIZE, "Unable to lookup hostname (%s) or cfengine service: %s", hostname,gai_strerror(err)); CfLog(cferror,g_output,""); return hostname; } for (ap = response; ap != NULL; ap = ap->ai_next) { strncpy(ipbuffer,sockaddr_ntop(ap->ai_addr),64); Debug("Found address (%s) for host %s\n",ipbuffer,hostname); freeaddrinfo(response); return ipbuffer; } #else struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); memset(ipbuffer,0,63); if ((hp = gethostbyname(hostname)) != NULL) { cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; strncpy(ipbuffer,inet_ntoa(cin.sin_addr),63); Verbose("Found address (%s) for host %s\n",ipbuffer,hostname); return ipbuffer; } #endif snprintf(ipbuffer,63,"Unknown IP %s",hostname); return ipbuffer; }
bool sockaddr_pton(int af, const void *src, void *genaddr) { switch (af) { case AF_INET: { struct sockaddr_in *addr = (struct sockaddr_in *) genaddr; memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr(src); CfDebug("Coded ipv4 %s\n", sockaddr_ntop((struct sockaddr *) genaddr)); return addr->sin_addr.s_addr != INADDR_NONE; } #if defined(HAVE_GETADDRINFO) case AF_INET6: { int err; struct sockaddr_in6 *addr = (struct sockaddr_in6 *) genaddr; memset(addr, 0, sizeof(struct sockaddr_in6)); addr->sin6_family = AF_INET6; err = inet_pton(AF_INET6, src, &addr->sin6_addr); CfDebug("Coded ipv6 %s\n", sockaddr_ntop((struct sockaddr *) genaddr)); return err > 0; } #endif default: CfDebug("Address family was %d\n", af); ProgrammingError("Software failure in sockaddr_pton\n"); } }
int revname(int *lookup, struct sockaddr_storage *addr, char *target, size_t target_size, int rvnfd) { struct rvn rpkt; int br; struct sockaddr_un su; socklen_t fl; fd_set sockset; struct timeval tv; int sstat = 0; memset(target, 0, target_size); if (*lookup) { if (rvnfd > 0) { su.sun_family = AF_UNIX; strcpy(su.sun_path, IPTSOCKNAME); rpkt.type = RVN_REQUEST; sockaddr_copy(&rpkt.addr, addr); sendto(rvnfd, &rpkt, sizeof(struct rvn), 0, (struct sockaddr *) &su, sizeof(su.sun_family) + strlen(su.sun_path)); fl = sizeof(su.sun_family) + strlen(su.sun_path); do { tv.tv_sec = 10; tv.tv_usec = 0; FD_ZERO(&sockset); FD_SET(rvnfd, &sockset); do { sstat = select(rvnfd + 1, &sockset, NULL, NULL, &tv); } while ((sstat < 0) && (errno == EINTR)); if (FD_ISSET(rvnfd, &sockset)) br = recvfrom(rvnfd, &rpkt, sizeof(struct rvn), 0, (struct sockaddr *) &su, &fl); else br = -1; } while ((br < 0) && (errno == EINTR)); if (br < 0) { sockaddr_ntop(addr, target, target_size); printipcerr(); *lookup = 0; return RESOLVED; } strncpy(target, rpkt.fqdn, target_size - 1); return (rpkt.ready); } else { struct hostent *he = sockaddr_gethostbyaddr(addr); if (he == NULL) { sockaddr_ntop(addr, target, target_size); } else { strncpy(target, he->h_name, target_size - 1); } return RESOLVED; } } else { sockaddr_ntop(addr, target, target_size); return RESOLVED; } return NOTRESOLVED; }
void RemoteSysLog(int log_priority, const char *log_string) { int sd, rfc3164_len = 1024; char message[CF_BUFSIZE]; time_t now = time(NULL); int pri = log_priority | FACILITY; #if defined(HAVE_GETADDRINFO) int err; struct addrinfo query, *response, *ap; char strport[CF_MAXVARSIZE]; snprintf(strport, CF_MAXVARSIZE - 1, "%u", (unsigned) SYSLOG_PORT); memset(&query, 0, sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_DGRAM; if ((err = getaddrinfo(SYSLOG_HOST, strport, &query, &response)) != 0) { CfOut(OUTPUT_LEVEL_INFORM, "", "Unable to find syslog_host or service: (%s/%s) %s", SYSLOG_HOST, strport, gai_strerror(err)); return; } for (ap = response; ap != NULL; ap = ap->ai_next) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Connect to syslog %s = %s on port %s\n", SYSLOG_HOST, sockaddr_ntop(ap->ai_addr), strport); if ((sd = socket(ap->ai_family, ap->ai_socktype, IPPROTO_UDP)) == -1) { CfOut(OUTPUT_LEVEL_INFORM, "socket", "Couldn't open a socket"); continue; } else { char timebuffer[26]; snprintf(message, rfc3164_len, "<%u>%.15s %s %s", pri, cf_strtimestamp_local(now, timebuffer) + 4, VFQNAME, log_string); if (sendto(sd, message, strlen(message), 0, ap->ai_addr, ap->ai_addrlen) == -1) { CfOut(OUTPUT_LEVEL_VERBOSE, "sendto", " -> Couldn't send \"%s\" to syslog server \"%s\"\n", message, SYSLOG_HOST); } else { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Syslog message: \"%s\" to server \"%s\"\n", message, SYSLOG_HOST); } close(sd); return; } } #else struct sockaddr_in addr; char timebuffer[26]; sockaddr_pton(AF_INET, SYSLOG_HOST, &addr); addr.sin_port = htons(SYSLOG_PORT); if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "sendto", " !! Unable to send syslog datagram"); return; } snprintf(message, rfc3164_len, "<%u>%.15s %s %s", pri, cf_strtimestamp_local(now, timebuffer) + 4, VFQNAME, log_string); if (sendto(sd, message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "sendto", " !! Unable to send syslog datagram"); return; } CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Syslog message: \"%s\" to server %s\n", message, SYSLOG_HOST); close(sd); #endif }
/* * Connect to ppp using either a local domain socket or a tcp socket. * * If we're given arguments, process them and quit, otherwise create two * threads to handle interactive mode. */ int main(int argc, char **argv) { struct sockaddr_un ifsun; int n, arg, fd, len, verbose, save_errno, hide1, hide1off, hide2; unsigned TimeoutVal; char *DoneWord = "x", *next, *start; struct sigaction act, oact; void *thread_ret; pthread_t mon; char Command[LINELEN]; char Buffer[LINELEN]; verbose = 0; TimeoutVal = 2; hide1 = hide1off = hide2 = 0; for (arg = 1; arg < argc; arg++) if (*argv[arg] == '-') { for (start = argv[arg] + 1; *start; start++) switch (*start) { case 't': TimeoutVal = (unsigned)atoi (start[1] ? start + 1 : argv[++arg]); start = DoneWord; break; case 'v': verbose = REC_VERBOSE; break; case 'p': if (start[1]) { hide1 = arg; hide1off = start - argv[arg]; passwd = start + 1; } else { hide1 = arg; hide1off = start - argv[arg]; passwd = argv[++arg]; hide2 = arg; } start = DoneWord; break; default: usage(); } } else break; if (argc < arg + 1) usage(); if (hide1) { char title[1024]; int pos, harg; for (harg = pos = 0; harg < argc; harg++) if (harg == 0 || harg != hide2) { if (harg == 0 || harg != hide1) n = snprintf(title + pos, sizeof title - pos, "%s%s", harg ? " " : "", argv[harg]); else if (hide1off > 1) n = snprintf(title + pos, sizeof title - pos, " %.*s", hide1off, argv[harg]); else n = 0; if (n < 0 || n >= sizeof title - pos) break; pos += n; } #ifdef __FreeBSD__ setproctitle("-%s", title); #else setproctitle("%s", title); #endif } if (*argv[arg] == '/') { memset(&ifsun, '\0', sizeof ifsun); ifsun.sun_len = strlen(argv[arg]); if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { warnx("%s: path too long", argv[arg]); return 1; } ifsun.sun_family = AF_LOCAL; strcpy(ifsun.sun_path, argv[arg]); if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) { warnx("cannot create local domain socket"); return 2; } if (connect(fd, (struct sockaddr *)&ifsun, sizeof(ifsun)) < 0) { if (errno) warn("cannot connect to socket %s", argv[arg]); else warnx("cannot connect to socket %s", argv[arg]); close(fd); return 3; } } else { char *addr, *p, *port; const char *caddr; struct addrinfo hints, *res, *pai; int gai; char local[] = "localhost"; addr = argv[arg]; if (addr[strspn(addr, "0123456789")] == '\0') { /* port on local machine */ port = addr; addr = local; } else if (*addr == '[') { /* [addr]:port */ if ((p = strchr(addr, ']')) == NULL) { warnx("%s: mismatched '['", addr); return 1; } addr++; *p++ = '\0'; if (*p != ':') { warnx("%s: missing port", addr); return 1; } port = ++p; } else { /* addr:port */ p = addr + strcspn(addr, ":"); if (*p != ':') { warnx("%s: missing port", addr); return 1; } *p++ = '\0'; port = p; } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; gai = getaddrinfo(addr, port, &hints, &res); if (gai != 0) { warnx("%s: %s", addr, gai_strerror(gai)); return 1; } for (pai = res; pai != NULL; pai = pai->ai_next) { if (fd = socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol), fd < 0) { warnx("cannot create socket"); continue; } TimedOut = 0; if (TimeoutVal) { act.sa_handler = Timeout; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, &oact); alarm(TimeoutVal); } if (connect(fd, pai->ai_addr, pai->ai_addrlen) == 0) break; if (TimeoutVal) { save_errno = errno; alarm(0); sigaction(SIGALRM, &oact, 0); errno = save_errno; } caddr = sockaddr_ntop(pai->ai_addr); if (caddr == NULL) caddr = argv[arg]; if (TimedOut) warnx("timeout: cannot connect to %s", caddr); else { if (errno) warn("cannot connect to %s", caddr); else warnx("cannot connect to %s", caddr); } close(fd); } freeaddrinfo(res); if (pai == NULL) return 1; if (TimeoutVal) { alarm(0); sigaction(SIGALRM, &oact, 0); } } len = 0; Command[sizeof(Command)-1] = '\0'; for (arg++; arg < argc; arg++) { if (len && len < sizeof(Command)-1) strcpy(Command+len++, " "); strncpy(Command+len, argv[arg], sizeof(Command)-len-1); len += strlen(Command+len); } switch (Receive(fd, verbose | REC_PASSWD)) { case 1: fprintf(stderr, "Password incorrect\n"); break; case 0: passwd = NULL; if (len == 0) { struct thread_data td; const char *env; int size; #ifndef __OpenBSD__ HistEvent hev = { 0, "" }; #endif td.hist = history_init(); if ((env = getenv("EL_SIZE"))) { size = atoi(env); if (size < 0) size = 20; } else size = 20; #ifdef __OpenBSD__ history(td.hist, H_EVENT, size); td.edit = el_init("pppctl", stdin, stdout); #else history(td.hist, &hev, H_SETSIZE, size); td.edit = el_init("pppctl", stdin, stdout, stderr); #endif el_source(td.edit, NULL); el_set(td.edit, EL_PROMPT, GetPrompt); if ((env = getenv("EL_EDITOR"))) { if (!strcmp(env, "vi")) el_set(td.edit, EL_EDITOR, "vi"); else if (!strcmp(env, "emacs")) el_set(td.edit, EL_EDITOR, "emacs"); } el_set(td.edit, EL_SIGNAL, 1); el_set(td.edit, EL_HIST, history, (const char *)td.hist); td.ppp = fd; td.trm = NULL; /* * We create two threads. The Terminal thread does all the * work while the Monitor thread simply tells the Terminal * thread when ``fd'' becomes readable. The telling is done * by sending a SIGUSR1 to the Terminal thread. The * sem_select semaphore is used to prevent the monitor * thread from firing excessive signals at the Terminal * thread (it's abused for exit handling too - see below). * * The Terminal thread never uses td.trm ! */ sem_init(&sem_select, 0, 0); pthread_create(&td.trm, NULL, Terminal, &td); pthread_create(&mon, NULL, Monitor, &td); /* Wait for the terminal thread to finish */ pthread_join(td.trm, &thread_ret); fprintf(stderr, "Connection closed\n"); /* Get rid of the monitor thread by abusing sem_select */ timetogo = 1; close(fd); fd = -1; sem_post(&sem_select); pthread_join(mon, &thread_ret); /* Restore our terminal and release resources */ el_end(td.edit); history_end(td.hist); sem_destroy(&sem_select); } else { start = Command; do { next = strchr(start, ';'); while (*start == ' ' || *start == '\t') start++; if (next) *next = '\0'; strcpy(Buffer, start); Buffer[sizeof(Buffer)-2] = '\0'; strcat(Buffer, "\n"); if (verbose) write(STDOUT_FILENO, Buffer, strlen(Buffer)); write(fd, Buffer, strlen(Buffer)); if (Receive(fd, verbose | REC_SHOW) != 0) { fprintf(stderr, "Connection closed\n"); break; } if (next) start = ++next; } while (next && *next); if (verbose) write(STDOUT_FILENO, "quit\n", 5); write(fd, "quit\n", 5); while (Receive(fd, verbose | REC_SHOW) == 0) ; if (verbose) puts(""); } break; default: warnx("ppp is not responding"); break; } if (fd != -1) close(fd); return 0; }
/*ARGSUSED*/ void player_accept(void *unused) { static int conn_cnt; struct sockaddr *sap; struct player *np; socklen_t len; const char *p; int ns; int set = 1; int stacksize; char buf[128]; #ifdef RESOLVE_IPADDRESS struct hostent *hostp; #endif /* auto sockaddr_storage would be simpler, but less portable */ sap = malloc(player_addrlen); len = player_addrlen; if (getsockname(player_socket, sap, &len)) { logerror("getsockname() failed: %s", strerror(errno)); p = NULL; } else { p = sockaddr_ntop(sap, buf, sizeof(buf)); CANT_HAPPEN(!p); } logerror("Listening on %s", p ? buf : "unknown address"); while (1) { empth_select(player_socket, EMPTH_FD_READ, NULL); len = player_addrlen; ns = accept(player_socket, sap, &len); /* FIXME accept() can block on some systems (RST after select() reports ready) */ if (ns < 0) { logerror("new socket accept"); continue; } (void)setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, &set, sizeof(set)); np = player_new(ns); if (!np) { logerror("can't create player for fd %d", ns); close(ns); continue; } if (!sockaddr_ntop(sap, np->hostaddr, sizeof(np->hostaddr))) { CANT_REACH(); player_delete(np); continue; } logerror("Connect from %s", np->hostaddr); #ifdef RESOLVE_IPADDRESS hostp = gethostbyaddr(inaddr, player_addrlen, sap->sa_family); if (NULL != hostp) strcpy(np->hostname, hostp->h_name); #endif /* RESOLVE_IPADDRESS */ /* FIXME ancient black magic; figure out true stack need */ stacksize = 100000 /* budget */ + MAX(WORLD_SZ() * sizeof(int) * 7, /* power */ MAXNOC * sizeof(struct powstr)); sprintf(buf, "Conn%d", conn_cnt++); empth_create(player_login, stacksize, 0, buf, np); } }
int OpenReceiverChannel(void) { int sd; int yes = 1; struct linger cflinger; #if defined(HAVE_GETADDRINFO) struct addrinfo query, *response, *ap; #else struct sockaddr_in sin; #endif cflinger.l_onoff = 1; cflinger.l_linger = 60; #if defined(HAVE_GETADDRINFO) char *ptr = NULL; memset(&query, 0, sizeof(struct addrinfo)); query.ai_flags = AI_PASSIVE; query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; /* * HvB : Bas van der Vlies */ if (BINDINTERFACE[0] != '\0') { ptr = BINDINTERFACE; } if (getaddrinfo(ptr, STR_CFENGINEPORT, &query, &response) != 0) { CfOut(cf_error, "getaddrinfo", "DNS/service lookup failure"); return -1; } sd = -1; for (ap = response; ap != NULL; ap = ap->ai_next) { if ((sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol)) == -1) { continue; } if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(int)) == -1) { CfOut(cf_error, "setsockopt", "Socket options were not accepted"); exit(1); } if (setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof(struct linger)) == -1) { CfOut(cf_error, "setsockopt", "Socket options were not accepted"); exit(1); } if (bind(sd, ap->ai_addr, ap->ai_addrlen) == 0) { if (DEBUG) { ThreadLock(cft_getaddr); printf("Bound to address %s on %s=%d\n", sockaddr_ntop(ap->ai_addr), CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS); ThreadUnlock(cft_getaddr); } #if defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) continue; /* *bsd doesn't map ipv6 addresses */ #else break; #endif } CfOut(cf_error, "bind", "Could not bind server address"); cf_closesocket(sd); sd = -1; } if (sd < 0) { CfOut(cf_error, "", "Couldn't open bind an open socket\n"); exit(1); } if (response != NULL) { freeaddrinfo(response); } #else memset(&sin, 0, sizeof(sin)); if (BINDINTERFACE[0] != '\0') { sin.sin_addr.s_addr = GetInetAddr(BINDINTERFACE); } else { sin.sin_addr.s_addr = INADDR_ANY; } sin.sin_port = (unsigned short) SHORT_CFENGINEPORT; sin.sin_family = AF_INET; if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { CfOut(cf_error, "socket", "Couldn't open socket"); exit(1); } if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(int)) == -1) { CfOut(cf_error, "sockopt", "Couldn't set socket options"); exit(1); } if (setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof(struct linger)) == -1) { CfOut(cf_error, "sockopt", "Couldn't set socket options"); exit(1); } if (bind(sd, (struct sockaddr *) &sin, sizeof(sin)) == -1) { CfOut(cf_error, "bind", "Couldn't bind to socket"); exit(1); } #endif return sd; }
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); } } } }
/* Handle ipv4 or ipv6 connection */ int RemoteConnect(char *host,int forceipv4) { int err; #if defined(HAVE_GETADDRINFO) && !defined(DARWIN) if (forceipv4 == 'n') { struct addrinfo query, *response, *ap; struct addrinfo query2, *response2, *ap2; int err,connected = false; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(host,"5308",&query,&response)) != 0) { snprintf(g_output,CF_BUFSIZE, "Unable to lookup hostname or cfengine service: %s", gai_strerror(err)); CfLog(cfinform,g_output,""); return false; } for (ap = response; ap != NULL; ap = ap->ai_next) { Verbose("Connect to %s = %s on port cfengine\n", host,sockaddr_ntop(ap->ai_addr)); if ((g_conn->sd = socket(ap->ai_family,ap->ai_socktype,ap->ai_protocol)) == -1) { CfLog(cfinform,"Couldn't open a socket","socket"); continue; } if (g_bindinterface[0] != '\0') { memset(&query2,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(g_bindinterface,NULL,&query2, &response2)) != 0) { snprintf(g_output,CF_BUFSIZE, "Unable to lookup hostname or " "cfengine service: %s", gai_strerror(err)); CfLog(cferror,g_output,""); return false; } for (ap2 = response2; ap2 != NULL; ap2 = ap2->ai_next) { if (bind(g_conn->sd, ap2->ai_addr, ap2->ai_addrlen) == 0) { freeaddrinfo(response2); break; } } if (response2) { free(response2); } } signal(SIGALRM,(void *)TimeOut); alarm(g_cf_timeout); if (connect(g_conn->sd,ap->ai_addr,ap->ai_addrlen) >= 0) { connected = true; alarm(0); signal(SIGALRM,SIG_DFL); break; } alarm(0); signal(SIGALRM,SIG_DFL); } if (connected) { g_conn->family = ap->ai_family; snprintf(g_conn->remoteip,CF_MAX_IP_LEN-1,"%s", sockaddr_ntop(ap->ai_addr)); } else { close(g_conn->sd); snprintf(g_output, CF_BUFSIZE*2, "Couldn't connect to host %s\n", host); g_conn->sd = CF_NOT_CONNECTED; } if (response != NULL) { freeaddrinfo(response); } if (!connected) { return false; } } else #endif /* ---------------------- only have ipv4 ---------------------------------*/ { struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); if ((hp = gethostbyname(host)) == NULL) { snprintf(g_output, CF_BUFSIZE, "Unable to look up " "IP address of %s", host); CfLog(cferror,g_output,"gethostbyname"); return false; } cin.sin_port = CfenginePort(); cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; cin.sin_family = AF_INET; Verbose("Connect to %s = %s, port h=%d\n", host,inet_ntoa(cin.sin_addr),htons(g_portnumber)); if ((g_conn->sd = socket(AF_INET,SOCK_STREAM,0)) == -1) { CfLog(cferror,"Couldn't open a socket","socket"); return false; } if (g_bindinterface[0] != '\0') { Verbose("Cannot bind interface with this OS.\n"); /* Could fix this - any point? */ } g_conn->family = AF_INET; snprintf(g_conn->remoteip, CF_MAX_IP_LEN-1, "%s", inet_ntoa(cin.sin_addr)); signal(SIGALRM,(void *)TimeOut); alarm(g_cf_timeout); if (err=connect(g_conn->sd,(void *)&cin,sizeof(cin)) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Couldn't connect to host %s\n", host); CfLog(cfinform,g_output,"connect"); return false; } alarm(0); signal(SIGALRM,SIG_DFL); } LastSeen(host,cf_connect); return true; }
int IdentifyForVerification(int sd,char *localip,int family) { char sendbuff[CF_BUFSIZE],dnsname[CF_BUFSIZE]; struct in_addr *iaddr; struct hostent *hp; int len,err; struct passwd *user_ptr; char *uname; #if defined(HAVE_GETADDRINFO) char myaddr[256]; /* Compilation trick for systems that don't know ipv6 */ #else struct sockaddr_in myaddr; #endif memset(sendbuff,0,CF_BUFSIZE); memset(dnsname,0,CF_BUFSIZE); if (!SKIPIDENTIFY && (strcmp(VDOMAIN,CF_START_DOMAIN) == 0)) { CfLog(cferror,"Undefined domain name",""); return false; } if (!SKIPIDENTIFY) { /* First we need to find out the IP address and DNS name of the socket we are sending from. This is not necessarily the same as VFQNAME if the machine has a different uname from its IP name (!) This can happen on stupidly set up machines or on hosts with multiple interfaces, with different names on each interface ... */ switch (family) { case AF_INET: len = sizeof(struct sockaddr_in); break; #if defined(HAVE_GETADDRINFO) case AF_INET6: len = sizeof(struct sockaddr_in6); break; #endif default: CfLog(cferror,"Software error in IdentifyForVerification",""); } if (getsockname(sd,(struct sockaddr *)&myaddr,&len) == -1) { CfLog(cferror,"Couldn't get socket address\n","getsockname"); return false; } snprintf(localip,CF_MAX_IP_LEN-1,"%s",sockaddr_ntop((struct sockaddr *)&myaddr)); Debug("Identifying this agent as %s i.e. %s, with signature %d\n",localip,VFQNAME,CFSIGNATURE); #if defined(HAVE_GETADDRINFO) if ((err=getnameinfo((struct sockaddr *)&myaddr,len,dnsname,CF_MAXVARSIZE,NULL,0,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't look up address v6 for %s: %s\n",dnsname,gai_strerror(err)); CfLog(cferror,OUTPUT,""); return false; } #else iaddr = &(myaddr.sin_addr); hp = gethostbyaddr((void *)iaddr,sizeof(myaddr.sin_addr),family); if ((hp == NULL) || (hp->h_name == NULL)) { CfLog(cferror,"Couldn't lookup IP address\n","gethostbyaddr"); return false; } strncpy(dnsname,hp->h_name,CF_MAXVARSIZE); if ((strstr(hp->h_name,".") == 0) && (strlen(VDOMAIN) > 0)) { strcat(dnsname,"."); strcat(dnsname,VDOMAIN); } #endif } else { strcpy(localip,VIPADDRESS); if (strlen(VFQNAME) > 0) { Verbose("SkipIdent was requested, so we are trusting and annoucning the identity as (%s) for this host\n",VFQNAME); strcat(dnsname,VFQNAME); } else { strcat(dnsname,"skipident"); } } user_ptr = getpwuid(getuid()); uname = user_ptr ? user_ptr->pw_name : "UNKNOWN"; /* Some resolvers will not return FQNAME and missing PTR will give numerical result */ if ((strlen(VDOMAIN) > 0) && !IsIPV6Address(dnsname) && !strchr(dnsname,'.')) { Debug("Appending domain %s to %s\n",VDOMAIN,dnsname); strcat(dnsname,"."); strncat(dnsname,VDOMAIN,CF_MAXVARSIZE/2); } if (strncmp(dnsname,localip,strlen(localip)) == 0) { /* Seems to be a bug in some resolvers that adds garbage, when it just returns the input */ strcpy(dnsname,localip); } if (strlen(dnsname) == 0) { strcpy(dnsname,localip); } snprintf(sendbuff,CF_BUFSIZE-1,"CAUTH %s %s %s %d",localip,dnsname,uname,CFSIGNATURE); Debug("SENT:::%s\n",sendbuff); SendTransaction(sd,sendbuff,0,CF_DONE); return true; }
int IdentifyAgent(int sd, char *localip, int family) { char uname[CF_BUFSIZE], sendbuff[CF_BUFSIZE], dnsname[CF_BUFSIZE]; socklen_t len; #if defined(HAVE_GETADDRINFO) int err; char myaddr[256]; /* Compilation trick for systems that don't know ipv6 */ #else struct sockaddr_in myaddr; struct in_addr *iaddr; struct hostent *hp; #endif memset(sendbuff, 0, CF_BUFSIZE); memset(dnsname, 0, CF_BUFSIZE); if ((!SKIPIDENTIFY) && (strcmp(VDOMAIN, CF_START_DOMAIN) == 0)) { CfOut(cf_error, "", "Undefined domain name"); return false; } if (!SKIPIDENTIFY) { /* First we need to find out the IP address and DNS name of the socket we are sending from. This is not necessarily the same as VFQNAME if the machine has a different uname from its IP name (!) This can happen on poorly set up machines or on hosts with multiple interfaces, with different names on each interface ... */ switch (family) { case AF_INET: len = sizeof(struct sockaddr_in); break; #if defined(HAVE_GETADDRINFO) case AF_INET6: len = sizeof(struct sockaddr_in6); break; #endif default: CfOut(cf_error, "", "Software error in IdentifyForVerification, family = %d", family); } if (getsockname(sd, (struct sockaddr *) &myaddr, &len) == -1) { CfOut(cf_error, "getsockname", "Couldn't get socket address\n"); return false; } snprintf(localip, CF_MAX_IP_LEN - 1, "%s", sockaddr_ntop((struct sockaddr *) &myaddr)); CfDebug("Identifying this agent as %s i.e. %s, with signature %d, family %d\n", localip, VFQNAME, CFSIGNATURE, family); #if defined(HAVE_GETADDRINFO) if ((err = getnameinfo((struct sockaddr *) &myaddr, len, dnsname, CF_MAXVARSIZE, NULL, 0, 0)) != 0) { CfOut(cf_error, "", "Couldn't look up address v6 for %s: %s\n", dnsname, gai_strerror(err)); return false; } #else iaddr = &(myaddr.sin_addr); hp = gethostbyaddr((void *) iaddr, sizeof(myaddr.sin_addr), family); if ((hp == NULL) || (hp->h_name == NULL)) { CfOut(cf_error, "gethostbyaddr", "Couldn't lookup IP address\n"); return false; } strncpy(dnsname, hp->h_name, CF_MAXVARSIZE); if ((strstr(hp->h_name, ".") == 0) && (strlen(VDOMAIN) > 0)) { strcat(dnsname, "."); strcat(dnsname, VDOMAIN); } #endif } else { strcpy(localip, VIPADDRESS); if (strlen(VFQNAME) > 0) { CfOut(cf_verbose, "", "skipidentify was promised, so we are trusting and simply announcing the identity as (%s) for this host\n", VFQNAME); strcat(dnsname, VFQNAME); } else { strcat(dnsname, "skipident"); } } /* client always identifies as root on windows */ #ifdef MINGW snprintf(uname, sizeof(uname), "%s", "root"); #else GetCurrentUserName(uname, sizeof(uname)); #endif /* Some resolvers will not return FQNAME and missing PTR will give numerical result */ if ((strlen(VDOMAIN) > 0) && (!IsIPV6Address(dnsname)) && (!strchr(dnsname, '.'))) { CfDebug("Appending domain %s to %s\n", VDOMAIN, dnsname); strcat(dnsname, "."); strncat(dnsname, VDOMAIN, CF_MAXVARSIZE / 2); } if (strncmp(dnsname, localip, strlen(localip)) == 0) { /* Seems to be a bug in some resolvers that adds garbage, when it just returns the input */ strcpy(dnsname, localip); } if (strlen(dnsname) == 0) { strcpy(dnsname, localip); } snprintf(sendbuff, CF_BUFSIZE - 1, "CAUTH %s %s %s %d", localip, dnsname, uname, CFSIGNATURE); if (SendTransaction(sd, sendbuff, 0, CF_DONE) == -1) { CfOut(cf_error, "", "!! IdentifyAgent: Could not send auth response"); return false; } CfDebug("SENT:::%s\n", sendbuff); return true; }
int RemoteConnect(char *host,char forceipv4,short oldport, char *newport) { int err; #if defined(HAVE_GETADDRINFO) if (forceipv4 == 'n') { struct addrinfo query, *response, *ap; struct addrinfo query2, *response2, *ap2; int err,connected = false; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(host,newport,&query,&response)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to find hostname or cfengine service: (%s/%s) %s",host,STR_CFENGINEPORT,gai_strerror(err)); CfLog(cfinform,OUTPUT,""); return false; } for (ap = response; ap != NULL; ap = ap->ai_next) { Verbose("Connect to %s = %s on port %s\n",host,sockaddr_ntop(ap->ai_addr),newport); if ((CONN->sd = socket(ap->ai_family,ap->ai_socktype,ap->ai_protocol)) == -1) { CfLog(cfinform,"Couldn't open a socket","socket"); continue; } if (BINDINTERFACE[0] != '\0') { memset(&query2,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(BINDINTERFACE,NULL,&query2,&response2)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to lookup hostname or cfengine service: %s",gai_strerror(err)); CfLog(cferror,OUTPUT,""); return false; } for (ap2 = response2; ap2 != NULL; ap2 = ap2->ai_next) { if (bind(CONN->sd, ap2->ai_addr, ap2->ai_addrlen) == 0) { freeaddrinfo(response2); response2 = NULL; break; } } if (response2) { freeaddrinfo(response2); } } signal(SIGALRM,(void *)TimeOut); alarm(CF_TIMEOUT); if (connect(CONN->sd,ap->ai_addr,ap->ai_addrlen) >= 0) { connected = true; alarm(0); signal(SIGALRM,SIG_DFL); break; } alarm(0); signal(SIGALRM,SIG_DFL); } if (connected) { CONN->family = ap->ai_family; snprintf(CONN->remoteip,CF_MAX_IP_LEN-1,"%s",sockaddr_ntop(ap->ai_addr)); } else { close(CONN->sd); snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't connect to host %s\n",host); CONN->sd = CF_NOT_CONNECTED; } if (response != NULL) { freeaddrinfo(response); } if (!connected) { return false; } } else #endif /* ---------------------- only have ipv4 ---------------------------------*/ { struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); if ((hp = gethostbyname(host)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to look up IP address of %s",host); CfLog(cferror,OUTPUT,"gethostbyname"); return false; } cin.sin_port = oldport; cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; cin.sin_family = AF_INET; Verbose("Connect to %s = %s, port =%u\n",host,inet_ntoa(cin.sin_addr),SHORT_CFENGINEPORT); if ((CONN->sd = socket(AF_INET,SOCK_STREAM,0)) == -1) { CfLog(cferror,"Couldn't open a socket","socket"); return false; } if (BINDINTERFACE[0] != '\0') { Verbose("Cannot bind interface with this OS.\n"); /* Could fix this - any point? */ } CONN->family = AF_INET; snprintf(CONN->remoteip,CF_MAX_IP_LEN-1,"%s",inet_ntoa(cin.sin_addr)); signal(SIGALRM,(void *)TimeOut); alarm(CF_TIMEOUT); if (err=connect(CONN->sd,(void *)&cin,sizeof(cin)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't connect to host %s\n",host); CfLog(cfinform,OUTPUT,"connect"); return false; } alarm(0); signal(SIGALRM,SIG_DFL); } LastSeen(host,cf_connect); return true; }