• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 13012068652

28 Jan 2025 01:59PM UTC coverage: 64.71% (+0.01%) from 64.699%
13012068652

Pull #14724

github

web-flow
Merge b15562560 into db18c3a17
Pull Request #14724: dnsdist: Add meson support

38328 of 90334 branches covered (42.43%)

Branch coverage included in aggregate %.

361 of 513 new or added lines in 35 files covered. (70.37%)

42 existing lines in 13 files now uncovered.

128150 of 166934 relevant lines covered (76.77%)

4540890.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.47
/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#ifndef BOOST_TEST_DYN_LINK
23
#define BOOST_TEST_DYN_LINK
24
#endif
25

26
#define BOOST_TEST_NO_MAIN
27

28
#include <boost/test/unit_test.hpp>
29

30
#include "dnsdist-lua-ffi.hh"
31
#include "dnsdist-cache.hh"
32
#include "dnsdist-configuration.hh"
33
#include "dnsdist-rings.hh"
34
#include "dnsdist-web.hh"
35
#include "dnsparser.hh"
36
#include "dnswriter.hh"
37

38
bool dnsdist::webserver::addMetricDefinition(const dnsdist::prometheus::PrometheusMetricDefinition& def)
39
{
×
NEW
40
  (void)def;
×
41
  return true;
×
42
}
×
43

44
BOOST_AUTO_TEST_SUITE(test_dnsdist_lua_ffi)
45

46
BOOST_AUTO_TEST_CASE(test_Query)
47
{
2✔
48
  InternalQueryState ids;
2✔
49
  ids.origRemote = ComboAddress("192.0.2.1:4242");
2✔
50
  ids.origDest = ComboAddress("192.0.2.255:53");
2✔
51
  ids.qtype = QType::A;
2✔
52
  ids.qclass = QClass::IN;
2✔
53
  ids.protocol = dnsdist::Protocol::DoUDP;
2✔
54
  ids.qname = DNSName("www.powerdns.com.");
2✔
55
  ids.queryRealTime.start();
2✔
56
  PacketBuffer query;
2✔
57
  GenericDNSPacketWriter<PacketBuffer> pwQ(query, ids.qname, QType::A, QClass::IN, 0);
2✔
58
  pwQ.getHeader()->rd = 1;
2✔
59
  pwQ.getHeader()->id = htons(42);
2✔
60

61
  DNSQuestion dq(ids, query);
2✔
62
  dnsdist_ffi_dnsquestion_t lightDQ(&dq);
2✔
63
  const auto initialData = dq.getData();
2✔
64

65
  {
2✔
66
    // dnsdist_ffi_dnsquestion_get_qtype
67
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_qtype(&lightDQ), ids.qtype);
2✔
68
  }
2✔
69

70
  {
2✔
71
    // dnsdist_ffi_dnsquestion_get_qclass
72
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_qclass(&lightDQ), ids.qclass);
2✔
73
  }
2✔
74

75
  {
2✔
76
    // dnsdist_ffi_dnsquestion_get_id
77
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_id(&lightDQ), ntohs(pwQ.getHeader()->id));
2✔
78
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_id(nullptr), 0U);
2✔
79
  }
2✔
80

81
  {
2✔
82
    // dnsdist_ffi_dnsquestion_get_localaddr, dnsdist_ffi_dnsquestion_get_local_port
83
    const char* buffer = nullptr;
2✔
84
    size_t bufferSize = 0;
2✔
85
    dnsdist_ffi_dnsquestion_get_localaddr(&lightDQ, reinterpret_cast<const void**>(&buffer), &bufferSize);
2✔
86
    BOOST_REQUIRE(buffer != nullptr);
2✔
87
    BOOST_REQUIRE_EQUAL(bufferSize, sizeof(ids.origDest.sin4.sin_addr.s_addr));
2✔
88
    BOOST_CHECK(memcmp(buffer, &ids.origDest.sin4.sin_addr.s_addr, sizeof(ids.origDest.sin4.sin_addr.s_addr)) == 0);
2✔
89
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_local_port(&lightDQ), 53U);
2✔
90
  }
2✔
91

92
  {
2✔
93
    // dnsdist_ffi_dnsquestion_get_remoteaddr, dnsdist_ffi_dnsquestion_get_remote_port
94
    const char* buffer = nullptr;
2✔
95
    size_t bufferSize = 0;
2✔
96
    dnsdist_ffi_dnsquestion_get_remoteaddr(&lightDQ, reinterpret_cast<const void**>(&buffer), &bufferSize);
2✔
97
    BOOST_REQUIRE(buffer != nullptr);
2✔
98
    BOOST_REQUIRE_EQUAL(bufferSize, sizeof(ids.origRemote.sin4.sin_addr.s_addr));
2✔
99
    BOOST_CHECK(memcmp(buffer, &ids.origRemote.sin4.sin_addr.s_addr, sizeof(ids.origRemote.sin4.sin_addr.s_addr)) == 0);
2✔
100
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_remote_port(&lightDQ), 4242U);
2✔
101
    BOOST_CHECK(!dnsdist_ffi_dnsquestion_is_remote_v6(nullptr));
2✔
102
    BOOST_CHECK(!dnsdist_ffi_dnsquestion_is_remote_v6(&lightDQ));
2✔
103
  }
2✔
104

105
  {
2✔
106
    // dnsdist_ffi_dnsquestion_get_masked_remoteaddr
107
    const char* buffer = nullptr;
2✔
108
    size_t bufferSize = 0;
2✔
109
    dnsdist_ffi_dnsquestion_get_masked_remoteaddr(&lightDQ, reinterpret_cast<const void**>(&buffer), &bufferSize, 16);
2✔
110
    BOOST_REQUIRE(buffer != nullptr);
2✔
111
    auto masked = Netmask(ids.origRemote, 16).getMaskedNetwork();
2✔
112
    BOOST_REQUIRE_EQUAL(bufferSize, sizeof(masked.sin4.sin_addr.s_addr));
2✔
113
    BOOST_CHECK(memcmp(buffer, &masked.sin4.sin_addr.s_addr, sizeof(masked.sin4.sin_addr.s_addr)) == 0);
2✔
114
  }
2✔
115

116
  {
2✔
117
    const char* buffer[6];
2✔
118
    size_t bufferSize = 6;
2✔
119

120
    // invalid
121
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_mac_addr(nullptr, buffer, 0), 0U);
2✔
122
    // too small
123
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_mac_addr(&lightDQ, buffer, 0), 0U);
2✔
124

125
    // we will not find the correspondig MAC address in /proc/net/arp, unfortunately, especially not on !linux
126
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_mac_addr(&lightDQ, buffer, bufferSize), 0U);
2✔
127
  }
2✔
128

129
  {
2✔
130
    // dnsdist_ffi_dnsquestion_get_qname_raw
131
    const char* buffer = nullptr;
2✔
132
    size_t bufferSize = 0;
2✔
133
    dnsdist_ffi_dnsquestion_get_qname_raw(&lightDQ, &buffer, &bufferSize);
2✔
134
    BOOST_REQUIRE(buffer != nullptr);
2✔
135
    BOOST_REQUIRE_EQUAL(bufferSize, ids.qname.getStorage().size());
2✔
136
    BOOST_CHECK(memcmp(buffer, ids.qname.getStorage().data(), ids.qname.getStorage().size()) == 0);
2✔
137
  }
2✔
138

