Пример #1
0
/** Resolve name and wait for the result.
 * This will lookup a name from the cache and return the value if available.
 * If there is no entry in the cache this will order a concurrent lookup of the
 * name and wait for the result.
 * @param name name to resolve
 * @param addr contains a pointer to the address record upon return, this record
 * is in the cache, so you may not free the resulting address! The address is
 * always of type struct sockaddr_in (IPv4) at the moment.
 * @param addrlen contains the length of addr in bytes upon return
 * @return true if resolution was successful, false otherwise
 */
bool
NetworkNameResolver::resolve_name_blocking(const char *name,
					   struct sockaddr **addr, socklen_t *addrlen)
{
  if ( resolve_name(name, addr, addrlen) ) {
    return true;
  } else {
    struct sockaddr *_addr;
    socklen_t _addrlen;
    if ( resolver_thread->resolve_name_immediately(name, &_addr, &_addrlen) ) {
      name_resolved(strdup(name), _addr, _addrlen);
      *addr = _addr;
      *addrlen = _addrlen;
      return true;
    } else {
      return false;
    }
  }
}
Пример #2
0
int main(void)
{
	int cfd;
	int ifd;

	struct hosts hostlist[NUM_CACHE_ENTRIES];
	char logmsg[160];

	unsigned int hostindex = 0;
	unsigned int lastfree = 0;
	unsigned int hi = 0;
	int readyidx = 0;
	int fr = 0;
	int maxlogged = 0;

	struct rvn rvnpacket;

	int br;

	int ss = 0;

	fd_set sockset;

	struct sockaddr_un csa, isa;	/* child and iptraf comm sockets */
	struct sockaddr_un fromaddr;
	socklen_t fromlen;

	FILE *logfile;

	/* Daemonization Sequence */

#ifndef DEBUG
	switch (fork()) {
	case -1:
		exit(1);
	case 0:
		break;
	default:
		exit(0);
	}

	setsid();
	int i = chdir("/");

	(void) i;
#endif

	signal(SIGCHLD, childreap);

	logfile = fopen(RVNDLOGFILE, "a");

	if (logfile == NULL)
		logfile = fopen("/dev/null", "a");

	writervnlog(logfile, "******** rvnamed started ********");
	writervnlog(logfile, "Clearing socket names");

	/*
	 * Get rid of any residue socket names in case of a previous
	 * abormal termination of rvnamed.
	 */

	unlink(CHILDSOCKNAME);
	unlink(IPTSOCKNAME);

	writervnlog(logfile, "Opening sockets");
	csa.sun_family = AF_UNIX;
	strcpy(csa.sun_path, CHILDSOCKNAME);

	isa.sun_family = AF_UNIX;
	strcpy(isa.sun_path, IPTSOCKNAME);

	cfd = socket(PF_UNIX, SOCK_DGRAM, 0);

	if (cfd < 0) {
		writervnlog(logfile,
			    "Unable to open child communication socket, aborting");
		exit(1);
	}
	if (bind
	    (cfd, (struct sockaddr *) &csa,
	     sizeof(csa.sun_family) + strlen(csa.sun_path)) < 0) {
		writervnlog(logfile,
			    "Error binding child communication socket, aborting");
		exit(1);
	}
	ifd = socket(PF_UNIX, SOCK_DGRAM, 0);

	if (ifd < 0) {
		writervnlog(logfile,
			    "Unable to open client communication socket, aborting");
		exit(1);
	}
	if (bind
	    (ifd, (struct sockaddr *) &isa,
	     sizeof(isa.sun_family) + strlen(isa.sun_path)) < 0) {
		writervnlog(logfile,
			    "Error binding client communication socket, aborting");
		exit(1);
	}
	while (1) {
		FD_ZERO(&sockset);
		FD_SET(cfd, &sockset);
		FD_SET(ifd, &sockset);

		do {
			ss = select(ifd + 1, &sockset, NULL, NULL, NULL);
		} while ((ss < 0) && (errno != ENOMEM));

		if (errno == ENOMEM) {
			writervnlog(logfile,
				    "Fatal error: no memory for descriptor monitoring");
			close(ifd);
			close(cfd);
			fclose(logfile);
			exit(1);
		}
		/*
		 * Code to process packets coming from the forked child.
		 */

		if (FD_ISSET(cfd, &sockset)) {
			fromlen =
			    sizeof(fromaddr.sun_family) +
			    strlen(fromaddr.sun_path);
			br = recvfrom(cfd, &rvnpacket, sizeof(struct rvn), 0,
				      (struct sockaddr *) &fromaddr, &fromlen);

			if (br > 0) {
				hi = 0;

				while (hi <= lastfree) {
					if ((hostlist[hi].addr ==
					     rvnpacket.saddr.s_addr)
					    && !memcmp(rvnpacket.s6addr.s6_addr,
						       hostlist[hi].addr6,
						       sizeof(hostlist[hi].
							      addr6)))
						break;
					hi++;
				}

				if (hi == lastfree) {	/* Address not in cache */
					memset(&(hostlist[hi]), 0,
					       sizeof(struct hosts));
					hi = hostindex;
					hostindex++;
					if (hostindex == NUM_CACHE_ENTRIES)
						hostindex = 0;

					hostlist[hi].addr =
					    rvnpacket.saddr.s_addr;
					memcpy(hostlist[hi].addr6,
					       rvnpacket.s6addr.s6_addr,
					       sizeof(hostlist[hi].addr6));
				}
				strncpy(hostlist[hi].fqdn, rvnpacket.fqdn, 44);

				hostlist[hi].ready = RESOLVED;
			}
		}
		/*
		 * This code section processes packets received from the IPTraf
		 * program.
		 */

		if (FD_ISSET(ifd, &sockset)) {
			fromlen = sizeof(struct sockaddr_un);
			br = recvfrom(ifd, &rvnpacket, sizeof(struct rvn), 0,
				      (struct sockaddr *) &fromaddr, &fromlen);
			if (br > 0) {
				switch (rvnpacket.type) {
				case RVN_HELLO:
					sendto(ifd, &rvnpacket,
					       sizeof(struct rvn), 0,
					       (struct sockaddr *)
					       &fromaddr,
					       sizeof(fromaddr.sun_family) +
					       strlen(fromaddr.sun_path));
					break;
				case RVN_QUIT:
#ifndef DEBUG
					writervnlog(logfile,
						    "Received quit instruction");
					writervnlog(logfile, "Closing sockets");
					close(ifd);
					close(cfd);
					writervnlog(logfile,
						    "Clearing socket names");
					unlink(IPTSOCKNAME);
					unlink(CHILDSOCKNAME);
					sprintf(logmsg,
						"rvnamed terminating: max processes spawned: %d",
						max_fork_count);
					writervnlog(logfile, logmsg);
					writervnlog(logfile,
						    "******** rvnamed terminated ********");
					fclose(logfile);
					exit(0);
#endif
				case RVN_REQUEST:
					readyidx =
					    name_resolved(&rvnpacket, hostlist,
							  lastfree);
					if (readyidx >= 0) {
						rvnpacket.type = RVN_REPLY;
						memset(rvnpacket.fqdn, 0, 45);
						strncpy(rvnpacket.fqdn,
							hostlist[readyidx].fqdn,
							44);
						rvnpacket.ready = RESOLVED;

						br = sendto(ifd, &rvnpacket,
							    sizeof(struct rvn),
							    0,
							    (struct sockaddr *)
							    &fromaddr,
							    sizeof(fromaddr.
								   sun_family)
							    +
							    strlen(fromaddr.
								   sun_path));
					} else {

						/*
						 * Add this IP address to the cache if this is a
						 * new one.
						 */

						if (addrstat
						    (&rvnpacket, hostlist,
						     lastfree) == NOTRESOLVED) {
							fflush(logfile);	/* flush all data prior */
							/* to fork() */

							if (fork_count <=
							    MAX_RVNAMED_CHILDREN)
							{
								/*
								 * If we can still fork(), we add the data
								 * to the cache array, but we don't update
								 * the indexes until after the fork()
								 * succeeds.  If the fork() fails, we'll
								 * just reuse this slot for the next query.
								 *
								 * This is so that if the fork() fails due
								 * to a temporary condition, rvnamed won't
								 * think it's RESOLVING while there isn't
								 * any actual child doing the resolution
								 * before the entry expires.
								 *
								 * However, we'll still tell IPTraf that the
								 * address is RESOLVING.
								 *
								 */
								hostlist
								    [hostindex].
								    addr =
								    rvnpacket.
								    saddr.
								    s_addr;
								memcpy(hostlist
								       [hostindex].
								       addr6,
								       rvnpacket.
								       s6addr.
								       s6_addr,
								       sizeof
								       (hostlist
									[hostindex].
									addr6));
								hostlist
								    [hostindex].
								    ready =
								    RESOLVING;

								maxlogged = 0;
								fr = fork();
							} else {
								fr = -1;
								if (!maxlogged)
									writervnlog
									    (logfile,
									     "Maximum child process limit reached");
								maxlogged = 1;
							}

							switch (fr) {
							case 0:	/* spawned child */
								fclose(logfile);	/* no logging in child */
								close(ifd);	/* no comm with client */

								/*
								 * Set auto-terminate timeout
								 */
								signal(SIGALRM,
								       auto_terminate);
								alarm(300);
								process_rvn_packet
								    (&rvnpacket);
								exit(0);
							case -1:
								if (!maxlogged)
									writervnlog
									    (logfile,
									     "Error on fork, returning IP address");
								break;
							default:	/* parent */
								if (fork_count >
								    max_fork_count)
									max_fork_count
									    =
									    fork_count;

								/*
								 * Increase cache indexes only if fork()
								 * succeeded, otherwise the previously
								 * allocated slots will be used for the
								 * next query.
								 */

								hostindex++;

								if (hostindex ==
								    NUM_CACHE_ENTRIES)
									hostindex
									    = 0;

								if (lastfree <
								    NUM_CACHE_ENTRIES)
									lastfree++;

								fork_count++;
								break;
							}
						}
						rvnpacket.type = RVN_REPLY;
						memset(rvnpacket.fqdn, 0, 45);
						if (rvnpacket.saddr.s_addr != 0)
							strcpy(rvnpacket.fqdn,
							       inet_ntoa
							       (rvnpacket.
								saddr));
						else
							inet_ntop(AF_INET6,
								  &rvnpacket.
								  s6addr,
								  rvnpacket.
								  fqdn,
								  sizeof
								  (rvnpacket.
								   fqdn));
						rvnpacket.ready = RESOLVING;

						br = sendto(ifd, &rvnpacket,
							    sizeof(struct rvn),
							    0,
							    (struct sockaddr *)
							    &fromaddr,
							    sizeof(fromaddr.
								   sun_family)
							    +
							    strlen(fromaddr.
								   sun_path));

					}
				}
			}
		}		/* end block for packets from IPTraf */
	}
}