コード例 #1
0
ファイル: unsquashfs_info.c プロジェクト: Distrotech/squashfs
void dump_state()
{
	disable_progress_bar();

	printf("Queue and cache status dump\n");
	printf("===========================\n");

	printf("file buffer read queue (main thread -> reader thread)\n");
	dump_queue(to_reader);

	printf("file buffer decompress queue (reader thread -> inflate"
							" thread(s))\n");
	dump_queue(to_inflate);

	printf("file buffer write queue (main thread -> writer thread)\n");
	dump_queue(to_writer);

	printf("\nbuffer cache (uncompressed blocks and compressed blocks "
							"'in flight')\n");
	dump_cache(data_cache);

	printf("fragment buffer cache (uncompressed frags and compressed"
						" frags 'in flight')\n");
	dump_cache(fragment_cache);

	enable_progress_bar();
}
コード例 #2
0
ファイル: hdt-dump-dmi.c プロジェクト: 1stMaster/syslinux
void dump_dmi(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {

	CREATE_NEW_OBJECT;
	add_hb(is_dmi_valid);

	if (hardware->is_dmi_valid == false) {
		FLUSH_OBJECT;
		goto exit;
	} else {
		char buffer[8]={0};
		snprintf(buffer,sizeof(buffer),"%d.%d",hardware->dmi.dmitable.major_version, hardware->dmi.dmitable.minor_version);
		add_s("dmi.version",buffer);
		FLUSH_OBJECT;
	}

	dump_base_board(hardware,config,item);
	dump_system(hardware,config,item);
	dump_bios(hardware,config,item);
	dump_chassis(hardware,config,item);
	dump_ipmi(hardware,config,item);
	dump_battery(hardware,config,item);
	dump_processor(hardware,config,item);
	dump_cache(hardware,config,item);
	dump_memory_banks(hardware,config,item);
	dump_memory_modules(hardware,config,item);
	dump_memory_size(hardware,config,item);
	dump_oem_strings(hardware,config,item);
	dump_hardware_security(hardware,config,item);
exit:
	to_cpio("dmi");
}
コード例 #3
0
ファイル: huge.c プロジェクト: lucab/gtk-gnutella
bool
huge_update_hashes(shared_file_t *sf,
	const struct sha1 *sha1, const struct tth *tth)
{
	struct sha1_cache_entry *cached;
	filestat_t sb;

	shared_file_check(sf);
	g_return_val_if_fail(sha1, FALSE);

	/*
	 * Make sure the file's timestamp is still accurate.
	 */

	if (-1 == stat(shared_file_path(sf), &sb)) {
		g_warning("discarding SHA1 for file \"%s\": can't stat(): %m",
			shared_file_path(sf));
		shared_file_remove(sf);
		return TRUE;
	}

	if (sb.st_mtime != shared_file_modification_time(sf)) {
		g_warning("file \"%s\" was modified whilst SHA1 was computed",
			shared_file_path(sf));
		shared_file_set_modification_time(sf, sb.st_mtime);
		request_sha1(sf);					/* Retry! */
		return TRUE;
	}

	if (huge_spam_check(sf, sha1)) {
		shared_file_remove(sf);
		return FALSE;
	}

	shared_file_set_sha1(sf, sha1);
	shared_file_set_tth(sf, tth);

	/* Update cache */

	cached = hikset_lookup(sha1_cache, shared_file_path(sf));

	if (cached) {
		update_volatile_cache(cached, shared_file_size(sf),
			shared_file_modification_time(sf), sha1, tth);
		cache_dirty = TRUE;

		/* Dump the cache at most about once per minute. */
		if (!cache_dumped || delta_time(tm_time(), cache_dumped) > 60) {
			dump_cache(FALSE);
		}
	} else {
		add_volatile_cache_entry(shared_file_path(sf),
			shared_file_size(sf), shared_file_modification_time(sf),
			sha1, tth, TRUE);
		add_persistent_cache_entry(shared_file_path(sf),
			shared_file_size(sf), shared_file_modification_time(sf),
			sha1, tth);
	}
	return TRUE;
}
コード例 #4
0
ファイル: huge.c プロジェクト: lucab/gtk-gnutella
/**
 * Read the whole persistent cache into memory.
 */
static G_GNUC_COLD void
sha1_read_cache(void)
{
	FILE *f;
	file_path_t fp[1];
	bool truncated = FALSE;

	g_return_if_fail(settings_config_dir());

	file_path_set(fp, settings_config_dir(), "sha1_cache");
	f = file_config_open_read("SHA-1 cache", fp, G_N_ELEMENTS(fp));
	if (f) {
		for (;;) {
			char buffer[4096];

			if (NULL == fgets(buffer, sizeof buffer, f))
				break;

			if (!file_line_chomp_tail(buffer, sizeof buffer, NULL)) {
				truncated = TRUE;
			} else if (truncated) {
				truncated = FALSE;
			} else {
				parse_and_append_cache_entry(buffer);
			}
		}
		fclose(f);
		dump_cache(TRUE);
	}
}
コード例 #5
0
ファイル: group.cpp プロジェクト: NeoRaider/mrd6
void aggr_source_discovery::dump_cache(base_stream &out) const {
	out.writeline("Source cache");

	out.inc_level();

	dump_cache(out, m_cache);

	out.dec_level();
}
コード例 #6
0
ファイル: dnsmasq.c プロジェクト: gittestusername/uClinux
int main (int argc, char **argv)
{
  char *int_err_string;
  int cachesize = CACHESIZ;
  int port = NAMESERVER_PORT;
  int query_port = 0;
  unsigned long local_ttl = 0;
  int logged_lease = 0, first_loop = 1;
  unsigned int options;
  char *runfile = RUNFILE;
  time_t resolv_changed = 0;
  time_t now, last = 0;
  time_t lease_file_change = 0;
  ino_t lease_file_inode = (ino_t)0;
  struct irec *iface, *interfaces = NULL;
  char *mxname = NULL;
  char *mxtarget = NULL;
  char *lease_file = NULL;
  char *addn_hosts = NULL;
  char *domain_suffix = NULL;
  char *username = CHUSER;
  char *groupname = CHGRP;
  struct iname *if_names = NULL;
  struct iname *if_addrs = NULL;
  struct iname *if_except = NULL;
  struct iname *if_tmp;
  struct server *serv_addrs = NULL;
  char *dnamebuff, *packet;
  struct server *servers, *last_server;
  struct resolvc default_resolv = { NULL, 1, 0, RESOLVFILE };
  struct resolvc *resolv = &default_resolv;
  struct bogus_addr *bogus_addr = NULL;
  struct serverfd *serverfdp, *sfds = NULL;

  sighup = 1; /* init cache the first time through */
  sigusr1 = 0; /* but don't dump */
  sigusr2 = 0; /* or rescan interfaces */
  signal(SIGUSR1, sig_handler);
  signal(SIGUSR2, sig_handler);
  signal(SIGHUP, sig_handler);

  /* These get allocated here to avoid overflowing the small stack
     on embedded systems. dnamebuff is big enough to hold one
     maximal sixed domain name and gets passed into all the processing
     code. We manage to get away with one buffer. */
  dnamebuff = safe_malloc(MAXDNAME);
  /* Size: we check after adding each record, so there must be 
     memory for the largest packet, and the largest record */
  packet = safe_malloc(PACKETSZ+MAXDNAME+RRFIXEDSZ);
  
  options = read_opts(argc, argv, dnamebuff, &resolv, &mxname, &mxtarget, &lease_file,
		      &username, &groupname, &domain_suffix, &runfile, 
		      &if_names, &if_addrs, &if_except, &bogus_addr, 
		      &serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts);
  
  int_err_string = enumerate_interfaces(&interfaces, if_names, if_addrs, if_except, port);
  
  if (int_err_string)
    die(int_err_string, NULL);
  
  for (if_tmp = if_names; if_tmp; if_tmp = if_tmp->next)
    if (if_tmp->name && !if_tmp->found)
      die("unknown interface %s", if_tmp->name);
  
  for (if_tmp = if_addrs; if_tmp; if_tmp = if_tmp->next)
    if (!if_tmp->found)
      {
	char addrbuff[ADDRSTRLEN];
#ifdef HAVE_IPV6
	if (if_tmp->addr.sa.sa_family == AF_INET)
	  inet_ntop(AF_INET, &if_tmp->addr.in.sin_addr,
		    addrbuff, ADDRSTRLEN);
	  else
	    inet_ntop(AF_INET6, &if_tmp->addr.in6.sin6_addr,
		      addrbuff, ADDRSTRLEN);
#else
	strcpy(addrbuff, inet_ntoa(if_tmp->addr.in.sin_addr));
#endif
	die("no interface with address %s", addrbuff);
      }
      
  forward_init(1);

  cache_init(cachesize, options & OPT_LOG);
  
  setbuf(stdout, NULL);

  if (!(options & OPT_DEBUG))
    {
      FILE *pidfile;
      struct passwd *ent_pw;
      int i;
        
      /* The following code "daemonizes" the process. 
	 See Stevens section 12.4 */

#ifndef NO_FORK
      if (fork() != 0 )
	exit(0);
      
      setsid();
      
      if (fork() != 0)
	exit(0);
#endif
      
      chdir("/");
      umask(022); /* make pidfile 0644 */
      
      /* write pidfile _after_ forking ! */
      if (runfile && (pidfile = fopen(runfile, "w")))
      	{
	  fprintf(pidfile, "%d\n", (int) getpid());
	  fclose(pidfile);
	}
      
      umask(0);

      for (i=0; i<64; i++)
	{
	  for (iface = interfaces; iface; iface = iface->next)
	    if (iface->fd == i)
	      break;
	  if (iface)
	    continue;
	  
	  close(i);
	}

      /* Change uid and gid for security */
      if (username && (ent_pw = getpwnam(username)))
	{
	  gid_t dummy;
	  struct group *gp;
	  /* remove all supplimentary groups */
	  setgroups(0, &dummy);
	  /* change group for /etc/ppp/resolv.conf 
	     otherwise get the group for "nobody" */
	  if ((groupname && (gp = getgrnam(groupname))) || 
	      (gp = getgrgid(ent_pw->pw_gid)))
	    setgid(gp->gr_gid); 
	  /* finally drop root */
	  setuid(ent_pw->pw_uid);
	}
    }

  openlog("dnsmasq", 
	  DNSMASQ_LOG_OPT(options & OPT_DEBUG), 
	  DNSMASQ_LOG_FAC(options & OPT_DEBUG));
  
  if (cachesize)
    syslog(LOG_INFO, "started, version %s cachesize %d", VERSION, cachesize);
  else
    syslog(LOG_INFO, "started, version %s cache disabled", VERSION);
  
  if (options & OPT_LOCALMX)
    syslog(LOG_INFO, "serving MX record for local hosts target %s", mxtarget);
  else if (mxname)
    syslog(LOG_INFO, "serving MX record for mailhost %s target %s", 
	   mxname, mxtarget);
  
  if (getuid() == 0 || geteuid() == 0)
    syslog(LOG_WARNING, "failed to drop root privs");
  
  servers = last_server = check_servers(serv_addrs, interfaces, &sfds);
  
  while (1)
    {
      int ready, maxfd = 0;
      fd_set rset;
      HEADER *header;
      struct stat statbuf;
   
      if (first_loop)
	/* do init stuff only first time round. */
	{
	  first_loop = 0;
	  ready = 0;
	}
      else
	{
	  FD_ZERO(&rset);

	  for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
	    {
	      FD_SET(serverfdp->fd, &rset);
	      if (serverfdp->fd > maxfd)
		maxfd = serverfdp->fd;
	    }

	  for (iface = interfaces; iface; iface = iface->next)
	    {
	      FD_SET(iface->fd, &rset);
	      if (iface->fd > maxfd)
		maxfd = iface->fd;
	    }
	  
	  ready = select(maxfd+1, &rset, NULL, NULL, NULL);
	  
	  if (ready == -1)
	    {
	      if (errno == EINTR)
		ready = 0; /* do signal handlers */
	      else
		continue;
	    }
	}
      
      if (sighup)
	{
	  signal(SIGHUP, SIG_IGN);
	  cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
	  if (resolv && (options & OPT_NO_POLL))
	    servers = last_server = 
	      check_servers(reload_servers(resolv->name, dnamebuff, servers, query_port), 
			    interfaces, &sfds);
	  sighup = 0;
	  signal(SIGHUP, sig_handler);
	}
      
      if (sigusr1)
	{
	  signal(SIGUSR1, SIG_IGN);
	  dump_cache(options & (OPT_DEBUG | OPT_LOG), cachesize);
	  sigusr1 = 0;
	  signal(SIGUSR1, sig_handler);
	}
      
      if (sigusr2)
	{
	  signal(SIGUSR2, SIG_IGN);
	  if (getuid() != 0 && port <= 1024)
	    syslog(LOG_ERR, "cannot re-scan interfaces unless --user=root");
	  else
	   {
	     syslog(LOG_INFO, "rescanning network interfaces");
	     int_err_string = enumerate_interfaces(&interfaces, if_names, if_addrs, if_except, port);
	     if (int_err_string)
	       syslog(LOG_ERR, int_err_string, strerror(errno));
	   }
	  sigusr2 = 0;
	  signal(SIGUSR2, sig_handler);
	  /* may be new file descriptors now, so redo select() */
	  ready = 0;
	}
      
      now = time(NULL);

      /* Check for changes to resolv files and DHCP leases file once per second max. */
      if (last == 0 || now > last)
	{
	  last = now;
	  if (!(options & OPT_NO_POLL))
	    {
	      struct resolvc *res = resolv, *latest = NULL;
	      time_t last_change = 0;
	      /* There may be more than one possible file. 
		 Go through and find the one which changed _last_.
		 Warn of any which can't be read. */
	      while (res)
		{
		  if (stat(res->name, &statbuf) == -1)
		    {
		      if (!res->logged)
			syslog(LOG_WARNING, "failed to access %s: %m", res->name);
		      res->logged = 1;
		    }
		  else
		    {
		      res->logged = 0;
		      if (statbuf.st_mtime > last_change)
			{
			  last_change = statbuf.st_mtime;
			  latest = res;
			}
		    }
		  res = res->next;
		}
	  
	      if (latest && last_change > resolv_changed)
		{
		  resolv_changed = last_change;
		  servers = last_server = 
		    check_servers(reload_servers(latest->name, dnamebuff, servers, query_port),
				  interfaces, &sfds);
		}
	    }

	  if (lease_file)
	    {
syslog(LOG_WARNING, "checking lease file %s", lease_file);
	      if (stat(lease_file, &statbuf) == -1)
		{
		  if (!logged_lease)
		    syslog(LOG_WARNING, "failed to access %s: %m", lease_file);
		  logged_lease = 1;
		}
	      else
		{ 
		  logged_lease = 0;
		  if ((statbuf.st_mtime != lease_file_change) ||
		      (statbuf.st_ino != lease_file_inode))
		    {
		      lease_file_change = statbuf.st_mtime;
		      lease_file_inode = statbuf.st_ino;
		      load_dhcp(lease_file, domain_suffix, now, dnamebuff);
		    }
		}
	    }
	}
		
      if (ready == 0)
	continue; /* no sockets ready */
      
       for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
	 if (FD_ISSET(serverfdp->fd, &rset))
	   last_server = reply_query(serverfdp->fd, options, packet, now, 
				     dnamebuff, last_server, bogus_addr);
      
      for (iface = interfaces; iface; iface = iface->next)
	{
	  if (FD_ISSET(iface->fd, &rset))
	    {
	      /* request packet, deal with query */
	      union mysockaddr udpaddr;
	      socklen_t udplen = sizeof(udpaddr);
	      int m, n = recvfrom(iface->fd, packet, PACKETSZ, 0, &udpaddr.sa, &udplen); 
	      udpaddr.sa.sa_family = iface->addr.sa.sa_family;
#ifdef HAVE_IPV6
	      if (udpaddr.sa.sa_family == AF_INET6)
		udpaddr.in6.sin6_flowinfo = htonl(0);
#endif	      
	      header = (HEADER *)packet;
	      if (n >= (int)sizeof(HEADER) && !header->qr)
		{
		  if (extract_request(header, (unsigned int)n, dnamebuff))
		    {
		      if (udpaddr.sa.sa_family == AF_INET) 
			log_query(F_QUERY | F_IPV4 | F_FORWARD, dnamebuff, 
				  (struct all_addr *)&udpaddr.in.sin_addr);
#ifdef HAVE_IPV6
		      else
			log_query(F_QUERY | F_IPV6 | F_FORWARD, dnamebuff, 
				  (struct all_addr *)&udpaddr.in6.sin6_addr);
#endif
		    }
		  
		  m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, 
				      mxname, mxtarget, options, now, local_ttl, dnamebuff);
		  if (m >= 1)
		    {
		      /* answered from cache, send reply */
		      sendto(iface->fd, (char *)header, m, 0, 
			     &udpaddr.sa, sa_len(&udpaddr));
		    }
		  else 
		    {
		      /* cannot answer from cache, send on to real nameserver */
		      last_server = forward_query(iface->fd, &udpaddr, header, n, 
						  options, dnamebuff, servers, 
						  last_server, now, local_ttl);
		    }
		}
	      
	    }
	}
    }
  
  return 0;
}
コード例 #7
0
ファイル: dnsmasq.c プロジェクト: NieHao/R7000
int main (int argc, char **argv)
{
  int i;
  int cachesize = CACHESIZ;
  int port = NAMESERVER_PORT;
  unsigned int options;
  int first_loop = 1;
#ifdef HAVE_FILE_SYSTEM
  int logged_resolv = 0, logged_lease = 0; 
  char *resolv = RESOLVFILE;
  char *runfile = RUNFILE;
  time_t resolv_changed = 0;
  char *lease_file = NULL;
  off_t lease_file_size = (off_t)0;
  ino_t lease_file_inode = (ino_t)0;
#endif
  struct irec *iface;
  int peerfd, peerfd6;
  struct irec *interfaces = NULL;
  char *mxname = NULL;
  char *mxtarget = NULL;
  char *domain_suffix = NULL;
  char *username = CHUSER;
  struct iname *if_names = NULL;
  struct iname *if_addrs = NULL;
  struct server *serv_addrs = NULL;
  char *dnamebuff, *packet;
  struct server *servers, *last_server;
 
  sighup = 1; /* init cache the first time through */
  sigusr1 = 0; /* but don't dump */
  signal(SIGUSR1, sig_handler);
  signal(SIGHUP, sig_handler);

  /* These get allocated here to avoid overflowing the small stack
     on embedded systems. dnamebuff is big enough to hold one
     maximal sixed domain name and gets passed into all the processing
     code. We manage to get away with one buffer. */
  dnamebuff = safe_malloc(MAXDNAME);
  /* Size: we check after adding each record, so there must be 
     memory for the largest packet, and the largest record */
  packet = safe_malloc(PACKETSZ+MAXDNAME+RRFIXEDSZ);

#ifdef HAVE_FILE_SYSTEM
  options = read_opts(argc, argv, dnamebuff, &resolv, &mxname, &mxtarget, &lease_file,
		      &username, &domain_suffix, &runfile, &if_names, &if_addrs, 
		      &serv_addrs, &cachesize, &port) ;
#else
  options = read_opts(argc, argv, dnamebuff, NULL, &mxname, &mxtarget, NULL,
		      &username, &domain_suffix, NULL, &if_names, &if_addrs, 
		      &serv_addrs, &cachesize, &port) ;
#endif
  
  /* peerfd is not bound to a low port
     so that we can send queries out on it without them getting
     blocked at firewalls */
  
  if ((peerfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 && 
      errno != EAFNOSUPPORT &&
      errno != EINVAL)
    die("dnsmasq: cannot create socket: %s", NULL);
  
#ifdef HAVE_IPV6
  if ((peerfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 && 
      errno != EAFNOSUPPORT &&
      errno != EINVAL)
    die("dnsmasq: cannot create IPv6 socket: %s", NULL);
#else
  peerfd6 = -1;
#endif
  
  if (peerfd == -1 && peerfd6 == -1)
    die("dnsmasq: no kernel support for IPv4 _or_ IPv6.", NULL);

  interfaces = find_all_interfaces(if_names, if_addrs, port);
  
  /* open a socket bound to NS port on each local interface.
     this is necessary to ensure that our replies originate from
     the address they were sent to. See Stevens page 531 */
  for (iface = interfaces; iface; iface = iface->next)
    {
      if ((iface->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1)
	die("cannot create socket: %s", NULL);
	      
      if (bind(iface->fd, &iface->addr.sa, sa_len(&iface->addr)))
	die("bind failed: %s", NULL);
    }

  forward_init(1);

  cache_init(cachesize, options & OPT_LOG);
  
  setbuf(stdout, NULL);

#ifdef HAVE_FILE_SYSTEM
  if (!(options & OPT_DEBUG))
    {
      FILE *pidfile;
      struct passwd *ent_pw;
        
      /* The following code "daemonizes" the process. 
	 See Stevens section 12.4 */

#ifdef HAVE_FORK
      if (fork() != 0 )
	exit(0);
      
      setsid();
      
      if (fork() != 0)
	exit(0);
#endif
      
      chdir("/");
      umask(022); /* make pidfile 0644 */
      
      /* write pidfile _after_ forking ! */
      if (runfile && (pidfile = fopen(runfile, "w")))
      	{
	  fprintf(pidfile, "%d\n", (int) getpid());
	  fclose(pidfile);
	}
      
      umask(0);

      for (i=0; i<64; i++)
	{
	  if (i == peerfd || i == peerfd6)
	    continue;
	  for (iface = interfaces; iface; iface = iface->next)
	    if (iface->fd == i)
	      break;
	  if (!iface)
	    close(i);
	}

      /* Change uid and gid for security */
      if (username && (ent_pw = getpwnam(username)))
	{
	  gid_t dummy;
	  struct group *gp;
	  /* remove all supplimentary groups */
	  setgroups(0, &dummy);
	  /* change group to "dip" if it exists, for /etc/ppp/resolv.conf 
	     otherwise get the group for "nobody" */
	  if ((gp = getgrnam("dip")) || (gp = getgrgid(ent_pw->pw_gid)))
	    setgid(gp->gr_gid); 
	  /* finally drop root */
	  setuid(ent_pw->pw_uid);
	}
    }
#else
#endif

  /* In debug mode, log to stderr too and cut the prefix crap. */
  openlog("dnsmasq", options & OPT_DEBUG ? LOG_PERROR : LOG_PID, LOG_DAEMON);
  
  if (cachesize)
    syslog(LOG_INFO, "started, version %s cachesize %d", VERSION, cachesize);
  else
    syslog(LOG_INFO, "started, version %s cache disabled", VERSION);
  
  if (mxname)
    syslog(LOG_INFO, "serving MX record for mailhost %s target %s", 
	   mxname, mxtarget);
  
  if (getuid() == 0 || geteuid() == 0)
    syslog(LOG_WARNING, "failed to drop root privs");
  
  serv_addrs = servers = last_server = check_servers(serv_addrs, interfaces, peerfd, peerfd6);
  
  while (1)
    {
      int ready, maxfd = peerfd > peerfd6 ? peerfd : peerfd6;
      fd_set rset;
      HEADER *header;
#ifdef HAVE_FILE_SYSTEM
      struct stat statbuf;
#endif
   
      if (first_loop)
	/* do init stuff only first time round. */
	{
	  first_loop = 0;
	  ready = 0;
	}
      else
	{
	  FD_ZERO(&rset);

	  if (peerfd != -1)
	    FD_SET(peerfd, &rset);
	  if (peerfd6 != -1)
	    FD_SET(peerfd6, &rset);
	    	  
	  for (iface = interfaces; iface; iface = iface->next)
	    {
	      FD_SET(iface->fd, &rset);
	      if (iface->fd > maxfd)
		maxfd = iface->fd;
	    }
	  
	  ready = select(maxfd+1, &rset, NULL, NULL, NULL);
	  
	  if (ready == -1)
	    {
	      if (errno == EINTR)
		ready = 0; /* do signal handlers */
	      else
		continue;
	    }
	}

#ifdef HAVE_FILE_SYSTEM
      if (sighup)
	{
	  signal(SIGHUP, SIG_IGN);
	  cache_reload(options & OPT_NO_HOSTS, dnamebuff);
	  if (resolv && (options & OPT_NO_POLL))
	    servers = last_server = 
	      check_servers(reload_servers(resolv, dnamebuff, servers), 
			    interfaces, peerfd, peerfd6);
	  sighup = 0;
	  signal(SIGHUP, sig_handler);
	}

      if (sigusr1)
	{
	  signal(SIGUSR1, SIG_IGN);
	  dump_cache(options & (OPT_DEBUG | OPT_LOG), cachesize);
	  sigusr1 = 0;
	  signal(SIGUSR1, sig_handler);
	}

      if (resolv && !(options & OPT_NO_POLL))
	{
	  if (stat(resolv, &statbuf) == -1)
	    {
	      if (!logged_resolv)
		syslog(LOG_WARNING, "failed to access %s: %m", resolv);
	      logged_resolv = 1;
	    }
	  else
	    {
	      logged_resolv = 0;
	      if ((statbuf.st_mtime > resolv_changed) &&
		  (statbuf.st_mtime < time(NULL) || resolv_changed == 0))
		{
		  resolv_changed = statbuf.st_mtime;
		  servers = last_server = 
		    check_servers(reload_servers(resolv, dnamebuff, servers),
				  interfaces, peerfd, peerfd6);
		}
	    }
	}
#else
#endif

#ifdef HAVE_FILE_SYSTEM
      if (lease_file)
	{
	  if (stat(lease_file, &statbuf) == -1)
	    {
	      if (!logged_lease)
		syslog(LOG_WARNING, "failed to access %s: %m", lease_file);
	      logged_lease = 1;
	    }
	  else
	    { 
	      logged_lease = 0;
	      if ((lease_file_size == (off_t)0) ||
		  (statbuf.st_size > lease_file_size) ||
		  (statbuf.st_ino != lease_file_inode))
		{
		  lease_file_size = statbuf.st_size;
		  lease_file_inode = statbuf.st_ino;
		  load_dhcp(lease_file, domain_suffix, time(NULL), dnamebuff);
		}
	    }
	}
#else
#endif

      if (ready == 0)
	continue; /* no sockets ready */
      
      if (peerfd != -1 && FD_ISSET(peerfd, &rset))
	last_server = reply_query(peerfd, packet, dnamebuff, last_server);
      if (peerfd6 != -1 && FD_ISSET(peerfd6, &rset))
	last_server = reply_query(peerfd6, packet, dnamebuff, last_server);

      for (iface = interfaces; iface; iface = iface->next)
	{
	  if (FD_ISSET(iface->fd, &rset))
	    {
	      /* request packet, deal with query */
	      union mysockaddr udpaddr;
	      socklen_t udplen = sizeof(udpaddr);
	      int m, n = recvfrom(iface->fd, packet, PACKETSZ, 0, &udpaddr.sa, &udplen); 
	      udpaddr.sa.sa_family = iface->addr.sa.sa_family;
#ifdef HAVE_IPV6
	      if (udpaddr.sa.sa_family == AF_INET6)
		udpaddr.in6.sin6_flowinfo = htonl(0);
#endif	      
	      header = (HEADER *)packet;
	      if (n >= (int)sizeof(HEADER) && !header->qr)
		{
		  m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, 
				      mxname, mxtarget, options, dnamebuff);
		  if (m >= 1)
		    {
		      /* answered from cache, send reply */
		      sendto(iface->fd, (char *)header, m, 0, 
			     &udpaddr.sa, sa_len(&udpaddr));
		    }
		  else 
		    {
		      /* cannot answer from cache, send on to real nameserver */
		      last_server = forward_query(iface->fd, peerfd, peerfd6, &udpaddr, header, n, 
						  options && OPT_ORDER, dnamebuff,
						  servers, last_server);
		    }
		}
	      
	    }
	}
    }
  
  return 0;
}
コード例 #8
0
static void *status_thread (void *p)
{
	THREAD_SIGINIT;
	/* (void)p; */  /* To inhibit "unused variable" warning */

	if (!global.strict_suid) {
		if (!run_as(global.run_as)) {
			pdnsd_exit();
		}
	}

	if (listen(stat_sock,5)==-1) {
		log_warn("Error: could not listen on socket: %s.\nStatus readback will be impossible",strerror(errno));
		goto exit_thread;
	}
	for(;;) {
		struct sockaddr_un ra;
		socklen_t res=sizeof(ra);
		int rs;
		if ((rs=accept(stat_sock,(struct sockaddr *)&ra,&res))!=-1) {
			uint16_t cmd;
			DEBUG_MSG("Status socket query pending.\n");
			if (read_short(rs,&cmd)) {
			    /* Check magic number in command */
			    if((cmd & 0xff00) == CTL_CMDVERNR) {
				const char *errmsg;
				cmd &= 0xff;
				switch(cmd) {
				case CTL_STATS: {
					struct utsname nm;
					DEBUG_MSG("Received STATUS query.\n");
					if(!print_succ(rs))
						break;
					uname(&nm);
					if(fsprintf(rs,"pdnsd-%s running on %s.\n",VERSION,nm.nodename)<0 ||
					   report_cache_stat(rs)<0 ||
					   report_thread_stat(rs)<0 ||
					   report_conf_stat(rs)<0)
					{
						DEBUG_MSG("Error writing to control socket: %s\n"
							  "Failed to send status report.\n",strerror(errno));
					}
				}
					break;
				case CTL_SERVER: {
					char *label,*dnsaddr;
					int indx;
					uint16_t cmd2;
					DEBUG_MSG("Received SERVER command.\n");
					if (read_allocstring(rs,&label,NULL)<=0) {
					    print_serr(rs,"Error reading server label.");
					    break;
					}
					if (!read_short(rs,&cmd2)) {
					    print_serr(rs,"Missing up|down|retest.");
					    goto free_label_break;
					}
					if(!read_allocstring(rs, &dnsaddr,NULL)) {
					    print_serr(rs,"Error reading DNS addresses.");
					    goto free_label_break;
					}
					/* Note by Paul Rombouts:
					   We are about to access server configuration data.
					   Now that the configuration can be changed during run time,
					   we should be using locks before accessing server config data, even if it
					   is read-only access.
					   However, as long as this is the only thread that calls reload_config_file()
					   it should be OK to read the server config without locks, but it is
					   something to keep in mind.
					*/
					{
					    char *endptr;
					    indx=strtol(label,&endptr,0);
					    if(!*endptr) {
						if (indx<0 || indx>=DA_NEL(servers)) {
						    print_serr(rs,"Server index out of range.");
						    goto free_dnsaddr_label_break;
						}
					    }
					    else {
						if (!strcmp(label, "all"))
						    indx=-2; /* all servers */
						else
						    indx=-1; /* compare names */
					    }
					}
					if(cmd2==CTL_S_UP || cmd2==CTL_S_DOWN || cmd2==CTL_S_RETEST) {
					    if(!dnsaddr) {
						if (indx==-1) {
						    int i;
						    for (i=0;i<DA_NEL(servers);++i) {
							char *servlabel=DA_INDEX(servers,i).label;
							if (servlabel && !strcmp(servlabel,label))
							    goto found_label;
						    }
						    print_serr(rs,"Bad server label.");
						    goto free_dnsaddr_label_break;
						found_label:;
						}
						if(mark_servers(indx,(indx==-1)?label:NULL,(cmd2==CTL_S_RETEST)?-1:(cmd2==CTL_S_UP))==0)
						    print_succ(rs);
						else
						    print_serr(rs,"Could not start up or signal server status thread.");
					    }
					    else { /* Change server addresses */
						if(indx==-2) {
						    print_serr(rs,"Can't use label \"all\" to change server addresses.");
						    goto free_dnsaddr_label_break;
						}
						if(indx==-1) {
						    int i;
						    for(i=0;i<DA_NEL(servers);++i) {
							char *servlabel=DA_INDEX(servers,i).label;
							if (servlabel && !strcmp(servlabel,label)) {
							    if(indx!=-1) {
								print_serr(rs,"server label must be unique to change server addresses.");
								goto free_dnsaddr_label_break;
							    }
							    indx=i;
							}
						    }
						    if(indx==-1) {
							print_serr(rs,"Bad server label.");
							goto free_dnsaddr_label_break;
						    }
						}
						{
						    char *ipstr,*q=dnsaddr;
						    addr_array ar=NULL;
						    pdnsd_a addr;
						    int err;
						    for(;;) {
							for(;;) {
							    if(!*q) goto change_servs;
							    if(*q!=',' && !isspace(*q)) break;
							    ++q;
							}
							ipstr=q;
							for(;;) {
							    ++q;
							    if(!*q) break;
							    if(*q==',' || isspace(*q)) {*q++=0; break; }
							}
							if(!str2pdnsd_a(ipstr,&addr)) {
							    print_serr(rs,"Bad server ip");
							    goto free_ar;
							}
							if(!(ar=DA_GROW1(ar))) {
							    print_serr(rs,"Out of memory.");
							    goto free_dnsaddr_label_break;
							}
							DA_LAST(ar)=addr;
						    }
						change_servs:
						    err=change_servers(indx,ar,(cmd2==CTL_S_RETEST)?-1:(cmd2==CTL_S_UP));
						    if(err==0)
							print_succ(rs);
						    else
							print_serr(rs,err==ETIMEDOUT?"Timed out while trying to gain access to server data.":
								      err==ENOMEM?"Out of memory.":
								      "Could not start up or signal server status thread.");
						free_ar:
						    da_free(ar);
						}
					    }
					}
					else
					    print_serr(rs,"Bad command.");

				free_dnsaddr_label_break:
					free(dnsaddr);
				free_label_break:
					free(label);
				}
					break;
				case CTL_RECORD: {
					uint16_t cmd2;
					unsigned char name[DNSNAMEBUFSIZE],buf[DNSNAMEBUFSIZE];
					DEBUG_MSG("Received RECORD command.\n");
					if (!read_short(rs,&cmd2))
						goto incomplete_command;
					if (read_domain(rs, charp buf, sizeof(buf))<=0)
						goto incomplete_command;
					if ((errmsg=parsestr2rhn(buf,sizeof(buf),name))!=NULL)
						goto bad_domain_name;
					switch (cmd2) {
					case CTL_R_DELETE:
						del_cache(name);
						print_succ(rs);
						break;
					case CTL_R_INVAL:
						invalidate_record(name);
						print_succ(rs);
						break;
					default:
						print_serr(rs,"Bad command.");
					}
				}
					break;
				case CTL_SOURCE: {
					uint32_t ttl;
					char *fn;
					uint16_t servaliases,flags;
					unsigned char buf[DNSNAMEBUFSIZE],owner[DNSNAMEBUFSIZE];

					DEBUG_MSG("Received SOURCE command.\n");
					if (read_allocstring(rs,&fn,NULL)<=0) {
						print_serr(rs,"Bad filename name.");
						break;
					}
					if (read_domain(rs, charp buf, sizeof(buf))<=0 ||
					    !read_long(rs,&ttl) ||
					    !read_short(rs,&servaliases) ||	/* serve aliases */
					    !read_short(rs,&flags))		/* caching flags */
					{
						print_serr(rs,"Malformed or incomplete command.");
						goto free_fn;
					}
					if ((errmsg=parsestr2rhn(buf,sizeof(buf),owner))!=NULL) {
						print_serr(rs,errmsg);
						goto free_fn;
					}
					if (ttl < 0) {
						print_serr(rs, "Bad TTL.");
						goto free_fn;
					}
					if(flags&DF_NEGATIVE) {
						print_serr(rs, "Bad cache flags.");
						goto free_fn;
					}
					{
						char *errmsg;
						if (read_hosts(fn,owner,ttl,flags,servaliases,&errmsg))
							print_succ(rs);
						else {
							print_serr(rs,errmsg?:"Out of memory.");
							free(errmsg);
						}
					}
				free_fn:
					free(fn);
				}
					break;
				case CTL_ADD: {
					uint32_t ttl;
					unsigned sz;
					uint16_t tp,flags,nadr=0;
					unsigned char name[DNSNAMEBUFSIZE],buf[DNSNAMEBUFSIZE],dbuf[2+DNSNAMEBUFSIZE];
					size_t adrbufsz=0;
					unsigned char *adrbuf=NULL;

					DEBUG_MSG("Received ADD command.\n");
					if (!read_short(rs,&tp))
						goto incomplete_command;
					if (read_domain(rs, charp buf, sizeof(buf))<=0)
						goto incomplete_command;
					if (!read_long(rs,&ttl))
						goto incomplete_command;
					if (!read_short(rs,&flags))	/* caching flags */
						goto incomplete_command;
					if ((errmsg=parsestr2rhn(buf,sizeof(buf),name))!=NULL)
						goto bad_domain_name;
					if (ttl < 0)
						goto bad_ttl;
					if(flags&DF_NEGATIVE)
						goto bad_flags;

					switch (tp) {
					case T_A:
						sz=sizeof(struct in_addr);
    #if ALLOW_LOCAL_AAAA
						goto read_adress_list;
					case T_AAAA:
						sz=sizeof(struct in6_addr);
					read_adress_list:
    #endif
						if (!read_short(rs,&nadr))
							goto incomplete_command;
						if (!nadr)
							goto bad_arg;
						adrbufsz= nadr * (size_t)sz;
						adrbuf= malloc(adrbufsz);
						if(!adrbuf)
							goto out_of_memory;
						{
							size_t nread=0;
							while(nread<adrbufsz) {
								ssize_t m=read(rs,adrbuf+nread,adrbufsz-nread);
								if(m<=0) {free(adrbuf); goto bad_arg;}
								nread += m;
							}
						}
						break;
					case T_CNAME:
					case T_PTR:
					case T_NS:
						if (read_domain(rs, charp buf, sizeof(buf))<=0)
							goto incomplete_command;
						if ((errmsg=parsestr2rhn(buf,sizeof(buf),dbuf))!=NULL)
							goto bad_domain_name;
						sz=rhnlen(dbuf);
						break;
					case T_MX:
						if (read(rs,dbuf,2)!=2)
							goto bad_arg;
						if (read_domain(rs, charp buf, sizeof(buf))<=0)
							goto incomplete_command;
						if ((errmsg=parsestr2rhn(buf,sizeof(buf),dbuf+2))!=NULL)
							goto bad_domain_name;
						sz=rhnlen(dbuf+2)+2;
						break;
					default:
						goto bad_arg;
					}
					{
						dns_cent_t cent;

						if (!init_cent(&cent, name, 0, 0, flags  DBG1)) {
							free(adrbuf);
							goto out_of_memory;
						}
						if(adrbuf) {
							unsigned char *adrp; int i;
							for(adrp=adrbuf,i=0; i<nadr; adrp += sz,++i) {
								if (!add_cent_rr(&cent,tp,ttl,0,CF_LOCAL,sz,adrp  DBG1)) {
									free_cent(&cent  DBG1);
									free(adrbuf);
									goto out_of_memory;
								}
							}
							free(adrbuf);
						}
						else if (!add_cent_rr(&cent,tp,ttl,0,CF_LOCAL,sz,dbuf  DBG1)) {
							free_cent(&cent  DBG1);
							goto out_of_memory;
						}

						if(cent.qname[0]==1 && cent.qname[1]=='*') {
							/* Wild card record.
							   Set the DF_WILD flag for the name with '*.' removed. */
							if(!set_cent_flags(&cent.qname[2],DF_WILD)) {
								print_serr(rs,
									   "Before defining records for a name with a wildcard"
									   " you must first define some records for the name"
									   " with '*.' removed.");
								goto cleanup_cent;
							}
						}

						add_cache(&cent);
						print_succ(rs);
					cleanup_cent:
						free_cent(&cent  DBG1);
					}
				}
					break;
				case CTL_NEG: {
					uint32_t ttl;
					uint16_t tp;
					unsigned char name[DNSNAMEBUFSIZE],buf[DNSNAMEBUFSIZE];

					DEBUG_MSG("Received NEG command.\n");
					if (read_domain(rs, charp buf, sizeof(buf))<=0)
						goto incomplete_command;
					if (!read_short(rs,&tp))
						goto incomplete_command;
					if (!read_long(rs,&ttl))
						goto incomplete_command;
					if ((errmsg=parsestr2rhn(buf,sizeof(buf),name))!=NULL) {
						DEBUG_MSG("NEG: received bad domain name.\n");
						goto bad_domain_name;
					}
					if (tp!=255 && PDNSD_NOT_CACHED_TYPE(tp)) {
						DEBUG_MSG("NEG: received bad record type.\n");
						print_serr(rs,"Bad record type.");
						break;
					}
					if (ttl < 0)
						goto bad_ttl;
					{
						dns_cent_t cent;

						if (tp==255) {
							if (!init_cent(&cent, name, ttl, 0, DF_LOCAL|DF_NEGATIVE  DBG1))
								goto out_of_memory;
						} else {
							if (!init_cent(&cent, name, 0, 0, 0  DBG1))
								goto out_of_memory;
							if (!add_cent_rrset_by_type(&cent,tp,ttl,0,CF_LOCAL|CF_NEGATIVE  DBG1)) {
								free_cent(&cent  DBG1);
								goto out_of_memory;
							}
						}
						add_cache(&cent);
						free_cent(&cent DBG1);
					}
					print_succ(rs);
				}
					break;
				case CTL_CONFIG: {
					char *fn,*errmsg;
					DEBUG_MSG("Received CONFIG command.\n");
					if (!read_allocstring(rs,&fn,NULL)) {
						print_serr(rs,"Bad filename name.");
						break;
					}
					if (reload_config_file(fn,&errmsg))
						print_succ(rs);
					else {
						print_serr(rs,errmsg?:"Out of memory.");
						free(errmsg);
					}
					free(fn);
				}
					break;
				case CTL_INCLUDE: {
					char *fn,*errmsg;
					DEBUG_MSG("Received INCLUDE command.\n");
					if (read_allocstring(rs,&fn,NULL)<=0) {
						print_serr(rs,"Bad filename name.");
						break;
					}
					if (read_config_file(fn,NULL,NULL,0,&errmsg))
						print_succ(rs);
					else {
						print_serr(rs,errmsg?:"Out of memory.");
						free(errmsg);
					}
					free(fn);
				}
					break;
				case CTL_EVAL: {
					char *str,*errmsg;
					DEBUG_MSG("Received EVAL command.\n");
					if (!read_allocstring(rs,&str,NULL)) {
						print_serr(rs,"Bad input string.");
						break;
					}
					if (confparse(NULL,str,NULL,NULL,0,&errmsg))
						print_succ(rs);
					else {
						print_serr(rs,errmsg?:"Out of memory.");
						free(errmsg);
					}
					free(str);
				}
					break;
				case CTL_EMPTY: {
					slist_array sla=NULL;
					char *names; unsigned len;

					DEBUG_MSG("Received EMPTY command.\n");
					if (!read_allocstring(rs,&names,&len)) {
						print_serr(rs,"Bad arguments.");
						break;
					}
					if(names) {
						char *p=names, *last=names+len;

						while(p<last) {
							int tp;
							char *q;
							slist_t *sl;
							unsigned sz;
							unsigned char rhn[DNSNAMEBUFSIZE];

							if(*p=='-') {
								tp=C_EXCLUDED;
								++p;
							}
							else {
								tp=C_INCLUDED;
								if(*p=='+') ++p;
							}
							/* skip a possible leading dot. */
							if(p+1<last && *p=='.' && *(p+1)) ++p;
							q=p;
							while(q<last && *q) ++q;
							if ((errmsg=parsestr2rhn(ucharp p,q-p,rhn))!=NULL) {
								DEBUG_MSG("EMPTY: received bad domain name: %s\n",p);
								print_serr(rs,errmsg);
								goto free_sla_names_break;
							}
							sz=rhnlen(rhn);
							if (!(sla=DA_GROW1_F(sla,free_slist_domain))) {
								print_serr(rs,"Out of memory.");
								goto free_names_break;
							}
							sl=&DA_LAST(sla);

							if (!(sl->domain=malloc(sz))) {
								print_serr(rs,"Out of memory.");
								goto free_sla_names_break;
							}
							memcpy(sl->domain,rhn,sz);
							sl->exact=0;
							sl->rule=tp;
							p = q+1;
						}
					}
					if(empty_cache(sla))
						print_succ(rs);
					else
						print_serr(rs,"Could not lock the cache.");
				free_sla_names_break:
					free_slist_array(sla);
				free_names_break:
					free(names);
				}
					break;
				case CTL_DUMP: {
					int rv,exact=0;
					unsigned char *nm=NULL;
					char buf[DNSNAMEBUFSIZE];
					unsigned char rhn[DNSNAMEBUFSIZE];
					DEBUG_MSG("Received DUMP command.\n");
					if (!(rv=read_domain(rs,buf,sizeof(buf)))) {
						print_serr(rs,"Bad domain name.");
						break;
					}
					if(rv>0) {
						int sz;
						exact=1; nm= ucharp buf; sz=sizeof(buf);
						if(buf[0]=='.' && buf[1]) {
							exact=0; ++nm; --sz;
						}
						if ((errmsg=parsestr2rhn(nm,sz,rhn))!=NULL)
							goto bad_domain_name;
						nm=rhn;
					}
					if(!print_succ(rs))
						break;
					if((rv=dump_cache(rs,nm,exact))<0 ||
					   (!rv && fsprintf(rs,"Could not find %s%s in the cache.\n",
							    exact?"":nm?"any entries matching ":"any entries",
							    nm?buf:"")<0))
					{
						DEBUG_MSG("Error writing to control socket: %s\n",strerror(errno));
					}
				}
					break;
				incomplete_command:
					print_serr(rs,"Malformed or incomplete command.");
					break;
				bad_arg:
					print_serr(rs,"Bad arg.");
					break;
				bad_domain_name:
					print_serr(rs,errmsg);
					break;
				bad_ttl:
					print_serr(rs, "Bad TTL.");
					break;
				bad_flags:
					print_serr(rs, "Bad cache flags.");
					break;
				out_of_memory:
					print_serr(rs,"Out of memory.");
					break;
				default:
					print_serr(rs,"Unknown command.");
				}
			    }
			    else {
				    DEBUG_MSG("Incorrect magic number in status-socket command code: %02x\n",cmd>>8);
				    print_serr(rs,"Command code contains incompatible version number.");
			    }
			}
			else {