139
  {
2✔
140
    // test V6 as well
141
    ids.origRemote = ComboAddress("[2001:db8::1]:65535");
2✔
142
    ids.origDest = ComboAddress("[2001:db8::2]:53");
2✔
143

144
    const char* buffer = nullptr;
2✔
145
    size_t bufferSize = 0;
2✔
146
    dnsdist_ffi_dnsquestion_get_remoteaddr(&lightDQ, reinterpret_cast<const void**>(&buffer), &bufferSize);
2✔
147
    BOOST_REQUIRE(buffer != nullptr);
2✔
148
    BOOST_REQUIRE_EQUAL(bufferSize, sizeof(ids.origRemote.sin6.sin6_addr.s6_addr));
2✔
149
    BOOST_CHECK(memcmp(buffer, &ids.origRemote.sin6.sin6_addr.s6_addr, sizeof(ids.origRemote.sin6.sin6_addr.s6_addr)) == 0);
2✔
150
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_remote_port(&lightDQ), 65535U);
2✔
151
  }
2✔
152

153
  {
2✔
154
    // dnsdist_ffi_dnsquestion_get_qname_hash
155
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_qname_hash(&lightDQ, 42), ids.qname.hash(42));
2✔
156
  }
2✔
157

158
  {
2✔
159
    // dnsdist_ffi_dnsquestion_get_rcode
160
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_rcode(&lightDQ), RCode::NoError);
2✔
161
  }
2✔
162

163
  {
2✔
164
    // dnsdist_ffi_dnsquestion_get_header
165
    BOOST_CHECK(memcmp(dnsdist_ffi_dnsquestion_get_header(&lightDQ), pwQ.getHeader(), sizeof(dnsheader)) == 0);
2✔
166
  }
2✔
167

168
  {
2✔
169
    // dnsdist_ffi_dnsquestion_get_len, dnsdist_ffi_dnsquestion_get_size
170
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_len(&lightDQ), query.size());
2✔
171
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_size(&lightDQ), query.size());
2✔
172

173
    auto oldSize = query.size();
2✔
174
    BOOST_CHECK(dnsdist_ffi_dnsquestion_set_size(&lightDQ, oldSize + 1));
2✔
175
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_size(&lightDQ), oldSize + 1);
2✔
176
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_len(&lightDQ), oldSize + 1);
2✔
177
    dnsdist_ffi_dnsquestion_set_len(&lightDQ, oldSize);
2✔
178

179
    auto max = std::numeric_limits<size_t>::max();
2✔
180
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_set_size(&lightDQ, max), 0U);
2✔
181
  }
2✔
182

183
  {
2✔
184
    // dnsdist_ffi_dnsquestion_get_opcode
185
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_opcode(&lightDQ), Opcode::Query);
2✔
186
  }
2✔
187

188
  {
2✔
189
    // dnsdist_ffi_dnsquestion_get_tcp
190
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tcp(&lightDQ), false);
2✔
191
  }
2✔
192

193
  {
2✔
194
    // dnsdist_ffi_dnsquestion_get_protocol
195
    BOOST_CHECK(static_cast<uint8_t>(dnsdist_ffi_dnsquestion_get_protocol(nullptr)) == dnsdist::Protocol(dnsdist::Protocol::DoUDP).toNumber());
2✔
196

197
    BOOST_CHECK(static_cast<uint8_t>(dnsdist_ffi_dnsquestion_get_protocol(&lightDQ)) == dnsdist::Protocol(dnsdist::Protocol::DoUDP).toNumber());
2✔
198
    for (const auto protocol : {dnsdist::Protocol::DoUDP, dnsdist::Protocol::DoTCP, dnsdist::Protocol::DNSCryptUDP, dnsdist::Protocol::DNSCryptTCP, dnsdist::Protocol::DoT, dnsdist::Protocol::DoH}) {
12✔
199
      dq.ids.protocol = protocol;
12✔
200
      BOOST_CHECK(static_cast<uint8_t>(dnsdist_ffi_dnsquestion_get_protocol(&lightDQ)) == protocol);
12✔
201
    }
12✔
202
  }
2✔
203

204
  {
2✔
205
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_elapsed_us(nullptr), 0U);
2✔
206
    BOOST_CHECK_GT(dnsdist_ffi_dnsquestion_get_elapsed_us(&lightDQ), 0U);
2✔
207
  }
2✔
208

209
  {
2✔
210
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_skip_cache(&lightDQ), false);
2✔
211
    dnsdist_ffi_dnsquestion_set_skip_cache(&lightDQ, true);
2✔
212
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_skip_cache(&lightDQ), true);
2✔
213
  }
2✔
214

215
  {
2✔
216
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_use_ecs(&lightDQ), true);
2✔
217
    dnsdist_ffi_dnsquestion_set_use_ecs(&lightDQ, false);
2✔
218
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_use_ecs(&lightDQ), false);
2✔
219
  }
2✔
220

221
  {
2✔
222
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_override(&lightDQ), false);
2✔
223
    dnsdist_ffi_dnsquestion_set_ecs_override(&lightDQ, true);
2✔
224
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_override(&lightDQ), true);
2✔
225
  }
2✔
226

227
  {
2✔
228
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_is_temp_failure_ttl_set(&lightDQ), false);
2✔
229
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_temp_failure_ttl(&lightDQ), 0U);
2✔
230

231
    dnsdist_ffi_dnsquestion_set_temp_failure_ttl(&lightDQ, 42);
2✔
232
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_is_temp_failure_ttl_set(&lightDQ), true);
2✔
233
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_temp_failure_ttl(&lightDQ), 42U);
2✔
234
    dnsdist_ffi_dnsquestion_unset_temp_failure_ttl(&lightDQ);
2✔
235
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_is_temp_failure_ttl_set(&lightDQ), false);
2✔
236
  }
2✔
237

238
  {
2✔
239
    BOOST_CHECK(!dnsdist_ffi_dnsquestion_get_do(&lightDQ));
2✔
240
  }
2✔
241

242
  {
2✔
243
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_prefix_length(&lightDQ), dnsdist::configuration::getCurrentRuntimeConfiguration().d_ECSSourcePrefixV4);
2✔
244
    dnsdist_ffi_dnsquestion_set_ecs_prefix_length(&lightDQ, 65535);
2✔
245
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_prefix_length(&lightDQ), 65535U);
2✔
246
  }
2✔
247

248
  {
2✔
249
    const char* buffer = nullptr;
2✔
250
    size_t bufferSize = 0;
2✔
251
    dnsdist_ffi_dnsquestion_get_sni(&lightDQ, &buffer, &bufferSize);
2✔
252
    BOOST_CHECK_EQUAL(bufferSize, 0U);
2✔
253
  }
2✔
254

255
  {
2✔
256
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_trailing_data(&lightDQ, nullptr), 0U);
2✔
257
    std::string garbage("thisissomegarbagetrailingdata");
2✔
258
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_set_trailing_data(&lightDQ, garbage.data(), garbage.size()), true);
2✔
259
    const char* buffer = nullptr;
2✔
260
    BOOST_REQUIRE_EQUAL(dnsdist_ffi_dnsquestion_get_trailing_data(&lightDQ, &buffer), garbage.size());
2✔
261
    BOOST_CHECK_EQUAL(garbage, std::string(buffer));
2✔
262
  }
2✔
263

264
  {
2✔
265
    dq.getMutableData() = initialData;
2✔
266
    const auto oldData = dq.getData();
2✔
267
    std::vector<dnsdist_ffi_raw_value> values;
2✔
268
    ComboAddress v4("192.0.2.1");
2✔
269
    ComboAddress v6("[2001:db8::42]");
2✔
270
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
271
    values.push_back({reinterpret_cast<const char*>(&v4.sin4.sin_addr.s_addr), sizeof(v4.sin4.sin_addr.s_addr)});
2✔
272
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
273
    values.push_back({reinterpret_cast<const char*>(&v6.sin6.sin6_addr.s6_addr), sizeof(v6.sin6.sin6_addr.s6_addr)});
2✔
274

275
    dnsdist_ffi_dnsquestion_spoof_addrs(&lightDQ, values.data(), values.size());
2✔
276
    BOOST_CHECK(dq.getData().size() > oldData.size());
2✔
277

278
    MOADNSParser mdp(false, reinterpret_cast<const char*>(dq.getData().data()), dq.getData().size());
2✔
279
    BOOST_CHECK_EQUAL(mdp.d_qname, ids.qname);
2✔
280
    BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
2✔
281
    /* only the A has been added since the query was not ANY */
282
    BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1U);
2✔
283
    BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
2✔
284
    BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0U);
2✔
285

286
    BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 1U);
2✔
287
    BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_type, static_cast<uint16_t>(QType::A));
2✔
288
    BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_class, QClass::IN);
2✔
289
    BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_name, ids.qname);
2✔
290

291
    dq.getMutableData() = oldData;
2✔
292
  }
2✔
293

294
  {
2✔
295
    BOOST_CHECK(!dnsdist_ffi_dnsquestion_set_restartable(nullptr));
2✔
296
    BOOST_CHECK(dnsdist_ffi_dnsquestion_set_restartable(&lightDQ));
2✔
297
  }
2✔
298

299
  {
2✔
300
    BOOST_CHECK_EQUAL(ids.ttlCap, 0U);
2✔
301
    dnsdist_ffi_dnsquestion_set_max_returned_ttl(&lightDQ, 42U);
2✔
302
    BOOST_CHECK_EQUAL(ids.ttlCap, 42U);
2✔
303
  }
2✔
304

305
  {
2✔
306
    const std::string tagName("my-tag");
2✔
307
    const std::string tagValue("my-value");
2✔
308
    const std::string tagRawValue("my-\0-binary-value");
2✔
309
    std::string buffer;
2✔
310
    buffer.resize(512);
2✔
311
    BOOST_CHECK(dnsdist_ffi_dnsquestion_get_tag(nullptr, nullptr) == nullptr);
2✔
312
    BOOST_CHECK(dnsdist_ffi_dnsquestion_get_tag(&lightDQ, nullptr) == nullptr);
2✔
313
    BOOST_CHECK(dnsdist_ffi_dnsquestion_get_tag(&lightDQ, tagName.c_str()) == nullptr);
2✔
314

315
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_raw(nullptr, nullptr, nullptr, 0), 0U);
2✔
316
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_raw(&lightDQ, tagName.c_str(), buffer.data(), buffer.size()), 0U);
2✔
317

318
    dnsdist_ffi_dnsquestion_set_tag(&lightDQ, tagName.c_str(), tagValue.c_str());
2✔
319

320
    auto got = dnsdist_ffi_dnsquestion_get_tag(&lightDQ, tagName.c_str());
2✔
321
    BOOST_CHECK(got != nullptr);
2✔
322
    BOOST_CHECK_EQUAL(got, tagValue.c_str());
2✔
323

324
    const dnsdist_ffi_tag_t* tags = nullptr;
2✔
325
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_array(nullptr, nullptr), 0U);
2✔
326
    BOOST_REQUIRE_EQUAL(dnsdist_ffi_dnsquestion_get_tag_array(&lightDQ, &tags), 1U);
2✔
327
    BOOST_CHECK_EQUAL(std::string(tags[0].name), tagName.c_str());
2✔
328
    BOOST_CHECK_EQUAL(std::string(tags[0].value), tagValue.c_str());
2✔
329

330
    dnsdist_ffi_dnsquestion_set_tag_raw(&lightDQ, tagName.c_str(), tagRawValue.c_str(), tagRawValue.size());
2✔
331

332
    // too small
333
    buffer.resize(1);
2✔
334
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_raw(&lightDQ, tagName.c_str(), buffer.data(), buffer.size()), 0U);
2✔
335

336
    buffer.resize(tagRawValue.size());
2✔
337
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_raw(&lightDQ, tagName.c_str(), buffer.data(), buffer.size()), tagRawValue.size());
2✔
338
    BOOST_CHECK_EQUAL(buffer, tagRawValue);
2✔
339

340
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_tag_raw(&lightDQ, "wrong tag name", buffer.data(), buffer.size()), 0U);
2✔
341

342
    // dnsdist_ffi_dnsquestion_get_tag_array
343

344
    {
2✔
345
      // no DOHUnit attached
346
      BOOST_CHECK(dnsdist_ffi_dnsquestion_get_http_path(&lightDQ) == nullptr);
2✔
347
      BOOST_CHECK(dnsdist_ffi_dnsquestion_get_http_query_string(&lightDQ) == nullptr);
2✔
348
      BOOST_CHECK(dnsdist_ffi_dnsquestion_get_http_host(&lightDQ) == nullptr);
2✔
349
      BOOST_CHECK(dnsdist_ffi_dnsquestion_get_http_scheme(&lightDQ) == nullptr);
2✔
350
      BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_http_headers(&lightDQ, nullptr), 0U);
2✔
351
      dnsdist_ffi_dnsquestion_set_http_response(&lightDQ, 0U, nullptr, 0U, nullptr);
2✔
352
    }
2✔
353
  }
2✔
354

355
  const std::string deviceID{"my-device-id"};
2✔
356
  const std::string deviceName{"my-device-name"};
2✔
357
  const std::string requestorID{"my-requestor-ID"};
2✔
358
  dnsdist_ffi_dnsquestion_set_device_id(nullptr, nullptr, 0);
2✔
359
  dnsdist_ffi_dnsquestion_set_device_id(&lightDQ, nullptr, 0);
2✔
360
  dnsdist_ffi_dnsquestion_set_device_id(&lightDQ, deviceID.c_str(), deviceID.size());
2✔
361
  dnsdist_ffi_dnsquestion_set_device_name(nullptr, nullptr, 0);
2✔
362
  dnsdist_ffi_dnsquestion_set_device_name(&lightDQ, nullptr, 0);
2✔
363
  dnsdist_ffi_dnsquestion_set_device_name(&lightDQ, deviceName.c_str(), deviceName.size());
2✔
364
  dnsdist_ffi_dnsquestion_set_requestor_id(nullptr, nullptr, 0);
2✔
365
  dnsdist_ffi_dnsquestion_set_requestor_id(&lightDQ, nullptr, 0);
2✔
366
  dnsdist_ffi_dnsquestion_set_requestor_id(&lightDQ, requestorID.c_str(), requestorID.size());
2✔
367
  BOOST_REQUIRE(ids.d_protoBufData != nullptr);
2✔
368
  BOOST_CHECK_EQUAL(ids.d_protoBufData->d_deviceID, deviceID);
2✔
369
  BOOST_CHECK_EQUAL(ids.d_protoBufData->d_deviceName, deviceName);
2✔
370
  BOOST_CHECK_EQUAL(ids.d_protoBufData->d_requestorID, requestorID);
2✔
371
}
2✔
372

373
BOOST_AUTO_TEST_CASE(test_Response)
374
{
2✔
375
  InternalQueryState ids;
2✔
376
  ids.origRemote = ComboAddress("192.0.2.1:4242");
2✔
377
  ids.origDest = ComboAddress("192.0.2.255:53");
2✔
378
  ids.qtype = QType::A;
2✔
379
  ids.qclass = QClass::IN;
2✔
380
  ids.protocol = dnsdist::Protocol::DoUDP;
2✔
381
  ids.qname = DNSName("www.powerdns.com.");
2✔
382
  ids.queryRealTime.start();
2✔
383

384
  PacketBuffer response;
2✔
385
  GenericDNSPacketWriter<PacketBuffer> pwR(response, ids.qname, QType::A, QClass::IN, 0);
2✔
386
  pwR.getHeader()->qr = 1;
2✔
387
  pwR.getHeader()->rd = 1;
2✔
388
  pwR.getHeader()->id = htons(42);
2✔
389

390
  ComboAddress dsAddr("192.0.2.1:53");
2✔
391
  auto ds = std::make_shared<DownstreamState>(dsAddr);
2✔
392

393
  DNSResponse dr(ids, response, ds);
2✔
394
  dnsdist_ffi_dnsresponse_t lightDR(&dr);
2✔
395

396
  {
2✔
397
    dnsdist_ffi_dnsresponse_set_min_ttl(&lightDR, 42);
2✔
398
    dnsdist_ffi_dnsresponse_set_max_ttl(&lightDR, 84);
2✔
399
    dnsdist_ffi_dnsresponse_limit_ttl(&lightDR, 42, 84);
2✔
400
  }
2✔
401

402
  {
2✔
403
    BOOST_CHECK_EQUAL(ids.ttlCap, 0U);
2✔
404
    dnsdist_ffi_dnsresponse_set_max_returned_ttl(&lightDR, 42);
2✔
405
    BOOST_CHECK_EQUAL(ids.ttlCap, 42U);
2✔
406
  }
2✔
407

408
  {
2✔
409
    /* invalid parameters */
410
    BOOST_CHECK(!dnsdist_ffi_dnsresponse_rebase(&lightDR, nullptr, 0));
2✔
411

412
    /* invalid name */
413
    BOOST_CHECK(!dnsdist_ffi_dnsresponse_rebase(&lightDR, "\5AAAA", 5));
2✔
414

415
    DNSName newName("not-powerdns.com.");
2✔
416
    BOOST_CHECK(dnsdist_ffi_dnsresponse_rebase(&lightDR, newName.getStorage().data(), newName.getStorage().size()));
2✔
417
    BOOST_CHECK_EQUAL(ids.qname.toString(), newName.toString());
2✔
418
  }
2✔
419

420
  {
2✔
421
    dnsdist_ffi_dnsresponse_clear_records_type(nullptr, QType::A);
2✔
422
    dnsdist_ffi_dnsresponse_clear_records_type(&lightDR, QType::A);
2✔
423
  }
2✔
424
}
2✔
425

426
BOOST_AUTO_TEST_CASE(test_Server)
427
{
2✔
428
  ComboAddress dsAddr("192.0.2.1:53");
2✔
429
  auto ds = std::make_shared<DownstreamState>(dsAddr);
2✔
430
  dnsdist_ffi_server_t server(ds);
2✔
431

432
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_outstanding(&server), 0U);
2✔
433
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_is_up(&server), false);
2✔
434
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_name(&server), "");
2✔
435
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_name_with_addr(&server), dsAddr.toStringWithPort());
2✔
436
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_weight(&server), 1);
2✔
437
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_order(&server), 1);
2✔
438
  BOOST_CHECK_EQUAL(dnsdist_ffi_server_get_latency(&server), 0.0);
2✔
439
}
2✔
440

441
BOOST_AUTO_TEST_CASE(test_PacketCache)
442
{
2✔
443
  auto packetCache = std::make_shared<DNSDistPacketCache>(10);
2✔
444

445
  ComboAddress ipv4("192.0.2.1");
2✔
446
  InternalQueryState ids;
2✔
447
  ids.qtype = QType::A;
2✔
448
  ids.qclass = QClass::IN;
2✔
449
  ids.protocol = dnsdist::Protocol::DoUDP;
2✔
450
  ids.qname = DNSName("powerdns.com.");
2✔
451
  PacketBuffer query;
2✔
452
  GenericDNSPacketWriter<PacketBuffer> pwQ(query, ids.qname, QType::A, QClass::IN, 0);
2✔
453
  pwQ.getHeader()->rd = 1;
2✔
454

455
  PacketBuffer response;
2✔
456
  GenericDNSPacketWriter<PacketBuffer> pwR(response, ids.qname, QType::A, QClass::IN, 0);
2✔
457
  pwR.getHeader()->id = pwQ.getHeader()->id;
2✔
458
  pwR.startRecord(ids.qname, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
2✔
459
  pwR.xfrCAWithoutPort(4, ipv4);
2✔
460
  pwR.commit();
2✔
461

462
  bool dnssecOK = true;
2✔
463
  bool receivedOverUDP = true;
2✔
464
  uint32_t key = 0;
2✔
465
  boost::optional<Netmask> subnet;
2✔
466
  ids.queryRealTime.start();
2✔
467
  DNSQuestion dq(ids, query);
2✔
468
  packetCache->get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
2✔
469
  packetCache->insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
2✔
470

471
  std::string poolName("test-pool");
2✔
472
  auto testPool = std::make_shared<ServerPool>();
2✔
473
  testPool->packetCache = packetCache;
2✔
474
  std::string poolWithNoCacheName("test-pool-without-cache");
2✔
475
  auto testPoolWithNoCache = std::make_shared<ServerPool>();
2✔
476
  dnsdist::configuration::updateRuntimeConfiguration([&poolName, &testPool, &poolWithNoCacheName, &testPoolWithNoCache](dnsdist::configuration::RuntimeConfiguration& config) {
2✔
477
    config.d_pools.emplace(poolName, testPool);
2✔
478
    config.d_pools.emplace(poolWithNoCacheName, testPoolWithNoCache);
2✔
479
  });
2✔
480

481
  {
2✔
482
    dnsdist_ffi_domain_list_t* list = nullptr;
2✔
483
    {
2✔
484
      // invalid parameters
485
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_domain_list_by_addr(nullptr, nullptr, nullptr), 0U);
2✔
486
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_domain_list_by_addr("not-existing-pool", ipv4.toString().c_str(), &list), 0U);
2✔
487
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_domain_list_by_addr(poolName.c_str(), "invalid-address", &list), 0U);
2✔
488
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_domain_list_by_addr(poolWithNoCacheName.c_str(), ipv4.toString().c_str(), &list), 0U);
2✔
489
    }
2✔
490

491
    {
2✔
492
      // no match
493
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_domain_list_by_addr(poolName.c_str(), ComboAddress("192.0.2.254").toString().c_str(), &list), 0U);
2✔
494
    }
2✔
495

496
    auto got = dnsdist_ffi_packetcache_get_domain_list_by_addr(poolName.c_str(), ipv4.toString().c_str(), &list);
2✔
497
    BOOST_REQUIRE_EQUAL(got, 1U);
2✔
498
    BOOST_REQUIRE(list != nullptr);
2✔
499

500
    {
2✔
501
      // invalid parameters
502
      BOOST_CHECK(dnsdist_ffi_domain_list_get(nullptr, 0) == nullptr);
2✔
503
      BOOST_CHECK(dnsdist_ffi_domain_list_get(list, 1) == nullptr);
2✔
504
    }
2✔
505

506
    {
2✔
507
      const char* domain = dnsdist_ffi_domain_list_get(list, 0);
2✔
508
      BOOST_CHECK(domain == ids.qname.toString());
2✔
509
    }
2✔
510

511
    dnsdist_ffi_domain_list_free(list);
2✔
512
  }
2✔
513

514
  {
2✔
515
    dnsdist_ffi_address_list_t* addresses = nullptr;
2✔
516
    {
2✔
517
      // invalid parameters
518
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_address_list_by_domain(nullptr, nullptr, nullptr), 0U);
2✔
519
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_address_list_by_domain("not-existing-pool", ids.qname.toString().c_str(), &addresses), 0U);
2✔
520
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_address_list_by_domain(poolName.c_str(), "invalid-dns...name", &addresses), 0U);
2✔
521
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_address_list_by_domain(poolWithNoCacheName.c_str(), ipv4.toString().c_str(), &addresses), 0U);
2✔
522
    }
2✔
523

524
    {
2✔
525
      // no match
526
      BOOST_CHECK_EQUAL(dnsdist_ffi_packetcache_get_address_list_by_domain(poolName.c_str(), "wrong.name.", &addresses), 0U);
2✔
527
    }
2✔
528

529
    auto got = dnsdist_ffi_packetcache_get_address_list_by_domain(poolName.c_str(), ids.qname.toString().c_str(), &addresses);
2✔
530
    BOOST_REQUIRE_EQUAL(got, 1U);
2✔
531
    BOOST_REQUIRE(addresses != nullptr);
2✔
532

533
    {
2✔
534
      // invalid parameters
535
      BOOST_CHECK(dnsdist_ffi_address_list_get(nullptr, 0) == nullptr);
2✔
536
      BOOST_CHECK(dnsdist_ffi_address_list_get(addresses, 1) == nullptr);
2✔
537
    }
2✔
538

539
    {
2✔
540
      const char* addr = dnsdist_ffi_address_list_get(addresses, 0);
2✔
541
      BOOST_CHECK(addr == ipv4.toString());
2✔
542
    }
2✔
543

544
    dnsdist_ffi_address_list_free(addresses);
2✔
545
  }
2✔
546
}
2✔
547

548
BOOST_AUTO_TEST_CASE(test_ProxyProtocol)
549
{
2✔
550
  ComboAddress v4("192.0.2.1");
2✔
551
  ComboAddress v6("[2001:db8::42]");
2✔
552

553
  std::vector<dnsdist_ffi_proxy_protocol_value> values;
2✔
554
  values.push_back({"test-value", 10U, 1U});
2✔
555

556
  std::vector<uint8_t> output;
2✔
557
  output.resize(4096);
2✔
558

559
  {
2✔
560
    // too small buffer
561
    auto got = dnsdist_ffi_generate_proxy_protocol_payload(sizeof(v4.sin4.sin_addr.s_addr), &v4.sin4.sin_addr.s_addr, &v4.sin4.sin_addr.s_addr, 4242U, 53U, true, values.size(), values.data(), output.data(), 0);
2✔
562
    BOOST_CHECK_EQUAL(got, 0U);
2✔
563
  }
2✔
564

565
  {
2✔
566
    // invalid address size
567
    auto got = dnsdist_ffi_generate_proxy_protocol_payload(0U, &v4.sin4.sin_addr.s_addr, &v4.sin4.sin_addr.s_addr, 4242U, 53U, true, values.size(), values.data(), output.data(), 0);
2✔
568
    BOOST_CHECK_EQUAL(got, 0U);
2✔
569
  }
2✔
570

571
  {
2✔
572
    auto got = dnsdist_ffi_generate_proxy_protocol_payload(sizeof(v4.sin4.sin_addr.s_addr), &v4.sin4.sin_addr.s_addr, &v4.sin4.sin_addr.s_addr, 4242U, 53U, true, values.size(), values.data(), output.data(), output.size());
2✔
573
    BOOST_CHECK_EQUAL(got, 41U);
2✔
574
  }
2✔
575
}
2✔
576

577
BOOST_AUTO_TEST_CASE(test_ProxyProtocolQuery)
578
{
2✔
579
  InternalQueryState ids;
2✔
580
  ids.origRemote = ComboAddress("192.0.2.1:4242");
2✔
581
  ids.origDest = ComboAddress("192.0.2.255:53");
2✔
582
  ids.qtype = QType::A;
2✔
583
  ids.qclass = QClass::IN;
2✔
584
  ids.protocol = dnsdist::Protocol::DoUDP;
2✔
585
  ids.qname = DNSName("www.powerdns.com.");
2✔
586
  ids.queryRealTime.start();
2✔
587
  PacketBuffer query;
2✔
588
  GenericDNSPacketWriter<PacketBuffer> pwQ(query, ids.qname, QType::A, QClass::IN, 0);
2✔
589
  pwQ.getHeader()->rd = 1;
2✔
590
  pwQ.getHeader()->id = htons(42);
2✔
591

592
  DNSQuestion dnsQuestion(ids, query);
2✔
593
  dnsdist_ffi_dnsquestion_t lightDQ(&dnsQuestion);
2✔
594

595
  std::vector<dnsdist_ffi_proxy_protocol_value> values;
2✔
596
  values.push_back({"test-value", 10U, 1U});
2✔
597

598
  {
2✔
599
    auto added = dnsdist_ffi_dnsquestion_add_proxy_protocol_values(nullptr, values.size(), values.data());
2✔
600
    BOOST_CHECK_EQUAL(added, false);
2✔
601
  }
2✔
602

603
  {
2✔
604
    auto added = dnsdist_ffi_dnsquestion_add_proxy_protocol_values(&lightDQ, 0, values.data());
2✔
605
    BOOST_CHECK_EQUAL(added, false);
2✔
606
  }
2✔
607

608
  {
2✔
609
    auto added = dnsdist_ffi_dnsquestion_add_proxy_protocol_values(&lightDQ, values.size(), nullptr);
2✔
610
    BOOST_CHECK_EQUAL(added, false);
2✔
611
  }
2✔
612

613
  {
2✔
614
    auto added = dnsdist_ffi_dnsquestion_add_proxy_protocol_values(&lightDQ, values.size(), values.data());
2✔
615
    BOOST_CHECK_EQUAL(added, true);
2✔
616
    BOOST_REQUIRE(dnsQuestion.proxyProtocolValues != nullptr);
2✔
617
    BOOST_REQUIRE_EQUAL(dnsQuestion.proxyProtocolValues->size(), values.size());
2✔
618
    BOOST_CHECK_EQUAL(dnsQuestion.proxyProtocolValues->at(0).type, values.at(0).type);
2✔
619
    BOOST_REQUIRE_EQUAL(dnsQuestion.proxyProtocolValues->at(0).content.size(), values.at(0).size);
2✔
620
    BOOST_CHECK_EQUAL(memcmp(dnsQuestion.proxyProtocolValues->at(0).content.data(), values.at(0).value, values.at(0).size), 0);
2✔
621
  }
2✔
622
}
2✔
623

624
BOOST_AUTO_TEST_CASE(test_ProxyProtocolIncoming)
625
{
2✔
626
  InternalQueryState ids;
2✔
627
  ids.origRemote = ComboAddress("192.0.2.1:4242");
2✔
628
  ids.origDest = ComboAddress("192.0.2.255:53");
2✔
629
  ids.qtype = QType::A;
2✔
630
  ids.qclass = QClass::IN;
2✔
631
  ids.protocol = dnsdist::Protocol::DoUDP;
2✔
632
  ids.qname = DNSName("www.powerdns.com.");
2✔
633
  ids.queryRealTime.start();
2✔
634
  PacketBuffer query;
2✔
635
  GenericDNSPacketWriter<PacketBuffer> pwQ(query, ids.qname, QType::A, QClass::IN, 0);
2✔
636
  pwQ.getHeader()->rd = 1;
2✔
637
  pwQ.getHeader()->id = htons(42);
2✔
638

639
  DNSQuestion dnsQuestion(ids, query);
2✔
640
  dnsdist_ffi_dnsquestion_t lightDQ(&dnsQuestion);
2✔
641

642
  {
2✔
643
    /* invalid dq */
644
    const dnsdist_ffi_proxy_protocol_value_t* out = nullptr;
2✔
645
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_proxy_protocol_values(nullptr, &out), 0U);
2✔
646
  }
2✔
647
  {
2✔
648
    /* invalid pointer */
649
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_proxy_protocol_values(&lightDQ, nullptr), 0U);
2✔
650
  }
2✔
651
  {
2✔
652
    /* no proxy protocol values */
653
    const dnsdist_ffi_proxy_protocol_value_t* out = nullptr;
2✔
654
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_proxy_protocol_values(&lightDQ, &out), 0U);
2✔
655
  }
2✔
656

657
  {
2✔
658
    /* add some proxy protocol TLV values */
659
    dnsQuestion.proxyProtocolValues = std::make_unique<std::vector<ProxyProtocolValue>>();
2✔
660
    dnsQuestion.proxyProtocolValues->emplace_back(ProxyProtocolValue{"foo", 42});
2✔
661
    dnsQuestion.proxyProtocolValues->emplace_back(ProxyProtocolValue{"bar", 255});
2✔
662
    dnsQuestion.proxyProtocolValues->emplace_back(ProxyProtocolValue{"", 0});
2✔
663
    const dnsdist_ffi_proxy_protocol_value_t* out = nullptr;
2✔
664
    auto count = dnsdist_ffi_dnsquestion_get_proxy_protocol_values(&lightDQ, &out);
2✔
665
    BOOST_REQUIRE_EQUAL(count, 3U);
2✔
666
    // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic): sorry, this is a C API
667
    BOOST_CHECK_EQUAL(out[0].type, 42U);
2✔
668
    BOOST_CHECK_EQUAL(out[0].value, "foo");
2✔
669
    BOOST_CHECK_EQUAL(out[1].type, 255U);
2✔
670
    BOOST_CHECK_EQUAL(out[1].value, "bar");
2✔
671
    BOOST_CHECK_EQUAL(out[2].type, 0U);
2✔
672
    BOOST_CHECK_EQUAL(out[2].value, "");
2✔
673
    // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic): sorry, this is a C API
674
  }
2✔
675
}
2✔
676

677
BOOST_AUTO_TEST_CASE(test_PacketOverlay)
678
{
2✔
679
  const DNSName target("powerdns.com.");
2✔
680
  PacketBuffer response;
2✔
681
  GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::A, QClass::IN, 0);
2✔
682
  pwR.getHeader()->qr = 1;
2✔
683
  pwR.getHeader()->rd = 1;
2✔
684
  pwR.getHeader()->ra = 1;
2✔
685
  pwR.getHeader()->id = htons(42);
2✔
686
  pwR.startRecord(target, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
2✔
687
  ComboAddress v4("192.0.2.1");
2✔
688
  pwR.xfrCAWithoutPort(4, v4);
2✔
689
  pwR.commit();
2✔
690
  pwR.startRecord(target, QType::AAAA, 7200, QClass::IN, DNSResourceRecord::ADDITIONAL);
2✔
691
  ComboAddress v6("2001:db8::1");
2✔
692
  pwR.xfrCAWithoutPort(6, v6);
2✔
693
  pwR.commit();
2✔
694
  pwR.addOpt(4096, 0, 0);
2✔
695
  pwR.commit();
2✔
696

697
  /* invalid parameters */
698
  BOOST_CHECK(!dnsdist_ffi_dnspacket_parse(nullptr, 0, nullptr));
2✔
699

700
  dnsdist_ffi_dnspacket_t* packet = nullptr;
2✔
701
  // invalid packet
702
  BOOST_CHECK(!dnsdist_ffi_dnspacket_parse(reinterpret_cast<const char*>(response.data()), response.size() - 1, &packet));
2✔
703
  BOOST_REQUIRE(dnsdist_ffi_dnspacket_parse(reinterpret_cast<const char*>(response.data()), response.size(), &packet));
2✔
704
  BOOST_REQUIRE(packet != nullptr);
2✔
705

706
  const char* qname = nullptr;
2✔
707
  size_t qnameSize = 0;
2✔
708

709
  // invalid parameters
710
  dnsdist_ffi_dnspacket_get_qname_raw(nullptr, nullptr, 0);
2✔
711
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_qtype(nullptr), 0U);
2✔
712
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_qclass(nullptr), 0U);
2✔
713
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_qtype(packet), QType::A);
2✔
714
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_qclass(packet), QClass::IN);
2✔
715

716
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(nullptr, 0), 0U);
2✔
717
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(packet, 0), 0U);
2✔
718
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(packet, 1), 1U);
2✔
719
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(packet, 2), 0U);
2✔
720
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(packet, 3), 2U);
2✔
721
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_records_count_in_section(packet, 4), 0U);
2✔
722

723
  dnsdist_ffi_dnspacket_get_qname_raw(packet, &qname, &qnameSize);
2✔
724
  BOOST_REQUIRE(qname != nullptr);
2✔
725
  BOOST_REQUIRE_EQUAL(qnameSize, target.wirelength());
2✔
726
  BOOST_CHECK_EQUAL(memcmp(qname, target.getStorage().data(), target.getStorage().size()), 0);
2✔
727

728
  {
2✔
729
    std::string parsedName;
2✔
730
    parsedName.resize(1024);
2✔
731

732
    // too small
733
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_name_at_offset_raw(reinterpret_cast<const char*>(response.data()), response.size(), sizeof(dnsheader), parsedName.data(), 1U), 0U);
2✔
734
    // invalid parameters
735
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_name_at_offset_raw(nullptr, 0, sizeof(dnsheader), parsedName.data(), parsedName.size()), 0U);
2✔
736
    // invalid packet
737
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_name_at_offset_raw(reinterpret_cast<const char*>(response.data()), sizeof(dnsheader) + 2, sizeof(dnsheader), parsedName.data(), parsedName.size()), 0U);
2✔
738

739
    auto parsedNameSize = dnsdist_ffi_dnspacket_get_name_at_offset_raw(reinterpret_cast<const char*>(response.data()), response.size(), sizeof(dnsheader), parsedName.data(), parsedName.size());
2✔
740
    BOOST_REQUIRE_GT(parsedNameSize, 0U);
2✔
741
    BOOST_REQUIRE_EQUAL(parsedNameSize, target.wirelength());
2✔
742
    BOOST_CHECK_EQUAL(memcmp(parsedName.c_str(), target.getStorage().data(), target.getStorage().size()), 0);
2✔
743
  }
2✔
744

745
  const char* name = nullptr;
2✔
746
  size_t nameSize = 0;
2✔
747
  dnsdist_ffi_dnspacket_get_record_name_raw(nullptr, 0, nullptr, 0);
2✔
748
  BOOST_REQUIRE(name == nullptr);
2✔
749

750
  // invalid parameters
751
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_type(nullptr, 0), 0U);
2✔
752
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_class(nullptr, 0), 0U);
2✔
753
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_ttl(nullptr, 0), 0U);
2✔
754
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_length(nullptr, 0), 0U);
2✔
755
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_offset(nullptr, 0), 0U);
2✔
756
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_name_at_offset_raw(nullptr, 0, 0, nullptr, 0), 0U);
2✔
757

758
  // first record */
759
  dnsdist_ffi_dnspacket_get_record_name_raw(packet, 0, &name, &nameSize);
