rfc1035.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /*
10  * Low level DNS protocol routines
11  *
12  * KNOWN BUGS:
13  *
14  * UDP replies with TC set should be retried via TCP
15  */
16 
17 #include "squid.h"
18 #include "dns/rfc1035.h"
19 #include "dns/rfc2671.h"
20 #include "util.h"
21 
22 #if HAVE_STRING_H
23 #include <string.h>
24 #endif
25 #if HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #if HAVE_MEMORY_H
29 #include <memory.h>
30 #endif
31 #if HAVE_ASSERT_H
32 #include <assert.h>
33 #endif
34 #if HAVE_NETINET_IN_H
35 #include <netinet/in.h>
36 #endif
37 #if HAVE_ARPA_INET_H
38 #include <arpa/inet.h>
39 #endif
40 #if HAVE_STRINGS_H
41 #include <strings.h>
42 #endif
43 
44 #define RFC1035_MAXLABELSZ 63
45 #define rfc1035_unpack_error 15
46 
47 #if 0
48 #define RFC1035_UNPACK_DEBUG fprintf(stderr, "unpack error at %s:%d\n", __FILE__,__LINE__)
49 #else
50 #define RFC1035_UNPACK_DEBUG (void)0
51 #endif
52 
53 /*
54  * rfc1035HeaderPack()
55  *
56  * Packs a rfc1035_header structure into a buffer.
57  * Returns number of octets packed (should always be 12)
58  */
59 int
60 rfc1035HeaderPack(char *buf, size_t sz, rfc1035_message * hdr)
61 {
62  int off = 0;
63  unsigned short s;
64  unsigned short t;
65  assert(sz >= 12);
66  s = htons(hdr->id);
67  memcpy(buf + off, &s, sizeof(s));
68  off += sizeof(s);
69  t = 0;
70  t |= hdr->qr << 15;
71  t |= (hdr->opcode << 11);
72  t |= (hdr->aa << 10);
73  t |= (hdr->tc << 9);
74  t |= (hdr->rd << 8);
75  t |= (hdr->ra << 7);
76  t |= hdr->rcode;
77  s = htons(t);
78  memcpy(buf + off, &s, sizeof(s));
79  off += sizeof(s);
80  s = htons(hdr->qdcount);
81  memcpy(buf + off, &s, sizeof(s));
82  off += sizeof(s);
83  s = htons(hdr->ancount);
84  memcpy(buf + off, &s, sizeof(s));
85  off += sizeof(s);
86  s = htons(hdr->nscount);
87  memcpy(buf + off, &s, sizeof(s));
88  off += sizeof(s);
89  s = htons(hdr->arcount);
90  memcpy(buf + off, &s, sizeof(s));
91  off += sizeof(s);
92  assert(off == 12);
93  return off;
94 }
95 
96 /*
97  * rfc1035LabelPack()
98  *
99  * Packs a label into a buffer. The format of
100  * a label is one octet specifying the number of character
101  * bytes to follow. Labels must be smaller than 64 octets.
102  * Returns number of octets packed.
103  */
104 static int
105 rfc1035LabelPack(char *buf, size_t sz, const char *label)
106 {
107  int off = 0;
108  size_t len = label ? strlen(label) : 0;
109  if (label)
110  assert(!strchr(label, '.'));
111  if (len > RFC1035_MAXLABELSZ)
112  len = RFC1035_MAXLABELSZ;
113  assert(sz >= len + 1);
114  *(buf + off) = (char) len;
115  off++;
116  memcpy(buf + off, label, len);
117  off += len;
118  return off;
119 }
120 
121 /*
122  * rfc1035NamePack()
123  *
124  * Packs a name into a buffer. Names are packed as a
125  * sequence of labels, terminated with NULL label.
126  * Note message compression is not supported here.
127  * Returns number of octets packed.
128  */
129 static int
130 rfc1035NamePack(char *buf, size_t sz, const char *name)
131 {
132  unsigned int off = 0;
133  char *copy = xstrdup(name);
134  char *t;
135  /*
136  * NOTE: use of strtok here makes names like foo....com valid.
137  */
138  for (t = strtok(copy, "."); t; t = strtok(NULL, "."))
139  off += rfc1035LabelPack(buf + off, sz - off, t);
140  xfree(copy);
141  off += rfc1035LabelPack(buf + off, sz - off, NULL);
142  assert(off <= sz);
143  return off;
144 }
145 
146 /*
147  * rfc1035QuestionPack()
148  *
149  * Packs a QUESTION section of a message.
150  * Returns number of octets packed.
151  */
152 int
154  const size_t sz,
155  const char *name,
156  const unsigned short type,
157  const unsigned short _class)
158 {
159  unsigned int off = 0;
160  unsigned short s;
161  off += rfc1035NamePack(buf + off, sz - off, name);
162  s = htons(type);
163  memcpy(buf + off, &s, sizeof(s));
164  off += sizeof(s);
165  s = htons(_class);
166  memcpy(buf + off, &s, sizeof(s));
167  off += sizeof(s);
168  assert(off <= sz);
169  return off;
170 }
171 
172 /*
173  * rfc1035HeaderUnpack()
174  *
175  * Unpacks a RFC1035 message header buffer into the header fields
176  * of the rfc1035_message structure.
177  *
178  * Updates the buffer offset, which is the same as number of
179  * octects unpacked since the header starts at offset 0.
180  *
181  * Returns 0 (success) or 1 (error)
182  */
183 int
184 rfc1035HeaderUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_message * h)
185 {
186  unsigned short s;
187  unsigned short t;
188  assert(*off == 0);
189  /*
190  * The header is 12 octets. This is a bogus message if the size
191  * is less than that.
192  */
193  if (sz < 12)
194  return 1;
195  memcpy(&s, buf + (*off), sizeof(s));
196  (*off) += sizeof(s);
197  h->id = ntohs(s);
198  memcpy(&s, buf + (*off), sizeof(s));
199  (*off) += sizeof(s);
200  t = ntohs(s);
201  h->qr = (t >> 15) & 0x01;
202  h->opcode = (t >> 11) & 0x0F;
203  h->aa = (t >> 10) & 0x01;
204  h->tc = (t >> 9) & 0x01;
205  h->rd = (t >> 8) & 0x01;
206  h->ra = (t >> 7) & 0x01;
207  /*
208  * We might want to check that the reserved 'Z' bits (6-4) are
209  * all zero as per RFC 1035. If not the message should be
210  * rejected.
211  * NO! RFCs say ignore inbound reserved, they may be used in future.
212  * NEW messages need to be set 0, thats all.
213  */
214  h->rcode = t & 0x0F;
215  memcpy(&s, buf + (*off), sizeof(s));
216  (*off) += sizeof(s);
217  h->qdcount = ntohs(s);
218  memcpy(&s, buf + (*off), sizeof(s));
219  (*off) += sizeof(s);
220  h->ancount = ntohs(s);
221  memcpy(&s, buf + (*off), sizeof(s));
222  (*off) += sizeof(s);
223  h->nscount = ntohs(s);
224  memcpy(&s, buf + (*off), sizeof(s));
225  (*off) += sizeof(s);
226  h->arcount = ntohs(s);
227  assert((*off) == 12);
228  return 0;
229 }
230 
231 /*
232  * rfc1035NameUnpack()
233  *
234  * Unpacks a Name in a message buffer into a char*.
235  * Note 'buf' points to the beginning of the whole message,
236  * 'off' points to the spot where the Name begins, and 'sz'
237  * is the size of the whole message. 'name' must be allocated
238  * by the caller.
239  *
240  * Supports the RFC1035 message compression through recursion.
241  *
242  * Updates the new buffer offset.
243  *
244  * Returns 0 (success) or 1 (error)
245  */
246 static int
247 rfc1035NameUnpack(const char *buf, size_t sz, unsigned int *off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
248 {
249  unsigned int no = 0;
250  unsigned char c;
251  size_t len;
252  assert(ns > 0);
253  do {
254  if ((*off) >= sz) {
256  return 1;
257  }
258  c = *(buf + (*off));
259  if (c > 191) {
260  /* blasted compression */
261  unsigned short s;
262  unsigned int ptr;
263  if (rdepth > 64) { /* infinite pointer loop */
265  return 1;
266  }
267  memcpy(&s, buf + (*off), sizeof(s));
268  s = ntohs(s);
269  (*off) += sizeof(s);
270  /* Sanity check */
271  if ((*off) > sz) {
273  return 1;
274  }
275  ptr = s & 0x3FFF;
276  /* Make sure the pointer is inside this message */
277  if (ptr >= sz) {
279  return 1;
280  }
281  return rfc1035NameUnpack(buf, sz, &ptr, rdlength, name + no, ns - no, rdepth + 1);
282  } else if (c > RFC1035_MAXLABELSZ) {
283  /*
284  * "(The 10 and 01 combinations are reserved for future use.)"
285  */
287  return 1;
288  } else {
289  (*off)++;
290  len = (size_t) c;
291  if (len == 0)
292  break;
293  if (len > (ns - no - 1)) { /* label won't fit */
295  return 1;
296  }
297  if ((*off) + len >= sz) { /* message is too short */
299  return 1;
300  }
301  memcpy(name + no, buf + (*off), len);
302  (*off) += len;
303  no += len;
304  *(name + (no++)) = '.';
305  if (rdlength)
306  *rdlength += len + 1;
307  }
308  } while (c > 0 && no < ns);
309  if (no)
310  *(name + no - 1) = '\0';
311  else
312  *name = '\0';
313  /* make sure we didn't allow someone to overflow the name buffer */
314  assert(no <= ns);
315  return 0;
316 }
317 
318 /*
319  * rfc1035RRPack()
320  *
321  * Packs a RFC1035 Resource Record into a message buffer from 'RR'.
322  * The caller must allocate and free RR->rdata and RR->name!
323  *
324  * Updates the new message buffer.
325  *
326  * Returns the number of bytes added to the buffer or 0 for error.
327  */
328 int
329 rfc1035RRPack(char *buf, const size_t sz, const rfc1035_rr * RR)
330 {
331  unsigned int off;
332  uint16_t s;
333  uint32_t i;
334 
335  off = rfc1035NamePack(buf, sz, RR->name);
336 
337  /*
338  * Make sure the remaining message has enough octets for the
339  * rest of the RR fields.
340  */
341  if ((off + sizeof(s)*3 + sizeof(i) + RR->rdlength) > sz) {
342  return 0;
343  }
344  s = htons(RR->type);
345  memcpy(buf + off, &s, sizeof(s));
346  off += sizeof(s);
347  s = htons(RR->_class);
348  memcpy(buf + off, &s, sizeof(s));
349  off += sizeof(s);
350  i = htonl(RR->ttl);
351  memcpy(buf + off, &i, sizeof(i));
352  off += sizeof(i);
353  s = htons(RR->rdlength);
354  memcpy(buf + off, &s, sizeof(s));
355  off += sizeof(s);
356  memcpy(buf + off, &(RR->rdata), RR->rdlength);
357  off += RR->rdlength;
358  assert(off <= sz);
359  return off;
360 }
361 
362 /*
363  * rfc1035RRUnpack()
364  *
365  * Unpacks a RFC1035 Resource Record into 'RR' from a message buffer.
366  * The caller must free RR->rdata!
367  *
368  * Updates the new message buffer offset.
369  *
370  * Returns 0 (success) or 1 (error)
371  */
372 static int
373 rfc1035RRUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_rr * RR)
374 {
375  unsigned short s;
376  unsigned int i;
377  unsigned short rdlength;
378  unsigned int rdata_off;
379  if (rfc1035NameUnpack(buf, sz, off, NULL, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
381  memset(RR, '\0', sizeof(*RR));
382  return 1;
383  }
384  /*
385  * Make sure the remaining message has enough octets for the
386  * rest of the RR fields.
387  */
388  if ((*off) + 10 > sz) {
390  memset(RR, '\0', sizeof(*RR));
391  return 1;
392  }
393  memcpy(&s, buf + (*off), sizeof(s));
394  (*off) += sizeof(s);
395  RR->type = ntohs(s);
396  memcpy(&s, buf + (*off), sizeof(s));
397  (*off) += sizeof(s);
398  RR->_class = ntohs(s);
399  memcpy(&i, buf + (*off), sizeof(i));
400  (*off) += sizeof(i);
401  RR->ttl = ntohl(i);
402  memcpy(&s, buf + (*off), sizeof(s));
403  (*off) += sizeof(s);
404  rdlength = ntohs(s);
405  if ((*off) + rdlength > sz) {
406  /*
407  * We got a truncated packet. 'dnscache' truncates UDP
408  * replies at 512 octets, as per RFC 1035.
409  */
411  memset(RR, '\0', sizeof(*RR));
412  return 1;
413  }
414  RR->rdlength = rdlength;
415  switch (RR->type) {
416 #if DNS_CNAME
417  case RFC1035_TYPE_CNAME:
418 #endif
419  case RFC1035_TYPE_PTR:
420  RR->rdata = (char*)xmalloc(RFC1035_MAXHOSTNAMESZ);
421  rdata_off = *off;
422  RR->rdlength = 0; /* Filled in by rfc1035NameUnpack */
423  if (rfc1035NameUnpack(buf, sz, &rdata_off, &RR->rdlength, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0)) {
425  return 1;
426  }
427  if (rdata_off > ((*off) + rdlength)) {
428  /*
429  * This probably doesn't happen for valid packets, but
430  * I want to make sure that NameUnpack doesn't go beyond
431  * the RDATA area.
432  */
434  xfree(RR->rdata);
435  memset(RR, '\0', sizeof(*RR));
436  return 1;
437  }
438  break;
439  case RFC1035_TYPE_A:
440  default:
441  RR->rdata = (char*)xmalloc(rdlength);
442  memcpy(RR->rdata, buf + (*off), rdlength);
443  break;
444  }
445  (*off) += rdlength;
446  assert((*off) <= sz);
447  return 0;
448 }
449 
450 const char *
452 {
453  if (n < 0)
454  n = -n;
455  switch (n) {
456  case 0:
457  return "No error condition";
458  break;
459  case 1:
460  return "Format Error: The name server was "
461  "unable to interpret the query.";
462  break;
463  case 2:
464  return "Server Failure: The name server was "
465  "unable to process this query.";
466  break;
467  case 3:
468  return "Name Error: The domain name does "
469  "not exist.";
470  break;
471  case 4:
472  return "Not Implemented: The name server does "
473  "not support the requested kind of query.";
474  break;
475  case 5:
476  return "Refused: The name server refuses to "
477  "perform the specified operation.";
478  break;
480  return "The DNS reply message is corrupt or could "
481  "not be safely parsed.";
482  break;
483  default:
484  return "Unknown Error";
485  break;
486  }
487 }
488 
489 void
491 {
492  if (*rr == NULL) {
493  return;
494  }
495 
496  while (n-- > 0) {
497  if ((*rr)[n].rdata)
498  xfree((*rr)[n].rdata);
499  }
500  xfree(*rr);
501  *rr = NULL;
502 }
503 
504 /*
505  * rfc1035QueryUnpack()
506  *
507  * Unpacks a RFC1035 Query Record into 'query' from a message buffer.
508  *
509  * Updates the new message buffer offset.
510  *
511  * Returns 0 (success) or 1 (error)
512  */
513 static int
514 rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query * query)
515 {
516  unsigned short s;
517  if (rfc1035NameUnpack(buf, sz, off, NULL, query->name, RFC1035_MAXHOSTNAMESZ, 0)) {
519  memset(query, '\0', sizeof(*query));
520  return 1;
521  }
522  if (*off + 4 > sz) {
524  memset(query, '\0', sizeof(*query));
525  return 1;
526  }
527  memcpy(&s, buf + *off, 2);
528  *off += 2;
529  query->qtype = ntohs(s);
530  memcpy(&s, buf + *off, 2);
531  *off += 2;
532  query->qclass = ntohs(s);
533  return 0;
534 }
535 
536 void
538 {
539  if (!*msg)
540  return;
541  if ((*msg)->query)
542  xfree((*msg)->query);
543  if ((*msg)->answer)
544  rfc1035RRDestroy(&(*msg)->answer, (*msg)->ancount);
545  xfree(*msg);
546  *msg = NULL;
547 }
548 
549 /*
550  * rfc1035QueryCompare()
551  *
552  * Compares two rfc1035_query entries
553  *
554  * Returns 0 (equal) or !=0 (different)
555  */
556 int
558 {
559  size_t la, lb;
560  if (a->qtype != b->qtype)
561  return 1;
562  if (a->qclass != b->qclass)
563  return 1;
564  la = strlen(a->name);
565  lb = strlen(b->name);
566  if (la != lb) {
567  /* Trim root label(s) */
568  while (la > 0 && a->name[la - 1] == '.')
569  la--;
570  while (lb > 0 && b->name[lb - 1] == '.')
571  lb--;
572  }
573  if (la != lb)
574  return 1;
575 
576  return strncasecmp(a->name, b->name, la);
577 }
578 
579 /*
580  * rfc1035MessageUnpack()
581  *
582  * Takes the contents of a DNS reply and fills in an array
583  * of resource record structures. The records array is allocated
584  * here, and should be freed by calling rfc1035RRDestroy().
585  *
586  * Returns number of records unpacked, zero if DNS reply indicates
587  * zero answers, or an error number < 0.
588  */
589 
590 int
592  size_t sz,
593  rfc1035_message ** answer)
594 {
595  unsigned int off = 0;
596  unsigned int i, j;
597  unsigned int nr = 0;
598  rfc1035_message *msg = NULL;
599  rfc1035_rr *recs = NULL;
600  rfc1035_query *querys = NULL;
601  msg = (rfc1035_message*)xcalloc(1, sizeof(*msg));
602  if (rfc1035HeaderUnpack(buf + off, sz - off, &off, msg)) {
604  xfree(msg);
605  return -rfc1035_unpack_error;
606  }
607  i = (unsigned int) msg->qdcount;
608  if (i != 1) {
609  /* This can not be an answer to our queries.. */
611  xfree(msg);
612  return -rfc1035_unpack_error;
613  }
614  querys = msg->query = (rfc1035_query*)xcalloc(i, sizeof(*querys));
615  for (j = 0; j < i; j++) {
616  if (rfc1035QueryUnpack(buf, sz, &off, &querys[j])) {
618  rfc1035MessageDestroy(&msg);
619  return -rfc1035_unpack_error;
620  }
621  }
622  *answer = msg;
623  if (msg->rcode) {
625  return -msg->rcode;
626  }
627  if (msg->ancount == 0)
628  return 0;
629  i = (unsigned int) msg->ancount;
630  recs = msg->answer = (rfc1035_rr*)xcalloc(i, sizeof(*recs));
631  for (j = 0; j < i; j++) {
632  if (off >= sz) { /* corrupt packet */
634  break;
635  }
636  if (rfc1035RRUnpack(buf, sz, &off, &recs[j])) { /* corrupt RR */
638  break;
639  }
640  nr++;
641  }
642  if (nr == 0) {
643  /*
644  * we expected to unpack some answers (ancount != 0), but
645  * didn't actually get any.
646  */
647  rfc1035MessageDestroy(&msg);
648  *answer = NULL;
649  return -rfc1035_unpack_error;
650  }
651  return nr;
652 }
653 
654 /*
655  * rfc1035BuildAQuery()
656  *
657  * Builds a message buffer with a QUESTION to lookup A records
658  * for a hostname. Caller must allocate 'buf' which should
659  * probably be at least 512 octets. The 'szp' initially
660  * specifies the size of the buffer, on return it contains
661  * the size of the message (i.e. how much to write).
662  * Returns the size of the query
663  */
664 ssize_t
665 rfc1035BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
666 {
667  static rfc1035_message h;
668  size_t offset = 0;
669  memset(&h, '\0', sizeof(h));
670  h.id = qid;
671  h.qr = 0;
672  h.rd = 1;
673  h.opcode = 0; /* QUERY */
674  h.qdcount = (unsigned int) 1;
675  h.arcount = (edns_sz > 0 ? 1 : 0);
676  offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
677  offset += rfc1035QuestionPack(buf + offset,
678  sz - offset,
679  hostname,
682  if (edns_sz > 0)
683  offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
684  if (query) {
685  query->qtype = RFC1035_TYPE_A;
686  query->qclass = RFC1035_CLASS_IN;
687  xstrncpy(query->name, hostname, sizeof(query->name));
688  }
689  assert(offset <= sz);
690  return offset;
691 }
692 
693 /*
694  * rfc1035BuildPTRQuery()
695  *
696  * Builds a message buffer with a QUESTION to lookup PTR records
697  * for an address. Caller must allocate 'buf' which should
698  * probably be at least 512 octets. The 'szp' initially
699  * specifies the size of the buffer, on return it contains
700  * the size of the message (i.e. how much to write).
701  * Returns the size of the query
702  */
703 ssize_t
704 rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
705 {
706  static rfc1035_message h;
707  size_t offset = 0;
708  static char rev[32];
709  unsigned int i;
710  memset(&h, '\0', sizeof(h));
711  i = (unsigned int) ntohl(addr.s_addr);
712  snprintf(rev, 32, "%u.%u.%u.%u.in-addr.arpa.",
713  i & 255,
714  (i >> 8) & 255,
715  (i >> 16) & 255,
716  (i >> 24) & 255);
717  h.id = qid;
718  h.qr = 0;
719  h.rd = 1;
720  h.opcode = 0; /* QUERY */
721  h.qdcount = (unsigned int) 1;
722  h.arcount = (edns_sz > 0 ? 1 : 0);
723  offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
724  offset += rfc1035QuestionPack(buf + offset,
725  sz - offset,
726  rev,
729  if (edns_sz > 0)
730  offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
731  if (query) {
732  query->qtype = RFC1035_TYPE_PTR;
733  query->qclass = RFC1035_CLASS_IN;
734  xstrncpy(query->name, rev, sizeof(query->name));
735  }
736  assert(offset <= sz);
737  return offset;
738 }
739 
740 /*
741  * We're going to retry a former query, but we
742  * just need a new ID for it. Lucky for us ID
743  * is the first field in the message buffer.
744  */
745 void
746 rfc1035SetQueryID(char *buf, unsigned short qid)
747 {
748  unsigned short s = htons(qid);
749  memcpy(buf, &s, sizeof(s));
750 }
751 
752 #if DRIVER
753 #include <sys/socket.h>
754 int
755 main(int argc, char *argv[])
756 {
757  char input[SQUID_DNS_BUFSZ];
758  char buf[SQUID_DNS_BUFSZ];
759  char rbuf[SQUID_DNS_BUFSZ];
760  size_t sz = SQUID_DNS_BUFSZ;
761  unsigned short sid;
762  int s;
763  int rl;
764  struct sockaddr_in S;
765  if (3 != argc) {
766  fprintf(stderr, "usage: %s ip port\n", argv[0]);
767  exit(EXIT_FAILURE);
768  }
769  setbuf(stdout, NULL);
770  setbuf(stderr, NULL);
771  s = socket(PF_INET, SOCK_DGRAM, 0);
772  if (s < 0) {
773  perror("socket");
774  exit(EXIT_FAILURE);
775  }
776  memset(&S, '\0', sizeof(S));
777  S.sin_family = AF_INET;
778  S.sin_port = htons(atoi(argv[2]));
779  S.sin_addr.s_addr = inet_addr(argv[1]);
780  while (fgets(input, RFC1035_DEFAULT_PACKET_SZ, stdin)) {
781  struct in_addr junk;
782  strtok(input, "\r\n");
783  memset(buf, '\0', RFC1035_DEFAULT_PACKET_SZ);
785  if (inet_pton(AF_INET, input, &junk)) {
786  sid = rfc1035BuildPTRQuery(junk, buf, &sz);
787  } else {
788  sid = rfc1035BuildAQuery(input, buf, &sz);
789  }
790  sendto(s, buf, sz, 0, (struct sockaddr *) &S, sizeof(S));
791  do {
792  fd_set R;
793  struct timeval to;
794  FD_ZERO(&R);
795  FD_SET(s, &R);
796  to.tv_sec = 10;
797  to.tv_usec = 0;
798  rl = select(s + 1, &R, NULL, NULL, &to);
799  } while (0);
800  if (rl < 1) {
801  printf("TIMEOUT\n");
802  continue;
803  }
804  memset(rbuf, '\0', RFC1035_DEFAULT_PACKET_SZ);
805  rl = recv(s, rbuf, RFC1035_DEFAULT_PACKET_SZ, 0);
806  {
807  unsigned short rid = 0;
808  int i;
809  int n;
810  rfc1035_rr *answers = NULL;
811  n = rfc1035AnswersUnpack(rbuf,
812  rl,
813  &answers,
814  &rid);
815  if (n < 0) {
816  printf("ERROR %d\n", -n);
817  } else if (rid != sid) {
818  printf("ERROR, ID mismatch (%#hx, %#hx)\n", sid, rid);
819  } else {
820  printf("%d answers\n", n);
821  for (i = 0; i < n; i++) {
822  if (answers[i].type == RFC1035_TYPE_A) {
823  struct in_addr a;
824  char ipa_str[sizeof(a)];
825  memcpy(&a, answers[i].rdata, 4);
826  printf("A\t%d\t%s\n", answers[i].ttl, inet_ntop(AF_INET,&a,tmp,sizeof(a)));
827  } else if (answers[i].type == RFC1035_TYPE_PTR) {
828  char ptr[128];
829  strncpy(ptr, answers[i].rdata, answers[i].rdlength);
830  printf("PTR\t%d\t%s\n", answers[i].ttl, ptr);
831  } else {
832  fprintf(stderr, "can't print answer type %d\n",
833  (int) answers[i].type);
834  }
835  }
836  }
837  }
838  }
839  return EXIT_SUCCESS;
840 }
841 #endif
842 
unsigned short id
Definition: rfc1035.h:56
#define assert(EX)
Definition: assert.h:17
void rfc1035MessageDestroy(rfc1035_message **msg)
Definition: rfc1035.cc:537
int main(int, char *[])
Definition: unitTestMain.h:25
unsigned int aa
Definition: rfc1035.h:59
int type
Definition: errorpage.cc:152
#define RFC1035_MAXHOSTNAMESZ
Definition: rfc1035.h:32
#define xcalloc
Definition: membanger.c:57
int i
Definition: membanger.c:49
#define xstrdup
unsigned short nscount
Definition: rfc1035.h:66
#define RFC1035_TYPE_CNAME
Definition: rfc1035.h:94
unsigned int qr
Definition: rfc1035.h:57
int rfc1035RRPack(char *buf, const size_t sz, const rfc1035_rr *RR)
Definition: rfc1035.cc:329
static int rfc1035RRUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_rr *RR)
Definition: rfc1035.cc:373
int rfc1035QueryCompare(const rfc1035_query *a, const rfc1035_query *b)
Definition: rfc1035.cc:557
int rfc1035HeaderPack(char *buf, size_t sz, rfc1035_message *hdr)
Definition: rfc1035.cc:60
#define inet_pton
Definition: inet_pton.h:28
char name[RFC1035_MAXHOSTNAMESZ]
Definition: rfc1035.h:39
#define rfc1035_unpack_error
Definition: rfc1035.cc:45
rfc1035_query * query
Definition: rfc1035.h:68
void rfc1035RRDestroy(rfc1035_rr **rr, int n)
Definition: rfc1035.cc:490
unsigned int rcode
Definition: rfc1035.h:63
rfc1035_rr * answer
Definition: rfc1035.h:69
#define inet_ntop
Definition: inet_ntop.h:25
#define RFC1035_CLASS_IN
Definition: rfc1035.h:96
void const char int sz
Definition: stub_cbdata.cc:16
#define RFC1035_TYPE_A
Definition: rfc1035.h:93
void rfc1035SetQueryID(char *buf, unsigned short qid)
Definition: rfc1035.cc:746
void * addr
Definition: membanger.c:46
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
#define RFC1035_TYPE_PTR
Definition: rfc1035.h:95
unsigned short qdcount
Definition: rfc1035.h:64
int rfc1035MessageUnpack(const char *buf, size_t sz, rfc1035_message **answer)
Definition: rfc1035.cc:591
static int rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query *query)
Definition: rfc1035.cc:514
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void const char * buf
Definition: stub_helper.cc:16
unsigned short arcount
Definition: rfc1035.h:67
ssize_t rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query *query, ssize_t edns_sz)
Definition: rfc1035.cc:704
#define RFC1035_DEFAULT_PACKET_SZ
Definition: rfc1035.h:34
unsigned short type
Definition: rfc1035.h:40
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
unsigned short rdlength
Definition: rfc1035.h:43
#define xmalloc
const char * rfc1035ErrorMessage(int n)
Definition: rfc1035.cc:451
static int rfc1035NamePack(char *buf, size_t sz, const char *name)
Definition: rfc1035.cc:130
unsigned short qtype
Definition: rfc1035.h:50
unsigned int tc
Definition: rfc1035.h:60
unsigned short qclass
Definition: rfc1035.h:51
unsigned int opcode
Definition: rfc1035.h:58
char * rdata
Definition: rfc1035.h:44
ssize_t rfc1035BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query *query, ssize_t edns_sz)
Definition: rfc1035.cc:665
int const char size_t
Definition: stub_liblog.cc:86
unsigned int ra
Definition: rfc1035.h:62
char name[RFC1035_MAXHOSTNAMESZ]
Definition: rfc1035.h:49
int a
Definition: membanger.c:50
static int rfc1035LabelPack(char *buf, size_t sz, const char *label)
Definition: rfc1035.cc:105
static int rfc1035NameUnpack(const char *buf, size_t sz, unsigned int *off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
Definition: rfc1035.cc:247
int rfc1035HeaderUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_message *h)
Definition: rfc1035.cc:184
int rfc1035QuestionPack(char *buf, const size_t sz, const char *name, const unsigned short type, const unsigned short _class)
Definition: rfc1035.cc:153
#define RFC1035_UNPACK_DEBUG
Definition: rfc1035.cc:50
#define RFC1035_MAXLABELSZ
Definition: rfc1035.cc:44
#define xfree
unsigned short _class
Definition: rfc1035.h:41
unsigned short ancount
Definition: rfc1035.h:65
#define NULL
Definition: types.h:166
int rfc2671RROptPack(char *buf, size_t sz, ssize_t edns_sz)
Definition: rfc2671.cc:14
unsigned int rd
Definition: rfc1035.h:61
unsigned int ttl
Definition: rfc1035.h:42

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors