177 const char* end = data + maxSize;
180 uint16_t
id = htons (packet.id);
181 ok &=
writeBytes (cur, end, &
id,
sizeof (
id));
183 uint16_t flags = htons (packet.flags);
184 ok &=
writeBytes (cur, end, &flags,
sizeof (flags));
186 uint16_t qcount = htons (
static_cast<uint16_t
> (packet.questions.size ()));
187 ok &=
writeBytes (cur, end, &qcount,
sizeof (qcount));
189 uint16_t ancount = htons (
static_cast<uint16_t
> (packet.answers.size ()));
190 ok &=
writeBytes (cur, end, &ancount,
sizeof (ancount));
192 uint16_t nscount = htons (
static_cast<uint16_t
> (packet.authorities.size ()));
193 ok &=
writeBytes (cur, end, &nscount,
sizeof (nscount));
195 uint16_t arcount = htons (
static_cast<uint16_t
> (packet.additionals.size ()));
196 ok &=
writeBytes (cur, end, &arcount,
sizeof (arcount));
198 for (
auto const& question : packet.questions)
200 ok &= encodeQuestion (question, cur, end);
203 for (
auto const& answer : packet.answers)
205 ok &= encodeResource (answer, cur, end);
208 for (
auto const& authority : packet.authorities)
210 ok &= encodeResource (authority, cur, end);
213 for (
auto const& additional : packet.additionals)
215 ok &= encodeResource (additional, cur, end);
218 return ok ? cur - data : -1;
230 const char* cur = data;
231 const char* end = data + size;
234 uint16_t qcount = 0, ancount = 0, nscount = 0, arcount = 0;
238 ok &=
readBytes (cur, end, &qcount,
sizeof (qcount));
239 ok &=
readBytes (cur, end, &ancount,
sizeof (ancount));
240 ok &=
readBytes (cur, end, &nscount,
sizeof (nscount));
241 ok &=
readBytes (cur, end, &arcount,
sizeof (arcount));
248 packet.
id = ntohs (packet.
id);
250 qcount = ntohs (qcount);
251 ancount = ntohs (ancount);
252 nscount = ntohs (nscount);
253 arcount = ntohs (arcount);
256 for (uint16_t i = 0; i < qcount; ++i)
259 if (decodeQuestion (question, cur, data, end) == -1)
263 packet.
questions.emplace_back (std::move (question));
267 for (uint16_t i = 0; i < ancount; ++i)
270 if (decodeResource (answer, cur, data, end) == -1)
274 packet.
answers.emplace_back (std::move (answer));
278 for (uint16_t i = 0; i < nscount; ++i)
281 if (decodeResource (authority, cur, data, end) == -1)
285 packet.
authorities.emplace_back (std::move (authority));
289 for (uint16_t i = 0; i < arcount; ++i)
292 if (decodeResource (additional, cur, data, end) == -1)
296 packet.
additionals.emplace_back (std::move (additional));
358 switch (recordClass & 0x7FFF)
374 bool encodeName (
const std::string& name,
char*& cur,
const char* end)
const
378 for (
size_t pos = 0; pos < name.size ();)
380 size_t dot = name.find (
'.', pos);
381 if (dot == std::string::npos)
386 uint8_t len =
static_cast<uint8_t
> (dot - pos);
387 ok &=
writeBytes (cur, end, &len,
sizeof (len));
388 ok &=
writeBytes (cur, end, name.data () + pos, len);
394 ok &=
writeBytes (cur, end, &root,
sizeof (root));
408 int decodeName (std::string& name,
const char*& cur,
const char* begin,
const char* end,
int depth = 0)
const
418 if (!
readBytes (cur, end, &first,
sizeof (first)))
423 if ((first & 0xC0) == 0xC0)
426 if (!
readBytes (cur, end, &second,
sizeof (second)))
431 const size_t offset = ((first & 0x3F) << 8) | second;
432 if (offset >=
static_cast<size_t> (end - begin))
438 const char* target = begin + offset;
439 if (decodeName (name, target, begin, end, depth + 1) == -1)
448 if (!name.empty () && name.back () ==
'.')
455 name.reserve (name.size () + first + 1);
456 name.resize (name.size () + first);
457 if (!
readBytes (cur, end, &name[name.size () - first], first))
474 bool encodeMail (
const std::string& mail,
char*& cur,
const char* end)
const
476 std::string encodedMail = mail;
477 size_t atPos = encodedMail.find (
'@');
479 if (atPos != std::string::npos)
481 encodedMail.replace (atPos, 1,
".");
484 return encodeName (encodedMail, cur, end);
495 int decodeMail (std::string& mail,
const char*& cur,
const char* begin,
const char* end)
const
497 if (decodeName (mail, cur, begin, end) == -1)
502 auto pos = mail.find (
'.');
503 if (pos != std::string::npos)
518 bool encodeQuestion (
const QuestionRecord& question,
char*& cur,
const char* end)
const
520 bool ok = encodeName (question.host, cur, end);
522 uint16_t type = htons (question.type);
523 ok &=
writeBytes (cur, end, &type,
sizeof (type));
525 uint16_t dnsclass = htons (question.dnsclass);
526 ok &=
writeBytes (cur, end, &dnsclass,
sizeof (dnsclass));
539 int decodeQuestion (QuestionRecord& question,
const char*& cur,
const char* begin,
const char* end)
const
541 if (decodeName (question.host, cur, begin, end) == -1)
547 ok &=
readBytes (cur, end, &question.type, sizeof (question.type));
548 ok &=
readBytes (cur, end, &question.dnsclass, sizeof (question.dnsclass));
555 question.type = ntohs (question.type);
556 question.dnsclass = ntohs (question.dnsclass);
568 bool encodeResource (
const ResourceRecord& resource,
char*& cur,
const char* end)
const
570 bool ok = encodeName (resource.host, cur, end);
572 uint16_t type = htons (resource.type);
573 ok &=
writeBytes (cur, end, &type,
sizeof (type));
575 uint16_t dnsclass = htons (resource.dnsclass);
576 ok &=
writeBytes (cur, end, &dnsclass,
sizeof (dnsclass));
578 uint32_t ttl = htonl (resource.ttl);
579 ok &=
writeBytes (cur, end, &ttl,
sizeof (ttl));
581 uint16_t dataLen = 0;
583 ok &=
writeBytes (cur, end, &dataLen,
sizeof (dataLen));
589 ok &=
writeBytes (cur, end, resource.addr.addr (), sizeof (in_addr));
593 ok &=
writeBytes (cur, end, resource.addr.addr (), sizeof (in6_addr));
597 ok &= encodeName (resource.name, cur, end);
601 ok &= encodeName (resource.name, cur, end);
605 ok &= encodeName (resource.name, cur, end);
609 uint16_t mxpref = htons (resource.mxpref);
610 ok &=
writeBytes (cur, end, &mxpref,
sizeof (mxpref));
611 ok &= encodeName (resource.name, cur, end);
615 ok &= encodeName (resource.name, cur, end);
616 ok &= encodeMail (resource.mail, cur, end);
618 uint32_t serial = htonl (resource.serial);
619 ok &=
writeBytes (cur, end, &serial,
sizeof (serial));
621 uint32_t refresh = htonl (resource.refresh);
622 ok &=
writeBytes (cur, end, &refresh,
sizeof (refresh));
624 uint32_t retry = htonl (resource.retry);
625 ok &=
writeBytes (cur, end, &retry,
sizeof (retry));
627 uint32_t expire = htonl (resource.expire);
628 ok &=
writeBytes (cur, end, &expire,
sizeof (expire));
630 uint32_t minimum = htonl (resource.minimum);
631 ok &=
writeBytes (cur, end, &minimum,
sizeof (minimum));
635 for (
auto const& txt : resource.txts)
637 uint8_t size =
static_cast<uint8_t
> (txt.size ());
638 ok &=
writeBytes (cur, end, &size,
sizeof (size));
639 ok &=
writeBytes (cur, end, txt.data (), size);
644 uint16_t priority = htons (resource.priority);
645 ok &=
writeBytes (cur, end, &priority,
sizeof (priority));
647 uint16_t weight = htons (resource.weight);
648 ok &=
writeBytes (cur, end, &weight,
sizeof (weight));
650 uint16_t
port = htons (resource.port);
651 ok &=
writeBytes (cur, end, &port,
sizeof (port));
653 ok &= encodeName (resource.name, cur, end);
658 dataLen = htons (
static_cast<uint16_t
> (cur - rdata));
659 ::memcpy (length, &dataLen,
sizeof (dataLen));
673 int decodeResource (ResourceRecord& resource,
const char*& cur,
const char* begin,
const char* end)
const
675 if (decodeName (resource.host, cur, begin, end) == -1)
680 uint16_t dataLen = 0;
683 ok &=
readBytes (cur, end, &resource.type, sizeof (resource.type));
684 ok &=
readBytes (cur, end, &resource.dnsclass, sizeof (resource.dnsclass));
685 ok &=
readBytes (cur, end, &resource.ttl, sizeof (resource.ttl));
686 ok &=
readBytes (cur, end, &dataLen,
sizeof (dataLen));
693 resource.type = ntohs (resource.type);
694 resource.dnsclass = ntohs (resource.dnsclass);
695 resource.ttl = ntohl (resource.ttl);
696 dataLen = ntohs (dataLen);
698 if (dataLen >
static_cast<size_t> (end - cur))
704 const char* rdataEnd = cur + dataLen;
709 if (!
readBytes (cur, end, &addr,
sizeof (addr)))
713 resource.addr = IpAddress (&addr,
sizeof (
struct in_addr));
717 struct in6_addr addr;
718 if (!
readBytes (cur, end, &addr,
sizeof (addr)))
722 resource.addr = IpAddress (&addr,
sizeof (
struct in6_addr));
726 if (decodeName (resource.name, cur, begin, end) == -1)
733 if (decodeName (resource.name, cur, begin, end) == -1)
740 if (decodeName (resource.name, cur, begin, end) == -1)
747 if (!
readBytes (cur, end, &resource.mxpref, sizeof (resource.mxpref)) ||
748 (decodeName (resource.name, cur, begin, end) == -1))
753 resource.mxpref = ntohs (resource.mxpref);
757 if ((decodeName (resource.name, cur, begin, end) == -1) ||
758 (decodeMail (resource.mail, cur, begin, end) == -1))
763 ok &=
readBytes (cur, end, &resource.serial, sizeof (resource.serial));
764 ok &=
readBytes (cur, end, &resource.refresh, sizeof (resource.refresh));
765 ok &=
readBytes (cur, end, &resource.retry, sizeof (resource.retry));
766 ok &=
readBytes (cur, end, &resource.expire, sizeof (resource.expire));
767 ok &=
readBytes (cur, end, &resource.minimum, sizeof (resource.minimum));
774 resource.serial = ntohl (resource.serial);
775 resource.refresh = ntohl (resource.refresh);
776 resource.retry = ntohl (resource.retry);
777 resource.expire = ntohl (resource.expire);
778 resource.minimum = ntohl (resource.minimum);
782 while (cur < rdataEnd)
785 if (!
readBytes (cur, end, &size,
sizeof (size)))
792 if (!
readBytes (cur, end, &txt[0], size))
797 resource.txts.emplace_back (std::move (txt));
802 ok &=
readBytes (cur, end, &resource.priority, sizeof (resource.priority));
803 ok &=
readBytes (cur, end, &resource.weight, sizeof (resource.weight));
804 ok &=
readBytes (cur, end, &resource.port, sizeof (resource.port));
806 if (!ok || (decodeName (resource.name, cur, begin, end) == -1))
811 resource.priority = ntohs (resource.priority);
812 resource.weight = ntohs (resource.weight);
813 resource.port = ntohs (resource.port);