예제 #1
0
static void apply_hosts_file(jdns_dnsparams_t *a, const char *path)
{
	int n;
	jdns_dnshostlist_t *list;

	list = read_hosts_file(path);
	for(n = 0; n < list->count; ++n)
		jdns_dnshostlist_append(a->hosts, list->item[n]);
	jdns_dnshostlist_delete(list);
}
예제 #2
0
/*
 * Function: main
 * Purpose:  
 * Comments: 
 */
int main(int argc, char *argv[])
{
  int                i;
  struct sigaction   si_sa;
  int                euid, ruid;
  struct host_entry *cursor;

  /*
   * first things first
   * if anything goes wrong anywhere, we want to be super careful to release
   * any file descriptor we have on /dev/lkm, and it probably makes sense to
   * shutdown the raw socket we have too.
   */
  atexit(cleanup);

  /*
   * get the effective and the real user id's so we know if we are running
   * with elevated permissions or not
   */
  euid = geteuid();
  ruid = getuid();

  /* check for the command line arguments */
  if(check_options(argc,argv) == 0)
    {
      return -1;
    }

  /*
   * open the raw socket now.  i used to have this further down closer to
   * where it was needed, but because you can't change the euid/uid to and
   * from root (unless you're the superuser) i can only do this once
   */
  if(options & OPT_IPV4)
    {
      if(open_ipmp_sockets4() == 0) return -1; 
    }
  else if(options & OPT_IPV6)
    {
      if(open_ipmp_sockets6() == 0) return -1; 
    }
  else
    {
      if(open_ipmp_sockets4() == 0) return -1;
      if(open_ipmp_sockets6() == 0) return -1;
    }

  /*
   * revoke the permissions we requested as we only need them to open a raw
   * socket.  this is to reduce the impact of any buffer overflow exploits
   * that may be present
   */
  if(ruid != euid)
    {
      setreuid(ruid, ruid);
    }

  /*
   * we get the pid so we can identify incoming ipmp packets destined for
   * this instance of ipmp_ping
   */
  pid = getpid();

  /*
   * need to know about the addresses this host has
   */
  learn_localaddresses();

  /*
   * in FreeBSD, the actual ping is done by a kernel module that has a syscall
   * in it.  the kernel module allows the protocol to get a timestamp as close
   * to when the mbuf is actually sent to ip_output as possible
   */
#if defined(__FreeBSD__)
  if((options & OPT_RAW) == 0)
    {
      i = get_syscall("ipmp_ping", &syscall_num);
      if(i != 0)
        {
          printerror(i, strerror, "could not get the syscall for ipmp_ping");
          return -1;
        }
    }
#endif

  /*
   * the -n option means that the user has supplied a list of hosts to
   * ping, so we read those entries and put them in an list of hosts with
   * details regarding each host.  the task of putting hosts into the list
   * is handled by read_hosts_file
   *
   * if the -n option isnt specified, we create a list containing just the 
   * one host to ping.  this way, all the program logic can be used in a
   * multitude of situations.
   */
  if(options & OPT_NLANR)
    {
      /*
       * if something went wrong parsing the file, we quit.
       */
      if(read_hosts_file() == 0)
	{
	  return -1;
	}
    }
  else
    {
      /*
       * if the user didnt specify a host to ping, we bail, telling them
       * why first...
       */
      if(argc - optind != 1)
	{
	  usage(0);
          return -1;
	}

      /*
       * if we can't add a host entry for the host supplied on the command line
       * tell the user that it couldnt be parse and cleanup
       */
      if(add_host_entry(argv[optind], NULL) == 0)
	{
	  return -1;
	}
    }

  /*
   * we now put some handlers into action so if the user ctrl-c's us we have
   * the opportunity to tell them what we found out first
   * also, if the user specified a timeout, put an alarm in for that so we
   * can bail when they tell us to...
   */
  sigemptyset(&si_sa.sa_mask);
  si_sa.sa_flags = 0;
  si_sa.sa_handler = alarm_bells;
  if(sigaction(SIGINT, &si_sa, 0) == -1)
    {
      printerror(errno, strerror, "could not set sigaction for SIGINT");
      return -1;
    }
  if(options & OPT_TIMEOUT)
    {
      if(sigaction(SIGALRM, &si_sa, 0) == -1)
	{
	  printerror(errno, strerror, "could not set sigaction for SIGALRM");
	  return -1;
	}
    }

  /*
   * we loop for as long as we have not been told to finish up.
   * the finish_up loop will exit when
   *  - there has been an alarm set that goes off
   *  - a SIGINT is received (from e.g. Ctrl-C)
   *  - we have got_all_response()'s
   *
   * this is not an expensive loop in terms of cpu cycles, as the
   * recv_echo_response will sleep if there is nothing to recv until we have
   * told it to stop blocking - typically one second or whatever the between
   * timeout is.
   *
   * the loop does two things:
   *  - sends echo requests
   *  - receives echo responses
   *
   * the loop sends packets, pausing for however long the timeout is set for
   * between packets.  this pause is implemented in the recv_echo_response
   * function in a call to select(2).  if we cannot send a request to one of
   * them, we bail, as this probably means the syscall could not be called.
   *
   * the loop recv's the response and associates the packet with a host_entry
   * we then parse that response for the host entry, and then check if we have
   * now got all the responses we are looking for.  if we have, we exit the
   * loop by setting the finish_up flag
   */

  sent_all_requests = 0;
  i = 0;

  cursor = head;

  while(finish_up == 0)
    {
      while(sent_all_requests == 0)
	{
	  if(send_echo_request(cursor) != 0)
	    {
	      return -1;
	    }
	  cursor->tx++;

	  if(cursor->tx == count)
	    {
	      cursor = cursor->next;
	      if(cursor == NULL)
		{
		  sent_all_requests = 1;
		  alarm(timeout);
		  break;
		}
	    }

	  if(wait_between > 0)
	    {
	      gettimeofday(&wait_between_tv, &tz);
	      timeval_add(&wait_between_tv, wait_between);
	      break;
	    }
	}

      while(time_to_send_request() == 0 && finish_up == 0)
	{
	  if(recv_echo_responses() > 0)
	    {
	      if(got_all_responses() == 1)
		{
		  finish_up = 1;
		}
	    }
	}
    }

  /*
   * if we have been given a list of hosts to ping, we have to print out which
   * hosts did not give us a reply
   */
  if(options & OPT_NLANR)
    {
      show_loss();
    }

  return 0;
}