OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bind_util.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/algorithm/string/join.hpp>
6 #include <boost/assign/list_of.hpp>
7 #include <boost/regex.hpp>
8 #include <bind/bind_util.h>
9 
10 using namespace boost::assign;
12 
13 DnsTypeMap g_dns_type_map = map_list_of<std::string, uint16_t>
14  ("A", 1)
15  ("NS", 2)
16  ("CNAME", 5)
17  ("SOA", 6)
18  ("PTR", 0x0C)
19  ("MX", 0x0F)
20  ("TXT", 0x10)
21  ("AAAA", 0x1C)
22  ("SRV", 0x21)
23  ("ANY", 0xFF);
24 
25 DnsTypeNumMap g_dns_type_num_map = map_list_of<uint16_t, std::string>
26  (DNS_A_RECORD, "A")
27  (DNS_NS_RECORD, "NS")
28  (DNS_CNAME_RECORD, "CNAME")
29  (DNS_TYPE_SOA, "SOA")
30  (DNS_PTR_RECORD, "PTR")
31  (DNS_MX_RECORD, "MX")
32  (DNS_TXT_RECORD, "TXT")
33  (DNS_AAAA_RECORD, "AAAA")
34  (DNS_SRV_RECORD, "SRV")
35  (DNS_TYPE_ANY, "ANY");
36 
37 DnsTypeNumMap g_dns_class_num_map = map_list_of<uint16_t, std::string>
38  (DNS_CLASS_IN, "IN")
39  (DNS_CLASS_NONE, "None")
40  (DNS_CLASS_ANY, "Any");
41 
42 DnsResponseMap g_dns_response_map = map_list_of<uint16_t, std::string>
43  (0, "No error")
44  (1, "Format error")
45  (2, "Server failure")
46  (3, "Non-existent domain")
47  (4, "Not implemented")
48  (5, "Query refused")
49  (6, "Name exists when it should not")
50  (7, "RR Set Exists when it should not")
51  (8, "RR Set that should exist does not")
52  (9, "Not Authorized")
53  (10, "Name not contained in zone")
54  (16, "Bad OPT Version")
55  (17, "Key not recognized")
56  (18, "Signature out of time window")
57  (19, "Bad TKEY Mode")
58  (20, "Duplicate key name")
59  (21, "Algorithm not supported")
60  (22, "Bad truncation")
61  (4095, "Invalid response code");
62 
63 std::string DnsItem::ToString() const {
64  return BindUtil::DnsClass(eclass) + "/" +
65  BindUtil::DnsType(type) + "/" + name + "/" + data + ";";
66 }
67 
68 bool Subnet::operator< (const Subnet &rhs) const {
69  if (prefix.is_v4()) {
70  if (rhs.prefix.is_v4()) {
71  Ip4Address me = prefix.to_v4(),
72  they = rhs.prefix.to_v4();
73  if (me != they) {
74  return me < they;
75  }
76  return plen < rhs.plen;
77  } else {
78  // IPv4 goes before IPv6 and garbage
79  return true;
80  }
81  } else if (prefix.is_v6()) {
82  if (rhs.prefix.is_v6()) {
83  Ip6Address me = prefix.to_v6(),
84  they = rhs.prefix.to_v6();
85  if (me != they)
86  return me < they;
87  return plen < rhs.plen;
88  } else {
89  // IPv4 goes before IPv6, IPv6 goes before garbage
90  return !rhs.prefix.is_v4();
91  }
92  } else {
93  // Garbage always sorts towards the end
94  return false;
95  }
96 }
97 
98 bool Subnet::Contains(const IpAddress &addr) const {
99  if (prefix.is_v4() && addr.is_v4()) {
100  return IsIp4SubnetMember(addr.to_v4(), prefix.to_v4(), plen);
101  } else if (prefix.is_v6() && addr.is_v6()) {
102  return IsIp6SubnetMember(addr.to_v6(), prefix.to_v6(), plen);
103  } else {
104  return false;
105  }
106 }
107 
108 void Subnet::GetReverseZones(ZoneList &zones) const {
109  BindUtil::GetReverseZoneList(prefix, plen, zones);
110 }
111 
112 uint16_t BindUtil::DnsClass(const std::string &cl) {
113  if (cl == "IN")
114  return DNS_CLASS_IN;
115  return DNS_CLASS_ANY;
116 }
117 
118 std::string BindUtil::DnsClass(uint16_t cl) {
119  DnsTypeNumIter iter = g_dns_class_num_map.find(cl);
120  if (iter == g_dns_class_num_map.end())
121  return integerToString(cl);
122  return iter->second;
123 }
124 
125 uint16_t BindUtil::DnsType(const std::string &tp) {
126  DnsTypeIter iter = g_dns_type_map.find(tp);
127  if (iter == g_dns_type_map.end())
128  return -1;
129  return iter->second;
130 }
131 
132 std::string BindUtil::DnsType(uint16_t tp) {
133  DnsTypeNumIter iter = g_dns_type_num_map.find(tp);
134  if (iter == g_dns_type_num_map.end())
135  return integerToString(tp);
136  return iter->second;
137 }
138 
139 const std::string &BindUtil::DnsResponseCode(uint16_t code) {
140  DnsResponseIter iter = g_dns_response_map.find(code);
141  if (iter == g_dns_response_map.end())
142  return DnsResponseCode(4095);
143  return iter->second;
144 }
145 
146 uint8_t *BindUtil::AddName(uint8_t *ptr, const std::string &addr,
147  uint16_t plen, uint16_t offset, uint16_t &length) {
148  std::size_t size = addr.size();
149  std::size_t cur_pos = 0;
150  std::size_t prev_pos = 0;
151  while (cur_pos < size && cur_pos != std::string::npos) {
152  if (offset && !plen) {
153  ptr = WriteShort(ptr, offset);
154  length += 2;
155  return ptr;
156  }
157  std::size_t len;
158  cur_pos = addr.find('.', prev_pos);
159  if (cur_pos == std::string::npos)
160  len = size - prev_pos;
161  else
162  len = cur_pos - prev_pos;
163 
164  *ptr = len;
165  memcpy(ptr + 1, addr.substr(prev_pos, len).data(), len);
166  ptr += len + 1;
167  plen = (plen > len) ? plen - len - 1 : 0;
168 
169  prev_pos = cur_pos + 1;
170  length += len + 1;
171  }
172  ptr = WriteByte(ptr, 0);
173  length++;
174 
175  return ptr;
176 }
177 
178 uint8_t *BindUtil::AddQuestionSection(uint8_t *ptr, const std::string &name,
179  uint16_t type, uint16_t cl,
180  uint16_t &length) {
181  ptr = AddName(ptr, name, 0, 0, length);
182  ptr = WriteShort(ptr, type);
183  ptr = WriteShort(ptr, cl);
184  length += 4;
185 
186  return ptr;
187 }
188 
189 uint8_t *BindUtil::AddData(uint8_t *ptr, const DnsItem &item,
190  uint16_t &length) {
191  boost::system::error_code ec;
192 
193  if (item.type == DNS_A_RECORD) {
194  ptr = WriteShort(ptr, 4);
195  ptr = WriteWord(ptr, boost::asio::ip::address_v4::from_string(
196  item.data, ec).to_ulong());
197  length += 2 + 4;
198  } else if (item.type == DNS_AAAA_RECORD) {
199  ptr = WriteShort(ptr, 16);
200  boost::asio::ip::address_v6 addr =
201  boost::asio::ip::address_v6::from_string(item.data, ec);
202  if (ec.value()) {
203  memset(ptr, 0, 16);
204  } else {
205  memcpy(ptr, addr.to_bytes().data(), 16);
206  }
207  ptr += 16;
208  length += 2 + 16;
209  } else if(item.type == DNS_TYPE_SOA) {
210  uint16_t data_len = DataLength(item.soa.ns_plen, item.soa.ns_offset,
211  item.soa.primary_ns.size()) +
212  DataLength(item.soa.mailbox_plen,
213  item.soa.mailbox_offset,
214  item.soa.mailbox.size()) + 20;
215  ptr = WriteShort(ptr, data_len);
216  ptr = AddName(ptr, item.soa.primary_ns, item.soa.ns_plen,
217  item.soa.ns_offset, length);
218  ptr = AddName(ptr, item.soa.mailbox, item.soa.mailbox_plen,
219  item.soa.mailbox_offset, length);
220  ptr = WriteWord(ptr, item.soa.serial);
221  ptr = WriteWord(ptr, item.soa.refresh);
222  ptr = WriteWord(ptr, item.soa.retry);
223  ptr = WriteWord(ptr, item.soa.expiry);
224  ptr = WriteWord(ptr, item.soa.ttl);
225  length += 2 + 20;
226  } else if(item.type == DNS_PTR_RECORD ||
227  item.type == DNS_CNAME_RECORD ||
228  item.type == DNS_NS_RECORD) {
229  uint16_t data_len = DataLength(item.data_plen, item.data_offset,
230  item.data.size());
231  ptr = WriteShort(ptr, data_len);
232  ptr = AddName(ptr, item.data, item.data_plen, item.data_offset, length);
233  length += 2;
234  } else if (item.type == DNS_MX_RECORD) {
235  uint16_t data_len = 2 + DataLength(item.data_plen, item.data_offset,
236  item.data.size());
237  ptr = WriteShort(ptr, data_len);
238  // An MX record has 16 bit preference followed by host name
239  ptr = WriteShort(ptr, item.priority);
240  ptr = AddName(ptr, item.data, item.data_plen, item.data_offset, length);
241  length += 2 + 2;
242  } else if (item.type == DNS_SRV_RECORD) {
243  uint16_t data_len = 6 + DataLength(item.srv.hn_plen, item.srv.hn_offset,
244  item.srv.hostname.size());
245  ptr = WriteShort(ptr, data_len);
246  ptr = WriteShort(ptr, item.srv.priority);
247  ptr = WriteShort(ptr, item.srv.weight);
248  ptr = WriteShort(ptr, item.srv.port);
249  ptr = AddName(ptr, item.srv.hostname, item.srv.hn_plen,
250  item.srv.hn_offset, length);
251  length += 2 + 6;
252  } else {
253  // TXT and other record types are handled here.
254  // TODO: In case a record type has domain name and name is compressed
255  // in the message that is being read, it may lead to problem if the
256  // offset in the message we send doesnt match with the offset in the
257  // message that is received. Each such message has to be handled
258  // as a different case here.
259  uint16_t size = item.data.size();
260  ptr = WriteShort(ptr, size);
261  if (size) {
262  memcpy(ptr, item.data.c_str(), size);
263  ptr += size;
264  }
265  length += 2 + size;
266  }
267 
268  return ptr;
269 }
270 
271 uint8_t *BindUtil::AddAnswerSection(uint8_t *ptr, const DnsItem &item,
272  uint16_t &length) {
273  ptr = AddName(ptr, item.name, item.name_plen, item.name_offset, length);
274  ptr = WriteShort(ptr, item.type);
275  ptr = WriteShort(ptr, item.eclass);
276  ptr = WriteWord(ptr, item.ttl);
277  length += 2 + 2 + 4;
278  ptr = AddData(ptr, item, length);
279 
280  return ptr;
281 }
282 
283 uint8_t *BindUtil::AddAdditionalSection(uint8_t *ptr, const std::string name,
284  uint16_t type, uint16_t cl,
285  uint32_t ttl, const std::string &data,
286  uint16_t &length) {
287  ptr = AddQuestionSection(ptr, name, type, cl, length);
288  ptr = WriteWord(ptr, ttl);
289  ptr = WriteShort(ptr, data.size() + 1);
290 
291  // adding the domain name as it is, without replacing '.' with length
292  ptr = WriteByte(ptr, data.size());
293  memcpy(ptr, data.data(), data.size());
294  ptr += data.size();
295  length += 4 + 2 + 1 + data.size();
296 
297  return ptr;
298 }
299 
300 uint8_t *BindUtil::AddUpdate(uint8_t *ptr, const DnsItem &item,
301  uint16_t cl, uint32_t ttl, uint16_t &length) {
302  ptr = AddQuestionSection(ptr, item.name, item.type, cl, length);
303  ptr = WriteWord(ptr, ttl);
304  length += 4;
305  ptr = AddData(ptr, item, length);
306 
307  return ptr;
308 }
309 
310 bool BindUtil::ReadName(uint8_t *dns, uint16_t dnslen, int *remlen,
311  std::string &name, uint16_t &plen, uint16_t &offset) {
312  if (*remlen <= 0) {
313  return false;
314  }
315 
316  uint8_t *ptr = dns + (dnslen - *remlen);
317  std::size_t len = *ptr;
318  while (len) {
319  if ((len & 0xC0) == 0xC0) {
320  plen = name.size() ? name.size() - 1 : 0;
321  if (ReadShort(dns, dnslen, remlen, offset) == false)
322  return false;
323  int offset_remlen = dnslen - (offset & ~0xC000);
324  uint16_t dummy;
325  return ReadName(dns, dnslen, &offset_remlen, name, dummy, dummy);
326  } else {
327  *remlen -= (len + 1);
328  if (*remlen < 0) {
329  return false;
330  }
331  name.append((char *)ptr+1, len);
332  ptr += len + 1;
333  len = *ptr;
334  if (len)
335  name.append(".");
336  }
337  }
338 
339  *remlen -= 1;
340  return true;
341 }
342 
343 bool BindUtil::ReadData(uint8_t *dns, uint16_t dnslen, int *remlen,
344  DnsItem &item) {
345  uint16_t length;
346  if (ReadShort(dns, dnslen, remlen, length) == false)
347  return false;
348 
349  boost::system::error_code ec;
350  if (item.type == DNS_A_RECORD) {
351  uint32_t ip;
352  if (ReadWord(dns, dnslen, remlen, ip) == false)
353  return false;
354  boost::asio::ip::address_v4 addr(ip);
355  item.data = addr.to_string(ec);
356  return true;
357  } else if(item.type == DNS_AAAA_RECORD) {
358  if (*remlen < 16) {
359  return false;
360  }
361  uint8_t *ptr = dns + (dnslen - *remlen);
362  boost::asio::ip::address_v6::bytes_type ip;
363  memcpy(&ip[0], ptr, 16);
364  boost::asio::ip::address_v6 addr(ip);
365  item.data = addr.to_string(ec);
366  *remlen -= 16;
367  return true;
368  } else if(item.type == DNS_TYPE_SOA) {
369  if (ReadName(dns, dnslen, remlen, item.soa.primary_ns,
370  item.soa.ns_plen, item.soa.ns_offset) == false)
371  return false;
372  if (ReadName(dns, dnslen, remlen, item.soa.mailbox,
373  item.soa.mailbox_plen, item.soa.mailbox_offset) == false)
374  return false;
375  if (ReadWord(dns, dnslen, remlen, item.soa.serial) == false)
376  return false;
377  if (ReadWord(dns, dnslen, remlen, item.soa.refresh) == false)
378  return false;
379  if (ReadWord(dns, dnslen, remlen, item.soa.retry) == false)
380  return false;
381  if (ReadWord(dns, dnslen, remlen, item.soa.expiry) == false)
382  return false;
383  return ReadWord(dns, dnslen, remlen, item.soa.ttl);
384  } else if(item.type == DNS_PTR_RECORD ||
385  item.type == DNS_CNAME_RECORD ||
386  item.type == DNS_NS_RECORD) {
387  return ReadName(dns, dnslen, remlen, item.data, item.data_plen, item.data_offset);
388  } else if(item.type == DNS_MX_RECORD) {
389  if (ReadShort(dns, dnslen, remlen, item.priority) == false)
390  return false;
391  return ReadName(dns, dnslen, remlen, item.data, item.data_plen, item.data_offset);
392  } else if (item.type == DNS_SRV_RECORD) {
393  if (ReadShort(dns, dnslen, remlen, item.srv.priority) == false)
394  return false;
395  if (ReadShort(dns, dnslen, remlen, item.srv.weight) == false)
396  return false;
397  if (ReadShort(dns, dnslen, remlen, item.srv.port) == false)
398  return false;
399  return ReadName(dns, dnslen, remlen, item.srv.hostname,
400  item.srv.hn_plen, item.srv.hn_offset);
401  } else {
402  // TXT and other record types are handled here.
403  // TODO: In case a record type has domain name and name is compressed
404  // in the message that is being read, it may lead to problem if the
405  // offset in the message we send doesnt match with the offset in the
406  // message that is received. Each such message has to be handled
407  // as a different case here.
408  if (*remlen < length) {
409  return false;
410  }
411  uint8_t *ptr = dns + (dnslen - *remlen);
412  item.data.assign((const char *)ptr, length);
413  *remlen -= length;
414  return true;
415  }
416 
417  DNS_BIND_TRACE(DnsBindError,
418  "Unsupported data type in DNS response : " << item.type);
419  return false;
420 }
421 
422 bool BindUtil::ReadQuestionEntry(uint8_t *dns, uint16_t dnslen, int *remlen,
423  DnsItem &item) {
424  if (ReadName(dns, dnslen, remlen, item.name, item.name_plen,
425  item.name_offset) == false)
426  return false;
427 
428  if (ReadShort(dns, dnslen, remlen, item.type) == false)
429  return false;
430 
431  return ReadShort(dns, dnslen, remlen, item.eclass);
432 }
433 
434 bool BindUtil::ReadAnswerEntry(uint8_t *dns, uint16_t dnslen, int *remlen,
435  DnsItem &item) {
436  if (ReadQuestionEntry(dns, dnslen, remlen, item) == false)
437  return false;
438 
439  if (ReadWord(dns, dnslen, remlen, item.ttl) == false)
440  return false;
441 
442  return ReadData(dns, dnslen, remlen, item);
443 }
444 
445 bool BindUtil::ParseDnsQuery(uint8_t *dns, uint16_t dnslen, uint16_t *parsed_length,
446  DnsItems &items) {
447  uint16_t xid = 0;
448  *parsed_length = 0;
449  if (dnslen <= sizeof(dnshdr)) {
450  DNS_BIND_TRACE(DnsBindError,
451  "Invalid DNS Query with header missing - dropping it");
452  return false;
453  }
454 
455  dnshdr *hdr = (dnshdr *) dns;
456  xid = ntohs(hdr->xid);
457  uint16_t ques_rrcount = ntohs(hdr->ques_rrcount);
458 
459  int remlen = dnslen - sizeof(dnshdr);
460  for (unsigned int i = 0; i < ques_rrcount; ++i) {
461  DnsItem item;
462  item.offset = (dnslen - remlen) | 0xC000;
463  if (ReadQuestionEntry(dns, dnslen, &remlen, item) == false) {
464  DNS_BIND_TRACE(DnsBindError, "DNS Query Parse error in question "
465  "section - xid : " << xid << " - dropping it");
466  return false;
467  }
468  items.push_back(item);
469  }
470 
471  *parsed_length = dnslen - remlen;
472  return true;
473 
474 }
475 
476 bool BindUtil::ParseDnsResponse(uint8_t *dns, uint16_t dnslen, uint16_t &xid,
477  dns_flags &flags, DnsItems &ques, DnsItems &ans,
478  DnsItems &auth, DnsItems &add) {
479  if (dnslen < sizeof(dnshdr)) {
480  DNS_BIND_TRACE(DnsBindError,
481  "Invalid DNS Response with header missing - dropping it");
482  return false;
483  }
484 
485  dnshdr *hdr = (dnshdr *) dns;
486  xid = ntohs(hdr->xid);
487  flags = hdr->flags;
488 
489  uint16_t ques_rrcount = ntohs(hdr->ques_rrcount);
490  uint16_t ans_rrcount = ntohs(hdr->ans_rrcount);
491  uint16_t auth_rrcount = ntohs(hdr->auth_rrcount);
492  uint16_t add_rrcount = ntohs(hdr->add_rrcount);
493 
494  int remlen = dnslen - sizeof(dnshdr);
495  std::string errmsg;
496 
497  // question section
498  for (unsigned int i = 0; i < ques_rrcount; ++i) {
499  DnsItem item;
500  if (ReadQuestionEntry(dns, dnslen, &remlen, item) == false) {
501  errmsg = "Parse error in question section";
502  goto error;
503  }
504  ques.push_back(item);
505  }
506 
507  // answer section
508  for (unsigned int i = 0; i < ans_rrcount; ++i) {
509  DnsItem item;
510  if (ReadAnswerEntry(dns, dnslen, &remlen, item) == false) {
511  errmsg = "Parse error in answer section";
512  goto error;
513  }
514  ans.push_back(item);
515  }
516 
517  // authority section
518  for (unsigned int i = 0; i < auth_rrcount; ++i) {
519  DnsItem item;
520  if (ReadAnswerEntry(dns, dnslen, &remlen, item) == false) {
521  errmsg = "Parse error in authority section";
522  goto error;
523  }
524  auth.push_back(item);
525  }
526 
527  // additional section
528  for (unsigned int i = 0; i < add_rrcount; ++i) {
529  DnsItem item;
530  if (ReadAnswerEntry(dns, dnslen, &remlen, item) == false) {
531  errmsg = "Parse error in additional section";
532  goto error;
533  }
534  add.push_back(item);
535  }
536 
537  return true;
538 
539 error:
540  DNS_BIND_TRACE(DnsBindError,
541  "Invalid DNS response : " << errmsg <<
542  " xid : " << xid << " - dropping it");
543  return false;
544 }
545 
546 bool BindUtil::ParseDnsUpdate(uint8_t *dns, uint16_t dnslen,
547  DnsUpdateData &data) {
548  if (dnslen <= sizeof(dnshdr)) {
549  DNS_BIND_TRACE(DnsBindError, "Invalid DNS Update with header missing "
550  "- dropping it");
551  return false;
552  }
553 
554  dnshdr *hdr = (dnshdr *) dns;
555  uint16_t zone_count = ntohs(hdr->ques_rrcount);
556  uint16_t prereq_count = ntohs(hdr->ans_rrcount);
557  uint16_t update_count = ntohs(hdr->auth_rrcount);
558  uint16_t xid = ntohs(hdr->xid);
559 
560  if (zone_count != 1) {
561  DNS_BIND_TRACE(DnsBindError,
562  "Invalid zone count in Update request : " << zone_count);
563  return false;
564  }
565 
566  if (prereq_count != 0) {
567  // Not supporting pre-requisites now
568  DNS_BIND_TRACE(DnsBindError, "Update has pre-requisites, " <<
569  "which is not supported; dropping the request");
570  return false;
571  }
572 
573  int remlen = dnslen - sizeof(dnshdr);
574  std::string errmsg;
575 
576  // Read zone
577  uint16_t zone_type, zone_class, plen, offset;
578  if (ReadName(dns, dnslen, &remlen, data.zone, plen, offset) == false ||
579  ReadShort(dns, dnslen, &remlen, zone_type) == false ||
580  ReadShort(dns, dnslen, &remlen, zone_class) == false) {
581  errmsg = "Parse error in reading zone";
582  goto error;
583  }
584 
585  // Read Updates
586  for (unsigned int i = 0; i < update_count; ++i) {
587  DnsItem item;
588  if (ReadName(dns, dnslen, &remlen, item.name, plen, offset) == false ||
589  ReadShort(dns, dnslen, &remlen, item.type) == false ||
590  ReadShort(dns, dnslen, &remlen, item.eclass) == false ||
591  ReadWord(dns, dnslen, &remlen, item.ttl) == false ||
592  ReadData(dns, dnslen, &remlen, item) == false) {
593  errmsg = "Parse error";
594  goto error;
595  }
596  data.items.push_back(item);
597  }
598 
599  return true;
600 
601 error:
602  DNS_BIND_TRACE(DnsBindError,
603  "Invalid DNS Update : " << errmsg <<
604  " xid : " << xid << " - dropping it");
605  return false;
606 }
607 
608 void BindUtil::BuildDnsHeader(dnshdr *dns, uint16_t xid, DnsReq req,
609  DnsOpcode op, bool rd, bool ra, uint8_t ret,
610  uint16_t ques_count) {
611  dns->xid = htons(xid);
612  dns->flags.req = req;
613  dns->flags.op = op;
614  dns->flags.auth = 0;
615  dns->flags.trunc = 0;
616  dns->flags.rd = rd;
617  dns->flags.ra = ra;
618  dns->flags.res = 0;
619  dns->flags.ad = 0;
620  dns->flags.cd = 0;
621  dns->flags.ret = ret;
622  dns->ques_rrcount = htons(ques_count);
623  dns->ans_rrcount = 0;
624  dns->auth_rrcount = 0;
625  dns->add_rrcount = 0;
626 }
627 
628 int BindUtil::BuildDnsQuery(uint8_t *buf, uint16_t xid,
629  const std::string &domain,
630  const DnsItems &items) {
631  dnshdr *dns = (dnshdr *) buf;
632  BuildDnsHeader(dns, xid, DNS_QUERY_REQUEST, DNS_OPCODE_QUERY,
633  1, 0, 0, items.size());
634 
635  // TODO : can be optimised to reuse any names using offsets
636  uint16_t len = sizeof(dnshdr);
637  uint8_t *ques = (uint8_t *) (dns + 1);
638  for (DnsItems::const_iterator it = items.begin(); it != items.end(); ++it) {
639  ques = AddQuestionSection(ques, (*it).name, (*it).type,
640  (*it).eclass, len);
641  }
642 
643  if (!domain.empty()) {
644  dns->add_rrcount = htons(1);
645  std::string view = "view=" + domain;
646  ques = AddAdditionalSection(ques, "view", DNS_TXT_RECORD, DNS_CLASS_IN,
647  0, view, len);
648  }
649 
650  return len;
651 }
652 
653 int BindUtil::BuildDnsUpdate(uint8_t *buf, Operation op, uint16_t xid,
654  const std::string &domain,
655  const std::string &zone,
656  const DnsItems &items) {
657  dnshdr *dns = (dnshdr *) buf;
658  BuildDnsHeader(dns, xid, DNS_QUERY_REQUEST, DNS_OPCODE_UPDATE, 0, 0, 0, 1);
659  // dns->ques_rrcount = htons(1); // Number of zones
660  // dns->ans_rrcount = 0; // Number of Prerequisites
661  dns->auth_rrcount = htons(items.size()); // Number of Updates
662  dns->add_rrcount = htons(1); // Number of Additional RRs
663 
664  // Add zone
665  uint16_t len = sizeof(dnshdr);
666  uint8_t *ptr = (uint8_t *) (dns + 1);
667  ptr = AddQuestionSection(ptr, zone, DNS_TYPE_SOA, DNS_CLASS_IN, len);
668 
669  // Add Updates
670  switch (op) {
671  case ADD_UPDATE:
672  case CHANGE_UPDATE:
673  for (DnsItems::const_iterator it = items.begin();
674  it != items.end(); ++it) {
675  ptr = AddUpdate(ptr, *it, (*it).eclass, (*it).ttl, len);
676  }
677  break;
678 
679  case DELETE_UPDATE:
680  for (DnsItems::const_iterator it = items.begin();
681  it != items.end(); ++it) {
682  ptr = AddUpdate(ptr, *it, DNS_CLASS_NONE, 0, len);
683  }
684  break;
685 
686  default:
687  assert(0);
688  }
689 
690  // Add Additional RRs
691  std::string view = "view=" + domain;
692  ptr = AddAdditionalSection(ptr, "view", DNS_TXT_RECORD, DNS_CLASS_IN,
693  0, view, len);
694 
695  return len;
696 }
697 
698 bool BindUtil::IsReverseZoneV4(const std::string &name) {
699  // According to the docs, boost::regex is thread-safe. Compile once then.
700  static boost::regex in_addr_arpa("(?:[0-9]+\\.){1,4}in-addr\\.arpa\\.?",
701  boost::regex::perl | boost::regex::icase);
702  return boost::regex_match(name, in_addr_arpa);
703 }
704 
705 bool BindUtil::IsReverseZoneV6(const std::string &name) {
706  static boost::regex ip6_arpa("(?:[0-9a-f]\\.){1,32}ip6\\.arpa\\.?",
707  boost::regex::perl | boost::regex::icase);
708  return boost::regex_match(name, ip6_arpa);
709 }
710 
711 bool BindUtil::IsReverseZone(const std::string &name) {
713 }
714 
715 bool BindUtil::IsIP(const std::string &name, IpAddress &addr) {
716  boost::system::error_code ec;
717  addr = boost::asio::ip::address::from_string(name, ec);
718  return !ec.value();
719 }
720 
721 inline uint8_t BindUtil::GetNibble(const Ip6Address::bytes_type &addr, size_t bit)
722 {
723  assert((bit >> 3) < 16);
724  uint8_t buf = addr[bit >> 3];
725  return ((bit & 0x7) ? (buf & 0xF) : (buf >> 4));
726 }
727 
728 // Takes nibbles up to (but not necessarily including) plen and builds
729 // ip6.arpa zone name suffix for them. The caller is responsible for
730 // prefixing it with remaining plen bits when plen is not a multiply of 4.
731 std::string BindUtil::BuildIp6ArpaSuffix(const Ip6Address::bytes_type &addr,
732  uint32_t plen) {
733  std::vector<std::string> items;
734  uint8_t buf;
735 
736  for (size_t i = 0; i < (plen >> 2); i++) {
737  buf = GetNibble(addr, i << 2);
738  std::stringstream str;
739  str << std::hex << static_cast<unsigned int>(buf);
740  items.push_back(str.str());
741  }
742 
743  std::reverse(items.begin(), items.end());
744  items.push_back("ip6.arpa");
745  return boost::algorithm::join(items, ".");
746 }
747 
748 // Get list of reverse zones, given a subnet
749 void BindUtil::GetReverseZoneList(const Ip4Address &mask, uint32_t plen,
750  ZoneList &zones) {
751  uint32_t addr = mask.to_ulong();
752  std::string zone_name = "in-addr.arpa.";
753  while (plen >= 8) {
754  std::stringstream str;
755  str << (addr >> 24);
756  zone_name = str.str() + "." + zone_name;
757  addr = addr << 8;
758  plen -= 8;
759  }
760  if (plen == 0) {
761  // when prefix len is a multiple of 8, add only one reverse zone
762  zones.push_back(zone_name);
763  return;
764  }
765  for (int j = 0; j <= (0xFF >> plen); j++) {
766  // when prefix len is not a multiple of 8, add reverse zones for all
767  // addresses upto the nearest 8 byte boundary for the prefix len. For
768  // example, a /22 prefix results in 4 reverse zones.
769  uint32_t last = (addr >> 24) + j;
770  std::stringstream str;
771  str << last;
772  std::string rev_zone_name = str.str() + "." + zone_name;
773  zones.push_back(rev_zone_name);
774  }
775 }
776 
777 void BindUtil::GetReverseZoneList(const Ip6Address &mask, uint32_t plen,
778  ZoneList &zones) {
779  Ip6Address::bytes_type addr = mask.to_bytes();
780  std::string zone_name;
781  uint8_t buf;
782 
783  if (!plen || plen > 128)
784  return;
785 
786  zone_name = BindUtil::BuildIp6ArpaSuffix(addr, plen) + ".";
787 
788  uint32_t bits_rem = plen & 0x3;
789  // Prefix doesn't end on nibble boundary
790  if (bits_rem) {
791  buf = BindUtil::GetNibble(addr, plen - bits_rem);
792  for (int j = 0; j <= (0xF >> bits_rem); j++) {
793  std::stringstream str;
794  str << std::hex << static_cast<unsigned int>(buf + j)
795  << "." << zone_name;
796  zones.push_back(str.str());
797  }
798  } else {
799  zones.push_back(zone_name);
800  }
801 }
802 
803 void BindUtil::GetReverseZoneList(const IpAddress &mask, uint32_t plen,
804  ZoneList &zones) {
805  if (mask.is_v4()) {
806  GetReverseZoneList(mask.to_v4(), plen, zones);
807  } else if (mask.is_v6()) {
808  GetReverseZoneList(mask.to_v6(), plen, zones);
809  }
810 }
811 
812 void BindUtil::GetReverseZone(const Ip4Address &ip, uint32_t plen,
813  std::string &zone) {
814  uint32_t addr = ip.to_ulong();
815  zone = "in-addr.arpa";
816  while (plen >= 8) {
817  std::stringstream str;
818  str << (addr >> 24);
819  zone = str.str() + "." + zone;
820  addr = addr << 8;
821  plen -= 8;
822  }
823  if (plen == 0) {
824  return;
825  }
826  // when prefix len is not a multiple of 8, add extra byte from the addr
827  std::stringstream str;
828  str << (addr >> 24);
829  zone = str.str() + "." + zone;
830 }
831 
832 void BindUtil::GetReverseZone(const Ip6Address &ip, uint32_t plen,
833  std::string &zone) {
834  Ip6Address::bytes_type addr = ip.to_bytes();
835  uint8_t buf;
836 
837  if (!plen || plen > 128)
838  return;
839 
840  zone = BindUtil::BuildIp6ArpaSuffix(addr, plen);
841 
842  uint32_t bits_rem = plen & 0x3;
843  // Add the trailing nibble
844  if (bits_rem) {
845  buf = BindUtil::GetNibble(addr, plen - bits_rem);
846  std::stringstream str;
847  str << std::hex << static_cast<unsigned int>(buf) << "." << zone;
848  zone = str.str();
849  }
850 }
851 
852 void BindUtil::GetReverseZone(const IpAddress &addr, uint32_t plen,
853  std::string &zone) {
854  if (addr.is_v4()) {
855  GetReverseZone(addr.to_v4(), plen, zone);
856  } else if (addr.is_v6()) {
857  GetReverseZone(addr.to_v6(), plen, zone);
858  }
859 }
860 
861 bool BindUtil::GetAddrFromPtrName(std::string &ptr_name, Ip4Address &ip) {
862  uint32_t addr = 0;
863  uint8_t dot;
864  uint32_t num;
865  if (!BindUtil::IsReverseZoneV4(ptr_name))
866  return false;
867  std::stringstream str(ptr_name);
868  if (str.peek() == '.')
869  str >> dot;
870  int count = 0;
871  while (count < 4) {
872  if (str.peek() == 'i')
873  break;
874  str >> num;
875  str >> dot;
876  addr |= (num << (8 * count));
877  count++;
878  }
879  while (count++ < 4)
880  addr = addr << 8;
881  ip = Ip4Address(addr);
882  return true;
883 }
884 
885 bool BindUtil::GetAddrFromPtrName(std::string &ptr_name, Ip6Address &ip) {
886  Ip6Address::bytes_type addr;
887  BOOST_ASSERT(addr.size() == 16);
888 
889  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
890  typedef boost::array<uint8_t, 32> nibbles;
891 
892  if (!BindUtil::IsReverseZoneV6(ptr_name))
893  return false;
894 
895  tokenizer tok(ptr_name, boost::char_separator<char>("."));
896  nibbles nib;
897 
898  tokenizer::const_iterator tok_it = tok.begin();
899  nibbles::iterator nib_it = nib.begin();
900  for (; tok_it != tok.end() && nib_it != nib.end(); ++tok_it, ++nib_it) {
901  std::stringstream str(*tok_it);
902  unsigned int buf;
903 
904  // found ip6.arpa
905  if (!(str >> std::hex >> buf))
906  break;
907 
908  *nib_it = static_cast<uint8_t>(buf);
909  }
910 
911  std::fill(addr.begin(), addr.end(), 0);
912 
913  std::reverse_iterator<nibbles::const_iterator> r_nib_it(nib_it);
914  Ip6Address::bytes_type::iterator addr_it = addr.begin();
915 
916  // the most significant nibble is #0 thus always even
917  bool odd_nib = false;
918  // we should never get past addr.end() as nib.size() is 2 * 16
919  for (; r_nib_it != nib.rend(); ++r_nib_it) {
920  if (odd_nib) {
921  *addr_it |= (*r_nib_it & 0xF);
922  ++addr_it;
923  } else {
924  *addr_it |= (*r_nib_it << 4);
925  }
926  odd_nib = !odd_nib;
927  }
928 
929  ip = Ip6Address(addr);
930  return true;
931 }
932 
933 bool BindUtil::GetAddrFromPtrName(std::string &ptr_name,
934  IpAddress &ip) {
935  std::string name = boost::to_lower_copy(ptr_name);
936  std::size_t pos;
937 
938  pos = name.find(".in-addr.arpa");
939  if (pos != std::string::npos) {
940  Ip4Address out;
941  bool success = BindUtil::GetAddrFromPtrName(ptr_name, out);
942  if (success)
943  ip = out;
944  return success;
945  }
946 
947  pos = name.find(".ip6.arpa");
948  if (pos != std::string::npos) {
949  Ip6Address out;
950  bool success = BindUtil::GetAddrFromPtrName(ptr_name, out);
951  if (success)
952  ip = out;
953  return success;
954  }
955 
956  return false;
957 }
958 
959 std::string BindUtil::GetPtrNameFromAddr(const Ip4Address &ip) {
960  std::stringstream str;
961  for (int i = 0; i < 4; i++) {
962  str << ((ip.to_ulong() >> (i * 8)) & 0xFF) << ".";
963  }
964  str << "in-addr.arpa";
965  return str.str();
966 }
967 
968 std::string BindUtil::GetPtrNameFromAddr(const Ip6Address &ip6) {
969  std::stringstream str;
970  // we start with nibble #31 which is always odd
971  bool odd_nibble = true;
972 
973  Ip6Address::bytes_type addr = ip6.to_bytes();
974  Ip6Address::bytes_type::reverse_iterator it = addr.rbegin();
975  while (it != addr.rend()) {
976  unsigned int buf;
977  if (odd_nibble) {
978  buf = (*it & 0xF);
979  } else {
980  buf = (*it >> 4);
981  ++it;
982  }
983  str << std::hex << buf << '.';
984  odd_nibble = !odd_nibble;
985  }
986  str << "ip6.arpa";
987 
988  return str.str();
989 }
990 
991 std::string BindUtil::GetFQDN(const std::string &name, const std::string &domain,
992  const std::string &match) {
993  if (name.find(match, 0) == std::string::npos)
994  return name + "." + domain;
995  else
996  return name;
997 }
998 
999 bool BindUtil::HasSpecialChars(const std::string &name) {
1000  for (unsigned int i = 0; i < name.size(); ++i) {
1001  uint8_t c = name[i];
1002  if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
1003  (c >= '0' && c <= '9') || (c == '-') || (c == '.')))
1004  return true;
1005  }
1006  return false;
1007 }
1008 
1009 void BindUtil::RemoveSpecialChars(std::string &name) {
1010  for (unsigned int i = 0; i < name.size(); ++i) {
1011  uint8_t c = name[i];
1012  if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
1013  (c >= '0' && c <= '9') || (c == '-') || (c == '.')))
1014  name[i] = '-';
1015  }
1016 }
1017 
1018 void DnsNameEncoder::AddName(std::string &name, uint16_t curr_msg_offset,
1019  uint16_t &name_plen, uint16_t &name_offset) {
1020  name_plen = 0;
1021  name_offset = 0;
1022  std::size_t pos = 0;
1023  while (pos < name.size()) {
1024  std::string str = name.substr(pos);
1025  if(IsPresent(str, name_offset)) {
1026  name_plen = pos ? pos - 1 : 0;
1027  break;
1028  }
1029 
1030  pos = name.find('.', pos + 1);
1031  if (pos == std::string::npos)
1032  break;
1033  pos++;
1034  }
1035  if (pos > 0)
1036  names_.push_back(Name(name, curr_msg_offset));
1037 }
1038 
1039 bool DnsNameEncoder::IsPresent(std::string &name, uint16_t &name_offset) {
1040  for (unsigned int i = 0; i < names_.size(); i++) {
1041  if (names_[i].name == name) {
1042  name_offset = names_[i].offset;
1043  return true;
1044  }
1045  }
1046  return false;
1047 }
static uint8_t * AddQuestionSection(uint8_t *ptr, const std::string &name, uint16_t type, uint16_t cl, uint16_t &length)
Definition: bind_util.cc:178
static uint8_t * AddAdditionalSection(uint8_t *ptr, const std::string name, uint16_t type, uint16_t cl, uint32_t ttl, const std::string &data, uint16_t &length)
Definition: bind_util.cc:283
uint8_t res
Definition: bind_util.h:84
std::map< std::string, uint16_t >::const_iterator DnsTypeIter
Definition: bind_util.h:68
std::map< uint16_t, std::string > DnsResponseMap
Definition: bind_util.h:71
DnsReq
Definition: bind_util.h:55
DnsSOAData soa
Definition: bind_util.h:161
#define DNS_BIND_TRACE(obj, arg)
Definition: bind_util.h:21
std::string zone
Definition: bind_util.h:207
SandeshTraceBufferPtr DnsBindTraceBuf
#define DNS_CLASS_ANY
Definition: bind_util.h:32
#define DNS_A_RECORD
Definition: bind_util.h:36
std::map< uint16_t, std::string >::const_iterator DnsResponseIter
Definition: bind_util.h:72
static int BuildDnsUpdate(uint8_t *buf, Operation op, uint16_t xid, const std::string &domain, const std::string &zone, const DnsItems &items)
Definition: bind_util.cc:653
std::map< std::string, uint16_t > DnsTypeMap
Definition: bind_util.h:67
uint16_t name_plen
Definition: bind_util.h:154
bool IsIp4SubnetMember(const Ip4Address &ip, const Ip4Address &prefix_ip, uint16_t plen)
Definition: address_util.cc:19
static int BuildDnsQuery(uint8_t *buf, uint16_t xid, const std::string &domain, const DnsItems &items)
Definition: bind_util.cc:628
#define DNS_PTR_RECORD
Definition: bind_util.h:40
boost::asio::ip::address IpAddress
Definition: address.h:13
uint8_t ra
Definition: bind_util.h:85
uint32_t expiry
Definition: bind_util.h:122
static uint8_t GetNibble(const Ip6Address::bytes_type &addr, size_t bit)
Definition: bind_util.cc:721
std::list< DnsItem > DnsItems
Definition: bind_util.h:193
uint16_t ns_offset
Definition: bind_util.h:116
uint8_t auth
Definition: bind_util.h:78
uint16_t priority
Definition: bind_util.h:152
uint16_t ans_rrcount
Definition: bind_util.h:106
#define DNS_CNAME_RECORD
Definition: bind_util.h:38
std::string name
Definition: bind_util.h:158
uint8_t op
Definition: bind_util.h:79
uint32_t refresh
Definition: bind_util.h:120
uint16_t data_offset
Definition: bind_util.h:157
#define DNS_CLASS_IN
Definition: bind_util.h:31
static uint8_t * AddAnswerSection(uint8_t *ptr, const DnsItem &item, uint16_t &length)
Definition: bind_util.cc:271
void AddName(std::string &name, uint16_t curr_msg_offset, uint16_t &name_plen, uint16_t &name_offset)
Definition: bind_util.cc:1018
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
uint16_t priority
Definition: bind_util.h:138
uint16_t hn_offset
Definition: bind_util.h:143
std::map< uint16_t, std::string >::const_iterator DnsTypeNumIter
Definition: bind_util.h:70
uint16_t offset
Definition: bind_util.h:153
static const std::string & DnsResponseCode(uint16_t code)
Definition: bind_util.cc:139
void GetReverseZones(ZoneList &zones) const
Definition: bind_util.cc:108
static bool ReadQuestionEntry(uint8_t *dns, uint16_t dnslen, int *remlen, DnsItem &item)
Definition: bind_util.cc:422
#define DNS_TYPE_SOA
Definition: bind_util.h:39
static bool ParseDnsResponse(uint8_t *dns, uint16_t dnslen, uint16_t &xid, dns_flags &flags, DnsItems &ques, DnsItems &ans, DnsItems &auth, DnsItems &add)
Definition: bind_util.cc:476
DnsOpcode
Definition: bind_util.h:60
static std::string GetFQDN(const std::string &name, const std::string &domain, const std::string &match)
Definition: bind_util.cc:991
static uint8_t * AddData(uint8_t *ptr, const DnsItem &item, uint16_t &length)
Definition: bind_util.cc:189
static void RemoveSpecialChars(std::string &name)
Definition: bind_util.cc:1009
static uint8_t * AddUpdate(uint8_t *ptr, const DnsItem &item, uint16_t cl, uint32_t ttl, uint16_t &length)
Definition: bind_util.cc:300
static bool regex_match(const std::string &input, const regex &regex)
Definition: regex.h:34
static bool IsReverseZone(const std::string &name)
Definition: bind_util.cc:711
#define DNS_TYPE_ANY
Definition: bind_util.h:45
static bool ParseDnsUpdate(uint8_t *dns, uint16_t dnslen, DnsUpdateData &data)
Definition: bind_util.cc:546
#define DNS_TXT_RECORD
Definition: bind_util.h:42
uint8_t req
Definition: bind_util.h:80
uint8_t type
Definition: load_balance.h:109
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
static bool ParseDnsQuery(uint8_t *dns, uint16_t dnslen, uint16_t *parsed_length, DnsItems &items)
Definition: bind_util.cc:445
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
static uint8_t * AddName(uint8_t *ptr, const std::string &addr, uint16_t plen, uint16_t offset, uint16_t &length)
Definition: bind_util.cc:146
std::string ToString() const
Definition: bind_util.cc:63
uint16_t eclass
Definition: bind_util.h:149
dns_flags flags
Definition: bind_util.h:104
#define DNS_SRV_RECORD
Definition: bind_util.h:44
static bool IsIP(const std::string &name, IpAddress &addr)
Definition: bind_util.cc:715
std::map< uint16_t, std::string > DnsTypeNumMap
Definition: bind_util.h:69
static std::string GetPtrNameFromAddr(const Ip4Address &ip)
Definition: bind_util.cc:959
std::string data
Definition: bind_util.h:160
uint16_t add_rrcount
Definition: bind_util.h:108
bool Contains(const IpAddress &addr) const
Definition: bind_util.cc:98
uint32_t serial
Definition: bind_util.h:119
boost::tokenizer< boost::char_separator< char > > tokenizer
bool operator<(const Subnet &rhs) const
Definition: bind_util.cc:68
uint16_t auth_rrcount
Definition: bind_util.h:107
uint8_t trunc
Definition: bind_util.h:77
static bool ReadAnswerEntry(uint8_t *dns, uint16_t dnslen, int *remlen, DnsItem &item)
Definition: bind_util.cc:434
#define DNS_CLASS_NONE
Definition: bind_util.h:33
uint8_t cd
Definition: bind_util.h:82
static uint16_t DnsClass(const std::string &cl)
Definition: bind_util.cc:112
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
static bool IsReverseZoneV4(const std::string &name)
Definition: bind_util.cc:698
#define DNS_AAAA_RECORD
Definition: bind_util.h:43
uint32_t retry
Definition: bind_util.h:121
static bool GetAddrFromPtrName(std::string &ptr_name, IpAddress &mask)
Definition: bind_util.cc:933
uint16_t mailbox_plen
Definition: bind_util.h:117
uint32_t ttl
Definition: bind_util.h:123
static bool ReadName(uint8_t *dns, uint16_t dnslen, int *remlen, std::string &name, uint16_t &plen, uint16_t &offset)
Definition: bind_util.cc:310
uint16_t weight
Definition: bind_util.h:139
static void BuildDnsHeader(dnshdr *dns, uint16_t xid, DnsReq req, DnsOpcode op, bool rd, bool ra, uint8_t ret, uint16_t ques_count)
Definition: bind_util.cc:608
uint16_t data_plen
Definition: bind_util.h:156
std::string primary_ns
Definition: bind_util.h:113
std::string mailbox
Definition: bind_util.h:114
uint8_t ad
Definition: bind_util.h:83
uint16_t hn_plen
Definition: bind_util.h:142
#define DNS_MX_RECORD
Definition: bind_util.h:41
static bool ReadData(uint8_t *dns, uint16_t dnslen, int *remlen, DnsItem &item)
Definition: bind_util.cc:343
DnsSRVData srv
Definition: bind_util.h:162
std::string hostname
Definition: bind_util.h:141
uint32_t ttl
Definition: bind_util.h:151
static bool HasSpecialChars(const std::string &name)
Definition: bind_util.cc:999
static uint16_t DnsType(const std::string &tp)
Definition: bind_util.cc:125
DnsTypeNumMap g_dns_class_num_map
Definition: bind_util.cc:37
static void GetReverseZoneList(const IpAddress &mask, uint32_t plen, ZoneList &zones)
Definition: bind_util.cc:803
uint16_t xid
Definition: bind_util.h:103
uint16_t mailbox_offset
Definition: bind_util.h:118
uint8_t ret
Definition: bind_util.h:81
uint8_t rd
Definition: bind_util.h:76
static void GetReverseZone(const Ip4Address &addr, uint32_t plen, std::string &zone)
Definition: bind_util.cc:812
DnsItems items
Definition: bind_util.h:208
uint16_t ques_rrcount
Definition: bind_util.h:105
uint32_t plen
Definition: bind_util.h:254
uint16_t port
Definition: bind_util.h:140
uint16_t name_offset
Definition: bind_util.h:155
uint16_t ns_plen
Definition: bind_util.h:115
bool IsIp6SubnetMember(const Ip6Address &ip, const Ip6Address &subnet, uint8_t plen)
Definition: address_util.cc:29
static std::string BuildIp6ArpaSuffix(const Ip6Address::bytes_type &addr, uint32_t plen)
Definition: bind_util.cc:731
DnsResponseMap g_dns_response_map
Definition: bind_util.cc:42
DnsTypeMap g_dns_type_map
Definition: bind_util.cc:13
IpAddress prefix
Definition: bind_util.h:253
static bool IsReverseZoneV6(const std::string &name)
Definition: bind_util.cc:705
std::vector< std::string > ZoneList
Definition: bind_util.h:250
bool IsPresent(std::string &name, uint16_t &name_offset)
Definition: bind_util.cc:1039
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
#define DNS_NS_RECORD
Definition: bind_util.h:37
uint16_t type
Definition: bind_util.h:150
DnsTypeNumMap g_dns_type_num_map
Definition: bind_util.cc:25