2✔
760
  BOOST_REQUIRE(name != nullptr);
2✔
761
  BOOST_REQUIRE_EQUAL(nameSize, target.wirelength());
2✔
762
  BOOST_CHECK_EQUAL(memcmp(name, target.getStorage().data(), target.getStorage().size()), 0);
2✔
763
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_type(packet, 0), QType::A);
2✔
764
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_class(packet, 0), QClass::IN);
2✔
765
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_ttl(packet, 0), 7200U);
2✔
766
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_length(packet, 0), sizeof(v4.sin4.sin_addr.s_addr));
2✔
767
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_offset(packet, 0), 42U);
2✔
768

769
  // second record
770
  dnsdist_ffi_dnspacket_get_record_name_raw(packet, 1, &name, &nameSize);
2✔
771
  BOOST_REQUIRE(name != nullptr);
2✔
772
  BOOST_REQUIRE_EQUAL(nameSize, target.wirelength());
2✔
773
  BOOST_CHECK_EQUAL(memcmp(name, target.getStorage().data(), target.getStorage().size()), 0);
2✔
774
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_type(packet, 1), QType::AAAA);
2✔
775
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_class(packet, 1), QClass::IN);
2✔
776
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_ttl(packet, 1), 7200U);
2✔
777
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_length(packet, 1), sizeof(v6.sin6.sin6_addr.s6_addr));
2✔
778
  BOOST_CHECK_EQUAL(dnsdist_ffi_dnspacket_get_record_content_offset(packet, 1), 58U);
2✔
779

780
  dnsdist_ffi_dnspacket_free(packet);
2✔
781
}
2✔
782

783
BOOST_AUTO_TEST_CASE(test_RingBuffers)
784
{
2✔
785
  dnsheader dh;
2✔
786
  memset(&dh, 0, sizeof(dh));
2✔
787
  dh.id = htons(42);
2✔
788
  dh.rd = 1;
2✔
789
  dh.ancount = htons(1);
2✔
790
  dh.nscount = htons(1);
2✔
791
  dh.arcount = htons(1);
2✔
792
  dh.rcode = RCode::NXDomain;
2✔
793
  DNSName qname("rings.luaffi.powerdns.com.");
2✔
794
  ComboAddress requestor1("192.0.2.1");
2✔
795
  ComboAddress backend("192.0.2.42");
2✔
796
  uint16_t qtype = QType::AAAA;
2✔
797
  uint16_t size = 42;
2✔
798
  dnsdist::Protocol protocol = dnsdist::Protocol::DoUDP;
2✔
799
  dnsdist::Protocol outgoingProtocol = dnsdist::Protocol::DoUDP;
2✔
800
  unsigned int responseTime = 0;
2✔
801
  struct timespec now;
2✔
802
  gettime(&now);
2✔
803

804
  g_rings.reset();
2✔
805
  g_rings.init(10000, 10);
2✔
806
  BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), 0U);
2✔
807

808
  g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
2✔
809
  g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
2✔
810

811
  dnsdist_ffi_ring_entry_list_t* list = nullptr;
2✔
812

813
  {
2✔
814
    // invalid
815
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries(nullptr), 0U);
2✔
816
    BOOST_CHECK(list == nullptr);
2✔
817
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries_by_addr(requestor1.toString().c_str(), nullptr), 0U);
2✔
818
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries_by_addr(nullptr, &list), 0U);
2✔
819
    BOOST_CHECK(list == nullptr);
2✔
820
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries_by_addr("invalid-address", &list), 0U);
2✔
821
    BOOST_CHECK(list == nullptr);
2✔
822
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries_by_mac(nullptr, nullptr), 0U);
2✔
823
    BOOST_CHECK(list == nullptr);
2✔
824
    BOOST_CHECK(!dnsdist_ffi_ring_entry_is_response(nullptr, 0));
2✔
825
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(nullptr, 0) == 0.0);
2✔
826
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_name(nullptr, 0) == nullptr);
2✔
827
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_type(nullptr, 0) == 0);
2✔
828
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(nullptr, 0) == nullptr);
2✔
829
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_backend(nullptr, 0) == nullptr);
2✔
830
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_protocol(nullptr, 0) == 0);
2✔
831
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_size(nullptr, 0) == 0);
2✔
832
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_latency(nullptr, 0) == 0);
2✔
833
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_id(nullptr, 0) == 0);
2✔
834
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rcode(nullptr, 0) == 0);
2✔
835
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_aa(nullptr, 0) == false);
2✔
836
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rd(nullptr, 0) == false);
2✔
837
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_tc(nullptr, 0) == false);
2✔
838
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_ancount(nullptr, 0) == 0);
2✔
839
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_nscount(nullptr, 0) == 0);
2✔
840
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_arcount(nullptr, 0) == 0);
2✔
841
    BOOST_CHECK(!dnsdist_ffi_ring_entry_has_mac_address(nullptr, 0));
2✔
842
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_mac_address(nullptr, 0) == nullptr);
2✔
843
  }
2✔
844

845
  BOOST_REQUIRE_EQUAL(dnsdist_ffi_ring_get_entries(&list), 2U);
2✔
846
  BOOST_CHECK(list != nullptr);
2✔
847

848
  BOOST_CHECK(!dnsdist_ffi_ring_entry_is_response(list, 0));
2✔
849
  BOOST_CHECK(dnsdist_ffi_ring_entry_is_response(list, 1));
2✔
850

851
  for (size_t idx = 0; idx < 2; idx++) {
6✔
852
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(list, idx) >= 0.0);
4✔
853
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(list, idx) < 2.0);
4✔
854
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_name(list, idx) == qname.toString());
4✔
855
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_type(list, idx) == qtype);
4✔
856
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(list, idx) == requestor1.toStringWithPort());
4✔
857
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_protocol(list, idx) == protocol.toNumber());
4✔
858
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_size(list, idx), size);
4✔
859
    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_id(list, idx), 42U);
4✔
860
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_aa(list, idx) == false);
4✔
861
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rd(list, idx) == true);
4✔
862
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_tc(list, idx) == false);
4✔
863
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_ancount(list, idx) == 1);
4✔
864
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_nscount(list, idx) == 1);
4✔
865
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_arcount(list, idx) == 1);
4✔
866
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rcode(list, idx) == RCode::NXDomain);
4✔
867
    if (dnsdist_ffi_ring_entry_is_response(list, idx)) {
4✔
868
      BOOST_CHECK(dnsdist_ffi_ring_entry_get_backend(list, idx) == backend.toStringWithPort());
2✔
869
      BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_latency(list, idx), responseTime);
2✔
870
    }
2✔
871
    BOOST_CHECK(!dnsdist_ffi_ring_entry_has_mac_address(list, idx));
4✔
872
    BOOST_CHECK(dnsdist_ffi_ring_entry_get_mac_address(list, idx) == std::string());
4✔
873
  }
4✔
874

875
  dnsdist_ffi_ring_entry_list_free(list);
2✔
876
  list = nullptr;
2✔
877

878
  // not the right requestor
879
  BOOST_REQUIRE_EQUAL(dnsdist_ffi_ring_get_entries_by_addr("192.0.2.2", &list), 0U);
2✔
880
  BOOST_CHECK(list == nullptr);
2✔
881

882
  BOOST_REQUIRE_EQUAL(dnsdist_ffi_ring_get_entries_by_addr(requestor1.toString().c_str(), &list), 2U);
2✔
883
  BOOST_CHECK(list != nullptr);
2✔
884
  dnsdist_ffi_ring_entry_list_free(list);
2✔
885
  list = nullptr;
