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-7.2/src/irc_res.c (file contents):
Revision 985 by michael, Sat Aug 15 20:31:54 2009 UTC vs.
Revision 1011 by michael, Fri Sep 18 10:14:09 2009 UTC

# 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"
32 #include "restart.h"
31   #include "rng_mt.h"
32   #include "fdlist.h"
33   #include "fileio.h" /* for fbopen / fbclose / fbputs */
# Line 40 | Line 38
38   #include "irc_res.h"
39   #include "irc_reslib.h"
40   #include "irc_getnameinfo.h"
41 + #include "common.h"
42  
43   #if (CHAR_BIT != 8)
44   #error this code needs to be able to address individual octets
# Line 88 | Line 87 | struct reslist
87    time_t timeout;
88    struct irc_ssaddr addr;
89    char *name;
90 <  struct DNSQuery *query;  /* query callback for this request */
90 >  dns_callback_fnc callback;
91 >  void *callback_ctx;
92   };
93  
94   static fde_t ResolverFileDescriptor;
95 < static dlink_list request_list    = { NULL, NULL, 0 };
95 > static dlink_list request_list = { NULL, NULL, 0 };
96 > static BlockHeap *dns_heap = NULL;
97  
98   static void rem_request(struct reslist *request);
99 < static struct reslist *make_request(struct DNSQuery *query);
100 < static void do_query_name(struct DNSQuery *query,
101 <                          const char* name, struct reslist *request, int);
102 < static void do_query_number(struct DNSQuery *query,
99 > static struct reslist *make_request(dns_callback_fnc callback, void *);
100 > static void do_query_name(dns_callback_fnc callback, void *,
101 >                          const char *, struct reslist *, int);
102 > static void do_query_number(dns_callback_fnc callback, void *ctx,
103                              const struct irc_ssaddr *,
104                              struct reslist *request);
105   static void query_name(const char *name, int query_class, int query_type,
# Line 107 | Line 108 | static int send_res_msg(const char *buf,
108   static void resend_query(struct reslist *request);
109   static int proc_answer(struct reslist *request, HEADER *header, char *, char *);
110   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];
111  
112  
113   /*
# Line 129 | Line 125 | static int
125   res_ourserver(const struct irc_ssaddr *inp)
126   {
127   #ifdef IPV6
128 <  struct sockaddr_in6 *v6;
129 <  struct sockaddr_in6 *v6in = (struct sockaddr_in6 *)inp;
128 >  const struct sockaddr_in6 *v6;
129 >  const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
130   #endif
131 <  struct sockaddr_in *v4;
132 <  struct sockaddr_in *v4in = (struct sockaddr_in *)inp;
131 >  const struct sockaddr_in *v4;
132 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
133    int ns;
134  
135    for (ns = 0; ns < irc_nscount; ns++)
136    {
137      const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
138   #ifdef IPV6
139 <    v6 = (struct sockaddr_in6 *)srv;
139 >    v6 = (const struct sockaddr_in6 *)srv;
140   #endif
141 <    v4 = (struct sockaddr_in *)srv;
141 >    v4 = (const struct sockaddr_in *)srv;
142  
143      /* could probably just memcmp(srv, inp, srv.ss_len) here
144       * but we'll air on the side of caution - stu
# Line 198 | Line 194 | timeout_query_list(time_t now)
194      {
195        if (--request->retries <= 0)
196        {
197 <        (*request->query->callback)(request->query->ptr, NULL);
197 >        (*request->callback)(request->callback_ctx, NULL, NULL);
198          rem_request(request);
199          continue;
200        }
# Line 256 | Line 252 | start_resolver(void)
252   void
253   init_resolver(void)
254   {
255 +  dns_heap = BlockHeapCreate("dns", sizeof(struct reslist), DNS_HEAP_SIZE);
256    memset(&ResolverFileDescriptor, 0, sizeof(fde_t));
257    start_resolver();
258   }
# Line 272 | Line 269 | restart_resolver(void)
269   }
270  
271   /*
275 * add_local_domain - Add the domain to hostname, if it is missing
276 * (as suggested by eps@TOASTER.SFSU.EDU)
277 */
278 void
279 add_local_domain(char *hname, size_t size)
280 {
281  /* try to fix up unqualified names
282   */
283  if (strchr(hname, '.') == NULL)
284  {
285    if (irc_domain[0])
286    {
287      size_t len = strlen(hname);
288
289      if ((strlen(irc_domain) + len + 2) < size)
290      {
291        hname[len++] = '.';
292        strcpy(hname + len, irc_domain);
293      }
294    }
295  }
296 }
297
298 /*
272   * rem_request - remove a request from the list.
273   * This must also free any memory that has been allocated for
274   * temporary storage of DNS results.
# Line 304 | Line 277 | static void
277   rem_request(struct reslist *request)
278   {
279    dlinkDelete(&request->node, &request_list);
280 +
281    MyFree(request->name);
282 <  MyFree(request);
282 >  BlockHeapFree(dns_heap, request);
283   }
284  
285   /*
286   * make_request - Create a DNS request record for the server.
287   */
288   static struct reslist *
289 < make_request(struct DNSQuery* query)
289 > make_request(dns_callback_fnc callback, void *ctx)
290   {
291 <  struct reslist *request;
318 <
319 <  request = (struct reslist *)MyMalloc(sizeof(struct reslist));
291 >  struct reslist *request = BlockHeapAlloc(dns_heap);
292  
293 <  request->sentat  = CurrentTime;
294 <  request->retries = 3;
295 <  request->resend  = 1;
296 <  request->timeout = 4;    /* start at 4 and exponential inc. */
297 <  request->query   = query;
298 <  request->state   = REQ_IDLE;
293 >  request->sentat       = CurrentTime;
294 >  request->retries      = 3;
295 >  request->resend       = 1;
296 >  request->timeout      = 4;    /* start at 4 and exponential inc. */
297 >  request->state        = REQ_IDLE;
298 >  request->callback     = callback;
299 >  request->callback_ctx = ctx;
300  
301    dlinkAdd(request, &request->node, &request_list);
302 <  return(request);
302 >  return request;
303   }
304  
305   /*
# Line 334 | Line 307 | make_request(struct DNSQuery* query)
307   * for which there no longer exist clients or conf lines.
308   */
309   void
310 < delete_resolver_queries(const struct DNSQuery *query)
310 > delete_resolver_queries(const void *vptr)
311   {
312 <  dlink_node *ptr;
340 <  dlink_node *next_ptr;
341 <  struct reslist *request;
312 >  dlink_node *ptr = NULL, *next_ptr = NULL;
313  
314    DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
315    {
316 <    if ((request = ptr->data) != NULL)
317 <    {
318 <      if (query == request->query)
319 <        rem_request(request);
349 <    }
316 >    struct reslist *request = ptr->data;
317 >
318 >    if (request->callback_ctx == vptr)
319 >      rem_request(request);
320    }
321   }
322  
# Line 406 | Line 376 | find_id(int id)
376   *
377   */
378   void
379 < gethost_byname_type(const char *name, struct DNSQuery *query, int type)
379 > gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
380   {
381    assert(name != 0);
382 <  do_query_name(query, name, NULL, type);
382 >  do_query_name(callback, ctx, name, NULL, type);
383   }
384  
385   /*
386   * gethost_byname - wrapper for _type - send T_AAAA first if IPV6 supported
387   */
388   void
389 < gethost_byname(const char *name, struct DNSQuery *query)
389 > gethost_byname(dns_callback_fnc callback, void *ctx, const char *name)
390   {
391   #ifdef IPV6
392 <  gethost_byname_type(name, query, T_AAAA);
392 >  gethost_byname_type(callback, ctx, name, T_AAAA);
393   #else
394 <  gethost_byname_type(name, query, T_A);
394 >  gethost_byname_type(callback, ctx, name, T_A);
395   #endif
396   }
397  
# Line 429 | Line 399 | gethost_byname(const char *name, struct
399   * gethost_byaddr - get host name from address
400   */
401   void
402 < gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
402 > gethost_byaddr(dns_callback_fnc callback, void *ctx, const struct irc_ssaddr *addr)
403   {
404 <  do_query_number(query, addr, NULL);
404 >  do_query_number(callback, ctx, addr, NULL);
405   }
406  
407   /*
408   * do_query_name - nameserver lookup name
409   */
410   static void
411 < do_query_name(struct DNSQuery *query, const char *name,
411 > do_query_name(dns_callback_fnc callback, void *ctx, const char *name,
412                struct reslist *request, int type)
413   {
414    char host_name[HOSTLEN + 1];
415  
416 <  strlcpy(host_name, name, HOSTLEN);
447 <  add_local_domain(host_name, HOSTLEN);
416 >  strlcpy(host_name, name, sizeof(host_name));
417  
418    if (request == NULL)
419    {
420 <    request       = make_request(query);
421 <    request->name = (char *)MyMalloc(strlen(host_name) + 1);
420 >    request       = make_request(callback, ctx);
421 >    request->name = MyMalloc(strlen(host_name) + 1);
422      request->type = type;
423      strcpy(request->name, host_name);
424   #ifdef IPV6
# Line 468 | Line 437 | do_query_name(struct DNSQuery *query, co
437   * do_query_number - Use this to do reverse IP# lookups.
438   */
439   static void
440 < do_query_number(struct DNSQuery *query, const struct irc_ssaddr *addr,
440 > do_query_number(dns_callback_fnc callback, void *ctx,
441 >                const struct irc_ssaddr *addr,
442                  struct reslist *request)
443   {
444    char ipbuf[128];
# Line 476 | Line 446 | do_query_number(struct DNSQuery *query,
446  
447    if (addr->ss.ss_family == AF_INET)
448    {
449 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
449 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
450      cp = (const unsigned char*)&v4->sin_addr.s_addr;
451  
452      ircsprintf(ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
# Line 486 | Line 456 | do_query_number(struct DNSQuery *query,
456   #ifdef IPV6
457    else if (addr->ss.ss_family == AF_INET6)
458    {
459 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
459 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
460      cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
461  
462      sprintf(ipbuf, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
# Line 511 | Line 481 | do_query_number(struct DNSQuery *query,
481   #endif
482    if (request == NULL)
483    {
484 <    request       = make_request(query);
484 >    request       = make_request(callback, ctx);
485      request->type = T_PTR;
486      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
487 <    request->name = (char *)MyMalloc(HOSTLEN + 1);
487 >    request->name = MyMalloc(HOSTLEN + 1);
488    }
489  
490    query_name(ipbuf, C_IN, T_PTR, request);
# Line 563 | Line 533 | resend_query(struct reslist *request)
533    switch (request->type)
534    {
535      case T_PTR:
536 <      do_query_number(NULL, &request->addr, request);
536 >      do_query_number(NULL, NULL, &request->addr, request);
537        break;
538      case T_A:
539 <      do_query_name(NULL, request->name, request, request->type);
539 >      do_query_name(NULL, NULL, request->name, request, request->type);
540        break;
541   #ifdef IPV6
542      case T_AAAA:
543        /* didnt work, try A */
544        if (request->state == REQ_AAAA)
545 <        do_query_name(NULL, request->name, request, T_A);
545 >        do_query_name(NULL, NULL, request->name, request, T_A);
546   #endif
547      default:
548        break;
# Line 696 | Line 666 | proc_answer(struct reslist *request, HEA
666          else if (n == 0)
667            return(0); /* no more answers left */
668  
669 <        strlcpy(request->name, hostbuf, HOSTLEN);
669 >        strlcpy(request->name, hostbuf, HOSTLEN + 1);
670  
671          return(1);
672          break;
# Line 749 | Line 719 | res_readreply(fde_t *fd, void *data)
719            ;
720    HEADER *header;
721    struct reslist *request = NULL;
752  struct DNSReply *reply  = NULL;
722    int rc;
754  int answer_count;
723    socklen_t len = sizeof(struct irc_ssaddr);
724    struct irc_ssaddr lsin;
725  
# Line 776 | Line 744 | res_readreply(fde_t *fd, void *data)
744    header->arcount = ntohs(header->arcount);
745  
746    /*
747 <   * response for an id which we have already received an answer for
780 <   * just ignore this response.
747 >   * check against possibly fake replies
748     */
749 <  if (0 == (request = find_id(header->id)))
749 >  if (!res_ourserver(&lsin))
750      return;
751  
752    /*
753 <   * check against possibly fake replies
753 >   * response for an id which we have already received an answer for
754 >   * just ignore this response.
755     */
756 <  if (!res_ourserver(&lsin))
756 >  if (!(request = find_id(header->id)))
757      return;
758  
759    if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
# Line 796 | Line 764 | res_readreply(fde_t *fd, void *data)
764         * If a bad error was returned, stop here and don't
765         * send any more (no retries granted).
766         */
767 <      (*request->query->callback)(request->query->ptr, NULL);
767 >      (*request->callback)(request->callback_ctx, NULL, NULL);
768        rem_request(request);
769      }
770   #ifdef IPV6
# Line 821 | Line 789 | res_readreply(fde_t *fd, void *data)
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 <  answer_count = proc_answer(request, header, buf, buf + rc);
825 <
826 <  if (answer_count)
792 >  if (proc_answer(request, header, buf, buf + rc))
793    {
794      if (request->type == T_PTR)
795      {
# Line 833 | Line 799 | res_readreply(fde_t *fd, void *data)
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->query->callback)(request->query->ptr, reply);
802 >        (*request->callback)(request->callback_ctx, NULL, NULL);
803          rem_request(request);
804          return;
805        }
# Line 845 | Line 811 | res_readreply(fde_t *fd, void *data)
811         */
812   #ifdef IPV6
813        if (request->addr.ss.ss_family == AF_INET6)
814 <        gethost_byname_type(request->name, request->query, T_AAAA);
814 >        gethost_byname_type(request->callback, request->callback_ctx, request->name, T_AAAA);
815        else
816   #endif
817 <      gethost_byname_type(request->name, request->query, T_A);
817 >      gethost_byname_type(request->callback, request->callback_ctx, request->name, T_A);
818        rem_request(request);
819      }
820      else
# Line 856 | Line 822 | res_readreply(fde_t *fd, void *data)
822        /*
823         * got a name and address response, client resolved
824         */
825 <      reply = make_dnsreply(request);
860 <      (*request->query->callback)(request->query->ptr, reply);
861 <      MyFree(reply);
825 >      (*request->callback)(request->callback_ctx, &request->addr, request->name);
826        rem_request(request);
827      }
828    }
# Line 874 | Line 838 | res_readreply(fde_t *fd, void *data)
838    }
839   }
840  
877 static struct DNSReply *
878 make_dnsreply(struct reslist *request)
879 {
880  struct DNSReply *cp;
881  assert(request != 0);
882
883  cp = (struct DNSReply *)MyMalloc(sizeof(struct DNSReply));
884
885  cp->h_name = request->name;
886  memcpy(&cp->addr, &request->addr, sizeof(cp->addr));
887  return(cp);
888 }
889
841   void
842   report_dns_servers(struct Client *source_p)
843   {
844    int i;
845 <  char ipaddr[HOSTIPLEN];
845 >  char ipaddr[HOSTIPLEN + 1];
846  
847    for (i = 0; i < irc_nscount; i++)
848    {
849      irc_getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
850 <                    irc_nsaddr_list[i].ss_len, ipaddr, HOSTIPLEN, NULL, 0,
851 <                    NI_NUMERICHOST);
850 >                    irc_nsaddr_list[i].ss_len, ipaddr,
851 >                    sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
852      sendto_one(source_p, form_str(RPL_STATSALINE),
853                 me.name, source_p->name, ipaddr);
854    }

Diff Legend

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