Переглянути джерело

Added DnsPacket and associated tests

develop
Robin Thoni 6 роки тому
джерело
коміт
09f0007241

+ 2
- 0
src/modules/dns/CMakeLists.txt Переглянути файл

@@ -12,6 +12,8 @@ add_library(qdnsagg-dns
12 12
         includes/dns/QDnsQuery.h
13 13
         src/QDnsResourceRecord.cpp
14 14
         includes/dns/QDnsResourceRecord.h
15
+        src/QDnsPacket.cpp
16
+        includes/dns/QDnsPacket.h
15 17
         )
16 18
 
17 19
 target_link_libraries(qdnsagg-dns Qt5::Core Qt5::Network)

+ 61
- 0
src/modules/dns/includes/dns/QDnsPacket.h Переглянути файл

@@ -0,0 +1,61 @@
1
+//
2
+// Created by robin on 1/8/18.
3
+//
4
+
5
+#ifndef QDNSAGG_QDNSPACKET_H
6
+#define QDNSAGG_QDNSPACKET_H
7
+
8
+#include <QByteArray>
9
+#include "QDnsHeader.h"
10
+#include "QDnsQuery.h"
11
+#include "QDnsResourceRecord.h"
12
+
13
+namespace QDns
14
+{
15
+
16
+    class QDnsPacket
17
+    {
18
+    public:
19
+        QDnsPacket();
20
+
21
+        static QDnsPacket parse(const QByteArray& data);
22
+        static QDnsPacket parse(const QByteArray& data, QDataStream& dataStream);
23
+        QByteArray serialize() const;
24
+        void serialize(QDataStream& dataStream) const;
25
+
26
+        bool isValid() const;
27
+
28
+        const QDnsHeader& getHeader() const;
29
+
30
+        void setHeader(const QDnsHeader& header);
31
+
32
+        const QList<QDnsQuery>& getQueries() const;
33
+
34
+        void setQueries(const QList<QDnsQuery>& queries);
35
+
36
+        const QList<QDnsResourceRecord>& getAnswerRecords() const;
37
+
38
+        void setAnswerRecords(const QList<QDnsResourceRecord>& answerRecords);
39
+
40
+        const QList<QDnsResourceRecord>& getAuthorityRecords() const;
41
+
42
+        void setAuthorityRecords(const QList<QDnsResourceRecord>& authorityRecords);
43
+
44
+        const QList<QDnsResourceRecord>& getAdditionalRecords() const;
45
+
46
+        void setAdditionalRecords(const QList<QDnsResourceRecord>& additionalRecords);
47
+
48
+    private:
49
+        bool m_isValid;
50
+
51
+        QDnsHeader m_header;
52
+
53
+        QList<QDnsQuery> m_queries;
54
+        QList<QDnsResourceRecord> m_answerRecords;
55
+        QList<QDnsResourceRecord> m_authorityRecords;
56
+        QList<QDnsResourceRecord> m_additionalRecords;
57
+    };
58
+
59
+}
60
+
61
+#endif //QDNSAGG_QDNSPACKET_H

+ 165
- 0
src/modules/dns/src/QDnsPacket.cpp Переглянути файл