2✔
886
}
2✔
887

888
BOOST_AUTO_TEST_CASE(test_NetworkEndpoint)
889
{
2✔
890
  {
2✔
891
    dnsdist_ffi_network_endpoint_t* endpoint = nullptr;
2✔
892
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_new("a", 1, nullptr));
2✔
893
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_new(nullptr, 1, &endpoint));
2✔
894
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_new("a", 0, &endpoint));
2✔
895
    // the path does not exist
896
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_new("a", 1, &endpoint));
2✔
897
  }
2✔
898

899
  {
2✔
900
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_is_valid(nullptr));
2✔
901
  }
2✔
902

903
  {
2✔
904
    dnsdist_ffi_network_endpoint_t* endpoint = nullptr;
2✔
905
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_send(nullptr, "a", 1));
2✔
906
    BOOST_CHECK(!dnsdist_ffi_network_endpoint_send(endpoint, nullptr, 1));
2✔
907
  }
2✔
908

909
  {
2✔
910
    dnsdist_ffi_network_endpoint_free(nullptr);
2✔
911
  }
2✔
912
}
2✔
913

914
BOOST_AUTO_TEST_CASE(test_hash)
915
{
2✔
916
  const uint32_t seed = 0x42;
2✔
917
  const std::array<unsigned char, 10> data{{'0', 'x', 'd', 'e', 'a', 'd', 'b', 'E', 'e', 'F'}};
2✔
918
  const std::array<unsigned char, 10> capitalizedData{{'0', 'X', 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'}};
2✔
919

920
  {
2✔
921
    /* invalid */
922
    BOOST_CHECK_EQUAL(dnsdist_ffi_hash(0, nullptr, 0, false), 0U);
2✔
923
    BOOST_CHECK_EQUAL(dnsdist_ffi_hash(seed, nullptr, 0, false), seed);
2✔
924
  }
2✔
925
  {
2✔
926
    /* case sensitive */
927
    auto hash = dnsdist_ffi_hash(seed, data.data(), data.size(), false);
2✔
928
    BOOST_CHECK_EQUAL(hash, burtle(data.data(), data.size(), seed));
2✔
929
    BOOST_CHECK_NE(hash, burtle(capitalizedData.data(), capitalizedData.size(), seed));
2✔
930
    BOOST_CHECK_NE(hash, burtleCI(capitalizedData.data(), capitalizedData.size(), seed));
2✔
931
  }
2✔
932
  {
2✔
933
    /* case insensitive */
934
    auto hash = dnsdist_ffi_hash(seed, data.data(), data.size(), true);
2✔
935
    BOOST_CHECK_EQUAL(hash, burtleCI(data.data(), data.size(), seed));
2✔
936
    BOOST_CHECK_NE(hash, burtle(capitalizedData.data(), capitalizedData.size(), seed));
2✔
937
    BOOST_CHECK_EQUAL(hash, burtleCI(capitalizedData.data(), capitalizedData.size(), seed));
2✔
938
  }
2✔
939
}
2✔
940

941
BOOST_AUTO_TEST_CASE(test_SVC_Generation)
942
{
2✔
943
  dnsdist_ffi_svc_record_parameters* parameters{nullptr};
2✔
944

945
  {
2✔
946
    /* invalid parameters */
947
    BOOST_CHECK_EQUAL(dnsdist_ffi_svc_record_parameters_new(nullptr, 0, false, &parameters), false);
2✔
948
    BOOST_CHECK_EQUAL(dnsdist_ffi_svc_record_parameters_new("powerdns.com.", 0, false, nullptr), false);
2✔
949
  }
2✔
950

951
  BOOST_REQUIRE_EQUAL(dnsdist_ffi_svc_record_parameters_new("powerdns.com.", 1, true, &parameters), true);
2✔
952
  BOOST_REQUIRE(parameters != nullptr);
2✔
953

954
  {
2✔
955
    /* invalid parameters */
956
    dnsdist_ffi_svc_record_parameters_set_port(nullptr, 0);
2✔
957
    dnsdist_ffi_svc_record_parameters_set_ech(nullptr, "alpn", 4);
2✔
958
    dnsdist_ffi_svc_record_parameters_set_additional_param(nullptr, 7, "/dns-query{?dns}", 16);
2✔
959
    dnsdist_ffi_svc_record_parameters_set_additional_param(parameters, 7, nullptr, 0);
2✔
960
    dnsdist_ffi_svc_record_parameters_add_mandatory_param(nullptr, 0);
2✔
961
    dnsdist_ffi_svc_record_parameters_add_alpn(nullptr, "h2", 2);
2✔
962
    dnsdist_ffi_svc_record_parameters_add_alpn(parameters, nullptr, 0);
2✔
963
    dnsdist_ffi_svc_record_parameters_add_ipv4_hint(parameters, nullptr, 0);
2✔
964
    dnsdist_ffi_svc_record_parameters_add_ipv4_hint(nullptr, nullptr, 0);
2✔
965
    dnsdist_ffi_svc_record_parameters_add_ipv6_hint(parameters, nullptr, 0);
2✔
966
    dnsdist_ffi_svc_record_parameters_add_ipv6_hint(nullptr, nullptr, 0);
2✔
967
    dnsdist_ffi_dnsquestion_generate_svc_response(nullptr, nullptr, 0, 0);
2✔
968
  }
2✔
969

970
  dnsdist_ffi_svc_record_parameters_set_port(parameters, 443);
2✔
971
  dnsdist_ffi_svc_record_parameters_set_ech(parameters, "binary", 6);
2✔
972
  dnsdist_ffi_svc_record_parameters_set_additional_param(parameters, 7, "/dns-query{?dns}", 16);
2✔
973
  dnsdist_ffi_svc_record_parameters_add_mandatory_param(parameters, 7);
2✔
974
  dnsdist_ffi_svc_record_parameters_add_alpn(parameters, "h2", 2);
2✔
975
  dnsdist_ffi_svc_record_parameters_add_ipv4_hint(parameters, "9.9.9.9", 8);
2✔
976
  dnsdist_ffi_svc_record_parameters_add_ipv6_hint(parameters, "2620:fe::fe", 11);
2✔
977

978
  {
2✔
979
    InternalQueryState ids;
2✔
980
    ids.origRemote = ComboAddress("192.0.2.1:4242");
2✔
981
    ids.origDest = ComboAddress("192.0.2.255:53");
2✔
982
    ids.qtype = QType::A;
2✔
983
    ids.qclass = QClass::IN;
2✔
984
    ids.protocol = dnsdist::Protocol::DoUDP;
2✔
985
    ids.qname = DNSName("www.powerdns.com.");
2✔
986
    ids.queryRealTime.start();
2✔
987
    PacketBuffer query;
2✔
988
    GenericDNSPacketWriter<PacketBuffer> pwQ(query, ids.qname, QType::A, QClass::IN, 0);
2✔
989
    pwQ.getHeader()->rd = 1;
2✔
990
    pwQ.getHeader()->id = htons(42);
2✔
991

992
    DNSQuestion dnsQuestion(ids, query);
2✔
993
    dnsdist_ffi_dnsquestion_t lightDQ(&dnsQuestion);
2✔
994
    std::array<const dnsdist_ffi_svc_record_parameters*, 1> list = {parameters};
2✔
995
    BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_generate_svc_response(&lightDQ, list.data(), list.size(), 42), true);
2✔
996
  }
2✔
997

998
  dnsdist_ffi_svc_record_parameters_free(parameters);
2✔
999
}
2✔
1000

1001
BOOST_AUTO_TEST_SUITE_END();
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc