ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/res.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/res.c (file contents):
Revision 4311 by michael, Thu Jul 31 17:02:13 2014 UTC vs.
Revision 4408 by michael, Wed Aug 6 21:19:38 2014 UTC

# Line 94 | Line 94 | typedef enum
94  
95   struct reslist
96   {
97 <  dlink_node node;            /**< Doubly linked list node. */
98 <  int id;                     /**< Request ID (from request header). */
99 <  int sent;                   /**< Number of requests sent */
100 <  request_state state;        /**< State the resolver machine is in */
101 <  char type;                  /**< Current request type. */
102 <  char retries;               /**< Retry counter */
103 <  unsigned int sends;         /**< Number of sends (>1 means resent). */
104 <  char resend;                /**< Send flag; 0 == don't resend. */
105 <  time_t sentat;              /**< Timestamp we last sent this request. */
106 <  time_t timeout;             /**< When this request times out. */
107 <  struct irc_ssaddr addr;     /**< Address for this request. */
108 <  char *name;                 /**< Hostname for this request. */
109 <  dns_callback_fnc callback;  /**< Callback function on completion. */
110 <  void *callback_ctx;         /**< Context pointer for callback. */
97 >  dlink_node node;                       /**< Doubly linked list node. */
98 >  int id;                                /**< Request ID (from request header). */
99 >  int sent;                              /**< Number of requests sent */
100 >  request_state state;                   /**< State the resolver machine is in */
101 >  char type;                             /**< Current request type. */
102 >  char retries;                          /**< Retry counter */
103 >  unsigned int sends;                    /**< Number of sends (>1 means resent). */
104 >  char resend;                           /**< Send flag; 0 == don't resend. */
105 >  time_t sentat;                         /**< Timestamp we last sent this request. */
106 >  time_t timeout;                        /**< When this request times out. */
107 >  struct irc_ssaddr addr;                /**< Address for this request. */
108 >  char name[RFC1035_MAX_DOMAIN_LENGTH];  /**< Hostname for this request. */
109 >  size_t namelength;                     /**< Actual hostname length. */
110 >  dns_callback_fnc callback;             /**< Callback function on completion. */
111 >  void *callback_ctx;                    /**< Context pointer for callback. */
112   };
113  
114   static fde_t ResolverFileDescriptor;
# Line 124 | Line 125 | static void
125   rem_request(struct reslist *request)
126   {
127    dlinkDelete(&request->node, &request_list);
127
128  MyFree(request->name);
128    mp_pool_release(request);
129   }
130  
# Line 345 | Line 344 | static void
344   do_query_name(dns_callback_fnc callback, void *ctx, const char *name,
345                struct reslist *request, int type)
346   {
347 <  char host_name[HOSTLEN + 1];
347 >  char host_name[RFC1035_MAX_DOMAIN_LENGTH + 1];
348  
349    strlcpy(host_name, name, sizeof(host_name));
350  
351    if (request == NULL)
352    {
353 <    request       = make_request(callback, ctx);
354 <    request->name = MyCalloc(strlen(host_name) + 1);
355 <    request->type = type;
357 <    strcpy(request->name, host_name);
353 >    request             = make_request(callback, ctx);
354 >    request->type       = type;
355 >    request->namelength = strlcpy(request->name, host_name, sizeof(request->name));
356   #ifdef IPV6
357      if (type != T_A)
358        request->state = REQ_AAAA;
# Line 418 | Line 416 | do_query_number(dns_callback_fnc callbac
416      request       = make_request(callback, ctx);
417      request->type = T_PTR;
418      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
421    request->name = MyCalloc(HOSTLEN + 1);
419    }
420  
421    query_name(ipbuf, C_IN, T_PTR, request);
# Line 487 | Line 484 | resend_query(struct reslist *request)
484   static int
485   proc_answer(struct reslist *request, HEADER *header, char *buf, char *eob)
486   {
487 <  char hostbuf[HOSTLEN + 100]; /* working buffer */
487 >  char hostbuf[RFC1035_MAX_DOMAIN_LENGTH + 100]; /* working buffer */
488    unsigned char *current;      /* current position in buf */
489    int type;                    /* answer type */
490    int n;                       /* temp count */
# Line 519 | Line 516 | proc_answer(struct reslist *request, HEA
516      if (n < 0  /* Broken message */ || n == 0  /* No more answers left */)
517        return 0;
518  
519 <    hostbuf[HOSTLEN] = '\0';
519 >    hostbuf[RFC1035_MAX_DOMAIN_LENGTH] = '\0';
520  
521      /*
522       * With Address arithmetic you have to be very anal
# Line 583 | Line 580 | proc_answer(struct reslist *request, HEA
580          if (n < 0  /* Broken message */ || n == 0  /* No more answers left */)
581            return 0;
582  
583 <        strlcpy(request->name, hostbuf, HOSTLEN + 1);
583 >        request->namelength = strlcpy(request->name, hostbuf, sizeof(request->name));
584          return 1;
585          break;
586        case T_CNAME:  /* First check we already haven't started looking into a cname */
# Line 630 | Line 627 | res_readreply(fde_t *fd, void *data)
627    socklen_t len = sizeof(struct irc_ssaddr);
628    struct irc_ssaddr lsin;
629  
630 <  rc = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len);
631 <
632 <  /*
633 <   * Re-schedule a read *after* recvfrom, or we'll be registering
637 <   * interest where it'll instantly be ready for read :-) -- adrian
638 <   */
639 <  comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0);
640 <
641 <  if (rc <= (ssize_t)sizeof(HEADER))
642 <    return;
630 >  while ((rc = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len)) != -1)
631 >  {
632 >    if (rc <= (ssize_t)sizeof(HEADER))
633 >      continue;
634  
635 <  /*
636 <   * Check against possibly fake replies
637 <   */
638 <  if (!res_ourserver(&lsin))
639 <    return;
635 >    /*
636 >     * Check against possibly fake replies
637 >     */
638 >    if (!res_ourserver(&lsin))
639 >      continue;
640  
641 <  /*
642 <   * Convert DNS reply reader from Network byte order to CPU byte order.
643 <   */
644 <  header = (HEADER *)buf;
645 <  header->ancount = ntohs(header->ancount);
646 <  header->qdcount = ntohs(header->qdcount);
647 <  header->nscount = ntohs(header->nscount);
648 <  header->arcount = ntohs(header->arcount);
641 >    /*
642 >     * Convert DNS reply reader from Network byte order to CPU byte order.
643 >     */
644 >    header = (HEADER *)buf;
645 >    header->ancount = ntohs(header->ancount);
646 >    header->qdcount = ntohs(header->qdcount);
647 >    header->nscount = ntohs(header->nscount);
648 >    header->arcount = ntohs(header->arcount);
649  
650 <  /*
651 <   * Response for an id which we have already received an answer for
652 <   * just ignore this response.
653 <   */
654 <  if ((request = find_id(header->id)) == NULL)
655 <    return;
650 >    /*
651 >     * Response for an id which we have already received an answer for
652 >     * just ignore this response.
653 >     */
654 >    if ((request = find_id(header->id)) == NULL)
655 >      continue;
656  
657 <  if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
667 <  {
668 <    if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN)
657 >    if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
658      {
659 <      /*
660 <       * If a bad error was returned, stop here and don't
661 <       * send any more (no retries granted).
662 <       */
663 <      (*request->callback)(request->callback_ctx, NULL, NULL);
664 <      rem_request(request);
665 <    }
659 >      if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN)
660 >      {
661 >        /*
662 >         * If a bad error was returned, stop here and don't
663 >         * send any more (no retries granted).
664 >         */
665 >        (*request->callback)(request->callback_ctx, NULL, NULL, 0);
666 >        rem_request(request);
667 >      }
668   #ifdef IPV6
669 <    else
679 <    {
680 <      /*
681 <       * If we havent already tried this, and we're looking up AAAA, try A now.
682 <       */
683 <      if (request->state == REQ_AAAA && request->type == T_AAAA)
669 >      else
670        {
671 <        request->timeout += 4;
672 <        resend_query(request);
671 >        /*
672 >         * If we havent already tried this, and we're looking up AAAA, try A now.
673 >         */
674 >        if (request->state == REQ_AAAA && request->type == T_AAAA)
675 >        {
676 >          request->timeout += 4;
677 >          resend_query(request);
678 >        }
679        }
688    }
680   #endif
681 +      continue;
682 +    }
683  
684 <    return;
685 <  }
684 >    /*
685 >     * If this fails there was an error decoding the received packet.
686 >     * We only give it one shot. If it fails, just leave the client
687 >     * unresolved.
688 >     */
689 >    if (!proc_answer(request, header, buf, buf + rc))
690 >    {
691 >      (*request->callback)(request->callback_ctx, NULL, NULL, 0);
692 >      rem_request(request);
693 >      continue;
694 >    }
695  
694  /*
695   * If this fails there was an error decoding the received packet,
696   * try it again and hope it works the next time.
697   */
698  if (proc_answer(request, header, buf, buf + rc))
699  {
696      if (request->type == T_PTR)
697      {
698 <      if (request->name == NULL)
698 >      if (request->namelength == 0)
699        {
700          /*
701           * Got a PTR response with no name, something bogus is happening
702           * don't bother trying again, the client address doesn't resolve
703           */
704 <        (*request->callback)(request->callback_ctx, NULL, NULL);
704 >        (*request->callback)(request->callback_ctx, NULL, NULL, 0);
705          rem_request(request);
706 <        return;
706 >        continue;
707        }
708  
709        /*
# Line 726 | Line 722 | res_readreply(fde_t *fd, void *data)
722        /*
723         * Got a name and address response, client resolved
724         */
725 <      (*request->callback)(request->callback_ctx, &request->addr, request->name);
725 >      (*request->callback)(request->callback_ctx, &request->addr, request->name, request->namelength);
726        rem_request(request);
727      }
732  }
733  else if (!request->sent)
734  {
735    /* XXX - we got a response for a query we didn't send with a valid id?
736     * this should never happen, bail here and leave the client unresolved
737     */
738    assert(0);
728  
729 <    (*request->callback)(request->callback_ctx, NULL, NULL);
741 <    /* XXX don't leak it */
742 <    rem_request(request);
729 >    continue;
730    }
731 +
732 +  comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0);
733   }
734  
735   void
# Line 778 | Line 767 | timeout_query_list(void)
767      {
768        if (--request->retries <= 0)
769        {
770 <        (*request->callback)(request->callback_ctx, NULL, NULL);
770 >        (*request->callback)(request->callback_ctx, NULL, NULL, 0);
771          rem_request(request);
772          continue;
773        }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)