int main (void) { int rc; setup_test_environment(); // Create the infrastructure void *ctx = zmq_ctx_new (); assert (ctx); void *rep = zmq_socket (ctx, ZMQ_REP); assert (rep); void *req = zmq_socket (ctx, ZMQ_REQ); assert (req); rc = zmq_bind(rep, "tcp://127.0.0.1:5560"); assert (rc == 0); rc = zmq_connect(req, "tcp://127.0.0.1:5560"); assert (rc == 0); char tmp[MSG_SIZE]; zmq_send(req, tmp, MSG_SIZE, 0); zmq_msg_t msg; rc = zmq_msg_init(&msg); assert (rc == 0); zmq_recvmsg(rep, &msg, 0); assert(zmq_msg_size(&msg) == MSG_SIZE); // get the messages source file descriptor int srcFd = zmq_msg_get(&msg, ZMQ_SRCFD); assert(srcFd >= 0); // get the remote endpoint struct sockaddr_storage ss; socklen_t addrlen = sizeof ss; rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen); assert (rc == 0); char host [NI_MAXHOST]; rc = getnameinfo ((struct sockaddr*) &ss, addrlen, host, sizeof host, NULL, 0, NI_NUMERICHOST); assert (rc == 0); // assert it is localhost which connected assert (strcmp(host, "127.0.0.1") == 0); rc = zmq_close (rep); assert (rc == 0); rc = zmq_close (req); assert (rc == 0); // sleep a bit for the socket to be freed usleep(30000); // getting name from closed socket will fail rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen); assert (rc == -1); assert (errno == EBADF); rc = zmq_ctx_term (ctx); assert (rc == 0); return 0 ; }
static char * get_remote_hostname(int sock, int use_dns) { struct sockaddr_storage from; int i; socklen_t fromlen; struct addrinfo hints, *ai, *aitop; char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; /* Get IP address of client. */ fromlen = sizeof(from); memset(&from, 0, sizeof(from)); if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) { debug("getpeername failed: %.100s", strerror(errno)); cleanup_exit(255); } if (from.ss_family == AF_INET) check_ip_options(sock, ntop); ipv64_normalise_mapped(&from, &fromlen); if (from.ss_family == AF_INET6) fromlen = sizeof(struct sockaddr_in6); if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed"); if (!use_dns) return xstrdup(ntop); debug3("Trying to reverse map address %.100s.", ntop); /* Map the IP address to a host name. */ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), NULL, 0, NI_NAMEREQD) != 0) { /* Host name not found. Use ip address. */ return xstrdup(ntop); } /* * if reverse lookup result looks like a numeric hostname, * someone is trying to trick us by PTR record like following: * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 */ memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(name, NULL, &hints, &ai) == 0) { logit("Nasty PTR record \"%s\" is set up for %s, ignoring", name, ntop); freeaddrinfo(ai); return xstrdup(ntop); } /* * Convert it to all lowercase (which is expected by the rest * of this software). */ for (i = 0; name[i]; i++) if (isupper(name[i])) name[i] = (char)tolower(name[i]); /* * Map it back to an IP address and check that the given * address actually is an address of this host. This is * necessary because anyone with access to a name server can * define arbitrary names for an IP address. Mapping from * name to IP address can be trusted better (but can still be * fooled if the intruder has access to the name server of * the domain). */ memset(&hints, 0, sizeof(hints)); hints.ai_family = from.ss_family; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { logit("reverse mapping checking getaddrinfo for %.700s " "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop); return xstrdup(ntop); } /* Look for the address from the list of addresses. */ for (ai = aitop; ai; ai = ai->ai_next) { if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && (strcmp(ntop, ntop2) == 0)) break; } freeaddrinfo(aitop); /* If we reached the end of the list, the address was not there. */ if (!ai) { /* Address not found for the host name. */ logit("Address %.100s maps to %.600s, but this does not " "map back to the address - POSSIBLE BREAK-IN ATTEMPT!", ntop, name); return xstrdup(ntop); } return xstrdup(name); }
int main(int argc, char** argv){ struct addrinfo hints; struct addrinfo *res; int info, sd; int nread; char buf[BUF_SIZE]; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; hints.ai_family = AF_UNSPEC; /*ipv4 o ipv6*/ hints.ai_socktype = SOCK_DGRAM; /*udp*/ hints.ai_flags = AI_PASSIVE; hints.ai_protocol = 0; if(argc < 1) perror("Error de argumentos.\n"); info = getaddrinfo("::", argv[1], &hints, &res); if(info != 0) perror("Error getaddrinfo.\n"); sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); bind(sd, res->ai_addr, res->ai_addrlen); int i; for(i = 0; i < 2; i++){ pid_t pid = fork(); if(pid == -1) perror("Error de pid.\n"); else if(pid == 0) { while(1){ struct sockaddr_storage sock; socklen_t sock_len = sizeof(sock); nread = recvfrom(sd, buf, BUF_SIZE, 0, (struct sockaddr *) &sock, &sock_len); buf[nread] = '\0'; getnameinfo((struct sockaddr *) &sock, sock_len, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if(strcmp(buf, "a") == 0 || strcmp(buf, "a\n") == 0){ sendto(sd, host, strlen(host), 0, (struct sockaddr *) &sock, sock_len); } else if(strcmp(buf, "p") == 0 || strcmp(buf, "p\n") == 0) { sendto(sd, serv, strlen(serv), 0, (struct sockaddr *) &sock, sock_len); } else if(strcmp(buf, "q") == 0 || strcmp(buf, "q\n") == 0) { sendto(sd, "ADIÓS\n", 6, 0, (struct sockaddr *) &sock, sock_len); freeaddrinfo(res); close(sd); return 0; } printf("[H: %d,%d] Host: %s Puerto: %s\n", getpid(), i+1, host, serv); } } } i = 0; while(i<2){ int status; wait(&status); i++; } freeaddrinfo(res); close(sd); return 0; }
int analyze_line(char *line[]) { char sec[LINE_COLUMNS]; struct tm *tm; struct sockaddr_in sa; char *l[LINE_COLUMNS]; char date[9]; char host[30]; //char cn_host[CN_LENGTH]; long i_tmp = 0; char *c_tmp; struct in_addr addr; memset(sec, 0, sizeof(sec)); memset(date, 0, sizeof(date)); sscanf(line[0], "%[^-]", sec); i_tmp = atol(sec); tm = localtime(&i_tmp); if(tm == NULL) { fprintf(stderr, " Error to parse time %s\n", sec); return EXIT_FAILURE; } if(strftime(date, sizeof(date), "%Y%m%d", tm) == 0) { fprintf(stderr, " Error to change time to human readable strings\n"); return EXIT_FAILURE; } l[0] = date; if(ip4insubnet(line[2], LOCAL_NET, LOCAL_NETBITS) == 1) { c_tmp = line[2]; l[2] = line[3]; if(line[6] != NULL && strcasecmp(line[4], "TCP") == 0) { l[5] = line[6]; } } else{ c_tmp = line[3]; l[2] = line[2]; if(line[5] != NULL && strcasecmp(line[4], "TCP") == 0) { l[5] = line[5]; } } memset(host, 0, sizeof(host)); bzero(&sa, sizeof(struct sockaddr_in)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr(c_tmp); getnameinfo((struct sockaddr *)&sa, sizeof(sa), host, sizeof(host), NULL, 0, NI_NOFQDN); if(strlen(host) <= 0) l[1] = c_tmp; else l[1] = host; l[3] = line[4]; l[4] = line[1]; l[7] = "\0"; if(strcasecmp(line[4], "TCP") == 0) { if(strcasecmp(line[7], "FA") == 0) l[6] = "1"; else l[6] = "0"; for(i_tmp = 8; i_tmp < LINE_COLUMNS; i_tmp++) { if(strcmp(line[i_tmp], "\n") == 0) { l[i_tmp] = NULL; break; } l[i_tmp] = line[i_tmp]; } /* if(i_tmp == 8 && (atoi(l[5]) == 443 || atoi(l[5]) == 8443)) { cn_host[0] = '\0'; pthread_mutex_lock(&mutex); get_crt_cn(l[2], l[5], cn_host); pthread_mutex_unlock(&mutex); l[7] = cn_host; } */ } else { l[5] = NULL; l[6] = NULL; } db_save(l); }
/* Map the host name NAME to the actual to be used host name. This allows us to manage round robin DNS names. We use our own strategy to choose one of the hosts. For example we skip those hosts which failed for some time and we stick to one host for a time independent of DNS retry times. */ static char * map_host (const char *name) { hostinfo_t hi; int idx; /* No hostname means localhost. */ if (!name || !*name) return xtrystrdup ("localhost"); /* See whether the host is in our table. */ idx = find_hostinfo (name); if (idx == -1) { /* We never saw this host. Allocate a new entry. */ struct addrinfo hints, *aibuf, *ai; int *reftbl; size_t reftblsize; int refidx; reftblsize = 100; reftbl = xtrymalloc (reftblsize * sizeof *reftbl); if (!reftbl) return NULL; refidx = 0; idx = create_new_hostinfo (name); if (idx == -1) { xfree (reftbl); return NULL; } hi = hosttable[idx]; /* Find all A records for this entry and put them into the pool list - if any. */ memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; if (!getaddrinfo (name, NULL, &hints, &aibuf)) { for (ai = aibuf; ai; ai = ai->ai_next) { char tmphost[NI_MAXHOST]; int tmpidx; int ec; int i; if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; log_printhex ("getaddrinfo returned", ai->ai_addr,ai->ai_addrlen); if ((ec=getnameinfo (ai->ai_addr, ai->ai_addrlen, tmphost, sizeof tmphost, NULL, 0, NI_NAMEREQD))) log_info ("getnameinfo failed while checking '%s': %s\n", name, gai_strerror (ec)); else if (refidx+1 >= reftblsize) { log_error ("getnameinfo returned for '%s': '%s'" " [index table full - ignored]\n", name, tmphost); } else { if ((tmpidx = find_hostinfo (tmphost)) != -1) { log_info ("getnameinfo returned for '%s': '%s'" " [already known]\n", name, tmphost); if (ai->ai_family == AF_INET) hosttable[tmpidx]->v4 = 1; if (ai->ai_family == AF_INET6) hosttable[tmpidx]->v6 = 1; for (i=0; i < refidx; i++) if (reftbl[i] == tmpidx) break; if (!(i < refidx) && tmpidx != idx) reftbl[refidx++] = tmpidx; } else { log_info ("getnameinfo returned for '%s': '%s'\n", name, tmphost); /* Create a new entry. */ tmpidx = create_new_hostinfo (tmphost); if (tmpidx == -1) log_error ("map_host for '%s' problem: %s - '%s'" " [ignored]\n", name, strerror (errno), tmphost); else { if (ai->ai_family == AF_INET) hosttable[tmpidx]->v4 = 1; if (ai->ai_family == AF_INET6) hosttable[tmpidx]->v6 = 1; for (i=0; i < refidx; i++) if (reftbl[i] == tmpidx) break; if (!(i < refidx) && tmpidx != idx) reftbl[refidx++] = tmpidx; } } } } } reftbl[refidx] = -1; if (refidx) { assert (!hi->pool); hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl); if (!hi->pool) { log_error ("shrinking index table in map_host failed: %s\n", strerror (errno)); xfree (reftbl); } qsort (reftbl, refidx, sizeof *reftbl, sort_hostpool); } else xfree (reftbl); } hi = hosttable[idx]; if (hi->pool) { /* If the currently selected host is now marked dead, force a re-selection . */ if (hi->poolidx >= 0 && hi->poolidx < hosttable_size && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead) hi->poolidx = -1; /* Select a host if needed. */ if (hi->poolidx == -1) { hi->poolidx = select_random_host (hi->pool); if (hi->poolidx == -1) { log_error ("no alive host found in pool '%s'\n", name); return NULL; } } assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size); hi = hosttable[hi->poolidx]; assert (hi); } if (hi->dead) { log_error ("host '%s' marked as dead\n", hi->name); return NULL; } return xtrystrdup (hi->name); }
/* * We will eventually be called from inetd or via the rc scripts directly * Parse arguments and act appropiately. */ int main(int argc, char **argv) { extern char *optarg; FILE *fp; int c, *s, ns; struct pollfd *pfds; #if PROFILE moncontrol(0); #endif if ((progname = strrchr(*argv, '/')) != NULL) { progname++; } else progname = *argv; /* initialise global session data */ memset(&session, 0, sizeof(session)); session.peer = tac_strdup("unknown"); if (argc <= 1) { usage(); tac_exit(1); } while ((c = getopt(argc, argv, "B:C:d:hiPp:tGgvSsLw:u:")) != EOF) switch (c) { case 'B': /* bind() address*/ bind_address = optarg; break; case 'L': /* lookup peer names via DNS */ lookup_peer = 1; break; case 's': /* don't respond to sendpass */ sendauth_only = 1; break; case 'v': /* print version and exit */ vers(); tac_exit(1); case 't': console = 1; /* log to console too */ break; case 'P': /* Parse config file only */ parse_only = 1; break; case 'G': /* foreground */ opt_G = 1; break; case 'g': /* single threaded */ single = 1; break; case 'p': /* port */ port = atoi(optarg); portstr = optarg; break; case 'd': /* debug */ debug |= atoi(optarg); break; case 'C': /* config file name */ session.cfgfile = tac_strdup(optarg); break; case 'h': /* usage */ usage(); tac_exit(0); case 'i': /* inetd mode */ standalone = 0; break; case 'S': /* enable single-connection */ opt_S = 1; break; #ifdef MAXSESS case 'w': /* wholog file */ wholog = tac_strdup(optarg); break; #endif case 'u': wtmpfile = tac_strdup(optarg); break; default: fprintf(stderr, "%s: bad switch %c\n", progname, c); usage(); tac_exit(1); } parser_init(); /* read the configuration/etc */ init(); #if defined(REAPCHILD) && defined(REAPSIGIGN) client_count_init(); #endif open_logfile(); signal(SIGUSR1, handler); signal(SIGHUP, handler); signal(SIGUSR2, dump_clients_handler); signal(SIGTERM, die); signal(SIGPIPE, SIG_IGN); if (parse_only) tac_exit(0); if (debug) report(LOG_DEBUG, "tac_plus server %s starting", version); if (!standalone) { /* running under inetd */ char host[NI_MAXHOST]; int on; #ifdef IPV6 struct sockaddr_in6 name; #else struct sockaddr_in name; #endif socklen_t name_len; name_len = sizeof(name); session.flags |= SESS_NO_SINGLECONN; session.sock = 0; #ifdef IPV6 if (getpeername(session.sock, (struct sockaddr6 *)&name, &name_len)) { report(LOG_ERR, "getpeername failure %s", strerror(errno)); #else if (getpeername(session.sock, (struct sockaddr *)&name, &name_len)) { report(LOG_ERR, "getpeername failure %s", strerror(errno)); #endif } else { if (lookup_peer) on = 0; else on = NI_NUMERICHOST; #ifdef IPV6 if (getnameinfo((struct sockaddr6 *)&name, name_len, host, 128, NULL, 0, on)) { #else if (getnameinfo((struct sockaddr *)&name, name_len, host, 128, NULL, 0, on)) { #endif strncpy(host, "unknown", NI_MAXHOST - 1); host[NI_MAXHOST - 1] = '\0'; } if (session.peer) free(session.peer); session.peer = tac_strdup(host); if (session.peerip) free(session.peerip); #ifdef IPV6 session.peerip = tac_strdup((char *)inet_ntop(name.sin6_family, &name.sin6_addr, host, name_len)); #else session.peerip = tac_strdup((char *)inet_ntop(name.sin_family, &name.sin_addr, host, name_len)); #endif if (debug & DEBUG_AUTHEN_FLAG) report(LOG_INFO, "session.peerip is %s", session.peerip); } #ifdef FIONBIO on = 1; if (ioctl(session.sock, FIONBIO, &on) < 0) { report(LOG_ERR, "ioctl(FIONBIO) %s", strerror(errno)); tac_exit(1); } #endif start_session(); tac_exit(0); } if (single) { session.flags |= SESS_NO_SINGLECONN; } else { /* * Running standalone; background ourselves and release controlling * tty, unless -G option was specified to keep the parent in the * foreground. */ #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif if (!opt_S) session.flags |= SESS_NO_SINGLECONN; if (!opt_G) { if ((childpid = fork()) < 0) report(LOG_ERR, "Can't fork first child"); else if (childpid > 0) exit(0); /* parent */ if (debug) report(LOG_DEBUG, "Backgrounded"); #if SETPGRP_VOID if (setpgrp() == -1) #else if (setpgrp(0, getpid()) == -1) #endif /* SETPGRP_VOID */ report(LOG_ERR, "Can't change process group: %s", strerror(errno)); /* XXX What does "REAPCHILD" have to do with TIOCNOTTY? */ #ifndef REAPCHILD c = open("/dev/tty", O_RDWR); if (c >= 0) { ioctl(c, TIOCNOTTY, (char *)0); (void) close(c); } #else /* REAPCHILD */ if ((childpid = fork()) < 0) report(LOG_ERR, "Can't fork second child"); else if (childpid > 0) exit(0); if (debug & DEBUG_FORK_FLAG) report(LOG_DEBUG, "Forked grandchild"); #endif /* REAPCHILD */ /* some systems require this */ closelog(); for (c = getdtablesize(); c >= 0; c--) (void)close(c); /* * make sure we can still log to syslog now that we have closed * everything */ open_logfile(); } } #if REAPCHILD #if REAPSIGIGN signal(SIGCHLD, reapchild); #else signal(SIGCHLD, SIG_IGN); #endif #endif ostream = NULL; /* chdir("/"); */ umask(022); errno = 0; get_socket(&s, &ns); #ifndef SOMAXCONN #define SOMAXCONN 5 #endif for (c = 0; c < ns; c++) { if (listen(s[c], SOMAXCONN) < 0) { console = 1; report(LOG_ERR, "listen: %s", strerror(errno)); tac_exit(1); } } if (port == TAC_PLUS_PORT) { if (bind_address == NULL) { strncpy(pidfilebuf, TACPLUS_PIDFILE, PIDSZ); if (pidfilebuf[PIDSZ - 1] != '\0') c = PIDSZ; else c = PIDSZ - 1; } else c = snprintf(pidfilebuf, PIDSZ, "%s.%s", TACPLUS_PIDFILE, bind_address); } else { if (bind_address == NULL) c = snprintf(pidfilebuf, PIDSZ, "%s.%d", TACPLUS_PIDFILE, port); else c = snprintf(pidfilebuf, PIDSZ, "%s.%s.%d", TACPLUS_PIDFILE, bind_address, port); } if (c >= PIDSZ) { pidfilebuf[PIDSZ - 1] = '\0'; report(LOG_ERR, "pid filename truncated: %s", pidfilebuf); childpid = 0; } else { /* write process id to pidfile */ if ((fp = fopen(pidfilebuf, "w")) != NULL) { fprintf(fp, "%d\n", (int)getpid()); fclose(fp); /* * After forking to disassociate; make sure we know we're the * mother so that we remove our pid file upon exit in die(). */ childpid = 1; } else { report(LOG_ERR, "Cannot write pid to %s %s", pidfilebuf, strerror(errno)); childpid = 0; } } #ifdef TACPLUS_GROUPID if (setgid(TACPLUS_GROUPID)) report(LOG_ERR, "Cannot set group id to %d %s", TACPLUS_GROUPID, strerror(errno)); #endif #ifdef TACPLUS_USERID if (setuid(TACPLUS_USERID)) report(LOG_ERR, "Cannot set user id to %d %s", TACPLUS_USERID, strerror(errno)); #endif #ifdef MAXSESS maxsess_loginit(); #endif /* MAXSESS */ report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d", getuid(), geteuid(), getgid(), getegid(), s); pfds = malloc(sizeof(struct pollfd) * ns); if (pfds == NULL) { report(LOG_ERR, "malloc failure: %s", strerror(errno)); tac_exit(1); } for (c = 0; c < ns; c++) { pfds[c].fd = s[c]; pfds[c].events = POLLIN | POLLERR | POLLHUP | POLLNVAL; } for (;;) { #if HAVE_PID_T pid_t pid; #else int pid; #endif char host[NI_MAXHOST]; #ifdef IPV6 struct sockaddr_in6 from; #else struct sockaddr_in from; #endif socklen_t from_len; int newsockfd, status; int flags; int procs_for_client; #if defined(REAPCHILD) && defined(REAPSIGIGN) if (reap_children) reapchildren(); #endif if (reinitialize) init(); if (dump_client_table) { report(LOG_ALERT, "Dumping Client Tables"); dump_client_tables(); dump_client_table = 0; } status = poll(pfds, ns, cfg_get_accepttimeout() * 1000); if (status == 0) continue; if (status == -1) if (errno == EINTR) continue; from_len = sizeof(from); memset((char *)&from, 0, from_len); for (c = 0; c < ns; c++) { if (pfds[c].revents & POLLIN) #ifdef IPV6 newsockfd = accept(s[c], (struct sockaddr6 *)&from, &from_len); #else newsockfd = accept(s[c], (struct sockaddr *)&from, &from_len); #endif else if (pfds[c].revents & (POLLERR | POLLHUP | POLLNVAL)) { report(LOG_ERR, "exception on listen FD %d", s[c]); tac_exit(1); } } if (newsockfd < 0) { if (errno == EINTR) continue; report(LOG_ERR, "accept: %s", strerror(errno)); continue; } if (lookup_peer) flags = 0; else flags = NI_NUMERICHOST; #ifdef IPV6 if (getnameinfo((struct sockaddr_in6 *)&from, from_len, host, 128, NULL, 0, flags)) { #else if (getnameinfo((struct sockaddr_in *)&from, from_len, host, 128, NULL, 0, flags)) { #endif strncpy(host, "unknown", NI_MAXHOST - 1); host[NI_MAXHOST - 1] = '\0'; } if (session.peer) free(session.peer); session.peer = tac_strdup(host); if (session.peerip) free(session.peerip); #ifdef IPV6 session.peerip = tac_strdup((char *)inet_ntop(from.sin6_family, &from.sin6_addr, host, INET6_ADDRSTRLEN)); #else session.peerip = tac_strdup((char *)inet_ntop(from.sin_family, &from.sin_addr, host, INET_ADDRSTRLEN)); #endif if (debug & DEBUG_PACKET_FLAG) report(LOG_DEBUG, "session request from %s sock=%d", session.peer, newsockfd); if (!single) { #if defined(REAPCHILD) && defined(REAPSIGIGN) /* first we check the tocal process count to see if we are at the limit */ if (total_child_count >= cfg_get_maxprocs()) { report(LOG_ALERT, "refused connection from %s [%s] at global max procs [%d]", session.peer, session.peerip, total_child_count); shutdown(newsockfd, 2); close(newsockfd); continue; } /* no we check the process count per client */ procs_for_client = get_client_count(session.peerip); report(LOG_ALERT, "connection [%d] from %s [%s]", procs_for_client + 1, session.peer, session.peerip); if (procs_for_client >= cfg_get_maxprocsperclt()) { report(LOG_ALERT, "refused connection from %s [%s] at client max procs [%d]", session.peer, session.peerip, procs_for_client); shutdown(newsockfd, 2); close(newsockfd); continue; } #endif pid = fork(); if (pid < 0) { report(LOG_ERR, "fork error"); tac_exit(1); } } else { pid = 0; } if (pid == 0) { /* child */ if (!single) { if (ns > 1) { for (c = 0; c < ns; c++) { close(s[c]); } } } session.sock = newsockfd; #ifdef LIBWRAP if (! hosts_ctl(progname,session.peer,session.peerip,progname)) { report(LOG_ALERT, "refused connection from %s [%s]", session.peer, session.peerip); shutdown(session.sock, 2); close(session.sock); if (!single) { tac_exit(0); } else { close(session.sock); continue; } } if (debug) report(LOG_DEBUG, "connect from %s [%s]", session.peer, session.peerip); #endif #if PROFILE moncontrol(1); #endif start_session(); shutdown(session.sock, 2); close(session.sock); if (!single) tac_exit(0); } else { /* parent */ #if defined(REAPCHILD) && defined(REAPSIGIGN) total_child_count++; procs_for_client = increment_client_count_for_proc(pid, session.peerip); snprintf(msgbuf, MSGBUFSZ, "forked %lu for %s, procs %d, procs for client %d", (long)pid, session.peerip, total_child_count, procs_for_client); report(LOG_DEBUG, msgbuf); #endif close(newsockfd); } } }
char * NET_BaseAdrToString(netadr_t a) { static char s[64], tmp[64]; struct sockaddr_storage ss; struct sockaddr_in6 *s6; switch (a.type) { case NA_IP: case NA_LOOPBACK: Com_sprintf(s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); break; case NA_BROADCAST: Com_sprintf(s, sizeof(s), "255.255.255.255"); break; case NA_IP6: case NA_MULTICAST6: memset(&ss, 0, sizeof(ss)); s6 = (struct sockaddr_in6 *)&ss; if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)a.ip)) { #ifdef __FreeBSD__ ss.ss_len = sizeof(struct sockaddr_in); #endif ss.ss_family = AF_INET; memcpy(&((struct sockaddr_in *)&ss)->sin_addr, &((struct in6_addr *)a.ip)->s6_addr[12], sizeof(struct in_addr)); } else { #ifdef __FreeBSD__ s6->sin6_len = sizeof(struct sockaddr_in6); #endif s6->sin6_scope_id = a.scope_id; s6->sin6_family = AF_INET6; memcpy(&s6->sin6_addr, a.ip, sizeof(struct in6_addr)); } #ifdef __FreeBSD__ socklen_t const salen = ss.ss_len; #else socklen_t const salen = sizeof(ss); #endif if (getnameinfo((struct sockaddr*)&ss, salen, s, sizeof(s), NULL, 0, NI_NUMERICHOST)) { Com_sprintf(s, sizeof(s), "<invalid>"); } else { if ((a.type == NA_MULTICAST6) || IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&ss)-> sin6_addr)) { /* If the address is multicast (link) or a link-local, need to carry the scope. The string format of the IPv6 address is used by the client to extablish the connect to the server. */ Com_sprintf(tmp, sizeof(tmp), "%s%%%d", s, s6->sin6_scope_id); memcpy(s, tmp, sizeof(s)); } } break; default: Com_sprintf(s, sizeof(s), "invalid IP address family type"); break; } return s; }
LWS_VISIBLE int libwebsockets_get_addresses(struct libwebsocket_context *context, void *ads, char *name, int name_len, char *rip, int rip_len) { struct addrinfo ai, *res; void *p = NULL; rip[0] = '\0'; name[0] = '\0'; #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, rip_len)) { lwsl_err("inet_ntop", strerror(LWS_ERRNO)); return -1; } // Strip off the IPv4 to IPv6 header if one exists if (strncmp(rip, "::ffff:", 7) == 0) memmove(rip, rip + 7, strlen(rip) - 6); getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6), name, name_len, NULL, 0, 0); return 0; } else #endif { memset(&ai, 0, sizeof ai); ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; ai.ai_flags = AI_CANONNAME; if (getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in), name, name_len, NULL, 0, 0)) return -1; if (!rip) return 0; if (getaddrinfo(name, NULL, &ai, &res)) return -1; while (!p && res) { switch (res->ai_family) { case AF_INET: p = &((struct sockaddr_in *)res->ai_addr)->sin_addr; break; } res = res->ai_next; } } if (!p) return -1; lws_plat_inet_ntop(AF_INET, p, rip, rip_len); return 0; }
void comm(SOCKET &sock) { CHAR rbuf[RBUFSIZE]; std::string sbuf, ckey, s, res; int i, n; BOOL recvflag = TRUE; while(recvflag) { ZeroMemory(rbuf, sizeof(rbuf)); n = recv(sock, rbuf, sizeof(rbuf) - 1, 0); if(n == SOCKET_ERROR || n <= 0) { disconnect(sock); return; } sbuf += rbuf; if(sbuf.empty()) { disconnect(sock); return; } switch(sbuf.front()) { case REQ_KEY: case REQ_CMP: if(rbuf[n - 1] == '\x20') { recvflag = FALSE; } break; case REQ_END: case REQ_VER: case REQ_HST: default: recvflag = FALSE; break; } } switch(sbuf.front()) { case REQ_END: disconnect(sock); return; break; case REQ_KEY: if(sbuf.size() > 2) { ckey = sbuf.substr(1, sbuf.size() - 2); n = (int)vdicinfo.size(); for(i = 0; i < n; i++) { s.clear(); if(vdicinfo[i].path.compare(0, wcslen(INIVAL_SKKSERV), INIVAL_SKKSERV) == 0) { search_skkserv(vdicinfo[i], ckey, s); } else if(vdicinfo[i].path.compare(0, wcslen(INIVAL_GOOGLECGIAPI), INIVAL_GOOGLECGIAPI) == 0) { search_google_cgiapi(vdicinfo[i], ckey, s); } else { search_dictionary(vdicinfo[i], ckey, s); } if(!s.empty()) { if(res.size() >= 2) { res.pop_back(); // '\n' res.pop_back(); // '/' } res += s; } } } if(res.empty()) { res.push_back(REP_NOT_FOUND); res.push_back('\n'); } else { res.insert(res.begin(), REP_FOUND); } break; case REQ_VER: res = resver; break; case REQ_HST: { CHAR host[NI_MAXHOST]; SOCKADDR_STORAGE sa; int len = sizeof(sa); if(getsockname(sock, (LPSOCKADDR)&sa, &len) == 0) { if(getnameinfo((LPSOCKADDR)&sa, len, host, _countof(host), nullptr, 0, NI_NAMEREQD) == 0) { res += host; res += "/"; } if(getnameinfo((LPSOCKADDR)&sa, len, host, _countof(host), nullptr, 0, NI_NUMERICHOST) == 0) { if(sa.ss_family == AF_INET6) res += "["; res += host; if(sa.ss_family == AF_INET6) res += "]"; res += ":"; res += WCTOU8(serv_port); res += "/\x20"; } } } break; case REQ_CMP: res.push_back(REP_NOT_FOUND); res.push_back('\n'); break; default: return; break; } if(send(sock, res.c_str(), (int)res.size(), 0) == SOCKET_ERROR) { disconnect(sock); return; } }
int main(int argc, char **argv) { int sfd = 0, s = 0; int efd = 0; struct epoll_event event = {}; struct epoll_event *events = NULL; if (argc != 2) { fprintf(stderr, "usage: %s [port]\n", argv[0]); exit(EXIT_FAILURE); } sfd = create_and_bind(argv[1]); if (sfd == -1) {abort();} fprintf(stdout, "sfd: %d\n", sfd); s = make_socket_non_blocking(sfd); if (s == -1) {abort();} s = listen(sfd, SOMAXCONN); if (s == -1) { perror("listen"); abort(); } efd = epoll_create(256); if (efd == -1) { perror("epoll_create1"); abort(); } event.data.fd = sfd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event); if (s == -1) { perror("epoll_ctl"); abort(); } //Buffer where events are returned events = calloc(MAXEVENTS, sizeof(event)); fprintf(stdout, "before event loop\n"); //The event loop while (1) { int n, i; n = epoll_wait(efd, events, MAXEVENTS, -1); fprintf(stdout, "epoll wait return: %d\n", n); for (i=0; i<n; i++) { fprintf(stdout, "events[%d].data.fd=%d\n", i, events[i].data.fd); if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { //an error has occured on this fd, or the socket is not ready for reading fprintf(stderr, "epoll error\n"); close(events[i].data.fd); continue; } else if (sfd == events[i].data.fd) { //we have a notification on the listening socket, which means one or more //incoming connections fprintf(stdout, "sfd == events[i].data.fd\n"); while (1) { struct sockaddr in_addr = {}; socklen_t in_len = 0; int infd = 0; char hbuf[NI_MAXHOST] = {}, sbuf[NI_MAXSERV] = {}; in_len = sizeof(in_addr); infd = accept(sfd, &in_addr, &in_len); if (infd == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { //we have processed all incoming connections fprintf(stderr, "accept error: %d\n", errno); break; } else { perror("accept"); break; } } fprintf(stdout, "infd=%d\n", infd); s = getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (s == 0) { printf("accepted connection on descriptor %d (host=%s, port=%s)\n", infd, hbuf, sbuf); } fprintf(stdout, "getnameinfo return s:%d\n", s); //make the incoming socket non-blocking and add it to the list of fds //to monitor s = make_socket_non_blocking(infd); if (s == -1) {abort();} event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror("epoll_ctl"); abort(); } } continue; } else { //we have data on the fd waiting to be read. Read and display it. We must read //whatever data is available completely, as we are running in edge-triggered //mode and won't get a notification again for the same data int done = 0; fprintf(stdout, "else\n"); while (1) { ssize_t count = 0; char buf[512] = "hello epoll"; count = read(events[i].data.fd, buf, sizeof(buf)); fprintf(stdout, "read return count=%d\n", count); if (count == -1) { //if errno == EAGAIN , that means we have read all data. //So go back to the main loop fprintf(stdout, "count==-1, errno:%d\n", errno); if (errno != EAGAIN) { perror("read"); done = 1; } break; } else if (count == 0) { //end of file. The remote has closed the connection fprintf(stdout, "count == 0\n"); done = -1; break; } printf("read data: %s\n", buf); //write the buffer to standard output s = write(STDOUT_FILENO, buf, count); if (s == -1) { perror("write"); abort(); } } if (done) { printf("closed connection on descriptor %d\n", events[i].data.fd); //closing the descriptor will make epoll remove it from the set of //descriptors which are monitored close(events[i].data.fd); } } } } free(events); events = NULL; close(sfd); return EXIT_SUCCESS; }
/* miniwget3() : * do all the work. * Return NULL if something failed. */ static void * miniwget3(const char * url, const char * host, unsigned short port, const char * path, int * size, char * addr_str, int addr_str_len, const char * httpversion) { char buf[2048]; int s; int n; int len; int sent; void * content; *size = 0; s = connecthostport(host, port); if(s < 0) return NULL; /* get address for caller ! */ if(addr_str) { struct sockaddr_storage saddr; socklen_t saddrlen; saddrlen = sizeof(saddr); if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) { perror("getsockname"); } else { #if defined(__amigaos__) && !defined(__amigaos4__) /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); * But his function make a string with the port : nn.nn.nn.nn:port */ /* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), NULL, addr_str, (DWORD *)&addr_str_len)) { printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); }*/ /* the following code is only compatible with ip v4 addresses */ strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); #else #if 0 if(saddr.sa_family == AF_INET6) { inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)&saddr)->sin6_addr), addr_str, addr_str_len); } else { inet_ntop(AF_INET, &(((struct sockaddr_in *)&saddr)->sin_addr), addr_str, addr_str_len); } #endif /* getnameinfo return ip v6 address with the scope identifier * such as : 2a01:e35:8b2b:7330::%4281128194 */ n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, addr_str, addr_str_len, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if(n != 0) { #ifdef _WIN32 fprintf(stderr, "getnameinfo() failed : %d\n", n); #else fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); #endif } #endif } #ifdef DEBUG printf("address miniwget : %s\n", addr_str); #endif } len = snprintf(buf, sizeof(buf), "GET %s HTTP/%s\r\n" "Host: %s:%d\r\n" "Connection: Close\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "\r\n", path, httpversion, host, port); sent = 0; /* sending the HTTP request */ while(sent < len) { n = send(s, buf+sent, len-sent, 0); if(n < 0) { perror("send"); closesocket(s); return NULL; } else { sent += n; } } content = getHTTPResponse(s, size); closesocket(s); return content; }
/* * Creates a listening socket and returns it in saddr_ptr. */ int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr ) { int fd, gret, saddrlen; struct addrinfo hints, *rp; socklen_t ssize = sizeof( struct sockaddr_storage ); struct sockaddr_storage saddrs, *saddr = &saddrs; static char errmsg[1024]; char *ftlisten = global.conf->ft_listen; if( errptr ) *errptr = errmsg; strcpy( port, "0" ); /* Format is <IP-A>[:<Port-A>];<IP-B>[:<Port-B>] where * A is for connections with the bitlbee client (DCC) * and B is for connections with IM peers. */ if( ftlisten ) { char *scolon = strchr( ftlisten, ';' ); char *colon; if( scolon ) { if( for_bitlbee_client ) { *scolon = '\0'; strncpy( host, ftlisten, HOST_NAME_MAX ); *scolon = ';'; } else { strncpy( host, scolon + 1, HOST_NAME_MAX ); } } else { strncpy( host, ftlisten, HOST_NAME_MAX ); } if( ( colon = strchr( host, ':' ) ) ) { *colon = '\0'; strncpy( port, colon + 1, 5 ); } } else if( copy_fd >= 0 && getsockname( copy_fd, (struct sockaddr*) &saddrs, &ssize ) == 0 && ( saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6 ) && getnameinfo( (struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX, NULL, 0, NI_NUMERICHOST ) == 0 ) { /* We just took our local address on copy_fd, which is likely to be a sensible address from which we can do a file transfer now - the most sensible we can get easily. */ } else { ASSERTSOCKOP( gethostname( host, HOST_NAME_MAX + 1 ), "gethostname()" ); } memset( &hints, 0, sizeof( struct addrinfo ) ); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICSERV; if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) != 0 ) { sprintf( errmsg, "getaddrinfo() failed: %s", gai_strerror( gret ) ); return -1; } saddrlen = rp->ai_addrlen; memcpy( saddr, rp->ai_addr, saddrlen ); freeaddrinfo( rp ); ASSERTSOCKOP( fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" ); ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, saddrlen ), "Binding socket" ); ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" ); if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ? ( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr : ( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr, host, HOST_NAME_MAX ) ) { strcpy( errmsg, "inet_ntop failed on listening socket" ); return -1; } ssize = sizeof( struct sockaddr_storage ); ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" ); if( saddr->ss_family == AF_INET ) g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in *) saddr )->sin_port ) ); else g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in6 *) saddr )->sin6_port ) ); if( saddr_ptr ) memcpy( saddr_ptr, saddr, saddrlen ); /* I hate static-length strings.. */ host[HOST_NAME_MAX] = '\0'; port[5] = '\0'; return fd; }
int main(int ac, char *av[]) { //initialize a lot of struct and data points needed struct addrinfo *in, *pin; struct addrinfo start; int sockets[10], socket_num = 0; allocatedMemory[0] = 0; myStruct *arg; pthread_t dthread; pthread_mutex_t *mutex; //clear the struct data values memset(&start, 0, sizeof start);//clear the object and then check for the right number of arguments passed if (ac < 3) { printf("Usage: %s -p <port>\n", av[0]), exit(0); } if (ac == 4) { printf("Usage: %s -p <port> -R <path>\n", av[0]), exit(0); } else if (ac == 5) { path = av[4]; } //set the flags for the correct type of server start.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_ADDRCONFIG; start.ai_protocol = IPPROTO_TCP; // only interested in TCP start.ai_family = AF_INET6; if (strcmp(av[1],"-p")) return -1; //gets the port number char *nport = av[2]; int gai = getaddrinfo(NULL, nport, &start, &in); if (gai != 0) { gai_strerror(gai); exit(-1); } char printed_addr[1024]; for (pin = in; pin; pin = pin->ai_next) { assert (pin->ai_protocol == IPPROTO_TCP); int gai = getnameinfo(pin->ai_addr, pin->ai_addrlen, printed_addr, sizeof printed_addr, NULL, 0, NI_NUMERICHOST); if (gai != 0) gai_strerror(gai), exit(-1); printf("%s: %s\n", pin->ai_family == AF_INET ? "AF_INET" : pin->ai_family == AF_INET6 ? "AF_INET6" : "?", printed_addr); int s = socket(pin->ai_family, pin->ai_socktype, pin->ai_protocol); if (s == -1) perror("socket"), exit(-1); int opt = 1; setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); gai = bind(s, pin->ai_addr, pin->ai_addrlen); if (gai == -1 && errno == EADDRINUSE) { // ignore Linux limitation close(s); continue; } if (gai == -1) perror("bind"), exit(-1); //begin listening on the socket gai = listen(s, 10); if (gai == -1) perror("listen"), exit(-1); assert(socket_num < sizeof(sockets)/sizeof(sockets[0])); sockets[socket_num++] = s; } freeaddrinfo(in); assert(socket_num == 1); //initialize mutex before accepting struct sockaddr_storage rem; socklen_t remlen = sizeof (rem); mutex = malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(mutex, NULL); while(1){ //accept a connection arg = malloc(sizeof(myStruct)); arg->mutex = mutex; //accept the connection arg->s = accept (sockets[0], (struct sockaddr *) &rem, &remlen); //if the connection works if (arg->s == -1) { pthread_mutex_lock(mutex); perror ("accept"); pthread_mutex_unlock(mutex); free(arg); pthread_mutex_destroy(mutex); exit(-1); } pthread_mutex_lock(mutex); char buffer[200]; //get information about the connection if (getnameinfo ((struct sockaddr *) &rem, remlen, buffer, sizeof (buffer), NULL, 0, 0)) strcpy (buffer, "???"); // hostname unknown char buf2[100]; (void) getnameinfo ((struct sockaddr *) &rem, remlen, buf2, sizeof (buf2), NULL, 0, NI_NUMERICHOST); printf ("connection from %s (%s)\n", buffer, buf2); //create the thread and call the echo functions //makes sure to lock and unlock and set the stack size pthread_mutex_unlock(mutex); arg->attribute = malloc(sizeof(pthread_attr_t)); pthread_attr_init(arg->attribute); pthread_attr_setstacksize(arg->attribute, PTHREAD_STACK_MIN+8192); pthread_attr_setdetachstate(arg->attribute, PTHREAD_CREATE_DETACHED); pthread_create(&dthread, arg->attribute, echo, arg); } return 0; }
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { int sd = -1; fd_set rset; struct timeval timeout; int ret_val; CfLock thislock; time_t last_collect = 0, 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(0); } 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 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, &last_policy_reload); } 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(COLLECT_WINDOW, &ServerEntryPoint); last_collect = now; continue; } /* 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); timeout.tv_sec = 60; timeout.tv_usec = 0; Log(LOG_LEVEL_DEBUG, "Waiting at incoming select..."); 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); } } } } 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; }
void NET_SendPacket ( netsrc_t sock, int length, void *data, netadr_t to ) { int ret; struct sockaddr_storage addr; int net_socket; int addr_size = sizeof(struct sockaddr_in); switch (to.type) { case NA_LOOPBACK: NET_SendLoopPacket(sock, length, data, to); return; break; case NA_BROADCAST: case NA_IP: net_socket = ip_sockets[sock]; if (!net_socket) { return; } break; case NA_IP6: case NA_MULTICAST6: net_socket = ip6_sockets[sock]; addr_size = sizeof(struct sockaddr_in6); if (!net_socket) { return; } break; case NA_IPX: case NA_BROADCAST_IPX: net_socket = ipx_sockets[sock]; if (!net_socket) { return; } break; default: Com_Error(ERR_FATAL, "NET_SendPacket: bad address type"); return; break; } NetadrToSockadr(&to, &addr); /* Re-check the address family. If to.type is NA_IP6 but contains an IPv4 mapped address, NetadrToSockadr will return an AF_INET struct. If so, switch back to AF_INET socket.*/ if ((to.type == NA_IP6) && (addr.ss_family == AF_INET)) { net_socket = ip_sockets[sock]; addr_size = sizeof(struct sockaddr_in); if (!net_socket) { return; } } if (addr.ss_family == AF_INET6) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&addr; /* If multicast socket, must specify scope. So multicast_interface must be specified */ if (IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) { struct addrinfo hints; struct addrinfo *res; char tmp[128], mcast_addr[128], mcast_port[10]; int error; if (multicast_interface != NULL) { /* Do a getnameinfo/getaddrinfo cycle to calculate the scope_id of the multicast address. getaddrinfo is passed a multicast address of the form ff0x::xxx%multicast_interface */ #ifdef __FreeBSD__ error = getnameinfo((struct sockaddr *)s6, s6->sin6_len, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST); #else error = getnameinfo((struct sockaddr *)s6, sizeof(struct sockaddr_in6), tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST); #endif if (error) { Com_Printf("NET_SendPacket: getnameinfo: %s\n", gai_strerror(error)); return; } Com_sprintf(mcast_addr, sizeof(mcast_addr), "%s%%%s", tmp, multicast_interface); Com_sprintf(mcast_port, sizeof(mcast_port), "%d", ntohs(s6->sin6_port)); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(mcast_addr, mcast_port, &hints, &res); if (error) { Com_Printf("NET_SendPacket: getaddrinfo: %s\n", gai_strerror(error)); return; } /* sockaddr_in6 should now have a valid scope_id. */ memcpy(s6, res->ai_addr, res->ai_addrlen); } else { Com_Printf("NET_SendPacket: IPv6 multicast destination but +set multicast not specified: %s\n", inet_ntop(AF_INET6, &s6->sin6_addr, tmp, sizeof(tmp))); return; } } } ret = sendto(net_socket, data, length, 0, (struct sockaddr *)&addr, addr_size); if (ret == -1) { Com_Printf("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), NET_AdrToString(to)); } }
int OpenReceiverChannel(void) { struct addrinfo *response, *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[10]; snprintf(servname, 10, "%d", CFENGINE_PORT); /* Resolve listening interface. */ if (getaddrinfo(ptr, servname, &query, &response) != 0) { Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)", GetErrorStr()); return -1; } int 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; } int yes = 1; if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { Log(LOG_LEVEL_ERR, "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)", GetErrorStr()); exit(1); } struct linger cflinger = { .l_onoff = 1, .l_linger = 60 }; if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &cflinger, sizeof(cflinger)) == -1) { Log(LOG_LEVEL_ERR, "Socket option SO_LINGER was not accepted. (setsockopt: %s)", GetErrorStr()); exit(1); } 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; } else { Log(LOG_LEVEL_ERR, "Could not bind server address. (bind: %s)", GetErrorStr()); cf_closesocket(sd); } } if (sd < 0) { Log(LOG_LEVEL_ERR, "Couldn't open/bind a socket"); exit(1); } freeaddrinfo(response); return sd; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, time_t *last_policy_reload) { time_t validated_at; Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config); if (*last_policy_reload < validated_at) { *last_policy_reload = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { Log(LOG_LEVEL_INFO, "Rereading policy file '%s'", config->input_file); /* Free & reload -- lock this to avoid access errors during reload */ EvalContextClear(ctx); free(SV.allowciphers); SV.allowciphers = NULL; DeleteItemList(SV.trustkeylist); DeleteItemList(SV.attackerlist); DeleteItemList(SV.nonattackerlist); DeleteItemList(SV.multiconnlist); DeleteAuthList(SV.admit); DeleteAuthList(SV.deny); DeleteAuthList(SV.varadmit); DeleteAuthList(SV.vardeny); DeleteAuthList(SV.roles); strcpy(VDOMAIN, "undefined.domain"); SV.admit = NULL; SV.admittop = NULL; SV.varadmit = NULL; SV.varadmittop = NULL; SV.deny = NULL; SV.denytop = NULL; SV.vardeny = NULL; SV.vardenytop = NULL; SV.roles = NULL; SV.rolestop = NULL; SV.trustkeylist = NULL; SV.attackerlist = NULL; SV.nonattackerlist = NULL; SV.multiconnlist = NULL; PolicyDestroy(*policy); *policy = NULL; { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); } UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); KeepHardClasses(ctx); EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); *policy = GenericAgentLoadPolicy(ctx, config); KeepPromises(ctx, *policy, config); Summarize(); } else { Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } }
char * inet6name(const unsigned char *in6) { char *cp; static char line[NI_MAXHOST]; static char domain[MAXHOSTNAMELEN]; static int first = 1; #ifdef NETSNMP_ENABLE_IPV6 struct hostent *hp; char hbuf[NI_MAXHOST]; const int niflag = NI_NUMERICHOST; struct sockaddr_in6 sin6; const struct in6_addr *in6p = (const struct in6_addr *)in6; #endif if (first && !nflag) { first = 0; if (gethostname(line, sizeof(line)) == 0 && (cp = strchr(line, '.'))) (void) strlcpy(domain, cp + 1, sizeof domain); else domain[0] = '\0'; } #ifdef NETSNMP_ENABLE_IPV6 cp = NULL; if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) { hp = netsnmp_gethostbyaddr((const char *)in6p, sizeof(*in6p), AF_INET6); if (hp) { if ((cp = strchr(hp->h_name, '.')) && !strcmp(cp + 1, domain)) *cp = 0; cp = hp->h_name; } } if (IN6_IS_ADDR_UNSPECIFIED(in6p)) strlcpy(line, "*", sizeof(line)); else if (cp) strlcpy(line, cp, sizeof(line)); else { memset(&sin6, 0, sizeof(sin6)); /* sin6.sin6_len = sizeof(sin6); */ sin6.sin6_family = AF_INET6; sin6.sin6_addr = *in6p; #ifdef __KAME__ if (IN6_IS_ADDR_LINKLOCAL(in6p) || IN6_IS_ADDR_MC_LINKLOCAL(in6p)) { sin6.sin6_scope_id = ntohs(*(const uint16_t *)&in6p->s6_addr[2]); sin6.sin6_addr.s6_addr[2] = 0; sin6.sin6_addr.s6_addr[3] = 0; } #endif if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) strlcpy(hbuf, "?", sizeof hbuf); strlcpy(line, hbuf, sizeof(line)); } #else strlcpy(line, "[[XXX - inet6 address]]", sizeof(line)); #endif return (line); }
/* * Setup to handle new incoming connections */ static void ssl_accept( const struct security_driver *driver, char * (*conf_fn)(char *, void *), int in, int out, void (*fn)(security_handle_t *, pkt_t *), void *datap) { sockaddr_union sin; socklen_t_equiv len = sizeof(struct sockaddr); struct tcp_conn *rc; char hostname[NI_MAXHOST]; int result; char *errmsg = NULL; int err; X509 *remote_cert; char *str; X509_NAME *x509_name; char *cert_hostname; SSL_CTX *ctx; SSL *ssl; int loc; char *ssl_dir = getconf_str(CNF_SSL_DIR); char *ssl_fingerprint_file = conf_fn("ssl_fingerprint_file", datap); char *ssl_cert_file = conf_fn("ssl_cert_file", datap); char *ssl_key_file = conf_fn("ssl_key_file", datap); char *ssl_ca_cert_file = conf_fn("ssl_ca_cert_file", datap); char *ssl_cipher_list = conf_fn("ssl_cipher_list", datap); int ssl_check_host = atoi(conf_fn("ssl_check_host", datap)); int ssl_check_certificate_host = atoi(conf_fn("ssl_check_certificate_host", datap)); if (getpeername(in, (struct sockaddr *)&sin, &len) < 0) { g_debug(_("getpeername returned: %s"), strerror(errno)); return; } if ((result = getnameinfo((struct sockaddr *)&sin, len, hostname, NI_MAXHOST, NULL, 0, 0) != 0)) { g_debug(_("getnameinfo failed: %s"), gai_strerror(result)); return; } if (ssl_check_host && check_name_give_sockaddr(hostname, (struct sockaddr *)&sin, &errmsg) < 0) { amfree(errmsg); return; } if (ssl_dir) { if (!ssl_cert_file || ssl_cert_file == '\0') { ssl_cert_file = g_strdup_printf("%s/me/crt.pem", ssl_dir); } if (!ssl_key_file || ssl_key_file == '\0') { ssl_key_file = g_strdup_printf("%s/me/private/key.pem", ssl_dir); } if (!ssl_ca_cert_file || ssl_ca_cert_file == '\0') { ssl_ca_cert_file = g_strdup_printf("%s/CA/crt.pem", ssl_dir); } } if (!ssl_cert_file) { g_debug(_("ssl-cert-file must be set in amanda-remote.conf")); return; } if (!ssl_key_file) { g_debug(_("ssl-key-file must be set in amanda-remote.conf")); return; } if (!ssl_ca_cert_file) { g_debug(_("ssl_ca_cert_file must be set in amanda-remote.conf")); return; } len = sizeof(sin); init_ssl(); /* Create a SSL_CTX structure */ #if OPENSSL_VERSION_NUMBER < 0x10100000L ctx = SSL_CTX_new(SSLv3_server_method()); #else ctx = SSL_CTX_new(TLS_server_method()); #endif if (!ctx) { g_debug(_("SSL_CTX_new failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); if (ssl_cipher_list) { g_debug("Set ssl_cipher_list to %s", ssl_cipher_list); if (SSL_CTX_set_cipher_list(ctx, ssl_cipher_list) == 0) { g_debug(_("SSL_CTX_set_cipher_list failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } } /* Load the me certificate into the SSL_CTX structure */ g_debug(_("Loading ssl-cert-file certificate %s"), ssl_cert_file); if (SSL_CTX_use_certificate_file(ctx, ssl_cert_file, SSL_FILETYPE_PEM) <= 0) { g_debug(_("Load ssl-cert-file failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } /* Load the private-key corresponding to the me certificate */ g_debug(_("Loading ssl-key-file private-key %s"), ssl_key_file); if (SSL_CTX_use_PrivateKey_file(ctx, ssl_key_file, SSL_FILETYPE_PEM) <= 0) { g_debug(_("Load ssl-key-file failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } if (ssl_ca_cert_file) { /* Load the RSA CA certificate into the SSL_CTX structure */ g_debug(_("Loading ssl-ca-cert-file ca certificate %s"), ssl_ca_cert_file); if (!SSL_CTX_load_verify_locations(ctx, ssl_ca_cert_file, NULL)) { g_debug(_("Load ssl-ca-cert-file failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } /* Set to require peer (remote) certificate verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); /* Set the verification depth to 1 */ SSL_CTX_set_verify_depth(ctx,1); } ssl = SSL_new(ctx); if (!ssl) { g_debug(_("SSL_new failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } SSL_set_accept_state(ssl); /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(ssl, in); /* Perform SSL Handshake on the SSL me */ err = SSL_accept(ssl); if (err == -1) { g_debug(_("SSL_accept failed: %s"), ERR_error_string(ERR_get_error(), NULL)); return; } /* Get the me's certificate (optional) */ remote_cert = SSL_get_peer_certificate (ssl); if (remote_cert == NULL) { g_debug(_("remote doesn't sent a certificate")); return; } x509_name = X509_get_subject_name(remote_cert); str = X509_NAME_oneline(X509_get_subject_name(remote_cert), 0, 0); auth_debug(1, _("\t subject: %s\n"), str); amfree (str); str = X509_NAME_oneline(X509_get_issuer_name(remote_cert), 0, 0); auth_debug(1, _("\t issuer: %s\n"), str); amfree(str); loc = -1; loc = X509_NAME_get_index_by_NID(x509_name, NID_commonName, loc); if (loc != -1) { X509_NAME_ENTRY *x509_entry = X509_NAME_get_entry(x509_name, loc); ASN1_STRING *asn1_string = X509_NAME_ENTRY_get_data(x509_entry); cert_hostname = (char *)ASN1_STRING_data(asn1_string); auth_debug(1, "common_name: %s\n", cert_hostname); if (ssl_check_certificate_host && check_name_give_sockaddr((char*)cert_hostname, (struct sockaddr *)&sin, &errmsg) < 0) { g_debug("Common name of certicate (%s) doesn't resolv to IP (%s)", cert_hostname, str_sockaddr(&sin)); amfree(errmsg); X509_free(remote_cert); return; } } else { g_debug("Certificate have no common name"); X509_free(remote_cert); return; } if (ssl_dir) { if (!ssl_fingerprint_file || ssl_fingerprint_file == '\0') { struct stat statbuf; ssl_fingerprint_file = g_strdup_printf("%s/remote/%s/fingerprint", ssl_dir, cert_hostname); if (stat(ssl_fingerprint_file, &statbuf) == -1) { g_free(ssl_fingerprint_file); ssl_fingerprint_file = NULL; } } } if (ssl_fingerprint_file) { g_debug(_("Loading ssl-fingerprint-file %s"), ssl_fingerprint_file); str = validate_fingerprints(remote_cert, ssl_fingerprint_file); if (str) { g_debug("%s", str); amfree(str); X509_free(remote_cert); return; } } X509_free(remote_cert); rc = sec_tcp_conn_get(NULL, hostname, 0); rc->recv_security_ok = &bsd_recv_security_ok; rc->prefix_packet = &bsd_prefix_packet; rc->need_priv_port = 0; copy_sockaddr(&rc->peer, &sin); rc->read = in; rc->write = out; rc->accept_fn = fn; rc->driver = driver; rc->conf_fn = conf_fn; rc->datap = datap; rc->ctx = ctx; rc->ssl = ssl; strncpy(rc->hostname, cert_hostname, sizeof(rc->hostname)-1); g_debug(_("SSL_cipher: %s"), SSL_get_cipher(rc->ssl)); sec_tcp_conn_read(rc); }
int IdentifyAgent(int sd) { char uname[CF_BUFSIZE], sendbuff[CF_BUFSIZE]; char dnsname[CF_MAXVARSIZE], localip[CF_MAX_IP_LEN]; int ret; if ((!SKIPIDENTIFY) && (strcmp(VDOMAIN, CF_START_DOMAIN) == 0)) { Log(LOG_LEVEL_ERR, "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 ... */ struct sockaddr_storage myaddr = {0}; socklen_t myaddr_len = sizeof(myaddr); if (getsockname(sd, (struct sockaddr *) &myaddr, &myaddr_len) == -1) { Log(LOG_LEVEL_ERR, "Couldn't get socket address. (getsockname: %s)", GetErrorStr()); return false; } /* No lookup, just convert the bound address to string. */ ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len, localip, sizeof(localip), NULL, 0, NI_NUMERICHOST); if (ret != 0) { Log(LOG_LEVEL_ERR, "During agent identification. (getnameinfo: %s)", gai_strerror(ret)); return false; } /* dnsname: Reverse lookup of the bound IP address. */ ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len, dnsname, sizeof(dnsname), NULL, 0, 0); if (ret != 0) { /* getnameinfo doesn't fail on resolution failure, it just prints * the IP, so here something else is wrong. */ Log(LOG_LEVEL_ERR, "During agent identification for '%s'. (getnameinfo: %s)", localip, gai_strerror(ret)); return false; } /* getnameinfo() should always return FQDN. Some resolvers will not * return FQNAME and missing PTR will give numerical result */ if ((strlen(VDOMAIN) > 0) /* TODO true always? */ && (!IsIPV6Address(dnsname)) && (!strchr(dnsname, '.'))) { strcat(dnsname, "."); strncat(dnsname, VDOMAIN, CF_MAXVARSIZE / 2); } /* Seems to be a bug in some resolvers that adds garbage, when it just * returns the input. */ if (strncmp(dnsname, localip, strlen(localip)) == 0 && dnsname[strlen(localip)] != '\0') { dnsname[strlen(localip)] = '\0'; Log(LOG_LEVEL_WARNING, "getnameinfo() seems to append garbage to unresolvable IPs, bug mitigated by CFEngine but please report your platform!"); } } else { assert(sizeof(localip) >= sizeof(VIPADDRESS)); strcpy(localip, VIPADDRESS); Log(LOG_LEVEL_VERBOSE, "skipidentify was promised, so we are trusting and simply announcing the identity as '%s' for this host", strlen(VFQNAME) > 0 ? VFQNAME : "skipident"); if (strlen(VFQNAME) > 0) { strcpy(dnsname, VFQNAME); } else { strcpy(dnsname, "skipident"); } } /* client always identifies as root on windows */ #ifdef __MINGW32__ snprintf(uname, sizeof(uname), "%s", "root"); #else GetCurrentUserName(uname, sizeof(uname)); #endif snprintf(sendbuff, sizeof(sendbuff), "CAUTH %s %s %s %d", localip, dnsname, uname, 0); if (SendTransaction(sd, sendbuff, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "During identify agent, could not send auth response. (SendTransaction: %s)", GetErrorStr()); return false; } return true; }
char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format) { struct ast_sockaddr sa_ipv4; const struct ast_sockaddr *sa_tmp; char host[NI_MAXHOST]; char port[NI_MAXSERV]; struct ast_str *str; int e; static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4; if (ast_sockaddr_isnull(sa)) { return "(null)"; } if (!(str = ast_str_thread_get(&ast_sockaddr_stringify_buf, size))) { return ""; } if (ast_sockaddr_ipv4_mapped(sa, &sa_ipv4)) { sa_tmp = &sa_ipv4; } else { sa_tmp = sa; } if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa_tmp->len, format & AST_SOCKADDR_STR_ADDR ? host : NULL, format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0, format & AST_SOCKADDR_STR_PORT ? port : 0, format & AST_SOCKADDR_STR_PORT ? sizeof(port): 0, NI_NUMERICHOST | NI_NUMERICSERV))) { ast_log(LOG_ERROR, "getnameinfo(): %s\n", gai_strerror(e)); return ""; } if ((format & AST_SOCKADDR_STR_REMOTE) == AST_SOCKADDR_STR_REMOTE) { char *p; if (ast_sockaddr_is_ipv6_link_local(sa) && (p = strchr(host, '%'))) { *p = '\0'; } } switch ((format & AST_SOCKADDR_STR_FORMAT_MASK)) { case AST_SOCKADDR_STR_DEFAULT: ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ? "[%s]:%s" : "%s:%s", host, port); break; case AST_SOCKADDR_STR_ADDR: ast_str_set(&str, 0, "%s", host); break; case AST_SOCKADDR_STR_HOST: ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host); break; case AST_SOCKADDR_STR_PORT: ast_str_set(&str, 0, "%s", port); break; default: ast_log(LOG_ERROR, "Invalid format\n"); return ""; } return ast_str_buffer(str); }
/* * Return a socket bound to an appropriate port number/address. Exits * the program on failure. */ static int get_socket(int **sa, int *nsa) { char host[NI_MAXHOST], serv[NI_MAXHOST]; struct addrinfo hint, *res, *rp; u_long inaddr; int ecode, flag, kalive = 1, s; memset(&hint, 0, sizeof(struct addrinfo)); hint.ai_family = AF_UNSPEC; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = IPPROTO_TCP; hint.ai_flags = AI_PASSIVE; #ifdef AI_ADDRCONFIG hint.ai_flags |= AI_ADDRCONFIG; #endif if (bind_address) ecode = getaddrinfo(bind_address, portstr, &hint, &res); else ecode = getaddrinfo(NULL, portstr, &hint, &res); if (ecode != 0) { report(LOG_ERR, "getaddrinfo: %s\n", gai_strerror(ecode)); tac_exit(1); } *sa = NULL; *nsa = 0; for (rp = res; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s == -1) continue; if (1 || debug & DEBUG_PACKET_FLAG) report(LOG_DEBUG, "socket FD %d AF %d", s, rp->ai_family); flag = 1; if (rp->ai_family == AF_INET6) setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)); #ifdef SO_REUSEADDR if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) perror("setsockopt - SO_REUSEADDR"); #endif if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&kalive, sizeof(kalive)) < 0) perror("setsockopt - SO_KEEPALIVE"); flag = 0; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)) < 0) perror("setsockopt - SO_NODELAY"); if (bind(s, rp->ai_addr, rp->ai_addrlen) < 0) { console = 1; ecode = errno; if (lookup_peer) flag = 0; else flag = NI_NUMERICHOST | NI_NUMERICSERV; if (getnameinfo(rp->ai_addr, rp->ai_addrlen, host, NI_MAXHOST, serv, NI_MAXHOST, flag)) { strncpy(host, "unknown", NI_MAXHOST - 1); host[NI_MAXHOST - 1] = '\0'; strncpy(serv, "unknown", NI_MAXHOST - 1); serv[NI_MAXHOST - 1] = '\0'; } report(LOG_ERR, "get_socket: bind %s:%s %s", host, serv, strerror(ecode)); console = 0; close(s); s = -1; continue; } if (*sa == NULL) *sa = malloc(sizeof(int) * ++(*nsa)); else *sa = realloc(*sa, sizeof(int) * ++(*nsa)); if (*sa == NULL) { report(LOG_ERR, "malloc failure: %s", strerror(errno)); tac_exit(1); } (*sa)[*nsa - 1] = s; } freeaddrinfo(res); if (*nsa < 1) { console = 1; report(LOG_ERR, "get_socket: could not bind a listening socket"); tac_exit(1); } return(0); }