@@ -0,0 +1,165 @@
1
+//
2
+// Created by robin on 1/8/18.
3
+//
4
+
5
+#include <QDataStream>
6
+#include "dns/QDnsPacket.h"
7
+
8
+namespace QDns
9
+{
10
+
11
+    QDnsPacket::QDnsPacket()
12
+        : m_isValid(true)
13
+    {
14
+    }
15
+
16
+    QDnsPacket QDnsPacket::parse(const QByteArray& data)
17
+    {
18
+        QDataStream dataStream(data);
19
+        return parse(data, dataStream);
20
+    }
21
+
22
+    QDnsPacket QDnsPacket::parse(const QByteArray& data, QDataStream& dataStream)
23
+    {
24
+        QDnsPacket packet;
25
+
26
+        packet.m_header = QDnsHeader::parse(dataStream);
27
+        if (!packet.m_header.isValid())
28
+        {
29
+            packet.m_isValid = false;
30
+        }
31
+        else
32
+        {
33
+            for (quint16 i = 0; i < packet.m_header.getQueryCount() && packet.m_isValid; ++i)
34
+            {
35
+                auto entry = QDnsQuery::parse(data, dataStream);
36
+                if (!entry.isValid())
37
+                {
38
+                    packet.m_isValid = false;
39
+                }
40
+                packet.m_queries.append(entry);
41
+            }
42
+            for (quint16 i = 0; i < packet.m_header.getAnswerCount() && packet.m_isValid; ++i)
43
+            {
44
+                auto entry = QDnsResourceRecord::parse(data, dataStream);
45
+                if (!entry.isValid())
46
+                {
47
+                    packet.m_isValid = false;
48
+                }
49
+                packet.m_answerRecords.append(entry);
50
+            }
51
+            for (quint16 i = 0; i < packet.m_header.getAuthorityCount() && packet.m_isValid; ++i)
52
+            {
53
+                auto entry = QDnsResourceRecord::parse(data, dataStream);
54
+                if (!entry.isValid())
55
+                {
56
+                    packet.m_isValid = false;
57
+                }
58
+                packet.m_authorityRecords.append(entry);
59
+            }
60
+            for (quint16 i = 0; i < packet.m_header.getAdditionalCount() && packet.m_isValid; ++i)
61
+            {
62
+                auto entry = QDnsResourceRecord::parse(data, dataStream);
63
+                if (!entry.isValid())
64
+                {
65
+                    packet.m_isValid = false;
66
+                }
67
+                packet.m_additionalRecords.append(entry);
68
+            }
69
+        }
70
+
71
+        return packet;
72
+    }
73
+
74
+    QByteArray QDnsPacket::serialize() const
75
+    {
76
+        QByteArray byteArray;
77
+        QDataStream dataStream(&byteArray, QIODevice::WriteOnly);
78
+        serialize(dataStream);
79
+        return byteArray;
80
+    }
81
+
82
+    void QDnsPacket::serialize(QDataStream& dataStream) const
83
+    {
84
+        m_header.serialize(dataStream);
85
+        for (const auto& entry : m_queries)
86
+        {
87
+            entry.serialize(dataStream);
88
+        }
89
+        for (const auto& entry : m_answerRecords)
90
+        {
91
+            entry.serialize(dataStream);
92
+        }
93
+        for (const auto& entry : m_authorityRecords)
94
+        {
95
+            entry.serialize(dataStream);
96
+        }
97
+        for (const auto& entry : m_additionalRecords)
98
+        {
99
+            entry.serialize(dataStream);
100
+        }
101
+    }
102
+
103
+    bool QDnsPacket::isValid() const
104
+    {
105
+        return m_isValid;
106
+    }
107
+
108
+    const QDnsHeader& QDnsPacket::getHeader() const
109
+    {
110
+        return m_header;
111
+    }
112
+
113
+    void QDnsPacket::setHeader(const QDnsHeader& header)
114
+    {
115
+        m_header = header;
116
+        m_header.setQueryCount((quint16) m_queries.length());
117
+        m_header.setAnswerCount((quint16) m_answerRecords.length());
118
+        m_header.setAuthorityCount((quint16) m_authorityRecords.length());
119
+        m_header.setAdditionalCount((quint16) m_additionalRecords.length());
120
+    }
121
+
122
+    const QList<QDnsQuery>& QDnsPacket::getQueries() const
123
+    {
124
+        return m_queries;
125
+    }
126
+
127
+    void QDnsPacket::setQueries(const QList<QDnsQuery>& queries)
128
+    {
129
+        m_queries = queries;
130
+        m_header.setQueryCount((quint16) m_queries.length());
131
+    }
132
+
133
+    const QList<QDnsResourceRecord>& QDnsPacket::getAnswerRecords() const
134
+    {
135
+        return m_answerRecords;
136
+    }
137
+
138
+    void QDnsPacket::setAnswerRecords(const QList<QDnsResourceRecord>& answerRecords)
139
+    {
140
+        m_answerRecords = answerRecords;
141
+        m_header.setAnswerCount((quint16) m_answerRecords.length());
142
+    }
143
+
144
+    const QList<QDnsResourceRecord>& QDnsPacket::getAuthorityRecords() const
145
+    {
146
+        return m_authorityRecords;
147
+    }
148
+
149
+    void QDnsPacket::setAuthorityRecords(const QList<QDnsResourceRecord>& authorityRecords)
150
+    {
151
+        m_authorityRecords = authorityRecords;
152
+        m_header.setAuthorityCount((quint16) m_authorityRecords.length());
153
+    }
154
+
155
+    const QList<QDnsResourceRecord>& QDnsPacket::getAdditionalRecords() const
156
+    {
157
+        return m_additionalRecords;
158
+    }
159
+
160
+    void QDnsPacket::setAdditionalRecords(const QList<QDnsResourceRecord>& additionalRecords)
161
+    {
162
+        m_additionalRecords = additionalRecords;
163
+        m_header.setAdditionalCount((quint16) m_additionalRecords.length());
164
+    }
165
+}

+ 2
- 1
tests/CMakeLists.txt Переглянути файл

@@ -10,7 +10,8 @@ add_executable(qdnsagg-tests
10 10
         DnsHeader.cpp
11 11
         DnsLabel.cpp
12 12
         DnsQuery.cpp
13
-        DnsResourceRecord.cpp)
13
+        DnsResourceRecord.cpp
14
+        DnsPacket.cpp)
14 15
 
15 16
 target_link_libraries(qdnsagg-tests gtest pthread qdnsagg-dns)
16 17
 add_test(qdnsagg-tests ${CMAKE_CURRENT_BINARY_DIR}/qdnsagg-tests)

+ 80
- 0
tests/DnsPacket.cpp Переглянути файл

@@ -0,0 +1,80 @@
1
+//
2
+// Created by robin on 1/10/18.
3
+//
4
+
5
+#include <gtest/gtest.h>
6
+#include <QByteArray>
7
+#include <QString>
8
+
9
+#include "dns/QDnsPacket.h"
10
+
11
+struct DnsPacketParseTestParams
12
+{
13
+    bool isValid;
14
+    const char* hexData;
15
+};
16
+
17
+class DnsPacketParseTest : public ::testing::TestWithParam<DnsPacketParseTestParams>
18
+{
19
+};
20
+
21
+TEST_P(DnsPacketParseTest, parse)
22
+{
23
+    auto params = GetParam();
24
+    auto data = QByteArray::fromHex(params.hexData);
25
+    auto packet = QDns::QDnsPacket::parse(data);
26
+
27
+    ASSERT_EQ(packet.isValid(), params.isValid);
28
+
29
+    if (packet.isValid())
30
+    {
31
+        // TODO improve tests
32
+    }
33
+}
34
+
35
+INSTANTIATE_TEST_CASE_P(DnsPacketParseTestInst,
36
+                        DnsPacketParseTest,
37
+                        ::testing::Values(
38
+                                DnsPacketParseTestParams {false, ""},
39
+                                DnsPacketParseTestParams {true, "1c588580000100020000000003777777067274686f6e6903636f6d0000010001c00c00050001000002580008057365727633c010c02c00010001000002580004d5f6343d"},
40
+                                DnsPacketParseTestParams {true, "1c580100000100000000000003777777067274686f6e6903636f6d0000010001"},
41
+                                DnsPacketParseTestParams {true, "42c3818000010001000000000377777706676f6f676c650266720000010001c00c000100010000012c0004d83ad3a3"},
42
+                                DnsPacketParseTestParams {true, "42c3010000010000000000000377777706676f6f676c650266720000010001"},
43
+                                DnsPacketParseTestParams {true, "07298180000100010000000006676f6f676c650266720000010001c00c000100010000012c0004acd913e3"},
44
+                                DnsPacketParseTestParams {true, "07290100000100000000000006676f6f676c650266720000010001"},
45
+                                DnsPacketParseTestParams {true, "e1bc818000010000000100000266720000010001c00c0006000100000e100030086e736d6173746572036e6963c00c0a686f73746d6173746572c029849e46cf00000e10000007080036ee8000001518"},
46
+                                DnsPacketParseTestParams {true, "e1bc010000010000000000000266720000010001"}
47
+                        ));
48
+
49
+struct DnsPacketSerializeTestParams
50
+{
51
+    const char* hexData1;
52
+    const char* hexData2;
53
+};
54
+
55
+class DnsPacketSerializeTest : public ::testing::TestWithParam<DnsPacketSerializeTestParams>
56
+{
57
+};
58
+
59
+TEST_P(DnsPacketSerializeTest, parse)
60
+{
61
+    auto params = GetParam();
62
+    auto data1 = QByteArray::fromHex(params.hexData1);
63
+    auto packet = QDns::QDnsPacket::parse(data1);
64
+
65
+    // TODO improve tests
66
+    ASSERT_EQ(packet.serialize().toHex(), QString(params.hexData2).remove(" "));
67
+}
68
+
69
+INSTANTIATE_TEST_CASE_P(DnsPacketSerializeTestInst,
70
+                        DnsPacketSerializeTest,
71
+                        ::testing::Values(
72
+                                DnsPacketSerializeTestParams {
73
+                                        "07290100000100000000000006676f6f676c650266720000010001",
74
+                                        "07290100000100000000000006676f6f676c650266720000010001"
75
+                                },
76
+                                DnsPacketSerializeTestParams {
77
+                                        "1c588580000100020000000003777777067274686f6e6903636f6d0000010001c00c00050001000002580008057365727633c010c02c00010001000002580004d5f6343d",
78
+                                        "1c588580000100020000000003777777067274686f6e6903636f6d000001000103777777067274686f6e6903636f6d0000050001000002580008057365727633c010057365727633067274686f6e6903636f6d0000010001000002580004d5f6343d"
79
+                                }
80
+                        ));

Завантаження…
Відмінити
Зберегти