예제 #1
0
static void printer_hes_callback(void *arg, int status, unsigned char *abuf,
				 int alen)
{
  struct printer_poll_args *pargs = (struct printer_poll_args *) arg;
  struct serverstate *state = pargs->state;
  struct printer *printer = pargs->printer;
  char **vec = NULL, *p, *q, *errmem;

  if (status == ARES_EDESTRUCTION)
    {
      syslog(LOG_DEBUG, "printer_hes_callback: printer %s hesiod query "
	     "halted for channel destruction", printer->name);
      free(pargs);
      return;
    }

  if (status != ARES_SUCCESS)
    {
      syslog(LOG_ERR, "printer_hes_callback: could not resolve Hesiod pcap "
	     "for printer %s: %s", printer->name,
	     ares_strerror(status, &errmem));
      ares_free_errmem(errmem);
      goto failure;
    }

  /* Parse the result buffer into text records. */
  vec = hesiod_parse_result(state->hescontext, abuf, alen);
  if (!vec || !*vec)
    {
      syslog(LOG_ERR, "printer_hes_callback: could not parse Hesiod pcap "
	     "result for printer %s: %m", printer->name);
      goto failure;
    }

  /* Look for the print server name. */
  p = strchr(*vec, ':');
  while (p)
    {
      if (strncmp(p + 1, "rm=", 3) == 0)
	break;
      p = strchr(p + 1, ':');
    }
  if (!p)
    {
      syslog(LOG_ERR, "printer_hes_callback: can't find print server name in "
	     "Hesiod pcap result for printer %s", printer->name);
      goto failure;
    }
  p += 4;
  q = p;
  while (*q && *q != ':')
    q++;
  *q = 0;

  syslog(LOG_DEBUG, "printer_hes_callback: printer %s starting query for %s",
	 printer->name, p);
  ares_gethostbyname(state->channel, p, AF_INET, printer_host_callback, pargs);
  hesiod_free_list(state->hescontext, vec);
  return;

failure:
  if (vec)
    hesiod_free_list(state->hescontext, vec);
  printer->timer = timer_set_rel(60, printer_poll, pargs);
}
예제 #2
0
static void callback(void *arg, int status, unsigned char *abuf, int alen)
{
  char *name = (char *) arg, *errmem;
  int id, qr, opcode, aa, tc, rd, ra, rcode, i;
  unsigned int qdcount, ancount, nscount, arcount;
  const unsigned char *aptr;

  /* Display the query name if given. */
  if (name)
    printf("Answer for query %s:\n", name);

  /* Display an error message if there was an error, but only stop if
   * we actually didn't get an answer buffer.
   */
  if (status != ARES_SUCCESS)
    {
      printf("%s\n", ares_strerror(status, &errmem));
      ares_free_errmem(errmem);
      if (!abuf)
	return;
    }

  /* Won't happen, but check anyway, for safety. */
  if (alen < HFIXEDSZ)
    return;

  /* Parse the answer header. */
  id = DNS_HEADER_QID(abuf);
  qr = DNS_HEADER_QR(abuf);
  opcode = DNS_HEADER_OPCODE(abuf);
  aa = DNS_HEADER_AA(abuf);
  tc = DNS_HEADER_TC(abuf);
  rd = DNS_HEADER_RD(abuf);
  ra = DNS_HEADER_RA(abuf);
  rcode = DNS_HEADER_RCODE(abuf);
  qdcount = DNS_HEADER_QDCOUNT(abuf);
  ancount = DNS_HEADER_ANCOUNT(abuf);
  nscount = DNS_HEADER_NSCOUNT(abuf);
  arcount = DNS_HEADER_ARCOUNT(abuf);

  /* Display the answer header. */
  printf("id: %d\n", id);
  printf("flags: %s%s%s%s%s\n",
	 qr ? "qr " : "",
	 aa ? "aa " : "",
	 tc ? "tc " : "",
	 rd ? "rd " : "",
	 ra ? "ra " : "");
  printf("opcode: %s\n", opcodes[opcode]);
  printf("rcode: %s\n", rcodes[rcode]);

  /* Display the questions. */
  printf("Questions:\n");
  aptr = abuf + HFIXEDSZ;
  for (i = 0; i < qdcount; i++)
    {
      aptr = display_question(aptr, abuf, alen);
      if (aptr == NULL)
	return;
    }

  /* Display the answers. */
  printf("Answers:\n");
  for (i = 0; i < ancount; i++)
    {
      aptr = display_rr(aptr, abuf, alen);
      if (aptr == NULL)
	return;
    }

  /* Display the NS records. */
  printf("NS records:\n");
  for (i = 0; i < nscount; i++)
    {
      aptr = display_rr(aptr, abuf, alen);
      if (aptr == NULL)
	return;
    }

  /* Display the additional records. */
  printf("Additional records:\n");
  for (i = 0; i < arcount; i++)
    {
      aptr = display_rr(aptr, abuf, alen);
      if (aptr == NULL)
	return;
    }
}
예제 #3
0
static void printer_host_callback(void *arg, int status, struct hostent *host)
{
  struct printer_poll_args *pargs = (struct printer_poll_args *) arg;
  struct printer *printer = pargs->printer;
  int s = -1, lport = IPPORT_RESERVED - 1, flags;
  unsigned short port;
  struct servent *servent;
  struct sockaddr_in sin;
  char *errmem;

  if (status == ARES_EDESTRUCTION)
    {
      syslog(LOG_DEBUG, "printer_host_callback: printer %s hostname query "
	     "halted for channel destruction", printer->name);
      free(pargs);
      return;
    }

  if (status != ARES_SUCCESS)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't resolve print "
	     "server name: %s", printer->name, ares_strerror(status, &errmem));
      ares_free_errmem(errmem);
      goto failure;
    }

  s = rresvport(&lport);
  if (s < 0)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't get reserved "
	     "port", printer->name);
      goto failure;
    }

  /* Set s non-blocking so we can do a non-blocking connect. */
  flags = fcntl(s, F_GETFL);
  fcntl(s, F_SETFL, flags | O_NONBLOCK);

  servent = getservbyname("printer", "tcp");
  port = (servent) ? servent->s_port : htons(PRINTER_FALLBACK_PORT);

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  memcpy(&sin.sin_addr, host->h_addr, sizeof(sin.sin_addr));
  sin.sin_port = port;
  if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1
      && errno != EINPROGRESS)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't connect to "
	     "print server %s: %m", printer->name, host->h_name);
      goto failure;
    }

  /* Set up the request we want to send; the main loop will call
   * printer_handle_output() when the socket selects true for
   * writing.
   */
  printer->s = s;
  printer->to_send = 1;
  sprintf(printer->buf, "\3%.*s\n", (int)(sizeof(printer->buf) - 3),
	  printer->name);
  printer->buflen = strlen(printer->buf);
  printer->jobs_counted = 0;
  printer->up_so_far = 1;

  syslog(LOG_DEBUG, "printer_host_callback: printer %s queued %d-byte query",
	 printer->name, printer->buflen);

  free(pargs);
  return;

failure:
  if (s >= 0)
    close(s);
  printer->timer = timer_set_rel(60, printer_poll, pargs);
  return;
}
예제 #4
0
int main(int argc, char **argv)
{
  ares_channel channel;
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  int status, nfds, count;
  struct ares_options options;
  struct hostent *hostent;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;
  char *errmem;

  options.flags = ARES_FLAG_NOCHECKRESP;
  options.servers = NULL;
  options.nservers = 0;
  while ((c = getopt(argc, argv, "f:s:c:t:T:U:")) != -1)
    {
      switch (c)
	{
	case 'f':
	  /* Add a flag. */
	  for (i = 0; i < nflags; i++)
	    {
	      if (strcmp(flags[i].name, optarg) == 0)
		break;
	    }
	  if (i == nflags)
	    usage();
	  options.flags |= flags[i].value;
	  break;

	case 's':
	  /* Add a server, and specify servers in the option mask. */
	  hostent = gethostbyname(optarg);
	  if (!hostent || hostent->h_addrtype != AF_INET)
	    {
	      fprintf(stderr, "adig: server %s not found.\n", optarg);
	      return 1;
	    }
	  options.servers = realloc(options.servers, (options.nservers + 1)
				    * sizeof(struct in_addr));
	  if (!options.servers)
	    {
	      fprintf(stderr, "Out of memory!\n");
	      return 1;
	    }
	  memcpy(&options.servers[options.nservers], hostent->h_addr,
		 sizeof(struct in_addr));
	  options.nservers++;
	  optmask |= ARES_OPT_SERVERS;
	  break;

	case 'c':
	  /* Set the query class. */
	  for (i = 0; i < nclasses; i++)
	    {
	      if (strcasecmp(classes[i].name, optarg) == 0)
		break;
	    }
	  if (i == nclasses)
	    usage();
	  dnsclass = classes[i].value;
	  break;

	case 't':
	  /* Set the query type. */
	  for (i = 0; i < ntypes; i++)
	    {
	      if (strcasecmp(types[i].name, optarg) == 0)
		break;
	    }
	  if (i == ntypes)
	    usage();
	  type = types[i].value;
	  break;

	case 'T':
	  /* Set the TCP port number. */
	  if (!isdigit((unsigned char)*optarg))
	    usage();
	  options.tcp_port = strtol(optarg, NULL, 0);
	  optmask |= ARES_OPT_TCP_PORT;
	  break;

	case 'U':
	  /* Set the UDP port number. */
	  if (!isdigit((unsigned char)*optarg))
	    usage();
	  options.udp_port = strtol(optarg, NULL, 0);
	  optmask |= ARES_OPT_UDP_PORT;
	  break;
	}
    }
  argc -= optind;
  argv += optind;
  if (argc == 0)
    usage();

  status = ares_init_options(&channel, &options, optmask);
  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init_options: %s\n",
	      ares_strerror(status, &errmem));
      ares_free_errmem(errmem);
      return 1;
    }

  /* Initiate the queries, one per command-line argument.  If there is
   * only one query to do, supply NULL as the callback argument;
   * otherwise, supply the query name as an argument so we can
   * distinguish responses for the user when printing them out.
   */
  if (argc == 1)
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  else
    {
      for (; *argv; argv++)
	ares_query(channel, *argv, dnsclass, type, callback, *argv);
    }

  /* Wait for all queries to complete. */
  while (1)
    {
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
	break;
      tvp = ares_timeout(channel, NULL, &tv);
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (count < 0 && errno != EINVAL)
	{
	  perror("select");
	  return 1;
	}
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);
  return 0;
}