|
@@ -0,0 +1,284 @@
|
|
|
|
|
+#include "Packet.h"
|
|
|
|
|
+#include "MalformedPacket.h"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+namespace Network {
|
|
|
|
|
+namespace Dns {
|
|
|
|
|
+
|
|
|
|
|
+Packet::Packet() :
|
|
|
|
|
+ m_identifier(0),
|
|
|
|
|
+ m_query(0),
|
|
|
|
|
+ m_authorativeAnswer(0),
|
|
|
|
|
+ m_truncation(0),
|
|
|
|
|
+ m_recursionDesired(0),
|
|
|
|
|
+ m_recursionAvailable(0),
|
|
|
|
|
+ m_zero(0),
|
|
|
|
|
+ m_operationCode(OperationCode::QUERY),
|
|
|
|
|
+ m_responseCode(ResponseCode::NO_ERROR)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Packet::Packet(DataReader reader, unsigned pos)
|
|
|
|
|
+{
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ m_identifier = reader.Read16(pos);
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t flags = reader.Read8(pos);
|
|
|
|
|
+ m_query = (flags & (1 << 7)) >> 7; // 10000000
|
|
|
|
|
+ m_operationCode = static_cast<OperationCode::type>(((flags & (((1 << 4) - 1) << 3)) >> 3)); // 01111000
|
|
|
|
|
+ m_authorativeAnswer = (flags & (1 << 2)) >> 2; // 00000100
|
|
|
|
|
+ m_truncation = (flags & (1 << 1)) >> 1; // 00000010
|
|
|
|
|
+ m_recursionDesired = (flags & (1 << 0)) >> 0; // 00000001
|
|
|
|
|
+
|
|
|
|
|
+ flags = reader.Read8(pos);
|
|
|
|
|
+ m_recursionAvailable = (flags & (1 << 7)) >> 7; // 10000000
|
|
|
|
|
+ m_zero = (flags & (((1 << 3) - 1) << 4)) >> 4; // 01110000
|
|
|
|
|
+ m_responseCode = static_cast<ResponseCode::type>((flags & ((1 << 4) - 1))); // 00001111
|
|
|
|
|
+
|
|
|
|
|
+ unsigned queryCount = reader.Read16(pos);
|
|
|
|
|
+ unsigned answerCount = reader.Read16(pos);
|
|
|
|
|
+ unsigned authorityCount = reader.Read16(pos);
|
|
|
|
|
+ unsigned additionalRecordsCount = reader.Read16(pos);
|
|
|
|
|
+
|
|
|
|
|
+ for (size_t i = 0; i < queryCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_queries.emplace_back();
|
|
|
|
|
+ pos = m_queries.back().ReadFromData(reader, pos);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (size_t i = 0; i < answerCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_answers.emplace_back();
|
|
|
|
|
+ pos = m_answers.back().ReadFromData(reader, pos);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (size_t i = 0; i < authorityCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_authorities.emplace_back();
|
|
|
|
|
+ pos = m_authorities.back().ReadFromData(reader, pos);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (size_t i = 0; i < additionalRecordsCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_additionalRecords.emplace_back();
|
|
|
|
|
+ pos = m_additionalRecords.back().ReadFromData(reader, pos);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (const DataReaderOutOfBounds& droob)
|
|
|
|
|
+ {
|
|
|
|
|
+ throw MalformedPacket();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Data Packet::GetData() const
|
|
|
|
|
+{
|
|
|
|
|
+ Data data;
|
|
|
|
|
+ data.append(static_cast<uint16_t>(m_identifier));
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t flags =
|
|
|
|
|
+ (static_cast<uint8_t>(m_query) << 7) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_operationCode) << 3) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_authorativeAnswer) << 2) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_truncation) << 1) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_recursionDesired) << 0);
|
|
|
|
|
+ data.append(flags);
|
|
|
|
|
+
|
|
|
|
|
+ flags =
|
|
|
|
|
+ (static_cast<uint8_t>(m_recursionAvailable) << 7) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_zero) << 4) |
|
|
|
|
|
+ (static_cast<uint8_t>(m_responseCode) << 0);
|
|
|
|
|
+ data.append(flags);
|
|
|
|
|
+
|
|
|
|
|
+ data.append(static_cast<uint16_t>(GetQueryCount()));
|
|
|
|
|
+ data.append(static_cast<uint16_t>(GetAnswerCount()));
|
|
|
|
|
+ data.append(static_cast<uint16_t>(GetAuthorityCount()));
|
|
|
|
|
+ data.append(static_cast<uint16_t>(GetAdditionalRecordsCount()));
|
|
|
|
|
+
|
|
|
|
|
+ for (const QueryImpl& q : m_queries)
|
|
|
|
|
+ data.append(q.GetData());
|
|
|
|
|
+ for (const ResourceRecordImpl& r : m_answers)
|
|
|
|
|
+ data.append(r.GetData());
|
|
|
|
|
+ for (const ResourceRecordImpl& r : m_authorities)
|
|
|
|
|
+ data.append(r.GetData());
|
|
|
|
|
+ for (const ResourceRecordImpl& r : m_additionalRecords)
|
|
|
|
|
+ data.append(r.GetData());
|
|
|
|
|
+ return data;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+uint16_t Packet::GetIdentifier() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_identifier;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool Packet::GetQuery() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_query;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+OperationCode::type Packet::GetOperationCode() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_operationCode;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool Packet::GetAuthorativeAnswer() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_authorativeAnswer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool Packet::GetTruncation() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_truncation;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool Packet::GetRecursionDesired() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_recursionDesired;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool Packet::GetRecursionAvailable() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_recursionAvailable;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+uint8_t Packet::GetZero() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_zero;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ResponseCode::type Packet::GetResponseCode() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_responseCode;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::vector<QueryImpl> Packet::GetQueries() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_queries;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::vector<ResourceRecordImpl> Packet::GetAnswers() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_answers;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::vector<ResourceRecordImpl> Packet::GetAuthorities() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_authorities;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::vector<ResourceRecordImpl> Packet::GetAdditionalRecords() const
|
|
|
|
|
+{
|
|
|
|
|
+ return m_additionalRecords;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+unsigned Packet::GetQueryCount() const
|
|
|
|
|
+{
|
|
|
|
|
+ return static_cast<unsigned>(m_queries.size());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+unsigned Packet::GetAnswerCount() const
|
|
|
|
|
+{
|
|
|
|
|
+ return static_cast<unsigned>(m_answers.size());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+unsigned Packet::GetAuthorityCount() const
|
|
|
|
|
+{
|
|
|
|
|
+ return static_cast<unsigned>(m_authorities.size());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+unsigned Packet::GetAdditionalRecordsCount() const
|
|
|
|
|
+{
|
|
|
|
|
+ return static_cast<unsigned>(m_additionalRecords.size());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetIdentifier(uint16_t identifier)
|
|
|
|
|
+{
|
|
|
|
|
+ m_identifier = identifier;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetQuery(bool query)
|
|
|
|
|
+{
|
|
|
|
|
+ m_query = query;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetOperationCode(OperationCode::type operationCode)
|
|
|
|
|
+{
|
|
|
|
|
+ m_operationCode = operationCode;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetAuthorativeAnswer(bool authorativeAnswer)
|
|
|
|
|
+{
|
|
|
|
|
+ m_authorativeAnswer = authorativeAnswer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetTruncation(bool truncation)
|
|
|
|
|
+{
|
|
|
|
|
+ m_truncation = truncation;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetRecursionDesired(bool recursionDesired)
|
|
|
|
|
+{
|
|
|
|
|
+ m_recursionDesired = recursionDesired;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetRecursionAvailable(bool recursionAvailable)
|
|
|
|
|
+{
|
|
|
|
|
+ m_recursionAvailable = recursionAvailable;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetZero(uint8_t zero)
|
|
|
|
|
+{
|
|
|
|
|
+ m_zero = zero;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::SetResponseCode(ResponseCode::type responseCode)
|
|
|
|
|
+{
|
|
|
|
|
+ m_responseCode = responseCode;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::AddQuery(const QueryImpl& query)
|
|
|
|
|
+{
|
|
|
|
|
+ m_queries.emplace_back(query);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::AddAnswer(const ResourceRecordImpl& record)
|
|
|
|
|
+{
|
|
|
|
|
+ m_answers.emplace_back(record);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::AddAuthority(const ResourceRecordImpl& record)
|
|
|
|
|
+{
|
|
|
|
|
+ m_authorities.emplace_back(record);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Packet::AddAdditionalRecords(const ResourceRecordImpl& record)
|
|
|
|
|
+{
|
|
|
|
|
+ m_additionalRecords.emplace_back(record);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::ostream& operator<<(std::ostream& stream, const Packet& packet)
|
|
|
|
|
+{
|
|
|
|
|
+ stream << "Packet (\n";
|
|
|
|
|
+ stream << " identifier = " << packet.m_identifier
|
|
|
|
|
+ << ", query = " << packet.m_query
|
|
|
|
|
+ << ", operationCode = " << static_cast<int>(packet.m_operationCode)
|
|
|
|
|
+ << ", authorativeAnswer = " << packet.m_authorativeAnswer
|
|
|
|
|
+ << ", truncation = " << packet.m_truncation
|
|
|
|
|
+ << ", recursionDesired = " << packet.m_recursionDesired << "\n";
|
|
|
|
|
+ stream << " recursionAvailable = " << packet.m_recursionAvailable
|
|
|
|
|
+ << ", zero = " << packet.m_zero
|
|
|
|
|
+ << ", responseCode = " << static_cast<int>(packet.m_responseCode) << "\n";
|
|
|
|
|
+ for (const QueryImpl& q : packet.m_queries)
|
|
|
|
|
+ stream << " Query: " << q << "\n";
|
|
|
|
|
+ for (const ResourceRecordImpl& r : packet.m_answers)
|
|
|
|
|
+ stream << " Answer: " << r << "\n";
|
|
|
|
|
+ for (const ResourceRecordImpl& r : packet.m_authorities)
|
|
|
|
|
+ stream << " Authority: " << r << "\n";
|
|
|
|
|
+ for (const ResourceRecordImpl& r : packet.m_additionalRecords)
|
|
|
|
|
+ stream << " AdditionalRecord: " << r << "\n";
|
|
|
|
|
+ stream << ")\n";
|
|
|
|
|
+ return stream;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+} // namespace Dns
|
|
|
|
|
+} // namespace Network
|