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/irc_res.c (file contents), Revision 1832 by michael, Fri Apr 19 19:16:09 2013 UTC vs.
ircd-hybrid/trunk/src/res.c (file contents), Revision 3652 by michael, Mon May 26 15:41:42 2014 UTC

# Line 1 | Line 1
1   /*
2 + *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 + *
4 + *  Copyright (c) 1997-2014 ircd-hybrid development team
5 + *
6 + *  This program is free software; you can redistribute it and/or modify
7 + *  it under the terms of the GNU General Public License as published by
8 + *  the Free Software Foundation; either version 2 of the License, or
9 + *  (at your option) any later version.
10 + *
11 + *  This program is distributed in the hope that it will be useful,
12 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 + *  GNU General Public License for more details.
15 + *
16 + *  You should have received a copy of the GNU General Public License
17 + *  along with this program; if not, write to the Free Software
18 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19 + *  USA
20 + */
21 +
22 + /*! \file res.c
23 + * \brief ircd resolver functions
24 + * \version $Id$
25 + */
26 +
27 + /*
28   * A rewrite of Darren Reeds original res.c As there is nothing
29   * left of Darrens original code, this is now licensed by the hybrid group.
30   * (Well, some of the function names are the same, and bits of the structs..)
# Line 14 | Line 40
40   *     --Bleep (Thomas Helvey <tomh@inxpress.net>)
41   *
42   * This was all needlessly complicated for irc. Simplified. No more hostent
43 < * All we really care about is the IP -> hostname mappings. Thats all.
43 > * All we really care about is the IP -> hostname mappings. Thats all.
44   *
45   * Apr 28, 2003 --cryogen and Dianora
46   */
# Line 30 | Line 56
56   #include "fdlist.h"
57   #include "s_bsd.h"
58   #include "log.h"
59 < #include "s_misc.h"
59 > #include "misc.h"
60   #include "send.h"
61   #include "memory.h"
62   #include "mempool.h"
63 < #include "irc_res.h"
64 < #include "irc_reslib.h"
63 > #include "res.h"
64 > #include "reslib.h"
65  
66   #if (CHAR_BIT != 8)
67 < #error this code needs to be able to address individual octets
67 > #error this code needs to be able to address individual octets
68   #endif
69  
70   static PF res_readreply;
71  
72   #define MAXPACKET      1024  /* rfc sez 512 but we expand names so ... */
47 #define RES_MAXALIASES 35    /* maximum aliases allowed */
48 #define RES_MAXADDRS   35    /* maximum addresses allowed */
73   #define AR_TTL         600   /* TTL in seconds for dns cache entries */
74  
75   /* RFC 1104/1105 wasn't very helpful about what these fields
# Line 58 | Line 82 | static PF res_readreply;
82   #define RDLENGTH_SIZE     (size_t)2
83   #define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE)
84  
85 < typedef enum
85 > typedef enum
86   {
87    REQ_IDLE,  /* We're doing not much at all */
88    REQ_PTR,   /* Looking up a PTR */
# Line 69 | Line 93 | typedef enum
93    REQ_CNAME  /* We got a CNAME in response, we better get a real answer next */
94   } request_state;
95  
96 < struct reslist
96 > struct reslist
97   {
98    dlink_node node;
99    int id;
# Line 78 | Line 102 | struct reslist
102    time_t ttl;
103    char type;
104    char retries;            /* retry counter */
105 <  char sends;              /* number of sends (>1 means resent) */
105 >  unsigned int sends;      /* number of sends (>1 means resent) */
106    char resend;             /* send flag. 0 == dont resend */
107    time_t sentat;
108    time_t timeout;
# Line 89 | Line 113 | struct reslist
113   };
114  
115   static fde_t ResolverFileDescriptor;
116 < static dlink_list request_list = { NULL, NULL, 0 };
117 < static mp_pool_t *dns_pool = NULL;
116 > static dlink_list request_list;
117 > static mp_pool_t *dns_pool;
118  
119   static void rem_request(struct reslist *);
120   static struct reslist *make_request(dns_callback_fnc, void *);
# Line 100 | Line 124 | static void do_query_number(dns_callback
124                              const struct irc_ssaddr *,
125                              struct reslist *);
126   static void query_name(const char *, int, int, struct reslist *);
127 < static int send_res_msg(const char *, int, int);
127 > static int send_res_msg(const char *, int, unsigned int);
128   static void resend_query(struct reslist *);
129   static int proc_answer(struct reslist *, HEADER *, char *, char *);
130   static struct reslist *find_id(int);
# Line 118 | Line 142 | static struct reslist *find_id(int);
142   *      revised for ircd, cryogen(stu) may03
143   */
144   static int
145 < res_ourserver(const struct irc_ssaddr *inp)
145 > res_ourserver(const struct irc_ssaddr *inp)
146   {
147   #ifdef IPV6
148    const struct sockaddr_in6 *v6;
149    const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
150   #endif
151    const struct sockaddr_in *v4;
152 <  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
129 <  int ns;
152 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
153  
154 <  for (ns = 0; ns < irc_nscount; ++ns)
154 >  for (unsigned int i = 0; i < irc_nscount; ++i)
155    {
156 <    const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
156 >    const struct irc_ssaddr *srv = &irc_nsaddr_list[i];
157   #ifdef IPV6
158      v6 = (const struct sockaddr_in6 *)srv;
159   #endif
# Line 166 | Line 189 | res_ourserver(const struct irc_ssaddr *i
189   }
190  
191   /*
192 < * timeout_query_list - Remove queries from the list which have been
192 > * timeout_query_list - Remove queries from the list which have been
193   * there too long without being resolved.
194   */
195   static time_t
196   timeout_query_list(time_t now)
197   {
198 <  dlink_node *ptr;
176 <  dlink_node *next_ptr;
198 >  dlink_node *ptr = NULL, *ptr_next = NULL;
199    struct reslist *request;
200    time_t next_time = 0;
201    time_t timeout   = 0;
202  
203 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
203 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
204    {
205      request = ptr->data;
206      timeout = request->sentat + request->timeout;
# Line 231 | Line 253 | start_resolver(void)
253        return;
254  
255      /* At the moment, the resolver FD data is global .. */
256 <    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ,
235 <        res_readreply, NULL, 0);
256 >    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ, res_readreply, NULL, 0);
257      eventAdd("timeout_resolver", timeout_resolver, NULL, 1);
258    }
259   }
# Line 255 | Line 276 | void
276   restart_resolver(void)
277   {
278    fd_close(&ResolverFileDescriptor);
279 <  eventDelete(timeout_resolver, NULL); /* -ddosen */
279 >  eventDelete(timeout_resolver, NULL);
280    start_resolver();
281   }
282  
283   /*
284 < * rem_request - remove a request from the list.
285 < * This must also free any memory that has been allocated for
284 > * rem_request - remove a request from the list.
285 > * This must also free any memory that has been allocated for
286   * temporary storage of DNS results.
287   */
288   static void
# Line 283 | Line 304 | make_request(dns_callback_fnc callback,
304  
305    memset(request, 0, sizeof(*request));
306    request->sentat       = CurrentTime;
307 <  request->retries      = 3;
307 >  request->retries      = 2;
308    request->resend       = 1;
309 <  request->timeout      = 4;    /* start at 4 and exponential inc. */
309 >  request->timeout      = 4;  /* Start at 4 and exponential inc. */
310    request->state        = REQ_IDLE;
311    request->callback     = callback;
312    request->callback_ctx = ctx;
# Line 295 | Line 316 | make_request(dns_callback_fnc callback,
316   }
317  
318   /*
319 < * delete_resolver_queries - cleanup outstanding queries
319 > * delete_resolver_queries - cleanup outstanding queries
320   * for which there no longer exist clients or conf lines.
321   */
322   void
323   delete_resolver_queries(const void *vptr)
324   {
325 <  dlink_node *ptr = NULL, *next_ptr = NULL;
325 >  dlink_node *ptr = NULL, *ptr_next = NULL;
326  
327 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
327 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
328    {
329      struct reslist *request = ptr->data;
330  
# Line 316 | Line 337 | delete_resolver_queries(const void *vptr
337   * send_res_msg - sends msg to all nameservers found in the "_res" structure.
338   * This should reflect /etc/resolv.conf. We will get responses
339   * which arent needed but is easier than checking to see if nameserver
340 < * isnt present. Returns number of messages successfully sent to
340 > * isnt present. Returns number of messages successfully sent to
341   * nameservers or -1 if no successful sends.
342   */
343   static int
344 < send_res_msg(const char *msg, int len, int rcount)
344 > send_res_msg(const char *msg, int len, unsigned int rcount)
345   {
325  int i;
346    int sent = 0;
347 <  int max_queries = IRCD_MIN(irc_nscount, rcount);
347 >  unsigned int max_queries = IRCD_MIN(irc_nscount, rcount);
348  
349    /* RES_PRIMARY option is not implemented
350     * if (res.options & RES_PRIMARY || 0 == max_queries)
# Line 332 | Line 352 | send_res_msg(const char *msg, int len, i
352    if (max_queries == 0)
353      max_queries = 1;
354  
355 <  for (i = 0; i < max_queries; i++)
355 >  for (unsigned int i = 0; i < max_queries; ++i)
356    {
357 <    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
358 <        (struct sockaddr*)&(irc_nsaddr_list[i]),
359 <        irc_nsaddr_list[i].ss_len) == len)
357 >    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
358 >        (struct sockaddr*)&(irc_nsaddr_list[i]),
359 >        irc_nsaddr_list[i].ss_len) == len)
360        ++sent;
361    }
362  
# Line 362 | Line 382 | find_id(int id)
382    return NULL;
383   }
384  
385 < /*
385 > /*
386   * gethost_byname_type - get host address from name
387   *
388   */
389   void
390   gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
391   {
392 <  assert(name != NULL);
392 >  assert(name);
393    do_query_name(callback, ctx, name, NULL, type);
394   }
395  
# Line 409 | Line 429 | do_query_name(dns_callback_fnc callback,
429    if (request == NULL)
430    {
431      request       = make_request(callback, ctx);
432 <    request->name = MyMalloc(strlen(host_name) + 1);
432 >    request->name = MyCalloc(strlen(host_name) + 1);
433      request->type = type;
434      strcpy(request->name, host_name);
435   #ifdef IPV6
# Line 432 | Line 452 | do_query_number(dns_callback_fnc callbac
452                  const struct irc_ssaddr *addr,
453                  struct reslist *request)
454   {
455 <  char ipbuf[128];
436 <  const unsigned char *cp;
455 >  char ipbuf[128] = "";
456  
457    if (addr->ss.ss_family == AF_INET)
458    {
459      const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
460 <    cp = (const unsigned char *)&v4->sin_addr.s_addr;
460 >    const unsigned char *cp = (const unsigned char *)&v4->sin_addr.s_addr;
461  
462      snprintf(ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
463               (unsigned int)(cp[3]), (unsigned int)(cp[2]),
# Line 448 | Line 467 | do_query_number(dns_callback_fnc callbac
467    else if (addr->ss.ss_family == AF_INET6)
468    {
469      const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
470 <    cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
470 >    const unsigned char *cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
471  
472      snprintf(ipbuf, sizeof(ipbuf),
473               "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
# Line 476 | Line 495 | do_query_number(dns_callback_fnc callbac
495      request       = make_request(callback, ctx);
496      request->type = T_PTR;
497      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
498 <    request->name = MyMalloc(HOSTLEN + 1);
498 >    request->name = MyCalloc(HOSTLEN + 1);
499    }
500  
501    query_name(ipbuf, C_IN, T_PTR, request);
# Line 494 | Line 513 | query_name(const char *name, int query_c
513  
514    memset(buf, 0, sizeof(buf));
515  
516 <  if ((request_len = irc_res_mkquery(name, query_class, type,
516 >  if ((request_len = irc_res_mkquery(name, query_class, type,
517        (unsigned char *)buf, sizeof(buf))) > 0)
518    {
519      HEADER *header = (HEADER *)buf;
# Line 577 | Line 596 | proc_answer(struct reslist *request, HEA
596      n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
597          hostbuf, sizeof(hostbuf));
598  
599 <    if (n < 0 /* broken message */ || n == 0 /* no more answers left */)
599 >    if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
600        return 0;
601  
602      hostbuf[HOSTLEN] = '\0';
# Line 586 | Line 605 | proc_answer(struct reslist *request, HEA
605       * this code was not working on alpha due to that
606       * (spotted by rodder/jailbird/dianora)
607       */
608 <    current += (size_t) n;
608 >    current += (size_t)n;
609  
610      if (!(((char *)current + ANSWER_FIXED_SIZE) < eob))
611        break;
# Line 603 | Line 622 | proc_answer(struct reslist *request, HEA
622      rd_length = irc_ns_get16(current);
623      current += RDLENGTH_SIZE;
624  
625 <    /*
626 <     * Wait to set request->type until we verify this structure
625 >    /*
626 >     * Wait to set request->type until we verify this structure
627       */
628      switch (type)
629      {
# Line 613 | Line 632 | proc_answer(struct reslist *request, HEA
632            return 0;
633  
634          /*
635 <         * check for invalid rd_length or too many addresses
635 >         * Check for invalid rd_length or too many addresses
636           */
637          if (rd_length != sizeof(struct in_addr))
638            return 0;
# Line 644 | Line 663 | proc_answer(struct reslist *request, HEA
663            return 0;
664  
665          n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
666 <            current, hostbuf, sizeof(hostbuf));
667 <        if (n < 0 /* broken message */ || n == 0 /* no more answers left */)
666 >                          current, hostbuf, sizeof(hostbuf));
667 >        if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
668            return 0;
669  
670          strlcpy(request->name, hostbuf, HOSTLEN + 1);
671          return 1;
672          break;
673 <      case T_CNAME: /* first check we already havent started looking
673 >      case T_CNAME: /* first check we already havent started looking
674                         into a cname */
675 <        if (request->type != T_PTR)
675 >        if (request->type != T_PTR)
676            return 0;
677  
678          if (request->state == REQ_CNAME)
# Line 669 | Line 688 | proc_answer(struct reslist *request, HEA
688          request->state = REQ_CNAME;
689          current += rd_length;
690          break;
691 <        
691 >
692        default:
693          /* XXX I'd rather just throw away the entire bogus thing
694           * but its possible its just a broken nameserver with still
# Line 690 | Line 709 | static void
709   res_readreply(fde_t *fd, void *data)
710   {
711    char buf[sizeof(HEADER) + MAXPACKET]
712 <        /* Sparc and alpha need 16bit-alignment for accessing header->id
713 <         * (which is uint16_t). Because of the header = (HEADER*) buf;
712 >        /* Sparc and alpha need 16bit-alignment for accessing header->id
713 >         * (which is uint16_t). Because of the header = (HEADER*) buf;
714           * lateron, this is neeeded. --FaUl
715           */
716 < #if defined(__sparc__) || defined(__alpha__)  
716 > #if defined(__sparc__) || defined(__alpha__)
717            __attribute__((aligned (16)))
718 < #endif
718 > #endif
719            ;
720    HEADER *header;
721    struct reslist *request = NULL;
# Line 716 | Line 735 | res_readreply(fde_t *fd, void *data)
735      return;
736  
737    /*
738 <   * convert DNS reply reader from Network byte order to CPU byte order.
738 >   * Convert DNS reply reader from Network byte order to CPU byte order.
739     */
740    header = (HEADER *)buf;
741    header->ancount = ntohs(header->ancount);
# Line 725 | Line 744 | res_readreply(fde_t *fd, void *data)
744    header->arcount = ntohs(header->arcount);
745  
746    /*
747 <   * check against possibly fake replies
747 >   * Check against possibly fake replies
748     */
749    if (!res_ourserver(&lsin))
750      return;
751  
752    /*
753 <   * response for an id which we have already received an answer for
753 >   * Response for an id which we have already received an answer for
754     * just ignore this response.
755     */
756    if (!(request = find_id(header->id)))
# Line 751 | Line 770 | res_readreply(fde_t *fd, void *data)
770   #ifdef IPV6
771      else
772      {
773 <      /*
773 >      /*
774         * If we havent already tried this, and we're looking up AAAA, try A
775         * now
776         */
# Line 767 | Line 786 | res_readreply(fde_t *fd, void *data)
786    }
787  
788    /*
789 <   * If this fails there was an error decoding the received packet,
789 >   * If this fails there was an error decoding the received packet,
790     * try it again and hope it works the next time.
791     */
792    if (proc_answer(request, header, buf, buf + rc))
# Line 777 | Line 796 | res_readreply(fde_t *fd, void *data)
796        if (request->name == NULL)
797        {
798          /*
799 <         * got a PTR response with no name, something bogus is happening
799 >         * Got a PTR response with no name, something bogus is happening
800           * don't bother trying again, the client address doesn't resolve
801           */
802          (*request->callback)(request->callback_ctx, NULL, NULL);
# Line 786 | Line 805 | res_readreply(fde_t *fd, void *data)
805        }
806  
807        /*
808 <       * Lookup the 'authoritative' name that we were given for the
790 <       * ip#.
791 <       *
808 >       * Lookup the 'authoritative' name that we were given for the ip#.
809         */
810   #ifdef IPV6
811        if (request->addr.ss.ss_family == AF_INET6)
# Line 801 | Line 818 | res_readreply(fde_t *fd, void *data)
818      else
819      {
820        /*
821 <       * got a name and address response, client resolved
821 >       * Got a name and address response, client resolved
822         */
823        (*request->callback)(request->callback_ctx, &request->addr, request->name);
824        rem_request(request);
# Line 822 | Line 839 | res_readreply(fde_t *fd, void *data)
839   void
840   report_dns_servers(struct Client *source_p)
841   {
842 <  int i;
826 <  char ipaddr[HOSTIPLEN + 1];
842 >  char ipaddr[HOSTIPLEN + 1] = "";
843  
844 <  for (i = 0; i < irc_nscount; i++)
844 >  for (unsigned int i = 0; i < irc_nscount; ++i)
845    {
846      getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
847                  irc_nsaddr_list[i].ss_len, ipaddr,
848                  sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
849 <    sendto_one(source_p, RPL_STATSALINE,
834 <               me.name, source_p->name, ipaddr);
849 >    sendto_one_numeric(source_p, &me, RPL_STATSALINE, ipaddr);
850    }
851   }

Diff Legend

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