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

Comparing:
ircd-hybrid/src/irc_res.c (file contents), Revision 31 by knight, Sun Oct 2 20:34:05 2005 UTC vs.
ircd-hybrid/branches/8.2.x/src/res.c (file contents), Revision 4087 by michael, Sat Jun 28 16:45:42 2014 UTC

# Line 1 | Line 1
1   /*
2 + *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 + *
4 + *  Copyright (c) 1997-2014 ircd-hybrid development team
5 + *
6 + *  This program is free software; you can redistribute it and/or modify
7 + *  it under the terms of the GNU General Public License as published by
8 + *  the Free Software Foundation; either version 2 of the License, or
9 + *  (at your option) any later version.
10 + *
11 + *  This program is distributed in the hope that it will be useful,
12 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 + *  GNU General Public License for more details.
15 + *
16 + *  You should have received a copy of the GNU General Public License
17 + *  along with this program; if not, write to the Free Software
18 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19 + *  USA
20 + */
21 +
22 + /*! \file res.c
23 + * \brief ircd resolver functions
24 + * \version $Id$
25 + */
26 +
27 + /*
28   * A rewrite of Darren Reeds original res.c As there is nothing
29   * left of Darrens original code, this is now licensed by the hybrid group.
30   * (Well, some of the function names are the same, and bits of the structs..)
# Line 14 | Line 40
40   *     --Bleep (Thomas Helvey <tomh@inxpress.net>)
41   *
42   * This was all needlessly complicated for irc. Simplified. No more hostent
43 < * All we really care about is the IP -> hostname mappings. Thats all.
43 > * All we really care about is the IP -> hostname mappings. Thats all.
44   *
45   * Apr 28, 2003 --cryogen and Dianora
46   */
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 "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;
71  
72   #define MAXPACKET      1024  /* rfc sez 512 but we expand names so ... */
50 #define RES_MAXALIASES 35    /* maximum aliases allowed */
51 #define RES_MAXADDRS   35    /* maximum addresses allowed */
73   #define AR_TTL         600   /* TTL in seconds for dns cache entries */
74  
75   /* RFC 1104/1105 wasn't very helpful about what these fields
# Line 61 | Line 82 | static PF res_readreply;
82   #define RDLENGTH_SIZE     (size_t)2
83   #define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE)
84  
85 < typedef enum
85 > typedef enum
86   {
87    REQ_IDLE,  /* We're doing not much at all */
88    REQ_PTR,   /* Looking up a PTR */
# Line 69 | Line 90 | typedef enum
90   #ifdef IPV6
91    REQ_AAAA,  /* Looking up an AAAA */
92   #endif
93 <  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 */
93 >  REQ_CNAME  /* We got a CNAME in response, we better get a real answer next */
94   } request_state;
95  
96 < struct reslist
96 > struct reslist
97   {
98    dlink_node node;
99    int id;
# Line 82 | Line 102 | struct reslist
102    time_t ttl;
103    char type;
104    char retries;            /* retry counter */
105 <  char sends;              /* number of sends (>1 means resent) */
105 >  unsigned int sends;      /* number of sends (>1 means resent) */
106    char resend;             /* send flag. 0 == dont resend */
107    time_t sentat;
108    time_t timeout;
109    struct irc_ssaddr addr;
110    char *name;
111 <  struct DNSQuery *query;  /* query callback for this request */
111 >  dns_callback_fnc callback;
112 >  void *callback_ctx;
113   };
114  
115   static fde_t ResolverFileDescriptor;
116 < static dlink_list request_list    = { NULL, NULL, 0 };
116 > static dlink_list request_list;
117 > static mp_pool_t *dns_pool;
118  
119 < static void rem_request(struct reslist *request);
120 < static struct reslist *make_request(struct DNSQuery *query);
121 < static void do_query_name(struct DNSQuery *query,
122 <                          const char* name, struct reslist *request, int);
123 < static void do_query_number(struct DNSQuery *query,
119 > static void rem_request(struct reslist *);
120 > static struct reslist *make_request(dns_callback_fnc, void *);
121 > static void do_query_name(dns_callback_fnc, void *,
122 >                          const char *, struct reslist *, int);
123 > static void do_query_number(dns_callback_fnc, void *,
124                              const struct irc_ssaddr *,
125 <                            struct reslist *request);
126 < static void query_name(const char *name, int query_class, int query_type,
127 <                       struct reslist *request);
128 < static int send_res_msg(const char *buf, int len, int count);
129 < static void resend_query(struct reslist *request);
130 < 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];
125 >                            struct reslist *);
126 > static void query_name(const char *, int, int, struct reslist *);
127 > static int send_res_msg(const char *, int, unsigned int);
128 > static void resend_query(struct reslist *);
129 > static int proc_answer(struct reslist *, HEADER *, char *, char *);
130 > static struct reslist *find_id(int);
131  
132  
133   /*
# Line 126 | Line 142 | extern char irc_domain[HOSTLEN+1];
142   *      revised for ircd, cryogen(stu) may03
143   */
144   static int
145 < res_ourserver(const struct irc_ssaddr *inp)
145 > res_ourserver(const struct irc_ssaddr *inp)
146   {
147   #ifdef IPV6
148 <  struct sockaddr_in6 *v6;
149 <  struct sockaddr_in6 *v6in = (struct sockaddr_in6 *)inp;
148 >  const struct sockaddr_in6 *v6;
149 >  const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
150   #endif
151 <  struct sockaddr_in *v4;
152 <  struct sockaddr_in *v4in = (struct sockaddr_in *)inp;
137 <  int ns;
151 >  const struct sockaddr_in *v4;
152 >  const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
153  
154 <  for (ns = 0;  ns < irc_nscount;  ns++)
154 >  for (unsigned int i = 0; i < irc_nscount; ++i)
155    {
156 <    const struct irc_ssaddr *srv = &irc_nsaddr_list[ns];
156 >    const struct irc_ssaddr *srv = &irc_nsaddr_list[i];
157   #ifdef IPV6
158 <    v6 = (struct sockaddr_in6 *)srv;
158 >    v6 = (const struct sockaddr_in6 *)srv;
159   #endif
160 <    v4 = (struct sockaddr_in *)srv;
160 >    v4 = (const struct sockaddr_in *)srv;
161  
162      /* could probably just memcmp(srv, inp, srv.ss_len) here
163       * but we'll air on the side of caution - stu
# Line 154 | Line 169 | res_ourserver(const struct irc_ssaddr *i
169        case AF_INET6:
170          if (srv->ss.ss_family == inp->ss.ss_family)
171            if (v6->sin6_port == v6in->sin6_port)
172 <            if ((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
173 <                    sizeof(struct in6_addr)) == 0) ||
174 <                (memcmp(&v6->sin6_addr.s6_addr, &in6addr_any,
160 <                        sizeof(struct in6_addr)) == 0))
161 <              return(1);
172 >            if (!memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
173 >                        sizeof(struct in6_addr)))
174 >              return 1;
175          break;
176   #endif
177        case AF_INET:
178          if (srv->ss.ss_family == inp->ss.ss_family)
179            if (v4->sin_port == v4in->sin_port)
180 <            if ((v4->sin_addr.s_addr == INADDR_ANY) ||
181 <                (v4->sin_addr.s_addr == v4in->sin_addr.s_addr))
169 <              return(1);
180 >            if (v4->sin_addr.s_addr == v4in->sin_addr.s_addr)
181 >              return 1;
182          break;
183        default:
184          break;
185      }
186    }
187  
188 <  return(0);
188 >  return 0;
189   }
190  
191   /*
192 < * timeout_query_list - Remove queries from the list which have been
192 > * timeout_query_list - Remove queries from the list which have been
193   * there too long without being resolved.
194   */
195   static time_t
196   timeout_query_list(time_t now)
197   {
198 <  dlink_node *ptr;
187 <  dlink_node *next_ptr;
198 >  dlink_node *ptr = NULL, *ptr_next = NULL;
199    struct reslist *request;
200    time_t next_time = 0;
201    time_t timeout   = 0;
202  
203 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
203 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
204    {
205      request = ptr->data;
206      timeout = request->sentat + request->timeout;
# Line 198 | Line 209 | timeout_query_list(time_t now)
209      {
210        if (--request->retries <= 0)
211        {
212 <        (*request->query->callback)(request->query->ptr, NULL);
212 >        (*request->callback)(request->callback_ctx, NULL, NULL);
213          rem_request(request);
214          continue;
215        }
# Line 211 | Line 222 | timeout_query_list(time_t now)
222      }
223  
224      if ((next_time == 0) || timeout < next_time)
214    {
225        next_time = timeout;
216    }
226    }
227  
228 <  return((next_time > now) ? next_time : (now + AR_TTL));
228 >  return (next_time > now) ? next_time : (now + AR_TTL);
229   }
230  
231   /*
# Line 244 | Line 253 | start_resolver(void)
253        return;
254  
255      /* At the moment, the resolver FD data is global .. */
256 <    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ,
248 <        res_readreply, NULL, 0);
256 >    comm_setselect(&ResolverFileDescriptor, COMM_SELECT_READ, res_readreply, NULL, 0);
257      eventAdd("timeout_resolver", timeout_resolver, NULL, 1);
258    }
259   }
# Line 256 | Line 264 | start_resolver(void)
264   void
265   init_resolver(void)
266   {
267 < #ifdef HAVE_SRAND48
260 <  srand48(CurrentTime);
261 < #endif
267 >  dns_pool = mp_pool_new(sizeof(struct reslist), MP_CHUNK_SIZE_DNS);
268    memset(&ResolverFileDescriptor, 0, sizeof(fde_t));
269    start_resolver();
270   }
# Line 270 | Line 276 | void
276   restart_resolver(void)
277   {
278    fd_close(&ResolverFileDescriptor);
279 <  eventDelete(timeout_resolver, NULL); /* -ddosen */
279 >  eventDelete(timeout_resolver, NULL);
280    start_resolver();
281   }
282  
283   /*
284 < * add_local_domain - Add the domain to hostname, if it is missing
285 < * (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
284 > * rem_request - remove a request from the list.
285 > * This must also free any memory that has been allocated for
286   * temporary storage of DNS results.
287   */
288   static void
289   rem_request(struct reslist *request)
290   {
291    dlinkDelete(&request->node, &request_list);
292 +
293    MyFree(request->name);
294 <  MyFree(request);
294 >  mp_pool_release(request);
295   }
296  
297   /*
298   * make_request - Create a DNS request record for the server.
299   */
300   static struct reslist *
301 < make_request(struct DNSQuery* query)
301 > make_request(dns_callback_fnc callback, void *ctx)
302   {
303 <  struct reslist *request;
303 >  struct reslist *request = mp_pool_get(dns_pool);
304  
305 <  request = (struct reslist *)MyMalloc(sizeof(struct reslist));
306 <  memset(request, 0, sizeof(struct reslist));
307 <
308 <  request->sentat  = CurrentTime;
309 <  request->retries = 3;
310 <  request->resend  = 1;
311 <  request->timeout = 4;    /* start at 4 and exponential inc. */
329 <  memset(&request->addr, 0, sizeof(request->addr));
330 <  request->query   = query;
331 <  request->state   = REQ_IDLE;
305 >  request->sentat       = CurrentTime;
306 >  request->retries      = 2;
307 >  request->resend       = 1;
308 >  request->timeout      = 4;  /* Start at 4 and exponential inc. */
309 >  request->state        = REQ_IDLE;
310 >  request->callback     = callback;
311 >  request->callback_ctx = ctx;
312  
313    dlinkAdd(request, &request->node, &request_list);
314 <  return(request);
314 >  return request;
315   }
316  
317   /*
318 < * delete_resolver_queries - cleanup outstanding queries
318 > * delete_resolver_queries - cleanup outstanding queries
319   * for which there no longer exist clients or conf lines.
320   */
321   void
322 < delete_resolver_queries(const struct DNSQuery *query)
322 > delete_resolver_queries(const void *vptr)
323   {
324 <  dlink_node *ptr;
345 <  dlink_node *next_ptr;
346 <  struct reslist *request;
324 >  dlink_node *ptr = NULL, *ptr_next = NULL;
325  
326 <  DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
326 >  DLINK_FOREACH_SAFE(ptr, ptr_next, request_list.head)
327    {
328 <    if ((request = ptr->data) != NULL)
329 <    {
330 <      if (query == request->query)
331 <        rem_request(request);
354 <    }
328 >    struct reslist *request = ptr->data;
329 >
330 >    if (request->callback_ctx == vptr)
331 >      rem_request(request);
332    }
333   }
334  
# Line 359 | Line 336 | delete_resolver_queries(const struct DNS
336   * send_res_msg - sends msg to all nameservers found in the "_res" structure.
337   * This should reflect /etc/resolv.conf. We will get responses
338   * which arent needed but is easier than checking to see if nameserver
339 < * isnt present. Returns number of messages successfully sent to
339 > * isnt present. Returns number of messages successfully sent to
340   * nameservers or -1 if no successful sends.
341   */
342   static int
343 < send_res_msg(const char *msg, int len, int rcount)
343 > send_res_msg(const char *msg, int len, unsigned int rcount)
344   {
368  int i;
345    int sent = 0;
346 <  int max_queries = IRCD_MIN(irc_nscount, rcount);
346 >  unsigned int max_queries = IRCD_MIN(irc_nscount, rcount);
347  
348    /* RES_PRIMARY option is not implemented
349     * if (res.options & RES_PRIMARY || 0 == max_queries)
# Line 375 | Line 351 | send_res_msg(const char *msg, int len, i
351    if (max_queries == 0)
352      max_queries = 1;
353  
354 <  for (i = 0; i < max_queries; i++)
354 >  for (unsigned int i = 0; i < max_queries; ++i)
355    {
356 <    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
357 <        (struct sockaddr*)&(irc_nsaddr_list[i]),
358 <        irc_nsaddr_list[i].ss_len) == len)
356 >    if (sendto(ResolverFileDescriptor.fd, msg, len, 0,
357 >        (struct sockaddr*)&(irc_nsaddr_list[i]),
358 >        irc_nsaddr_list[i].ss_len) == len)
359        ++sent;
360    }
361  
362 <  return(sent);
362 >  return sent;
363   }
364  
365   /*
# Line 392 | Line 368 | send_res_msg(const char *msg, int len, i
368   static struct reslist *
369   find_id(int id)
370   {
371 <  dlink_node *ptr;
396 <  struct reslist *request;
371 >  dlink_node *ptr = NULL;
372  
373    DLINK_FOREACH(ptr, request_list.head)
374    {
375 <    request = ptr->data;
375 >    struct reslist *request = ptr->data;
376  
377      if (request->id == id)
378 <      return(request);
378 >      return request;
379    }
380  
381 <  return(NULL);
381 >  return NULL;
382   }
383  
384 < /*
384 > /*
385   * gethost_byname_type - get host address from name
386   *
387   */
388   void
389 < gethost_byname_type(const char *name, struct DNSQuery *query, int type)
389 > gethost_byname_type(dns_callback_fnc callback, void *ctx, const char *name, int type)
390   {
391 <  assert(name != 0);
392 <  do_query_name(query, name, NULL, type);
391 >  assert(name);
392 >  do_query_name(callback, ctx, name, NULL, type);
393   }
394  
395   /*
396   * gethost_byname - wrapper for _type - send T_AAAA first if IPV6 supported
397   */
398   void
399 < gethost_byname(const char *name, struct DNSQuery *query)
399 > gethost_byname(dns_callback_fnc callback, void *ctx, const char *name)
400   {
401   #ifdef IPV6
402 <  gethost_byname_type(name, query, T_AAAA);
402 >  gethost_byname_type(callback, ctx, name, T_AAAA);
403   #else
404 <  gethost_byname_type(name, query, T_A);
404 >  gethost_byname_type(callback, ctx, name, T_A);
405   #endif
406   }
407  
# Line 434 | Line 409 | gethost_byname(const char *name, struct
409   * gethost_byaddr - get host name from address
410   */
411   void
412 < gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
412 > gethost_byaddr(dns_callback_fnc callback, void *ctx, const struct irc_ssaddr *addr)
413   {
414 <  do_query_number(query, addr, NULL);
414 >  do_query_number(callback, ctx, addr, NULL);
415   }
416  
417   /*
418   * do_query_name - nameserver lookup name
419   */
420   static void
421 < do_query_name(struct DNSQuery *query, const char *name,
421 > do_query_name(dns_callback_fnc callback, void *ctx, const char *name,
422                struct reslist *request, int type)
423   {
424    char host_name[HOSTLEN + 1];
425  
426 <  strlcpy(host_name, name, HOSTLEN);
452 <  add_local_domain(host_name, HOSTLEN);
426 >  strlcpy(host_name, name, sizeof(host_name));
427  
428    if (request == NULL)
429    {
430 <    request       = make_request(query);
431 <    request->name = (char *)MyMalloc(strlen(host_name) + 1);
430 >    request       = make_request(callback, ctx);
431 >    request->name = MyCalloc(strlen(host_name) + 1);
432      request->type = type;
433      strcpy(request->name, host_name);
434   #ifdef IPV6
435 <    if (type == T_A)
462 <      request->state = REQ_A;
463 <    else
435 >    if (type != T_A)
436        request->state = REQ_AAAA;
437 < #else
466 <    request->state = REQ_A;
437 >    else
438   #endif
439 +    request->state = REQ_A;
440    }
441  
442    request->type = type;
# Line 475 | Line 447 | do_query_name(struct DNSQuery *query, co
447   * do_query_number - Use this to do reverse IP# lookups.
448   */
449   static void
450 < do_query_number(struct DNSQuery *query, const struct irc_ssaddr *addr,
450 > do_query_number(dns_callback_fnc callback, void *ctx,
451 >                const struct irc_ssaddr *addr,
452                  struct reslist *request)
453   {
454 <  char ipbuf[128];
455 <  const unsigned char *cp;
483 < #ifdef IPV6
484 <  const char *intarpa;
485 < #endif
454 >  char ipbuf[128] = "";
455 >
456    if (addr->ss.ss_family == AF_INET)
457    {
458 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
459 <    cp = (const unsigned char*)&v4->sin_addr.s_addr;
458 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
459 >    const unsigned char *cp = (const unsigned char *)&v4->sin_addr.s_addr;
460  
461 <    ircsprintf(ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
462 <               (unsigned int)(cp[3]), (unsigned int)(cp[2]),
463 <               (unsigned int)(cp[1]), (unsigned int)(cp[0]));
461 >    snprintf(ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
462 >             (unsigned int)(cp[3]), (unsigned int)(cp[2]),
463 >             (unsigned int)(cp[1]), (unsigned int)(cp[0]));
464    }
465   #ifdef IPV6
466    else if (addr->ss.ss_family == AF_INET6)
467    {
468 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
469 <    cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
500 <
501 <    if (request != NULL && request->state == REQ_INT)
502 <      intarpa = "int";
503 <    else
504 <      intarpa = "arpa";
468 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
469 >    const unsigned char *cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
470  
471 <    (void)sprintf(ipbuf, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
472 <                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.%s.",
473 <                  (unsigned int)(cp[15]&0xf), (unsigned int)(cp[15]>>4),
474 <                  (unsigned int)(cp[14]&0xf), (unsigned int)(cp[14]>>4),
475 <                  (unsigned int)(cp[13]&0xf), (unsigned int)(cp[13]>>4),
476 <                  (unsigned int)(cp[12]&0xf), (unsigned int)(cp[12]>>4),
477 <                  (unsigned int)(cp[11]&0xf), (unsigned int)(cp[11]>>4),
478 <                  (unsigned int)(cp[10]&0xf), (unsigned int)(cp[10]>>4),
479 <                  (unsigned int)(cp[9]&0xf), (unsigned int)(cp[9]>>4),
480 <                  (unsigned int)(cp[8]&0xf), (unsigned int)(cp[8]>>4),
481 <                  (unsigned int)(cp[7]&0xf), (unsigned int)(cp[7]>>4),
482 <                  (unsigned int)(cp[6]&0xf), (unsigned int)(cp[6]>>4),
483 <                  (unsigned int)(cp[5]&0xf), (unsigned int)(cp[5]>>4),
484 <                  (unsigned int)(cp[4]&0xf), (unsigned int)(cp[4]>>4),
485 <                  (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
486 <                  (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
487 <                  (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
488 <                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4), intarpa);
471 >    snprintf(ipbuf, sizeof(ipbuf),
472 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
473 >             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
474 >             (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4),
475 >             (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4),
476 >             (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4),
477 >             (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4),
478 >             (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4),
479 >             (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4),
480 >             (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4),
481 >             (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4),
482 >             (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4),
483 >             (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4),
484 >             (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4),
485 >             (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4),
486 >             (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4),
487 >             (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4),
488 >             (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4),
489 >             (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4));
490    }
491   #endif
492    if (request == NULL)
493    {
494 <    request       = make_request(query);
494 >    request       = make_request(callback, ctx);
495      request->type = T_PTR;
496      memcpy(&request->addr, addr, sizeof(struct irc_ssaddr));
497 <    request->name = (char *)MyMalloc(HOSTLEN + 1);
497 >    request->name = MyCalloc(HOSTLEN + 1);
498    }
499  
500    query_name(ipbuf, C_IN, T_PTR, request);
# Line 546 | Line 512 | query_name(const char *name, int query_c
512  
513    memset(buf, 0, sizeof(buf));
514  
515 <  if ((request_len = irc_res_mkquery(name, query_class, type,
515 >  if ((request_len = irc_res_mkquery(name, query_class, type,
516        (unsigned char *)buf, sizeof(buf))) > 0)
517    {
518      HEADER *header = (HEADER *)buf;
519 < #ifndef HAVE_LRAND48
554 <    int k = 0;
555 <    struct timeval tv;
556 < #endif
519 >
520      /*
521       * generate an unique id
522       * NOTE: we don't have to worry about converting this to and from
523       * network byte order, the nameserver does not interpret this value
524       * and returns it unchanged
525       */
563 #ifdef HAVE_LRAND48
526      do
527 <    {
528 <      header->id = (header->id + lrand48()) & 0xffff;
529 <    } while (find_id(header->id));
568 < #else
569 <    gettimeofday(&tv, NULL);
570 <    do
571 <    {
572 <      header->id = (header->id + k + tv.tv_usec) & 0xffff;
573 <      k++;
574 <    } while (find_id(header->id));
575 < #endif /* HAVE_LRAND48 */
527 >      header->id = (header->id + genrand_int32()) & 0xffff;
528 >    while (find_id(header->id));
529 >
530      request->id = header->id;
531      ++request->sends;
532  
# Line 586 | Line 540 | resend_query(struct reslist *request)
540    if (request->resend == 0)
541      return;
542  
543 <  switch(request->type)
543 >  switch (request->type)
544    {
545      case T_PTR:
546 <      do_query_number(NULL, &request->addr, request);
546 >      do_query_number(NULL, NULL, &request->addr, request);
547        break;
548      case T_A:
549 <      do_query_name(NULL, request->name, request, request->type);
549 >      do_query_name(NULL, NULL, request->name, request, request->type);
550        break;
551   #ifdef IPV6
552      case T_AAAA:
553        /* didnt work, try A */
554        if (request->state == REQ_AAAA)
555 <        do_query_name(NULL, request->name, request, T_A);
555 >        do_query_name(NULL, NULL, request->name, request, T_A);
556   #endif
557      default:
558        break;
# Line 609 | Line 563 | resend_query(struct reslist *request)
563   * proc_answer - process name server reply
564   */
565   static int
566 < proc_answer(struct reslist *request, HEADER* header, char* buf, char* eob)
566 > proc_answer(struct reslist *request, HEADER *header, char *buf, char *eob)
567   {
568    char hostbuf[HOSTLEN + 100]; /* working buffer */
569    unsigned char *current;      /* current position in buf */
# Line 628 | Line 582 | proc_answer(struct reslist *request, HEA
582      if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0)
583        break;
584  
585 <    current += (size_t) n + QFIXEDSZ;
585 >    current += (size_t)n + QFIXEDSZ;
586    }
587  
588    /*
# Line 641 | Line 595 | proc_answer(struct reslist *request, HEA
595      n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
596          hostbuf, sizeof(hostbuf));
597  
598 <    if (n < 0)
599 <    {
646 <      /*
647 <       * broken message
648 <       */
649 <      return(0);
650 <    }
651 <    else if (n == 0)
652 <    {
653 <      /*
654 <       * no more answers left
655 <       */
656 <      return(0);
657 <    }
598 >    if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
599 >      return 0;
600  
601      hostbuf[HOSTLEN] = '\0';
602  
# Line 662 | Line 604 | proc_answer(struct reslist *request, HEA
604       * this code was not working on alpha due to that
605       * (spotted by rodder/jailbird/dianora)
606       */
607 <    current += (size_t) n;
607 >    current += (size_t)n;
608  
609      if (!(((char *)current + ANSWER_FIXED_SIZE) < eob))
610        break;
# Line 679 | Line 621 | proc_answer(struct reslist *request, HEA
621      rd_length = irc_ns_get16(current);
622      current += RDLENGTH_SIZE;
623  
624 <    /*
625 <     * Wait to set request->type until we verify this structure
624 >    /*
625 >     * Wait to set request->type until we verify this structure
626       */
627      switch (type)
628      {
629        case T_A:
630          if (request->type != T_A)
631 <          return(0);
631 >          return 0;
632  
633          /*
634 <         * check for invalid rd_length or too many addresses
634 >         * Check for invalid rd_length or too many addresses
635           */
636          if (rd_length != sizeof(struct in_addr))
637 <          return(0);
637 >          return 0;
638 >
639          v4 = (struct sockaddr_in *)&request->addr;
640          request->addr.ss_len = sizeof(struct sockaddr_in);
641          v4->sin_family = AF_INET;
642          memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
643 <        return(1);
643 >        return 1;
644          break;
645   #ifdef IPV6
646        case T_AAAA:
647          if (request->type != T_AAAA)
648 <          return(0);
648 >          return 0;
649 >
650          if (rd_length != sizeof(struct in6_addr))
651 <          return(0);
651 >          return 0;
652 >
653          request->addr.ss_len = sizeof(struct sockaddr_in6);
654          v6 = (struct sockaddr_in6 *)&request->addr;
655          v6->sin6_family = AF_INET6;
656          memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr));
657 <        return(1);
657 >        return 1;
658          break;
659   #endif
660        case T_PTR:
661          if (request->type != T_PTR)
662 <          return(0);
718 <        n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
719 <            current, hostbuf, sizeof(hostbuf));
720 <        if (n < 0)
721 <          return(0); /* broken message */
722 <        else if (n == 0)
723 <          return(0); /* no more answers left */
662 >          return 0;
663  
664 <        strlcpy(request->name, hostbuf, HOSTLEN);
664 >        n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob,
665 >                          current, hostbuf, sizeof(hostbuf));
666 >        if (n < 0 /* Broken message */ || n == 0 /* No more answers left */)
667 >          return 0;
668  
669 <        return(1);
669 >        strlcpy(request->name, hostbuf, HOSTLEN + 1);
670 >        return 1;
671          break;
672 <      case T_CNAME: /* first check we already havent started looking
672 >      case T_CNAME: /* first check we already havent started looking
673                         into a cname */
674 <        if (request->type != T_PTR)
675 <          return(0);
674 >        if (request->type != T_PTR)
675 >          return 0;
676  
677          if (request->state == REQ_CNAME)
678          {
# Line 737 | Line 680 | proc_answer(struct reslist *request, HEA
680                              current, hostbuf, sizeof(hostbuf));
681  
682            if (n < 0)
683 <            return(0);
684 <          return(1);
683 >            return 0;
684 >          return 1;
685          }
686  
687          request->state = REQ_CNAME;
688          current += rd_length;
689          break;
690 <        
690 >
691        default:
692          /* XXX I'd rather just throw away the entire bogus thing
693           * but its possible its just a broken nameserver with still
694           * valid answers. But lets do some rudimentary logging for now...
695           */
696 <        ilog(L_ERROR, "irc_res.c bogus type %d", type);
696 >        ilog(LOG_TYPE_IRCD, "irc_res.c bogus type %d", type);
697          break;
698      }
699    }
700  
701 <  return(1);
701 >  return 1;
702   }
703  
704   /*
# 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;
735  
736    /*
737 <   * convert DNS reply reader from Network byte order to CPU byte order.
737 >   * Convert DNS reply reader from Network byte order to CPU byte order.
738     */
739    header = (HEADER *)buf;
740    header->ancount = ntohs(header->ancount);
# 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 <      /*
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,
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      {
795        if (request->name == NULL)
796        {
797          /*
798 <         * got a PTR response with no name, something bogus is happening
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        }
805  
806        /*
807 <       * Lookup the 'authoritative' name that we were given for the
870 <       * ip#.
871 <       *
807 >       * Lookup the 'authoritative' name that we were given for the ip#.
808         */
809   #ifdef IPV6
810        if (request->addr.ss.ss_family == AF_INET6)
811 <        gethost_byname_type(request->name, request->query, T_AAAA);
811 >        gethost_byname_type(request->callback, request->callback_ctx, request->name, T_AAAA);
812        else
813   #endif
814 <      gethost_byname_type(request->name, request->query, T_A);
814 >      gethost_byname_type(request->callback, request->callback_ctx, request->name, T_A);
815        rem_request(request);
816      }
817      else
818      {
819        /*
820 <       * got a name and address response, client resolved
820 >       * Got a name and address response, client resolved
821         */
822 <      reply = make_dnsreply(request);
887 <      (*request->query->callback)(request->query->ptr, reply);
888 <      MyFree(reply);
822 >      (*request->callback)(request->callback_ctx, &request->addr, request->name);
823        rem_request(request);
824      }
825    }
# Line 901 | Line 835 | res_readreply(fde_t *fd, void *data)
835    }
836   }
837  
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
838   void
839   report_dns_servers(struct Client *source_p)
840   {
841 <  int i;
921 <  char ipaddr[HOSTIPLEN];
841 >  char ipaddr[HOSTIPLEN + 1] = "";
842  
843 <  for (i = 0; i < irc_nscount; i++)
843 >  for (unsigned int i = 0; i < irc_nscount; ++i)
844    {
845 <    irc_getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
846 <                    irc_nsaddr_list[i].ss_len, ipaddr, HOSTIPLEN, NULL, 0,
847 <                    NI_NUMERICHOST);
848 <    sendto_one(source_p, form_str(RPL_STATSALINE),
929 <               me.name, source_p->name, ipaddr);
845 >    getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
846 >                irc_nsaddr_list[i].ss_len, ipaddr,
847 >                sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
848 >    sendto_one_numeric(source_p, &me, RPL_STATSALINE, ipaddr);
849    }
850   }

Comparing:
ircd-hybrid/src/irc_res.c (property svn:keywords), Revision 31 by knight, Sun Oct 2 20:34:05 2005 UTC vs.
ircd-hybrid/branches/8.2.x/src/res.c (property svn:keywords), Revision 4087 by michael, Sat Jun 28 16:45:42 2014 UTC

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

Diff Legend

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