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/src/irc_res.c (file contents), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid-7.3/src/irc_res.c (file contents), Revision 1123 by michael, Sun Feb 6 21:57:50 2011 UTC

# Line 7 | Line 7
7   * The authors takes no responsibility for any damage or loss
8   * of property which results from the use of this software.
9   *
10 < * $Id: irc_res.c,v 7.46 2005/07/30 03:35:18 metalrock Exp $
10 > * $Id$
11   *
12   * July 1999 - Rewrote a bunch of stuff here. Change hostent builder code,
13   *     added callbacks and reference counting of returned hostents.
# Line 20 | Line 20
20   */
21  
22   #include "stdinc.h"
23 #include "tools.h"
24 #include "client.h"
23   #include "list.h"
24 < #include "common.h"
24 > #include "balloc.h"
25 > #include "client.h"
26   #include "event.h"
27   #include "irc_string.h"
28   #include "sprintf_irc.h"
29   #include "ircd.h"
30   #include "numeric.h"
31 < #include "restart.h"
31 > #include "rng_mt.h"
32   #include "fdlist.h"
33   #include "fileio.h" /* for fbopen / fbclose / fbputs */
34   #include "s_bsd.h"
# Line 38 | Line 37
37   #include "memory.h"
38   #include "irc_res.h"
39   #include "irc_reslib.h"
40 < #include "irc_getnameinfo.h"
40 > #include "common.h"
41  
42   #if (CHAR_BIT != 8)
43   #error this code needs to be able to address individual octets
# Line 69 | Line 68 | typedef enum
68   #ifdef IPV6
69    REQ_AAAA,  /* Looking up an AAAA */
70   #endif
71 <  REQ_CNAME, /* We got a CNAME in response, we better get a real answer next */
73 <  REQ_INT    /* ip6.arpa failed, falling back to ip6.int */
71 >  REQ_CNAME  /* We got a CNAME in response, we better get a real answer next */
72   } request_state;
73  
74   struct reslist
# Line 88 | Line 86 | struct reslist
86    time_t timeout;
87    struct irc_ssaddr addr;
88    char *name;
89 <  struct DNSQuery *query;  /* query callback for this request */
89 >  dns_callback_fnc callback;
90 >  void *callback_ctx;
91   };
92  
93   static fde_t ResolverFileDescriptor;
94 < static dlink_list request_list    = { NULL, NULL, 0 };
94 > static dlink_list request_list = { NULL, NULL, 0 };
95 > static BlockHeap *dns_heap = NULL;
96  
97   static void rem_request(struct reslist *request);
98 < static struct reslist *make_request(struct DNSQuery *query);
99 < static void do_query_name(struct DNSQuery *query,
100 <                          const char* name, struct reslist *request, int);
101 < static void do_query_number(struct DNSQuery *query,
98 > static struct reslist *make_request(dns_callback_fnc callback, void *);
99 > static void do_query_name(dns_callback_fnc callback, void *,
100 >                          const char *, struct reslist *, int);
101 > static void do_query_number(dns_callback_fnc callback, void *ctx,
102                              const struct irc_ssaddr *,
103                              struct reslist *request);
104   static void query_name(const char *name, int query_class, int query_type,
# Line 107 | Line 107 | static int send_res_msg(const char *buf,
107   static void resend_query(struct reslist *request);
108   static int proc_answer(struct reslist *request, HEADER *header, char *, char *);
109   static struct reslist *find_id(int id);
110 static struct DNSReply *make_dnsreply(struct reslist *request);
111
112 extern struct irc_ssaddr irc_nsaddr_list[IRCD_MAXNS];
113 extern int irc_nscount;
114 extern char irc_domain[HOSTLEN+1];
110  
111  
112   /*
# Line 129 | Line 124 | static int
124   res_ourserver(const struct irc_ssaddr *inp)
125   {
126   #ifdef IPV6
127 <  struct sockaddr_in6 *v6;
128 <  struct sockaddr_in6 *v6in = (struct sockaddr_in6 *)inp;
127 >  const struct sockaddr_in6 *v6;
128 >  const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
129   #endif
130 <  struct sockaddr_in *v4;
131 <  struct sockaddr_in *v4in = (struct sockaddr_in *)inp;
130 >  const struct sockaddr_in *v4;
131 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
132    int ns;
133  
134 <  for (ns = 0;  ns < irc_nscount;  ns++)
134 >  for (ns = 0; ns < irc_nscount; ns++)
135    {
136      const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
137   #ifdef IPV6
138 <    v6 = (struct sockaddr_in6 *)srv;
138 >    v6 = (const struct sockaddr_in6 *)srv;
139   #endif
140 <    v4 = (struct sockaddr_in *)srv;
140 >    v4 = (const struct sockaddr_in *)srv;
141  
142      /* could probably just memcmp(srv, inp, srv.ss_len) here
143       * but we'll air on the side of caution - stu
# Line 198 | Line 193 | timeout_query_list(time_t now)
193      {
194        if (--request->retries <= 0)
195        {
196 <        (*request->query->callback)(request->query->ptr, NULL);
196 >        (*request->callback)(request->callback_ctx, NULL, NULL);
197          rem_request(request);
198          continue;
199        }
# Line 256 | Line 251 | start_resolver(void)
251   void
252   init_resolver(void)
253   {
254 < #ifdef HAVE_SRAND48
260 <  srand48(CurrentTime);
261 < #endif
254 >  dns_heap = BlockHeapCreate("dns", sizeof(struct reslist), DNS_HEAP_SIZE);
255    memset(&ResolverFileDescriptor, 0, sizeof(fde_t));
256    start_resolver();
257   }
# Line 275 | Line 268 | restart_resolver(void)
268   }
269  
270   /*
278 * add_local_domain - Add the domain to hostname, if it is missing
279 * (as suggested by eps@TOASTER.SFSU.EDU)
280 */
281 void
282 add_local_domain(char *hname, size_t size)
283 {
284  /* try to fix up unqualified names
285   */
286  if (strchr(hname, '.') == NULL)
287  {
288    if (irc_domain[0])
289    {
290      size_t len = strlen(hname);
291
292      if ((strlen(irc_domain) + len + 2) < size)
293      {
294        hname[len++] = '.';
295        strcpy(hname + len, irc_domain);
296      }
297    }
298  }
299 }
300
301 /*
271   * rem_request - remove a request from the list.
272   * This must also free any memory that has been allocated for
273   * temporary storage of DNS results.
# Line 307 | Line 276 | static void
276   rem_request(struct reslist *request)
277   {
278    dlinkDelete(&request->node, &request_list);
279 +
280    MyFree(request->name);
281 <  MyFree(request);
281 >  BlockHeapFree(dns_heap, request);
282   }
283  
284   /*
285   * make_request - Create a DNS request record for the server.
286   */
287   static struct reslist *
288 < make_request(struct DNSQuery* query)
288 > make_request(dns_callback_fnc callback, void *ctx)
289   {
290 <  struct reslist *request;
321 <
322 <  request = (struct reslist *)MyMalloc(sizeof(struct reslist));
323 <  memset(request, 0, sizeof(struct reslist));
290 >  struct reslist *request = BlockHeapAlloc(dns_heap);
291  
292 <  request->sentat  = CurrentTime;
293 <  request->retries = 3;
294 <  request->resend  = 1;
295 <  request->timeout = 4;    /* start at 4 and exponential inc. */
296 <  memset(&request->addr, 0, sizeof(request->addr));
297 <  request->query   = query;
298 <  request->state   = REQ_IDLE;
292 >  request->sentat       = CurrentTime;
293 >  request->retries      = 3;
294 >  request->resend       = 1;
295 >  request->timeout      = 4;    /* start at 4 and exponential inc. */
296 >  request->state        = REQ_IDLE;
297 >  request->callback     = callback;
298 >  request->callback_ctx = ctx;
299  
300    dlinkAdd(request, &request->node, &request_list);
301 <  return(request);
301 >  return request;
302   }
303  
304   /*
# Line 339 | Line 306 | make_request(struct DNSQuery* query)
306   * for which there no longer exist clients or conf lines.
307   */
308   void
309 < delete_resolver_queries(const struct DNSQuery *query)
309 > delete_resolver_queries(const void *vptr)
310   {
311 <  dlink_node *ptr;
345 <  dlink_node *next_ptr;
346 <  struct reslist *request;
311 >  dlink_node *ptr = NULL, *next_ptr = NULL;
312  
313    DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
314    {
315 <    if ((request = ptr->data) != NULL)
316 <    {
317 <      if (query == request->query)
318 <        rem_request(request);
354 <    }
315 >    struct reslist *request = ptr->data;
316 >
317 >    if (request->callback_ctx == vptr)
318 >      rem_request(request);
319    }
320   }
321  
# Line 411 | Line 375 | find_id(int id)
375   *
376   */
377   void
378 < gethost_byname_type(const char *name, struct DNSQuery *query, int type)
378 > gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
379   {
380    assert(name != 0);
381 <  do_query_name(query, name, NULL, type);
381 >  do_query_name(callback, ctx, name, NULL, type);
382   }
383  
384   /*
385   * gethost_byname - wrapper for _type - send T_AAAA first if IPV6 supported
386   */
387   void
388 < gethost_byname(const char *name, struct DNSQuery *query)
388 > gethost_byname(dns_callback_fnc callback, void *ctx, const char *name)
389   {
390   #ifdef IPV6
391 <  gethost_byname_type(name, query, T_AAAA);
391 >  gethost_byname_type(callback, ctx, name, T_AAAA);
392   #else
393 <  gethost_byname_type(name, query, T_A);
393 >  gethost_byname_type(callback, ctx, name, T_A);
394   #endif
395   }
396  
# Line 434 | Line 398 | gethost_byname(const char *name, struct
398   * gethost_byaddr - get host name from address
399   */
400   void
401 < gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
401 > gethost_byaddr(dns_callback_fnc callback, void *ctx, const struct irc_ssaddr *addr)
402   {
403 <  do_query_number(query, addr, NULL);
403 >  do_query_number(callback, ctx, addr, NULL);
404   }
405  
406   /*
407   * do_query_name - nameserver lookup name
408   */
409   static void
410 < do_query_name(struct DNSQuery *query, const char *name,
410 > do_query_name(dns_callback_fnc callback, void *ctx, const char *name,
411                struct reslist *request, int type)
412   {
413    char host_name[HOSTLEN + 1];
414  
415 <  strlcpy(host_name, name, HOSTLEN);
452 <  add_local_domain(host_name, HOSTLEN);
415 >  strlcpy(host_name, name, sizeof(host_name));
416  
417    if (request == NULL)
418    {
419 <    request       = make_request(query);
420 <    request->name = (char *)MyMalloc(strlen(host_name) + 1);
419 >    request       = make_request(callback, ctx);
420 >    request->name = MyMalloc(strlen(host_name) + 1);
421      request->type = type;
422      strcpy(request->name, host_name);
423   #ifdef IPV6
424 <    if (type == T_A)
462 <      request->state = REQ_A;
463 <    else
424 >    if (type != T_A)
425        request->state = REQ_AAAA;
426 < #else
466 <    request->state = REQ_A;
426 >    else
427   #endif
428 +    request->state = REQ_A;
429    }
430  
431    request->type = type;
# Line 475 | Line 436 | do_query_name(struct DNSQuery *query, co
436   * do_query_number - Use this to do reverse IP# lookups.
437   */
438   static void
439 < do_query_number(struct DNSQuery *query, const struct irc_ssaddr *addr,
439 > do_query_number(dns_callback_fnc callback, void *ctx,
440 >                const struct irc_ssaddr *addr,
441                  struct reslist *request)
442   {
443    char ipbuf[128];
444    const unsigned char *cp;
445 < #ifdef IPV6
484 <  const char *intarpa;
485 < #endif
445 >
446    if (addr->ss.ss_family == AF_INET)
447    {
448 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
448 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
449      cp = (const unsigned char*)&v4->sin_addr.s_addr;
450  
451      ircsprintf(ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
# Line 495 | Line 455 | do_query_number(struct DNSQuery *query,
455   #ifdef IPV6
456    else if (addr->ss.ss_family == AF_INET6)
457    {
458 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
458 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
459      cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
460  
461 <    if (request != NULL && request->state == REQ_INT)
462 <      intarpa = "int";
503 <    else
504 <      intarpa = "arpa";
505 <
506 <    (void)sprintf(ipbuf, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
507 <                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.%s.",
461 >    sprintf(ipbuf, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
462 >                   "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
463                    (unsigned int)(cp[15]&0xf), (unsigned int)(cp[15]>>4),
464                    (unsigned int)(cp[14]&0xf), (unsigned int)(cp[14]>>4),
465                    (unsigned int)(cp[13]&0xf), (unsigned int)(cp[13]>>4),
# Line 520 | Line 475 | do_query_number(struct DNSQuery *query,
475                    (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
476                    (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
477                    (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
478 <                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4), intarpa);
478 >                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4));
479    }
480   #endif
481    if (request == NULL)
482    {
483 <    request       = make_request(query);
483 >    request       = make_request(callback, ctx);
484      request->type = T_PTR;
485      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
486 <    request->name = (char *)MyMalloc(HOSTLEN + 1);
486 >    request->name = MyMalloc(HOSTLEN + 1);
487    }
488  
489    query_name(ipbuf, C_IN, T_PTR, request);
# Line 550 | Line 505 | query_name(const char *name, int query_c
505        (unsigned char *)buf, sizeof(buf))) > 0)
506    {
507      HEADER *header = (HEADER *)buf;
508 < #ifndef HAVE_LRAND48
554 <    int k = 0;
555 <    struct timeval tv;
556 < #endif
508 >
509      /*
510       * generate an unique id
511       * NOTE: we don't have to worry about converting this to and from
512       * network byte order, the nameserver does not interpret this value
513       * and returns it unchanged
514       */
563 #ifdef HAVE_LRAND48
564    do
565    {
566      header->id = (header->id + lrand48()) & 0xffff;
567    } while (find_id(header->id));
568 #else
569    gettimeofday(&tv, NULL);
515      do
516 <    {
517 <      header->id = (header->id + k + tv.tv_usec) & 0xffff;
518 <      k++;
574 <    } while (find_id(header->id));
575 < #endif /* HAVE_LRAND48 */
516 >      header->id = (header->id + genrand_int32()) & 0xffff;
517 >    while (find_id(header->id));
518 >
519      request->id = header->id;
520      ++request->sends;
521  
# Line 586 | Line 529 | resend_query(struct reslist *request)
529    if (request->resend == 0)
530      return;
531  
532 <  switch(request->type)
532 >  switch (request->type)
533    {
534      case T_PTR:
535 <      do_query_number(NULL, &request->addr, request);
535 >      do_query_number(NULL, NULL, &request->addr, request);
536        break;
537      case T_A:
538 <      do_query_name(NULL, request->name, request, request->type);
538 >      do_query_name(NULL, NULL, request->name, request, request->type);
539        break;
540   #ifdef IPV6
541      case T_AAAA:
542        /* didnt work, try A */
543        if (request->state == REQ_AAAA)
544 <        do_query_name(NULL, request->name, request, T_A);
544 >        do_query_name(NULL, NULL, request->name, request, T_A);
545   #endif
546      default:
547        break;
# Line 722 | Line 665 | proc_answer(struct reslist *request, HEA
665          else if (n == 0)
666            return(0); /* no more answers left */
667  
668 <        strlcpy(request->name, hostbuf, HOSTLEN);
668 >        strlcpy(request->name, hostbuf, HOSTLEN + 1);
669  
670          return(1);
671          break;
# Line 764 | Line 707 | proc_answer(struct reslist *request, HEA
707   static void
708   res_readreply(fde_t *fd, void *data)
709   {
710 <  char buf[sizeof(HEADER) + MAXPACKET];
710 >  char buf[sizeof(HEADER) + MAXPACKET]
711 >        /* Sparc and alpha need 16bit-alignment for accessing header->id
712 >         * (which is uint16_t). Because of the header = (HEADER*) buf;
713 >         * lateron, this is neeeded. --FaUl
714 >         */
715 > #if defined(__sparc__) || defined(__alpha__)  
716 >          __attribute__((aligned (16)))
717 > #endif
718 >          ;
719    HEADER *header;
720    struct reslist *request = NULL;
770  struct DNSReply *reply  = NULL;
721    int rc;
772  int answer_count;
722    socklen_t len = sizeof(struct irc_ssaddr);
723    struct irc_ssaddr lsin;
724  
# Line 779 | Line 728 | res_readreply(fde_t *fd, void *data)
728     * interest where it'll instantly be ready for read :-) -- adrian
729     */
730    comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0);
731 +
732    /* Better to cast the sizeof instead of rc */
733    if (rc <= (int)(sizeof(HEADER)))
734      return;
# Line 793 | Line 743 | res_readreply(fde_t *fd, void *data)
743    header->arcount = ntohs(header->arcount);
744  
745    /*
746 <   * response for an id which we have already received an answer for
797 <   * just ignore this response.
746 >   * check against possibly fake replies
747     */
748 <  if (0 == (request = find_id(header->id)))
748 >  if (!res_ourserver(&lsin))
749      return;
750  
751    /*
752 <   * check against possibly fake replies
752 >   * response for an id which we have already received an answer for
753 >   * just ignore this response.
754     */
755 <  if (!res_ourserver(&lsin))
755 >  if (!(request = find_id(header->id)))
756      return;
757  
758    if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
759    {
760 <    if (SERVFAIL == header->rcode)
761 <      resend_query(request);
760 >    if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN)
761 >    {
762 >      /*
763 >       * If a bad error was returned, stop here and don't
764 >       * send any more (no retries granted).
765 >       */
766 >      (*request->callback)(request->callback_ctx, NULL, NULL);
767 >      rem_request(request);
768 >    }
769 > #ifdef IPV6
770      else
771      {
772        /*
773         * If we havent already tried this, and we're looking up AAAA, try A
774         * now
775         */
818
819 #ifdef IPV6
776        if (request->state == REQ_AAAA && request->type == T_AAAA)
777        {
778          request->timeout += 4;
779          resend_query(request);
780        }
825      else if (request->type == T_PTR && request->state != REQ_INT &&
826               request->addr.ss.ss_family == AF_INET6)
827      {
828        request->state = REQ_INT;
829        request->timeout += 4;
830        request->retries--;
831        resend_query(request);
832      }
833      else
834 #endif
835      {
836        /*
837         * If a bad error was returned, we stop here and dont send
838         * send any more (no retries granted).
839         */
840        (*request->query->callback)(request->query->ptr, NULL);
841        rem_request(request);
842      }
781      }
782 + #endif
783  
784      return;
785    }
786 +
787    /*
788     * If this fails there was an error decoding the received packet,
789     * try it again and hope it works the next time.
790     */
791 <  answer_count = proc_answer(request, header, buf, buf + rc);
852 <
853 <  if (answer_count)
791 >  if (proc_answer(request, header, buf, buf + rc))
792    {
793      if (request->type == T_PTR)
794      {
# Line 860 | Line 798 | res_readreply(fde_t *fd, void *data)
798           * got a PTR response with no name, something bogus is happening
799           * don't bother trying again, the client address doesn't resolve
800           */
801 <        (*request->query->callback)(request->query->ptr, reply);
801 >        (*request->callback)(request->callback_ctx, NULL, NULL);
802          rem_request(request);
803          return;
804        }
# Line 872 | Line 810 | res_readreply(fde_t *fd, void *data)
810         */
811   #ifdef IPV6
812        if (request->addr.ss.ss_family == AF_INET6)
813 <        gethost_byname_type(request->name, request->query, T_AAAA);
813 >        gethost_byname_type(request->callback, request->callback_ctx, request->name, T_AAAA);
814        else
815   #endif
816 <      gethost_byname_type(request->name, request->query, T_A);
816 >      gethost_byname_type(request->callback, request->callback_ctx, request->name, T_A);
817        rem_request(request);
818      }
819      else
# Line 883 | Line 821 | res_readreply(fde_t *fd, void *data)
821        /*
822         * got a name and address response, client resolved
823         */
824 <      reply = make_dnsreply(request);
887 <      (*request->query->callback)(request->query->ptr, reply);
888 <      MyFree(reply);
824 >      (*request->callback)(request->callback_ctx, &request->addr, request->name);
825        rem_request(request);
826      }
827    }
# Line 901 | Line 837 | res_readreply(fde_t *fd, void *data)
837    }
838   }
839  
904 static struct DNSReply *
905 make_dnsreply(struct reslist *request)
906 {
907  struct DNSReply *cp;
908  assert(request != 0);
909
910  cp = (struct DNSReply *)MyMalloc(sizeof(struct DNSReply));
911
912  cp->h_name = request->name;
913  memcpy(&cp->addr, &request->addr, sizeof(cp->addr));
914  return(cp);
915 }
916
840   void
841   report_dns_servers(struct Client *source_p)
842   {
843    int i;
844 <  char ipaddr[HOSTIPLEN];
844 >  char ipaddr[HOSTIPLEN + 1];
845  
846    for (i = 0; i < irc_nscount; i++)
847    {
848 <    irc_getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
849 <                    irc_nsaddr_list[i].ss_len, ipaddr, HOSTIPLEN, NULL, 0,
850 <                    NI_NUMERICHOST);
848 >    getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
849 >                irc_nsaddr_list[i].ss_len, ipaddr,
850 >                sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
851      sendto_one(source_p, form_str(RPL_STATSALINE),
852                 me.name, source_p->name, ipaddr);
853    }

Comparing:
ircd-hybrid/src/irc_res.c (property svn:keywords), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid-7.3/src/irc_res.c (property svn:keywords), Revision 1123 by michael, Sun Feb 6 21:57:50 2011 UTC

# Line 1 | Line 1
1 < "Id Revision"
1 > Id Revision

Diff Legend

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