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 463 by db, Mon Feb 13 03:30:53 2006 UTC vs.
ircd-hybrid/trunk/src/res.c (file contents), Revision 3322 by michael, Tue Apr 15 16:11:11 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   */
47  
48   #include "stdinc.h"
23 #include "tools.h"
24 #include "client.h"
49   #include "list.h"
50 < #include "common.h"
50 > #include "client.h"
51   #include "event.h"
52   #include "irc_string.h"
29 #include "sprintf_irc.h"
53   #include "ircd.h"
54   #include "numeric.h"
55 < #include "restart.h"
55 > #include "rng_mt.h"
56   #include "fdlist.h"
34 #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 "irc_res.h"
63 < #include "irc_reslib.h"
64 < #include "irc_getnameinfo.h"
62 > #include "mempool.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;
# Line 61 | 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 69 | Line 92 | typedef enum
92   #ifdef IPV6
93    REQ_AAAA,  /* Looking up an AAAA */
94   #endif
95 <  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 */
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 82 | Line 104 | struct reslist
104    time_t ttl;
105    char type;
106    char retries;            /* retry counter */
107 <  char sends;              /* number of sends (>1 means resent) */
107 >  unsigned int sends;      /* number of sends (>1 means resent) */
108    char resend;             /* send flag. 0 == dont resend */
109    time_t sentat;
110    time_t timeout;
111    struct irc_ssaddr addr;
112    char *name;
113 <  struct DNSQuery *query;  /* query callback for this request */
113 >  dns_callback_fnc callback;
114 >  void *callback_ctx;
115   };
116  
117   static fde_t ResolverFileDescriptor;
118 < static dlink_list request_list    = { NULL, NULL, 0 };
118 > static dlink_list request_list;
119 > static mp_pool_t *dns_pool;
120  
121 < static void rem_request(struct reslist *request);
122 < static struct reslist *make_request(struct DNSQuery *query);
123 < static void do_query_name(struct DNSQuery *query,
124 <                          const char* name, struct reslist *request, int);
125 < static void do_query_number(struct DNSQuery *query,
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, 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);
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];
127 >                            struct reslist *);
128 > static void query_name(const char *, int, int, struct reslist *);
129 > static int send_res_msg(const char *, int, unsigned 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 126 | Line 144 | extern char irc_domain[HOSTLEN+1];
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 <  struct sockaddr_in6 *v6;
151 <  struct sockaddr_in6 *v6in = (struct sockaddr_in6 *)inp;
150 >  const struct sockaddr_in6 *v6;
151 >  const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
152   #endif
153 <  struct sockaddr_in *v4;
154 <  struct sockaddr_in *v4in = (struct sockaddr_in *)inp;
137 <  int ns;
153 >  const struct sockaddr_in *v4;
154 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
155  
156 <  for (ns = 0;  ns < irc_nscount;  ns++)
156 >  for (unsigned int i = 0; i < irc_nscount; ++i)
157    {
158 <    const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
158 >    const struct irc_ssaddr *srv = &irc_nsaddr_list[i];
159   #ifdef IPV6
160 <    v6 = (struct sockaddr_in6 *)srv;
160 >    v6 = (const struct sockaddr_in6 *)srv;
161   #endif
162 <    v4 = (struct sockaddr_in *)srv;
162 >    v4 = (const struct sockaddr_in *)srv;
163  
164      /* could probably just memcmp(srv, inp, srv.ss_len) here
165       * but we'll air on the side of caution - stu
# Line 154 | Line 171 | res_ourserver(const struct irc_ssaddr *i
171        case AF_INET6:
172          if (srv->ss.ss_family == inp->ss.ss_family)
173            if (v6->sin6_port == v6in->sin6_port)
174 <            if ((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
175 <                    sizeof(struct in6_addr)) == 0) ||
176 <                (memcmp(&v6->sin6_addr.s6_addr, &in6addr_any,
160 <                        sizeof(struct in6_addr)) == 0))
161 <              return(1);
174 >            if (!memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
175 >                        sizeof(struct in6_addr)))
176 >              return 1;
177          break;
178   #endif
179        case AF_INET:
180          if (srv->ss.ss_family == inp->ss.ss_family)
181            if (v4->sin_port == v4in->sin_port)
182 <            if ((v4->sin_addr.s_addr == INADDR_ANY) ||
183 <                (v4->sin_addr.s_addr == v4in->sin_addr.s_addr))
169 <              return(1);
182 >            if (v4->sin_addr.s_addr == v4in->sin_addr.s_addr)
183 >              return 1;
184          break;
185        default:
186          break;
187      }
188    }
189  
190 <  return(0);
190 >  return 0;
191   }
192  
193   /*
194 < * timeout_query_list - Remove queries from the list which have been
194 > * timeout_query_list - Remove queries from the list which have been
195   * there too long without being resolved.
196   */
197   static time_t
198   timeout_query_list(time_t now)
199   {
200 <  dlink_node *ptr;
187 <  dlink_node *next_ptr;
200 >  dlink_node *ptr = NULL, *ptr_next = NULL;
201    struct reslist *request;
202    time_t next_time = 0;
203    time_t timeout   = 0;
204  
205 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
205 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
206    {
207      request = ptr->data;
208      timeout = request->sentat + request->timeout;
# Line 198 | Line 211 | timeout_query_list(time_t now)
211      {
212        if (--request->retries <= 0)
213        {
214 <        (*request->query->callback)(request->query->ptr, NULL);
214 >        (*request->callback)(request->callback_ctx, NULL, NULL);
215          rem_request(request);
216          continue;
217        }
# Line 211 | Line 224 | timeout_query_list(time_t now)
224      }
225  
226      if ((next_time == 0) || timeout < next_time)
214    {
227        next_time = timeout;
216    }
228    }
229  
230 <  return((next_time > now) ? next_time : (now + AR_TTL));
230 >  return (next_time > now) ? next_time : (now + AR_TTL);
231   }
232  
233   /*
# Line 244 | Line 255 | start_resolver(void)
255        return;
256  
257      /* At the moment, the resolver FD data is global .. */
258 <    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ,
248 <        res_readreply, NULL, 0);
258 >    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ, res_readreply, NULL, 0);
259      eventAdd("timeout_resolver", timeout_resolver, NULL, 1);
260    }
261   }
# Line 256 | Line 266 | start_resolver(void)
266   void
267   init_resolver(void)
268   {
269 < #ifdef HAVE_SRAND48
260 <  srand48(CurrentTime);
261 < #endif
269 >  dns_pool = mp_pool_new(sizeof(struct reslist), MP_CHUNK_SIZE_DNS);
270    memset(&ResolverFileDescriptor, 0, sizeof(fde_t));
271    start_resolver();
272   }
# Line 270 | Line 278 | void
278   restart_resolver(void)
279   {
280    fd_close(&ResolverFileDescriptor);
281 <  eventDelete(timeout_resolver, NULL); /* -ddosen */
281 >  eventDelete(timeout_resolver, NULL);
282    start_resolver();
283   }
284  
285   /*
286 < * add_local_domain - Add the domain to hostname, if it is missing
287 < * (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 < /*
302 < * rem_request - remove a request from the list.
303 < * This must also free any memory that has been allocated for
286 > * rem_request - remove a request from the list.
287 > * This must also free any memory that has been allocated for
288   * temporary storage of DNS results.
289   */
290   static void
291   rem_request(struct reslist *request)
292   {
293    dlinkDelete(&request->node, &request_list);
294 +
295    MyFree(request->name);
296 <  MyFree(request);
296 >  mp_pool_release(request);
297   }
298  
299   /*
300   * make_request - Create a DNS request record for the server.
301   */
302   static struct reslist *
303 < make_request(struct DNSQuery* query)
303 > make_request(dns_callback_fnc callback, void *ctx)
304   {
305 <  struct reslist *request;
321 <
322 <  request = (struct reslist *)MyMalloc(sizeof(struct reslist));
305 >  struct reslist *request = mp_pool_get(dns_pool);
306  
307 <  request->sentat  = CurrentTime;
308 <  request->retries = 3;
309 <  request->resend  = 1;
310 <  request->timeout = 4;    /* start at 4 and exponential inc. */
311 <  request->query   = query;
312 <  request->state   = REQ_IDLE;
307 >  memset(request, 0, sizeof(*request));
308 >  request->sentat       = CurrentTime;
309 >  request->retries      = 2;
310 >  request->resend       = 1;
311 >  request->timeout      = 4;  /* Start at 4 and exponential inc. */
312 >  request->state        = REQ_IDLE;
313 >  request->callback     = callback;
314 >  request->callback_ctx = ctx;
315  
316    dlinkAdd(request, &request->node, &request_list);
317 <  return(request);
317 >  return request;
318   }
319  
320   /*
321 < * delete_resolver_queries - cleanup outstanding queries
321 > * delete_resolver_queries - cleanup outstanding queries
322   * for which there no longer exist clients or conf lines.
323   */
324   void
325 < delete_resolver_queries(const struct DNSQuery *query)
325 > delete_resolver_queries(const void *vptr)
326   {
327 <  dlink_node *ptr;
343 <  dlink_node *next_ptr;
344 <  struct reslist *request;
327 >  dlink_node *ptr = NULL, *ptr_next = NULL;
328  
329 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
329 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
330    {
331 <    if ((request = ptr->data) != NULL)
332 <    {
333 <      if (query == request->query)
334 <        rem_request(request);
352 <    }
331 >    struct reslist *request = ptr->data;
332 >
333 >    if (request->callback_ctx == vptr)
334 >      rem_request(request);
335    }
336   }
337  
# Line 357 | Line 339 | delete_resolver_queries(const struct DNS
339   * send_res_msg - sends msg to all nameservers found in the "_res" structure.
340   * This should reflect /etc/resolv.conf. We will get responses
341   * which arent needed but is easier than checking to see if nameserver
342 < * isnt present. Returns number of messages successfully sent to
342 > * isnt present. Returns number of messages successfully sent to
343   * nameservers or -1 if no successful sends.
344   */
345   static int
346 < send_res_msg(const char *msg, int len, int rcount)
346 > send_res_msg(const char *msg, int len, unsigned int rcount)
347   {
366  int i;
348    int sent = 0;
349 <  int max_queries = IRCD_MIN(irc_nscount, rcount);
349 >  unsigned int max_queries = IRCD_MIN(irc_nscount, rcount);
350  
351    /* RES_PRIMARY option is not implemented
352     * if (res.options & RES_PRIMARY || 0 == max_queries)
# Line 373 | Line 354 | send_res_msg(const char *msg, int len, i
354    if (max_queries == 0)
355      max_queries = 1;
356  
357 <  for (i = 0; i < max_queries; i++)
357 >  for (unsigned int i = 0; i < max_queries; ++i)
358    {
359 <    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
360 <        (struct sockaddr*)&(irc_nsaddr_list[i]),
361 <        irc_nsaddr_list[i].ss_len) == len)
359 >    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
360 >        (struct sockaddr*)&(irc_nsaddr_list[i]),
361 >        irc_nsaddr_list[i].ss_len) == len)
362        ++sent;
363    }
364  
365 <  return(sent);
365 >  return sent;
366   }
367  
368   /*
# Line 390 | Line 371 | send_res_msg(const char *msg, int len, i
371   static struct reslist *
372   find_id(int id)
373   {
374 <  dlink_node *ptr;
394 <  struct reslist *request;
374 >  dlink_node *ptr = NULL;
375  
376    DLINK_FOREACH(ptr, request_list.head)
377    {
378 <    request = ptr->data;
378 >    struct reslist *request = ptr->data;
379  
380      if (request->id == id)
381 <      return(request);
381 >      return request;
382    }
383  
384 <  return(NULL);
384 >  return NULL;
385   }
386  
387 < /*
387 > /*
388   * gethost_byname_type - get host address from name
389   *
390   */
391   void
392 < gethost_byname_type(const char *name, struct DNSQuery *query, int type)
392 > gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
393   {
394 <  assert(name != 0);
395 <  do_query_name(query, name, NULL, type);
394 >  assert(name);
395 >  do_query_name(callback, ctx, name, NULL, type);
396   }
397  
398   /*
399   * gethost_byname - wrapper for _type - send T_AAAA first if IPV6 supported
400   */
401   void
402 < gethost_byname(const char *name, struct DNSQuery *query)
402 > gethost_byname(dns_callback_fnc callback, void *ctx, const char *name)
403   {
404   #ifdef IPV6
405 <  gethost_byname_type(name, query, T_AAAA);
405 >  gethost_byname_type(callback, ctx, name, T_AAAA);
406   #else
407 <  gethost_byname_type(name, query, T_A);
407 >  gethost_byname_type(callback, ctx, name, T_A);
408   #endif
409   }
410  
# Line 432 | Line 412 | gethost_byname(const char *name, struct
412   * gethost_byaddr - get host name from address
413   */
414   void
415 < gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
415 > gethost_byaddr(dns_callback_fnc callback, void *ctx, const struct irc_ssaddr *addr)
416   {
417 <  do_query_number(query, addr, NULL);
417 >  do_query_number(callback, ctx, addr, NULL);
418   }
419  
420   /*
421   * do_query_name - nameserver lookup name
422   */
423   static void
424 < do_query_name(struct DNSQuery *query, const char *name,
424 > do_query_name(dns_callback_fnc callback, void *ctx, const char *name,
425                struct reslist *request, int type)
426   {
427    char host_name[HOSTLEN + 1];
428  
429 <  strlcpy(host_name, name, HOSTLEN);
450 <  add_local_domain(host_name, HOSTLEN);
429 >  strlcpy(host_name, name, sizeof(host_name));
430  
431    if (request == NULL)
432    {
433 <    request       = make_request(query);
434 <    request->name = (char *)MyMalloc(strlen(host_name) + 1);
433 >    request       = make_request(callback, ctx);
434 >    request->name = MyMalloc(strlen(host_name) + 1);
435      request->type = type;
436      strcpy(request->name, host_name);
437   #ifdef IPV6
438 <    if (type == T_A)
460 <      request->state = REQ_A;
461 <    else
438 >    if (type != T_A)
439        request->state = REQ_AAAA;
440 < #else
464 <    request->state = REQ_A;
440 >    else
441   #endif
442 +    request->state = REQ_A;
443    }
444  
445    request->type = type;
# Line 473 | Line 450 | do_query_name(struct DNSQuery *query, co
450   * do_query_number - Use this to do reverse IP# lookups.
451   */
452   static void
453 < do_query_number(struct DNSQuery *query, const struct irc_ssaddr *addr,
453 > do_query_number(dns_callback_fnc callback, void *ctx,
454 >                const struct irc_ssaddr *addr,
455                  struct reslist *request)
456   {
457 <  char ipbuf[128];
458 <  const unsigned char *cp;
481 < #ifdef IPV6
482 <  const char *intarpa;
483 < #endif
457 >  char ipbuf[128] = "";
458 >
459    if (addr->ss.ss_family == AF_INET)
460    {
461 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
462 <    cp = (const unsigned char*)&v4->sin_addr.s_addr;
461 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
462 >    const unsigned char *cp = (const unsigned char *)&v4->sin_addr.s_addr;
463  
464 <    ircsprintf(ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
465 <               (unsigned int)(cp[3]), (unsigned int)(cp[2]),
466 <               (unsigned int)(cp[1]), (unsigned int)(cp[0]));
464 >    snprintf(ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
465 >             (unsigned int)(cp[3]), (unsigned int)(cp[2]),
466 >             (unsigned int)(cp[1]), (unsigned int)(cp[0]));
467    }
468   #ifdef IPV6
469    else if (addr->ss.ss_family == AF_INET6)
470    {
471 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
472 <    cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
471 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
472 >    const unsigned char *cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
473  
474 <    if (request != NULL && request->state == REQ_INT)
475 <      intarpa = "int";
476 <    else
477 <      intarpa = "arpa";
478 <
479 <    (void)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.%s.",
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),
518 <                  (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
519 <                  (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
520 <                  (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
521 <                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4), intarpa);
474 >    snprintf(ipbuf, sizeof(ipbuf),
475 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
476 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
477 >             (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4),
478 >             (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4),
479 >             (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4),
480 >             (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4),
481 >             (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4),
482 >             (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4),
483 >             (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4),
484 >             (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4),
485 >             (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4),
486 >             (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4),
487 >             (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4),
488 >             (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4),
489 >             (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4),
490 >             (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4),
491 >             (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4),
492 >             (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4));
493    }
494   #endif
495    if (request == NULL)
496    {
497 <    request       = make_request(query);
497 >    request       = make_request(callback, ctx);
498      request->type = T_PTR;
499      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
500 <    request->name = (char *)MyMalloc(HOSTLEN + 1);
500 >    request->name = MyMalloc(HOSTLEN + 1);
501    }
502  
503    query_name(ipbuf, C_IN, T_PTR, request);
# Line 544 | Line 515 | query_name(const char *name, int query_c
515  
516    memset(buf, 0, sizeof(buf));
517  
518 <  if ((request_len = irc_res_mkquery(name, query_class, type,
518 >  if ((request_len = irc_res_mkquery(name, query_class, type,
519        (unsigned char *)buf, sizeof(buf))) > 0)
520    {
521      HEADER *header = (HEADER *)buf;
522 < #ifndef HAVE_LRAND48
552 <    int k = 0;
553 <    struct timeval tv;
554 < #endif
522 >
523      /*
524       * generate an unique id
525       * NOTE: we don't have to worry about converting this to and from
526       * network byte order, the nameserver does not interpret this value
527       * and returns it unchanged
528       */
561 #ifdef HAVE_LRAND48
562    do
563    {
564      header->id = (header->id + lrand48()) & 0xffff;
565    } while (find_id(header->id));
566 #else
567    gettimeofday(&tv, NULL);
529      do
530 <    {
531 <      header->id = (header->id + k + tv.tv_usec) & 0xffff;
532 <      k++;
572 <    } while (find_id(header->id));
573 < #endif /* HAVE_LRAND48 */
530 >      header->id = (header->id + genrand_int32()) & 0xffff;
531 >    while (find_id(header->id));
532 >
533      request->id = header->id;
534      ++request->sends;
535  
# Line 584 | Line 543 | resend_query(struct reslist *request)
543    if (request->resend == 0)
544      return;
545  
546 <  switch(request->type)
546 >  switch (request->type)
547    {
548      case T_PTR:
549 <      do_query_number(NULL, &request->addr, request);
549 >      do_query_number(NULL, NULL, &request->addr, request);
550        break;
551      case T_A:
552 <      do_query_name(NULL, request->name, request, request->type);
552 >      do_query_name(NULL, NULL, request->name, request, request->type);
553        break;
554   #ifdef IPV6
555      case T_AAAA:
556        /* didnt work, try A */
557        if (request->state == REQ_AAAA)
558 <        do_query_name(NULL, request->name, request, T_A);
558 >        do_query_name(NULL, NULL, request->name, request, T_A);
559   #endif
560      default:
561        break;
# Line 607 | Line 566 | resend_query(struct reslist *request)
566   * proc_answer - process name server reply
567   */
568   static int
569 < proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
569 > proc_answer(struct reslist *request, HEADER *header, char *buf, char *eob)
570   {
571    char hostbuf[HOSTLEN + 100]; /* working buffer */
572    unsigned char *current;      /* current position in buf */
# Line 626 | Line 585 | proc_answer(struct reslist *request, HEA
585      if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0)
586        break;
587  
588 <    current += (size_t) n + QFIXEDSZ;
588 >    current += (size_t)n + QFIXEDSZ;
589    }
590  
591    /*
# Line 639 | Line 598 | proc_answer(struct reslist *request, HEA
598      n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
599          hostbuf, sizeof(hostbuf));
600  
601 <    if (n < 0)
602 <    {
644 <      /*
645 <       * broken message
646 <       */
647 <      return(0);
648 <    }
649 <    else if (n == 0)
650 <    {
651 <      /*
652 <       * no more answers left
653 <       */
654 <      return(0);
655 <    }
601 >    if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
602 >      return 0;
603  
604      hostbuf[HOSTLEN] = '\0';
605  
# Line 660 | Line 607 | proc_answer(struct reslist *request, HEA
607       * this code was not working on alpha due to that
608       * (spotted by rodder/jailbird/dianora)
609       */
610 <    current += (size_t) n;
610 >    current += (size_t)n;
611  
612      if (!(((char *)current + ANSWER_FIXED_SIZE) < eob))
613        break;
# Line 677 | Line 624 | proc_answer(struct reslist *request, HEA
624      rd_length = irc_ns_get16(current);
625      current += RDLENGTH_SIZE;
626  
627 <    /*
628 <     * Wait to set request->type until we verify this structure
627 >    /*
628 >     * Wait to set request->type until we verify this structure
629       */
630      switch (type)
631      {
632        case T_A:
633          if (request->type != T_A)
634 <          return(0);
634 >          return 0;
635  
636          /*
637 <         * check for invalid rd_length or too many addresses
637 >         * Check for invalid rd_length or too many addresses
638           */
639          if (rd_length != sizeof(struct in_addr))
640 <          return(0);
640 >          return 0;
641 >
642          v4 = (struct sockaddr_in *)&request->addr;
643          request->addr.ss_len = sizeof(struct sockaddr_in);
644          v4->sin_family = AF_INET;
645          memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
646 <        return(1);
646 >        return 1;
647          break;
648   #ifdef IPV6
649        case T_AAAA:
650          if (request->type != T_AAAA)
651 <          return(0);
651 >          return 0;
652 >
653          if (rd_length != sizeof(struct in6_addr))
654 <          return(0);
654 >          return 0;
655 >
656          request->addr.ss_len = sizeof(struct sockaddr_in6);
657          v6 = (struct sockaddr_in6 *)&request->addr;
658          v6->sin6_family = AF_INET6;
659          memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr));
660 <        return(1);
660 >        return 1;
661          break;
662   #endif
663        case T_PTR:
664          if (request->type != T_PTR)
665 <          return(0);
716 <        n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
717 <            current, hostbuf, sizeof(hostbuf));
718 <        if (n < 0)
719 <          return(0); /* broken message */
720 <        else if (n == 0)
721 <          return(0); /* no more answers left */
665 >          return 0;
666  
667 <        strlcpy(request->name, hostbuf, HOSTLEN);
667 >        n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
668 >                          current, hostbuf, sizeof(hostbuf));
669 >        if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
670 >          return 0;
671  
672 <        return(1);
672 >        strlcpy(request->name, hostbuf, HOSTLEN + 1);
673 >        return 1;
674          break;
675 <      case T_CNAME: /* first check we already havent started looking
675 >      case T_CNAME: /* first check we already havent started looking
676                         into a cname */
677 <        if (request->type != T_PTR)
678 <          return(0);
677 >        if (request->type != T_PTR)
678 >          return 0;
679  
680          if (request->state == REQ_CNAME)
681          {
# Line 735 | Line 683 | proc_answer(struct reslist *request, HEA
683                              current, hostbuf, sizeof(hostbuf));
684  
685            if (n < 0)
686 <            return(0);
687 <          return(1);
686 >            return 0;
687 >          return 1;
688          }
689  
690          request->state = REQ_CNAME;
691          current += rd_length;
692          break;
693 <        
693 >
694        default:
695          /* XXX I'd rather just throw away the entire bogus thing
696           * but its possible its just a broken nameserver with still
697           * valid answers. But lets do some rudimentary logging for now...
698           */
699 <        ilog(L_ERROR, "irc_res.c bogus type %d", type);
699 >        ilog(LOG_TYPE_IRCD, "irc_res.c bogus type %d", type);
700          break;
701      }
702    }
703  
704 <  return(1);
704 >  return 1;
705   }
706  
707   /*
# Line 763 | Line 711 | static void
711   res_readreply(fde_t *fd, void *data)
712   {
713    char buf[sizeof(HEADER) + MAXPACKET]
714 <        /* Sparc and alpha need 16bit-alignment for accessing header->id
715 <         * (which is uint16_t). Because of the header = (HEADER*) buf;
714 >        /* Sparc and alpha need 16bit-alignment for accessing header->id
715 >         * (which is uint16_t). Because of the header = (HEADER*) buf;
716           * lateron, this is neeeded. --FaUl
717           */
718 < #if defined(__sparc__) || defined(__alpha__)  
718 > #if defined(__sparc__) || defined(__alpha__)
719            __attribute__((aligned (16)))
720 < #endif
720 > #endif
721            ;
722    HEADER *header;
723    struct reslist *request = NULL;
776  struct DNSReply *reply  = NULL;
724    int rc;
778  int answer_count;
725    socklen_t len = sizeof(struct irc_ssaddr);
726    struct irc_ssaddr lsin;
727  
# Line 785 | Line 731 | res_readreply(fde_t *fd, void *data)
731     * interest where it'll instantly be ready for read :-) -- adrian
732     */
733    comm_setselect(fd, COMM_SELECT_READ, res_readreply, NULL, 0);
734 +
735    /* Better to cast the sizeof instead of rc */
736    if (rc <= (int)(sizeof(HEADER)))
737      return;
738  
739    /*
740 <   * convert DNS reply reader from Network byte order to CPU byte order.
740 >   * Convert DNS reply reader from Network byte order to CPU byte order.
741     */
742    header = (HEADER *)buf;
743    header->ancount = ntohs(header->ancount);
# Line 799 | Line 746 | res_readreply(fde_t *fd, void *data)
746    header->arcount = ntohs(header->arcount);
747  
748    /*
749 <   * response for an id which we have already received an answer for
803 <   * just ignore this response.
749 >   * Check against possibly fake replies
750     */
751 <  if (0 == (request = find_id(header->id)))
751 >  if (!res_ourserver(&lsin))
752      return;
753  
754    /*
755 <   * check against possibly fake replies
755 >   * Response for an id which we have already received an answer for
756 >   * just ignore this response.
757     */
758 <  if (!res_ourserver(&lsin))
758 >  if (!(request = find_id(header->id)))
759      return;
760  
761    if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
762    {
763 <    if (NXDOMAIN == header->rcode)
763 >    if (header->rcode == SERVFAIL || header->rcode == NXDOMAIN)
764      {
765 <      /*
765 >      /*
766 >       * If a bad error was returned, stop here and don't
767 >       * send any more (no retries granted).
768 >       */
769 >      (*request->callback)(request->callback_ctx, NULL, NULL);
770 >      rem_request(request);
771 >    }
772 > #ifdef IPV6
773 >    else
774 >    {
775 >      /*
776         * If we havent already tried this, and we're looking up AAAA, try A
777         * now
778         */
822 #ifdef IPV6
779        if (request->state == REQ_AAAA && request->type == T_AAAA)
780        {
781          request->timeout += 4;
782          resend_query(request);
783        }
828      else if (request->type == T_PTR && request->state != REQ_INT &&
829               request->addr.ss.ss_family == AF_INET6)
830      {
831        request->state = REQ_INT;
832        request->timeout += 4;
833        request->retries--;
834        resend_query(request);
835      }
836      else
837 #endif
838      {
839        /*
840         * If a bad error was returned, stop here and don't
841         * send any more (no retries granted).
842         */
843        (*request->query->callback)(request->query->ptr, NULL);
844        rem_request(request);
845      }
846      return;
784      }
785 + #endif
786 +
787 +    return;
788    }
789 +
790    /*
791 <   * If this fails there was an error decoding the received packet,
791 >   * If this fails there was an error decoding the received packet,
792     * try it again and hope it works the next time.
793     */
794 <  answer_count = proc_answer(request, header, buf, buf + rc);
854 <
855 <  if (answer_count)
794 >  if (proc_answer(request, header, buf, buf + rc))
795    {
796      if (request->type == T_PTR)
797      {
798        if (request->name == NULL)
799        {
800          /*
801 <         * got a PTR response with no name, something bogus is happening
801 >         * Got a PTR response with no name, something bogus is happening
802           * don't bother trying again, the client address doesn't resolve
803           */
804 <        (*request->query->callback)(request->query->ptr, reply);
804 >        (*request->callback)(request->callback_ctx, NULL, NULL);
805          rem_request(request);
806          return;
807        }
808  
809        /*
810 <       * Lookup the 'authoritative' name that we were given for the
872 <       * ip#.
873 <       *
810 >       * Lookup the 'authoritative' name that we were given for the ip#.
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
821      {
822        /*
823 <       * got a name and address response, client resolved
823 >       * Got a name and address response, client resolved
824         */
825 <      reply = make_dnsreply(request);
889 <      (*request->query->callback)(request->query->ptr, reply);
890 <      MyFree(reply);
825 >      (*request->callback)(request->callback_ctx, &request->addr, request->name);
826        rem_request(request);
827      }
828    }
# Line 903 | Line 838 | res_readreply(fde_t *fd, void *data)
838    }
839   }
840  
906 static struct DNSReply *
907 make_dnsreply(struct reslist *request)
908 {
909  struct DNSReply *cp;
910  assert(request != 0);
911
912  cp = (struct DNSReply *)MyMalloc(sizeof(struct DNSReply));
913
914  cp->h_name = request->name;
915  memcpy(&cp->addr, &request->addr, sizeof(cp->addr));
916  return(cp);
917 }
918
841   void
842   report_dns_servers(struct Client *source_p)
843   {
844 <  int i;
923 <  char ipaddr[HOSTIPLEN];
844 >  char ipaddr[HOSTIPLEN + 1] = "";
845  
846 <  for (i = 0; i < irc_nscount; i++)
846 >  for (unsigned int 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);
851 <    sendto_one(source_p, form_str(RPL_STATSALINE),
931 <               me.name, source_p->name, ipaddr);
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_numeric(source_p, &me, RPL_STATSALINE, ipaddr);
852    }
853   }

Diff Legend

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