libspf2  1.2.10
spf_dns_resolv.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of either:
4  *
5  * a) The GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 2.1, or (at your option) any
7  * later version,
8  *
9  * OR
10  *
11  * b) The two-clause BSD license.
12  *
13  * These licenses can be found with the distribution in the file LICENSES
14  */
15 
29 #ifndef _WIN32
30 
31 #include "spf_sys_config.h"
32 
33 #ifdef HAVE_ERRNO_H
34 #include <errno.h>
35 #endif
36 
37 #ifdef STDC_HEADERS
38 # include <stdio.h> /* stdin / stdout */
39 # include <stdlib.h> /* malloc / free */
40 #endif
41 
42 #ifdef HAVE_STRING_H
43 # include <string.h> /* strstr / strdup */
44 #else
45 # ifdef HAVE_STRINGS_H
46 # include <strings.h> /* strstr / strdup */
47 # endif
48 #endif
49 
50 #ifdef HAVE_RESOLV_H
51 # include <resolv.h> /* dn_skipname */
52 #endif
53 #ifdef HAVE_NETDB_H
54 # include <netdb.h>
55 #endif
56 
57 #ifdef HAVE_PTHREAD_H
58 # include <pthread.h>
59 #endif
60 
61 #include "spf.h"
62 #include "spf_dns.h"
63 #include "spf_internal.h"
64 #include "spf_dns_internal.h"
65 #include "spf_dns_resolv.h"
66 
72 static const struct res_sym ns_sects[] = {
73  { ns_s_qd, "QUESTION", "Question" },
74  { ns_s_an, "ANSWER", "Answer" },
75  { ns_s_ns, "AUTHORITY", "Authority" },
76  { ns_s_ar, "ADDITIONAL", "Additional" },
77 };
78 
79 static const int num_ns_sect = sizeof(ns_sects) / sizeof(*ns_sects);
80 
81 
82 #if HAVE_DECL_RES_NINIT
83 # define SPF_h_errno res_state->res_h_errno
84 #else
85 # define SPF_h_errno h_errno
86 #endif
87 
88 #if HAVE_DECL_RES_NINIT
89 static pthread_once_t res_state_control = PTHREAD_ONCE_INIT;
90 static pthread_key_t res_state_key;
91 
92 static void
93 SPF_dns_resolv_thread_term(void *arg)
94 {
95 #if HAVE_DECL_RES_NDESTROY
96  res_ndestroy( (struct __res_state *)arg );
97 #else
98  res_nclose( (struct __res_state *)arg );
99 #endif
100  free(arg);
101 }
102 
103 static void
104 SPF_dns_resolv_init_key(void)
105 {
106  pthread_key_create(&res_state_key, SPF_dns_resolv_thread_term);
107 }
108 #endif
109 
111 static void
112 SPF_dns_resolv_debug(SPF_dns_server_t *spf_dns_server, ns_rr rr,
113  const u_char *responsebuf, size_t responselen,
114  const u_char *rdata, size_t rdlen)
115 {
116  char ip4_buf[ INET_ADDRSTRLEN ];
117  char ip6_buf[ INET6_ADDRSTRLEN ];
118  char name_buf[ NS_MAXDNAME ];
119  int prio;
120  int err;
121 
122  switch (ns_rr_type(rr)) {
123  case ns_t_a:
124  if (rdlen != 4)
125  SPF_debugf("A: wrong rdlen %lu", (unsigned long)rdlen);
126  else
127  SPF_debugf("A: %s",
128  inet_ntop(AF_INET, rdata,
129  ip4_buf, sizeof(ip4_buf)));
130  break;
131 
132  case ns_t_aaaa:
133  if (rdlen != 16)
134  SPF_debugf("AAAA: wrong rdlen %lu", (unsigned long)rdlen);
135  else
136  SPF_debugf("AAAA: %s",
137  inet_ntop(AF_INET6, rdata,
138  ip6_buf, sizeof(ip6_buf)));
139  break;
140 
141  case ns_t_ns:
142  err = ns_name_uncompress(responsebuf,
143  responsebuf + responselen,
144  rdata,
145  name_buf, sizeof(name_buf));
146  if (err < 0) /* 0 or -1 */
147  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
148  err, strerror(errno), errno);
149  else
150  SPF_debugf("NS: %s", name_buf);
151  break;
152 
153  case ns_t_cname:
154  err = ns_name_uncompress(responsebuf,
155  responsebuf + responselen,
156  rdata,
157  name_buf, sizeof(name_buf));
158  if ( err < 0 ) /* 0 or -1 */
159  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
160  err, strerror(errno), errno );
161  else
162  SPF_debugf("CNAME: %s", name_buf);
163  break;
164 
165  case ns_t_mx:
166  if (rdlen < NS_INT16SZ) {
167  SPF_debugf("MX: rdlen too short: %lu", (unsigned long)rdlen);
168  break;
169  }
170  prio = ns_get16(rdata);
171  err = ns_name_uncompress(responsebuf,
172  responsebuf + responselen,
173  rdata + NS_INT16SZ,
174  name_buf, sizeof(name_buf));
175  if (err < 0) /* 0 or -1 */
176  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
177  err, strerror(errno), errno);
178  else
179  SPF_debugf("MX: %d %s", prio, name_buf);
180  break;
181 
182  case ns_t_spf:
183  case ns_t_txt:
184  if (rdlen < 1) {
185  SPF_debugf(ns_rr_type(rr) == ns_t_txt ? "TXT" : "SPF" ": rdlen too short: %lu", (unsigned long)rdlen);
186  break;
187  }
188  /* XXX I think this is wrong/unsafe. Shevek. */
189  /* XXX doesn't parse the different TXT "sections" */
190  SPF_debugf(ns_rr_type(rr) == ns_t_txt ? "TXT" : "SPF" ": (%lu) \"%.*s\"",
191  (unsigned long)rdlen, (int)rdlen - 1, rdata + 1);
192  break;
193 
194  case ns_t_ptr:
195  err = ns_name_uncompress(responsebuf,
196  responsebuf + responselen,
197  rdata,
198  name_buf, sizeof(name_buf));
199  if (err < 0) /* 0 or -1 */
200  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
201  err, strerror(errno), errno);
202  else
203  SPF_debugf("PTR: %s", name_buf);
204  break;
205 
206  default:
207  SPF_debugf("not parsed: type: %d", ns_rr_type(rr));
208  break;
209  }
210 
211 }
212 
218 static SPF_dns_rr_t *
219 SPF_dns_resolv_lookup(SPF_dns_server_t *spf_dns_server,
220  const char *domain, ns_type rr_type, int should_cache)
221 {
222  SPF_dns_rr_t *spfrr;
223 
224  int err;
225  int i;
226  int nrec;
227  int cnt;
228 
229  u_char *responsebuf;
230  size_t responselen;
231 
232  ns_msg ns_handle;
233  ns_rr rr;
234 
235  int ns_sect;
236  // int num_ns_sect = sizeof( ns_sects ) / sizeof( *ns_sects );
237 
238  char name_buf[ NS_MAXDNAME ];
239 
240  size_t rdlen;
241  const u_char *rdata;
242 
243 #if HAVE_DECL_RES_NINIT
244  void *res_spec;
245  struct __res_state *res_state;
246 #endif
247 
248  SPF_ASSERT_NOTNULL(spf_dns_server);
249 
250 #if HAVE_DECL_RES_NINIT
251 
252  res_spec = pthread_getspecific(res_state_key);
253  if (res_spec == NULL) {
254  res_state = (struct __res_state *)
255  malloc(sizeof(struct __res_state));
256  /* XXX The interface doesn't allow to communicate back failure
257  * to allocate memory, but SPF_errorf aborts anyway. */
258  if (! res_state)
259  SPF_errorf("Failed to allocate %lu bytes for res_state",
260  (unsigned long)sizeof(struct __res_state));
261  memset(res_state, 0, sizeof(struct __res_state));
262  if (res_ninit(res_state) != 0)
263  SPF_error("Failed to call res_ninit()");
264  pthread_setspecific(res_state_key, (void *)res_state);
265  }
266  else {
267  res_state = (struct __res_state *)res_spec;
268  }
269 #endif
270 
271  responselen = 2048;
272  responsebuf = (u_char *)malloc(responselen);
273  if (! responsebuf)
274  return NULL; /* NULL always means OOM from DNS lookup. */
275  memset(responsebuf, 0, responselen);
276 
277  /*
278  * Retry the lookup until our response buffer is big enough.
279  *
280  * This loop repeats until either we fail a lookup or we succeed.
281  * The size of the response buffer is monotonic increasing, so eventually we
282  * must either succeed, or we try to malloc more RAM than we can.
283  *
284  * The Linux man pages do not describe res_nquery adequately. Solaris says:
285  *
286  * The res_nquery() and res_query() routines return a length that may be bigger
287  * than anslen. In that case, retry the query with a larger buf. The answer to the
288  * second query may be larger still], so it is recommended that you supply a buf
289  * larger than the answer returned by the previous query. answer must be large
290  * enough to receive a maximum UDP response from the server or parts of the answer
291  * will be silently discarded. The default maximum UDP response size is 512 bytes.
292  */
293  for (;;) {
294  int dns_len;
295 
296 #if HAVE_DECL_RES_NINIT
297  /* Resolve the name. */
298  dns_len = res_nquery(res_state, domain, ns_c_in, rr_type,
299  responsebuf, responselen);
300 #else
301  dns_len = res_query(domain, ns_c_in, rr_type,
302  responsebuf, responselen);
303 #endif
304 
305  if (dns_len < 0) {
306  /* We failed to perform a lookup. */
307  /* This block returns unconditionally. */
308  free(responsebuf);
309  if (spf_dns_server->debug)
310  SPF_debugf("query failed: err = %d %s (%d): %s",
311  dns_len, hstrerror(SPF_h_errno), SPF_h_errno,
312  domain);
313  if ((SPF_h_errno == HOST_NOT_FOUND) &&
314  (spf_dns_server->layer_below != NULL)) {
315  return SPF_dns_lookup(spf_dns_server->layer_below,
316  domain, rr_type, should_cache);
317  }
318  return SPF_dns_rr_new_init(spf_dns_server,
319  domain, rr_type, 0, SPF_h_errno);
320  }
321  else if (dns_len > responselen) {
322  void *tmp;
323  /* We managed a lookup but our buffer was too small. */
324  responselen = dns_len + (dns_len >> 1);
325 #if 0
326  /* Sanity-trap - we should never hit this. */
327  if (responselen > 1048576) { /* One megabyte. */
328  free(responsebuf);
329  return SPF_dns_rr_new_init(spf_dns_server,
330  domain, rr_type, 0, SPF_h_errno);
331  }
332 #endif
333  tmp = realloc(responsebuf, responselen);
334  if (!tmp) {
335  free(responsebuf);
336  return NULL;
337  }
338  responsebuf = tmp;
339  }
340  else {
341  /* We managed a lookup, and our buffer was large enough. */
342  responselen = dns_len;
343  break;
344  }
345  }
346 
347 
348 
349  /*
350  * initialize stuff
351  */
352  spfrr = SPF_dns_rr_new_init(spf_dns_server,
353  domain, rr_type, 0, NETDB_SUCCESS);
354  if (!spfrr) {
355  free(responsebuf);
356  return NULL;
357  }
358 
359  err = ns_initparse(responsebuf, responselen, &ns_handle);
360 
361  if (err < 0) { /* 0 or -1 */
362  if (spf_dns_server->debug)
363  SPF_debugf("ns_initparse failed: err = %d %s (%d)",
364  err, strerror(errno), errno);
365  free(responsebuf);
366  spfrr->herrno = NO_RECOVERY;
367  return spfrr;
368  }
369 
370 
371  if (spf_dns_server->debug > 1) {
372  SPF_debugf("msg id: %d", ns_msg_id(ns_handle));
373  SPF_debugf("ns_f_qr quest/resp: %d", ns_msg_getflag(ns_handle, ns_f_qr));
374  SPF_debugf("ns_f_opcode: %d", ns_msg_getflag(ns_handle, ns_f_opcode));
375  SPF_debugf("ns_f_aa auth ans: %d", ns_msg_getflag(ns_handle, ns_f_aa));
376  SPF_debugf("ns_f_tc truncated: %d", ns_msg_getflag(ns_handle, ns_f_tc));
377  SPF_debugf("ns_f_rd rec desire: %d", ns_msg_getflag(ns_handle, ns_f_rd));
378  SPF_debugf("ns_f_ra rec avail: %d", ns_msg_getflag(ns_handle, ns_f_ra));
379  SPF_debugf("ns_f_rcode: %d", ns_msg_getflag(ns_handle, ns_f_rcode));
380  }
381 
382 
383  spfrr->num_rr = 0;
384  for (ns_sect = 0; ns_sect < num_ns_sect; ns_sect++) {
385  /* We pass this point if:
386  * - We are the 'answer' section.
387  * Otherwise, we continue to the next section.
388  */
389  if (ns_sects[ns_sect].number != ns_s_an)
390  continue;
391 
392  nrec = ns_msg_count(ns_handle, ns_sects[ns_sect].number);
393 
394  if (spf_dns_server->debug > 1)
395  SPF_debugf("%s: %d", ns_sects[ns_sect].name, nrec);
396 
397  cnt = 0;
398  for (i = 0; i < nrec; i++) {
399  err = ns_parserr(&ns_handle, ns_sects[ns_sect].number, i, &rr);
400  if (err < 0) { /* 0 or -1 */
401  if (spf_dns_server->debug > 1)
402  SPF_debugf("ns_parserr failed: err = %d %s (%d)",
403  err, strerror(errno), errno);
404  free(responsebuf);
405  spfrr->herrno = NO_RECOVERY;
406  return spfrr;
407  }
408 
409  rdlen = ns_rr_rdlen(rr);
410  if (spf_dns_server->debug > 1)
411  SPF_debugf("name: %s type: %d class: %d ttl: %d rdlen: %lu",
412  ns_rr_name(rr), ns_rr_type(rr), ns_rr_class(rr),
413  ns_rr_ttl(rr), (unsigned long)rdlen);
414 
415  if (rdlen <= 0)
416  continue;
417 
418  rdata = ns_rr_rdata(rr);
419 
420  if (spf_dns_server->debug > 1)
421  SPF_dns_resolv_debug(spf_dns_server, rr,
422  responsebuf, responselen, rdata, rdlen);
423 
424  /* And now, if we aren't the answer section, we skip the section. */
425  if (ns_sects[ns_sect].number != ns_s_an)
426  continue;
427 
428  /* Now, we are in the answer section. */
429  if (ns_rr_type(rr) != spfrr->rr_type && ns_rr_type(rr) != ns_t_cname) {
430  SPF_debugf("unexpected rr type: %d expected: %d",
431  ns_rr_type(rr), rr_type);
432  continue;
433  }
434 
435  switch (ns_rr_type(rr)) {
436  case ns_t_a:
437  if (rdlen != 4) {
438  free(responsebuf);
439  spfrr->herrno = NO_RECOVERY;
440  return spfrr;
441  }
442  if (SPF_dns_rr_buf_realloc(spfrr, cnt,
443  sizeof(spfrr->rr[cnt]->a)) != SPF_E_SUCCESS) {
444  free(responsebuf);
445  spfrr->herrno = TRY_AGAIN;
446  return spfrr;
447  }
448  memcpy(&spfrr->rr[cnt]->a, rdata, sizeof(spfrr->rr[cnt]->a));
449  cnt++;
450  break;
451 
452  case ns_t_aaaa:
453  if (rdlen != 16) {
454  free(responsebuf);
455  spfrr->herrno = NO_RECOVERY;
456  return spfrr;
457  }
458  if (SPF_dns_rr_buf_realloc(spfrr, cnt,
459  sizeof(spfrr->rr[cnt]->aaaa)) != SPF_E_SUCCESS) {
460  free(responsebuf);
461  spfrr->herrno = TRY_AGAIN;
462  return spfrr;
463  }
464  memcpy(&spfrr->rr[cnt]->aaaa, rdata, sizeof(spfrr->rr[cnt]->aaaa));
465  cnt++;
466  break;
467 
468  case ns_t_ns:
469  break;
470 
471  case ns_t_cname:
472  /* FIXME: are CNAMEs always sent with the real RR? */
473  break;
474 
475  case ns_t_mx:
476  if (rdlen < NS_INT16SZ) {
477  free(responsebuf);
478  spfrr->herrno = NO_RECOVERY;
479  return spfrr;
480  }
481  err = ns_name_uncompress(responsebuf,
482  responsebuf + responselen,
483  rdata + NS_INT16SZ,
484  name_buf, sizeof(name_buf));
485  if (err < 0) { /* 0 or -1 */
486  if (spf_dns_server->debug > 1)
487  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
488  err, strerror(errno), errno);
489  free(responsebuf);
490  spfrr->herrno = NO_RECOVERY;
491  return spfrr;
492  }
493 
494  if (SPF_dns_rr_buf_realloc(spfrr, cnt,
495  strlen(name_buf) + 1 ) != SPF_E_SUCCESS) {
496  free(responsebuf);
497  spfrr->herrno = TRY_AGAIN;
498  return spfrr;
499  }
500  strcpy(spfrr->rr[cnt]->mx, name_buf);
501  cnt++;
502  break;
503 
504  case ns_t_spf:
505  case ns_t_txt:
506  if (rdlen > 1) {
507  u_char *src, *dst;
508  size_t len;
509 
510  /* Just rdlen is enough because there is at least one
511  * length byte, which we do not copy. */
512  if (SPF_dns_rr_buf_realloc(spfrr, cnt, rdlen) != SPF_E_SUCCESS) {
513  free(responsebuf);
514  spfrr->herrno = TRY_AGAIN;
515  return spfrr;
516  }
517 
518  dst = (u_char *)spfrr->rr[cnt]->txt;
519  src = (u_char *)rdata;
520  len = 0;
521  while (rdlen > 0) {
522  /* Consume one byte into a length. */
523  len = *src;
524  src++;
525  rdlen--;
526 
527  /* Avoid buffer overrun if len is junk. */
528  /* XXX don't we rather want to flag this as error? */
529  if (len > rdlen)
530  len = rdlen;
531  memcpy(dst, src, len);
532 
533  /* Consume the data. */
534  src += len;
535  dst += len;
536  rdlen -= len;
537  }
538  *dst = '\0';
539  }
540  else {
541  if (SPF_dns_rr_buf_realloc(spfrr, cnt, 1) != SPF_E_SUCCESS) {
542  free(responsebuf);
543  spfrr->herrno = TRY_AGAIN;
544  return spfrr;
545  }
546  spfrr->rr[cnt]->txt[0] = '\0';
547  }
548 
549  cnt++;
550  break;
551 
552  case ns_t_ptr:
553  err = ns_name_uncompress(responsebuf,
554  responsebuf + responselen,
555  rdata,
556  name_buf, sizeof(name_buf));
557  if (err < 0) { /* 0 or -1 */
558  if (spf_dns_server->debug > 1)
559  SPF_debugf("ns_name_uncompress failed: err = %d %s (%d)",
560  err, strerror(errno), errno);
561  free(responsebuf);
562  spfrr->herrno = NO_RECOVERY;
563  return spfrr;
564  }
565 
566  if (SPF_dns_rr_buf_realloc(spfrr, cnt,
567  strlen(name_buf) + 1) != SPF_E_SUCCESS) {
568  free(responsebuf);
569  spfrr->herrno = TRY_AGAIN;
570  return spfrr;
571  }
572  strcpy(spfrr->rr[cnt]->ptr, name_buf);
573  cnt++;
574  break;
575 
576  default:
577  break;
578  }
579  }
580 
581  spfrr->num_rr += cnt;
582  }
583 
584  if (spfrr->num_rr == 0)
585  spfrr->herrno = NO_DATA;
586 
587  free(responsebuf);
588  return spfrr;
589 }
590 
591 
592 static void
593 SPF_dns_resolv_free(SPF_dns_server_t *spf_dns_server)
594 {
595  SPF_ASSERT_NOTNULL(spf_dns_server);
596 
597 #if ! HAVE_DECL_RES_NINIT
598  res_close();
599 #endif
600 
601  free(spf_dns_server);
602 }
603 
604 SPF_dns_server_t *
605 SPF_dns_resolv_new(SPF_dns_server_t *layer_below,
606  const char *name, int debug)
607 {
608  SPF_dns_server_t *spf_dns_server;
609 
610 #if HAVE_DECL_RES_NINIT
611  pthread_once(&res_state_control, SPF_dns_resolv_init_key);
612 #else
613  if (res_init() != 0) {
614  SPF_warning("Failed to call res_init()");
615  return NULL;
616  }
617 #endif
618 
619  spf_dns_server = malloc(sizeof(SPF_dns_server_t));
620  if (spf_dns_server == NULL)
621  return NULL;
622  memset(spf_dns_server, 0, sizeof(SPF_dns_server_t));
623 
624  if (name == NULL)
625  name = "resolv";
626 
627  spf_dns_server->destroy = SPF_dns_resolv_free;
628  spf_dns_server->lookup = SPF_dns_resolv_lookup;
629  spf_dns_server->get_spf = NULL;
630  spf_dns_server->get_exp = NULL;
631  spf_dns_server->add_cache = NULL;
632  spf_dns_server->layer_below = layer_below;
633  spf_dns_server->name = name;
634  spf_dns_server->debug = debug;
635 
636  return spf_dns_server;
637 }
638 
639 #endif /* _WIN32 */
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
#define NO_RECOVERY
Definition: spf_dns.h:105
int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr)
#define ns_get16
Definition: arpa_nameser.h:525
#define ns_rr_name(rr)
Definition: arpa_nameser.h:196
#define ns_rr_class(rr)
Definition: arpa_nameser.h:198
#define ns_rr_ttl(rr)
Definition: arpa_nameser.h:199
ns_sect
Definition: arpa_nameser.h:146
size_t len
Definition: memcmp.c:10
int ns_initparse(const u_char *msg, int msglen, ns_msg *handle)
SPF_errcode_t SPF_dns_rr_buf_realloc(SPF_dns_rr_t *spfrr, int idx, size_t len)
Definition: spf_dns_rr.c:134
#define SPF_error(errmsg)
Definition: spf_log.h:40
SPF_dns_stat_t herrno
Definition: spf_dns_rr.h:66
#define ns_msg_getflag
Definition: arpa_nameser.h:524
SPF_dns_rr_data_t ** rr
Definition: spf_dns_rr.h:60
SPF_dns_rr_t * SPF_dns_rr_new_init(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int ttl, SPF_dns_stat_t herrno)
Definition: spf_dns_rr.c:61
ns_type
Definition: arpa_nameser.h:300
#define SPF_h_errno
#define ns_rr_rdlen(rr)
Definition: arpa_nameser.h:200
#define NULL
Definition: spf_internal.h:28
#define ns_msg_count(handle, section)
Definition: arpa_nameser.h:181
#define ns_t_spf
Definition: spf_dns.h:89
#define NO_DATA
Definition: spf_dns.h:106
SPF_dns_rr_t * SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int should_cache)
Definition: spf_dns.c:133
#define ns_rr_type(rr)
Definition: arpa_nameser.h:197
#define NS_INT16SZ
Definition: arpa_nameser.h:135
#define NETDB_SUCCESS
Definition: spf_dns.h:102
#define ns_msg_id(handle)
Definition: arpa_nameser.h:177
#define HOST_NOT_FOUND
Definition: spf_dns.h:103
struct in_addr a
Definition: spf_dns_rr.h:33
#define TRY_AGAIN
Definition: spf_dns.h:104
SPF_dns_server_t * SPF_dns_resolv_new(SPF_dns_server_t *layer_below, const char *name, int debug)
#define SPF_debugf
Definition: spf_log.h:80
#define SPF_errorf
Definition: spf_log.h:77
#define ns_rr_rdata(rr)
Definition: arpa_nameser.h:201
#define SPF_warning(errmsg)
Definition: spf_log.h:45
struct in6_addr aaaa
Definition: spf_dns_rr.h:37
ns_type rr_type
Definition: spf_dns_rr.h:56
#define debug
#define NS_MAXDNAME
Definition: arpa_nameser.h:127
u_int const u_char * src
Definition: __ns_get16.c:16
int ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, char *dst, size_t dstsiz)