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

Comparing:
ircd-hybrid-7.3/src/irc_res.c (file contents), Revision 1123 by michael, Sun Feb 6 21:57:50 2011 UTC vs.
ircd-hybrid/trunk/src/irc_res.c (file contents), Revision 2916 by michael, Sat Jan 25 21:09:18 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 irc_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   */
47  
48   #include "stdinc.h"
49   #include "list.h"
24 #include "balloc.h"
50   #include "client.h"
51   #include "event.h"
52   #include "irc_string.h"
28 #include "sprintf_irc.h"
53   #include "ircd.h"
54   #include "numeric.h"
55   #include "rng_mt.h"
56   #include "fdlist.h"
33 #include "fileio.h" /* for fbopen / fbclose / fbputs */
57   #include "s_bsd.h"
58 < #include "s_log.h"
58 > #include "log.h"
59 > #include "s_misc.h"
60   #include "send.h"
61   #include "memory.h"
62 + #include "mempool.h"
63   #include "irc_res.h"
64   #include "irc_reslib.h"
40 #include "common.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;
# Line 60 | Line 84 | static PF res_readreply;
84   #define RDLENGTH_SIZE     (size_t)2
85   #define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE)
86  
87 < typedef enum
87 > typedef enum
88   {
89    REQ_IDLE,  /* We're doing not much at all */
90    REQ_PTR,   /* Looking up a PTR */
# Line 71 | Line 95 | typedef enum
95    REQ_CNAME  /* We got a CNAME in response, we better get a real answer next */
96   } request_state;
97  
98 < struct reslist
98 > struct reslist
99   {
100    dlink_node node;
101    int id;
# Line 92 | Line 116 | struct reslist
116  
117   static fde_t ResolverFileDescriptor;
118   static dlink_list request_list = { NULL, NULL, 0 };
119 < static BlockHeap *dns_heap = NULL;
119 > static mp_pool_t *dns_pool = NULL;
120  
121 < static void rem_request(struct reslist *request);
122 < static struct reslist *make_request(dns_callback_fnc callback, void *);
123 < static void do_query_name(dns_callback_fnc callback, void *,
121 > static void rem_request(struct reslist *);
122 > static struct reslist *make_request(dns_callback_fnc, void *);
123 > static void do_query_name(dns_callback_fnc, void *,
124                            const char *, struct reslist *, int);
125 < static void do_query_number(dns_callback_fnc callback, void *ctx,
125 > static void do_query_number(dns_callback_fnc, void *,
126                              const struct irc_ssaddr *,
127 <                            struct reslist *request);
128 < static void query_name(const char *name, int query_class, int query_type,
129 <                       struct reslist *request);
130 < static int send_res_msg(const char *buf, int len, int count);
131 < static void resend_query(struct reslist *request);
132 < static int proc_answer(struct reslist *request, HEADER *header, char *, char *);
109 < static struct reslist *find_id(int id);
127 >                            struct reslist *);
128 > static void query_name(const char *, int, int, struct reslist *);
129 > static int send_res_msg(const char *, int, int);
130 > static void resend_query(struct reslist *);
131 > static int proc_answer(struct reslist *, HEADER *, char *, char *);
132 > static struct reslist *find_id(int);
133  
134  
135   /*
# Line 121 | Line 144 | static struct reslist *find_id(int id);
144   *      revised for ircd, cryogen(stu) may03
145   */
146   static int
147 < res_ourserver(const struct irc_ssaddr *inp)
147 > res_ourserver(const struct irc_ssaddr *inp)
148   {
149   #ifdef IPV6
150    const struct sockaddr_in6 *v6;
151    const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
152   #endif
153    const struct sockaddr_in *v4;
154 <  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
154 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
155    int ns;
156  
157 <  for (ns = 0; ns < irc_nscount; ns++)
157 >  for (ns = 0; ns < irc_nscount; ++ns)
158    {
159      const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
160   #ifdef IPV6
# Line 149 | Line 172 | res_ourserver(const struct irc_ssaddr *i
172        case AF_INET6:
173          if (srv->ss.ss_family == inp->ss.ss_family)
174            if (v6->sin6_port == v6in->sin6_port)
175 <            if ((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
176 <                    sizeof(struct in6_addr)) == 0) ||
177 <                (memcmp(&v6->sin6_addr.s6_addr, &in6addr_any,
155 <                        sizeof(struct in6_addr)) == 0))
156 <              return(1);
175 >            if (!memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
176 >                        sizeof(struct in6_addr)))
177 >              return 1;
178          break;
179   #endif
180        case AF_INET:
181          if (srv->ss.ss_family == inp->ss.ss_family)
182            if (v4->sin_port == v4in->sin_port)
183 <            if ((v4->sin_addr.s_addr == INADDR_ANY) ||
184 <                (v4->sin_addr.s_addr == v4in->sin_addr.s_addr))
164 <              return(1);
183 >            if (v4->sin_addr.s_addr == v4in->sin_addr.s_addr)
184 >              return 1;
185          break;
186        default:
187          break;
188      }
189    }
190  
191 <  return(0);
191 >  return 0;
192   }
193  
194   /*
195 < * timeout_query_list - Remove queries from the list which have been
195 > * timeout_query_list - Remove queries from the list which have been
196   * there too long without being resolved.
197   */
198   static time_t
# Line 206 | Line 226 | timeout_query_list(time_t now)
226      }
227  
228      if ((next_time == 0) || timeout < next_time)
209    {
229        next_time = timeout;
211    }
230    }
231  
232 <  return((next_time > now) ? next_time : (now + AR_TTL));
232 >  return (next_time > now) ? next_time : (now + AR_TTL);
233   }
234  
235   /*
# Line 251 | Line 269 | start_resolver(void)
269   void
270   init_resolver(void)
271   {
272 <  dns_heap = BlockHeapCreate("dns", sizeof(struct reslist), DNS_HEAP_SIZE);
272 >  dns_pool = mp_pool_new(sizeof(struct reslist), MP_CHUNK_SIZE_DNS);
273    memset(&ResolverFileDescriptor, 0, sizeof(fde_t));
274    start_resolver();
275   }
# Line 268 | Line 286 | restart_resolver(void)
286   }
287  
288   /*
289 < * rem_request - remove a request from the list.
290 < * This must also free any memory that has been allocated for
289 > * rem_request - remove a request from the list.
290 > * This must also free any memory that has been allocated for
291   * temporary storage of DNS results.
292   */
293   static void
# Line 278 | Line 296 | rem_request(struct reslist *request)
296    dlinkDelete(&request->node, &request_list);
297  
298    MyFree(request->name);
299 <  BlockHeapFree(dns_heap, request);
299 >  mp_pool_release(request);
300   }
301  
302   /*
# Line 287 | Line 305 | rem_request(struct reslist *request)
305   static struct reslist *
306   make_request(dns_callback_fnc callback, void *ctx)
307   {
308 <  struct reslist *request = BlockHeapAlloc(dns_heap);
308 >  struct reslist *request = mp_pool_get(dns_pool);
309  
310 +  memset(request, 0, sizeof(*request));
311    request->sentat       = CurrentTime;
312    request->retries      = 3;
313    request->resend       = 1;
# Line 302 | Line 321 | make_request(dns_callback_fnc callback,
321   }
322  
323   /*
324 < * delete_resolver_queries - cleanup outstanding queries
324 > * delete_resolver_queries - cleanup outstanding queries
325   * for which there no longer exist clients or conf lines.
326   */
327   void
# Line 323 | Line 342 | delete_resolver_queries(const void *vptr
342   * send_res_msg - sends msg to all nameservers found in the "_res" structure.
343   * This should reflect /etc/resolv.conf. We will get responses
344   * which arent needed but is easier than checking to see if nameserver
345 < * isnt present. Returns number of messages successfully sent to
345 > * isnt present. Returns number of messages successfully sent to
346   * nameservers or -1 if no successful sends.
347   */
348   static int
# Line 341 | Line 360 | send_res_msg(const char *msg, int len, i
360  
361    for (i = 0; i < max_queries; i++)
362    {
363 <    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
364 <        (struct sockaddr*)&(irc_nsaddr_list[i]),
365 <        irc_nsaddr_list[i].ss_len) == len)
363 >    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
364 >        (struct sockaddr*)&(irc_nsaddr_list[i]),
365 >        irc_nsaddr_list[i].ss_len) == len)
366        ++sent;
367    }
368  
369 <  return(sent);
369 >  return sent;
370   }
371  
372   /*
# Line 356 | Line 375 | send_res_msg(const char *msg, int len, i
375   static struct reslist *
376   find_id(int id)
377   {
378 <  dlink_node *ptr;
360 <  struct reslist *request;
378 >  dlink_node *ptr = NULL;
379  
380    DLINK_FOREACH(ptr, request_list.head)
381    {
382 <    request = ptr->data;
382 >    struct reslist *request = ptr->data;
383  
384      if (request->id == id)
385 <      return(request);
385 >      return request;
386    }
387  
388 <  return(NULL);
388 >  return NULL;
389   }
390  
391 < /*
391 > /*
392   * gethost_byname_type - get host address from name
393   *
394   */
395   void
396   gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
397   {
398 <  assert(name != 0);
398 >  assert(name != NULL);
399    do_query_name(callback, ctx, name, NULL, type);
400   }
401  
# Line 446 | Line 464 | do_query_number(dns_callback_fnc callbac
464    if (addr->ss.ss_family == AF_INET)
465    {
466      const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
467 <    cp = (const unsigned char*)&v4->sin_addr.s_addr;
467 >    cp = (const unsigned char *)&v4->sin_addr.s_addr;
468  
469 <    ircsprintf(ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
470 <               (unsigned int)(cp[3]), (unsigned int)(cp[2]),
471 <               (unsigned int)(cp[1]), (unsigned int)(cp[0]));
469 >    snprintf(ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
470 >             (unsigned int)(cp[3]), (unsigned int)(cp[2]),
471 >             (unsigned int)(cp[1]), (unsigned int)(cp[0]));
472    }
473   #ifdef IPV6
474    else if (addr->ss.ss_family == AF_INET6)
# Line 458 | Line 476 | do_query_number(dns_callback_fnc callbac
476      const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
477      cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
478  
479 <    sprintf(ipbuf, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
480 <                   "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
481 <                  (unsigned int)(cp[15]&0xf), (unsigned int)(cp[15]>>4),
482 <                  (unsigned int)(cp[14]&0xf), (unsigned int)(cp[14]>>4),
483 <                  (unsigned int)(cp[13]&0xf), (unsigned int)(cp[13]>>4),
484 <                  (unsigned int)(cp[12]&0xf), (unsigned int)(cp[12]>>4),
485 <                  (unsigned int)(cp[11]&0xf), (unsigned int)(cp[11]>>4),
486 <                  (unsigned int)(cp[10]&0xf), (unsigned int)(cp[10]>>4),
487 <                  (unsigned int)(cp[9]&0xf), (unsigned int)(cp[9]>>4),
488 <                  (unsigned int)(cp[8]&0xf), (unsigned int)(cp[8]>>4),
489 <                  (unsigned int)(cp[7]&0xf), (unsigned int)(cp[7]>>4),
490 <                  (unsigned int)(cp[6]&0xf), (unsigned int)(cp[6]>>4),
491 <                  (unsigned int)(cp[5]&0xf), (unsigned int)(cp[5]>>4),
492 <                  (unsigned int)(cp[4]&0xf), (unsigned int)(cp[4]>>4),
493 <                  (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
494 <                  (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
495 <                  (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
496 <                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4));
479 >    snprintf(ipbuf, sizeof(ipbuf),
480 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
481 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
482 >             (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4),
483 >             (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4),
484 >             (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4),
485 >             (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4),
486 >             (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4),
487 >             (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4),
488 >             (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4),
489 >             (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4),
490 >             (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4),
491 >             (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4),
492 >             (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4),
493 >             (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4),
494 >             (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4),
495 >             (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4),
496 >             (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4),
497 >             (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4));
498    }
499   #endif
500    if (request == NULL)
# Line 501 | Line 520 | query_name(const char *name, int query_c
520  
521    memset(buf, 0, sizeof(buf));
522  
523 <  if ((request_len = irc_res_mkquery(name, query_class, type,
523 >  if ((request_len = irc_res_mkquery(name, query_class, type,
524        (unsigned char *)buf, sizeof(buf))) > 0)
525    {
526      HEADER *header = (HEADER *)buf;
# Line 552 | Line 571 | resend_query(struct reslist *request)
571   * proc_answer - process name server reply
572   */
573   static int
574 < proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
574 > proc_answer(struct reslist *request, HEADER *header, char *buf, char *eob)
575   {
576    char hostbuf[HOSTLEN + 100]; /* working buffer */
577    unsigned char *current;      /* current position in buf */
# Line 571 | Line 590 | proc_answer(struct reslist *request, HEA
590      if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0)
591        break;
592  
593 <    current += (size_t) n + QFIXEDSZ;
593 >    current += (size_t)n + QFIXEDSZ;
594    }
595  
596    /*
# Line 584 | Line 603 | proc_answer(struct reslist *request, HEA
603      n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
604          hostbuf, sizeof(hostbuf));
605  
606 <    if (n < 0)
607 <    {
589 <      /*
590 <       * broken message
591 <       */
592 <      return(0);
593 <    }
594 <    else if (n == 0)
595 <    {
596 <      /*
597 <       * no more answers left
598 <       */
599 <      return(0);
600 <    }
606 >    if (n < 0 /* broken message */ || n == 0 /* no more answers left */)
607 >      return 0;
608  
609      hostbuf[HOSTLEN] = '\0';
610  
# Line 622 | Line 629 | proc_answer(struct reslist *request, HEA
629      rd_length = irc_ns_get16(current);
630      current += RDLENGTH_SIZE;
631  
632 <    /*
633 <     * Wait to set request->type until we verify this structure
632 >    /*
633 >     * Wait to set request->type until we verify this structure
634       */
635      switch (type)
636      {
637        case T_A:
638          if (request->type != T_A)
639 <          return(0);
639 >          return 0;
640  
641          /*
642           * check for invalid rd_length or too many addresses
643           */
644          if (rd_length != sizeof(struct in_addr))
645 <          return(0);
645 >          return 0;
646 >
647          v4 = (struct sockaddr_in *)&request->addr;
648          request->addr.ss_len = sizeof(struct sockaddr_in);
649          v4->sin_family = AF_INET;
650          memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
651 <        return(1);
651 >        return 1;
652          break;
653   #ifdef IPV6
654        case T_AAAA:
655          if (request->type != T_AAAA)
656 <          return(0);
656 >          return 0;
657 >
658          if (rd_length != sizeof(struct in6_addr))
659 <          return(0);
659 >          return 0;
660 >
661          request->addr.ss_len = sizeof(struct sockaddr_in6);
662          v6 = (struct sockaddr_in6 *)&request->addr;
663          v6->sin6_family = AF_INET6;
664          memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr));
665 <        return(1);
665 >        return 1;
666          break;
667   #endif
668        case T_PTR:
669          if (request->type != T_PTR)
670 <          return(0);
670 >          return 0;
671 >
672          n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
673              current, hostbuf, sizeof(hostbuf));
674 <        if (n < 0)
675 <          return(0); /* broken message */
665 <        else if (n == 0)
666 <          return(0); /* no more answers left */
674 >        if (n < 0 /* broken message */ || n == 0 /* no more answers left */)
675 >          return 0;
676  
677          strlcpy(request->name, hostbuf, HOSTLEN + 1);
678 <
670 <        return(1);
678 >        return 1;
679          break;
680 <      case T_CNAME: /* first check we already havent started looking
680 >      case T_CNAME: /* first check we already havent started looking
681                         into a cname */
682 <        if (request->type != T_PTR)
683 <          return(0);
682 >        if (request->type != T_PTR)
683 >          return 0;
684  
685          if (request->state == REQ_CNAME)
686          {
# Line 680 | Line 688 | proc_answer(struct reslist *request, HEA
688                              current, hostbuf, sizeof(hostbuf));
689  
690            if (n < 0)
691 <            return(0);
692 <          return(1);
691 >            return 0;
692 >          return 1;
693          }
694  
695          request->state = REQ_CNAME;
696          current += rd_length;
697          break;
698 <        
698 >
699        default:
700          /* XXX I'd rather just throw away the entire bogus thing
701           * but its possible its just a broken nameserver with still
702           * valid answers. But lets do some rudimentary logging for now...
703           */
704 <        ilog(L_ERROR, "irc_res.c bogus type %d", type);
704 >        ilog(LOG_TYPE_IRCD, "irc_res.c bogus type %d", type);
705          break;
706      }
707    }
708  
709 <  return(1);
709 >  return 1;
710   }
711  
712   /*
# Line 708 | Line 716 | static void
716   res_readreply(fde_t *fd, void *data)
717   {
718    char buf[sizeof(HEADER) + MAXPACKET]
719 <        /* Sparc and alpha need 16bit-alignment for accessing header->id
720 <         * (which is uint16_t). Because of the header = (HEADER*) buf;
719 >        /* Sparc and alpha need 16bit-alignment for accessing header->id
720 >         * (which is uint16_t). Because of the header = (HEADER*) buf;
721           * lateron, this is neeeded. --FaUl
722           */
723 < #if defined(__sparc__) || defined(__alpha__)  
723 > #if defined(__sparc__) || defined(__alpha__)
724            __attribute__((aligned (16)))
725 < #endif
725 > #endif
726            ;
727    HEADER *header;
728    struct reslist *request = NULL;
# Line 769 | Line 777 | res_readreply(fde_t *fd, void *data)
777   #ifdef IPV6
778      else
779      {
780 <      /*
780 >      /*
781         * If we havent already tried this, and we're looking up AAAA, try A
782         * now
783         */
# Line 785 | Line 793 | res_readreply(fde_t *fd, void *data)
793    }
794  
795    /*
796 <   * If this fails there was an error decoding the received packet,
796 >   * If this fails there was an error decoding the received packet,
797     * try it again and hope it works the next time.
798     */
799    if (proc_answer(request, header, buf, buf + rc))
# Line 805 | Line 813 | res_readreply(fde_t *fd, void *data)
813  
814        /*
815         * Lookup the 'authoritative' name that we were given for the
816 <       * ip#.
816 >       * ip#.
817         *
818         */
819   #ifdef IPV6
# Line 849 | Line 857 | report_dns_servers(struct Client *source
857                  irc_nsaddr_list[i].ss_len, ipaddr,
858                  sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
859      sendto_one(source_p, form_str(RPL_STATSALINE),
860 <               me.name, source_p->name, ipaddr);
860 >               me.name, source_p->name, ipaddr);
861    }
862   }

Diff Legend

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