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

PowerDNS / pdns / 18743945403

23 Oct 2025 09:29AM UTC coverage: 65.845% (+0.02%) from 65.829%
18743945403

Pull #16356

github

web-flow
Merge 8a2027ef1 into efa3637e8
Pull Request #16356: auth 5.0: backport "pdnsutil: fix b2b-migrate to from sql to non-sql"

42073 of 92452 branches covered (45.51%)

Branch coverage included in aggregate %.

128008 of 165855 relevant lines covered (77.18%)

6379935.17 hits per line

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

92.4
/pdns/protozero.hh
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
#pragma once
23

24
#include "config.h"
25

26
#include "iputils.hh"
27
#include "gettime.hh"
28
#include "uuid-utils.hh"
29

30
#ifndef DISABLE_PROTOBUF
31

32
#include <protozero/pbf_writer.hpp>
33

34
namespace pdns
35
{
36
namespace ProtoZero
37
{
38
  class Message
39
  {
40
  public:
41
    enum class MetaValueField : protozero::pbf_tag_type
42
    {
43
      stringVal = 1,
44
      intVal = 2
45
    };
46
    enum class HTTPVersion : protozero::pbf_tag_type
47
    {
48
      HTTP1 = 1,
49
      HTTP2 = 2,
50
      HTTP3 = 3
51
    };
52
    enum class MetaField : protozero::pbf_tag_type
53
    {
54
      key = 1,
55
      value = 2
56
    };
57
    enum class Event : protozero::pbf_tag_type
58
    {
59
      ts = 1,
60
      event = 2,
61
      start = 3,
62
      boolVal = 4,
63
      intVal = 5,
64
      stringVal = 6,
65
      bytesVal = 7,
66
      custom = 8
67
    };
68
    enum class MessageType : int32_t
69
    {
70
      DNSQueryType = 1,
71
      DNSResponseType = 2,
72
      DNSOutgoingQueryType = 3,
73
      DNSIncomingResponseType = 4
74
    };
75
    enum class Field : protozero::pbf_tag_type
76
    {
77
      type = 1,
78
      messageId = 2,
79
      serverIdentity = 3,
80
      socketFamily = 4,
81
      socketProtocol = 5,
82
      from = 6,
83
      to = 7,
84
      inBytes = 8,
85
      timeSec = 9,
86
      timeUsec = 10,
87
      id = 11,
88
      question = 12,
89
      response = 13,
90
      originalRequestorSubnet = 14,
91
      requestorId = 15,
92
      initialRequestId = 16,
93
      deviceId = 17,
94
      newlyObservedDomain = 18,
95
      deviceName = 19,
96
      fromPort = 20,
97
      toPort = 21,
98
      meta = 22,
99
      trace = 23,
100
      httpVersion = 24,
101
      workerId = 25,
102
      packetCacheHit = 26,
103
      outgoingQueries = 27,
104
      headerFlags = 28,
105
      ednsVersion = 29,
106
      openTelemetryData = 30,
107
    };
108
    enum class QuestionField : protozero::pbf_tag_type
109
    {
110
      qName = 1,
111
      qType = 2,
112
      qClass = 3
113
    };
114
    enum class ResponseField : protozero::pbf_tag_type
115
    {
116
      rcode = 1,
117
      rrs = 2,
118
      appliedPolicy = 3,
119
      tags = 4,
120
      queryTimeSec = 5,
121
      queryTimeUsec = 6,
122
      appliedPolicyType = 7,
123
      appliedPolicyTrigger = 8,
124
      appliedPolicyHit = 9,
125
      appliedPolicyKind = 10,
126
      validationState = 11
127
    };
128
    enum class RRField : protozero::pbf_tag_type
129
    {
130
      name = 1,
131
      type = 2,
132
      class_ = 3,
133
      ttl = 4,
134
      rdata = 5,
135
      udr = 6
136
    };
137
    enum class TransportProtocol : protozero::pbf_tag_type
138
    {
139
      UDP = 1,
140
      TCP = 2,
141
      DoT = 3,
142
      DoH = 4,
143
      DNSCryptUDP = 5,
144
      DNSCryptTCP = 6,
145
      DoQ = 7
146
    };
147

148
    Message(std::string& buffer) :
149
      d_buffer(buffer), d_message{d_buffer}
38✔
150
    {
3,264✔
151
    }
3,264✔
152
    ~Message() = default;
3,264✔
153
    Message(const Message&) = delete;
154
    Message(Message&&) = delete;
155
    Message& operator=(const Message&) = delete;
156
    Message& operator=(Message&&) = delete;
157

158
    void setRequest(const boost::uuids::uuid& uniqueId, const ComboAddress& requestor, const ComboAddress& local, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint16_t qid, TransportProtocol proto, size_t len);
159
    void setResponse(const DNSName& qname, uint16_t qtype, uint16_t qclass);
160

161
    void setType(MessageType mtype)
162
    {
131✔
163
      add_enum(d_message, Field::type, static_cast<int32_t>(mtype));
131✔
164
    }
131✔
165

166
    void setHTTPVersion(HTTPVersion version)
167
    {
5✔
168
      add_enum(d_message, Field::httpVersion, static_cast<int32_t>(version));
5✔
169
    }
5✔
170

171
    void setMessageIdentity(const boost::uuids::uuid& uniqueId)
172
    {
138✔
173
      add_bytes(d_message, Field::messageId, reinterpret_cast<const char*>(uniqueId.begin()), uniqueId.size()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast): it's the API
138✔
174
    }
138✔
175

176
    void setServerIdentity(const std::string& serverIdentity)
177
    {
131✔
178
      add_bytes(d_message, Field::serverIdentity, serverIdentity.data(), serverIdentity.length());
131✔
179
    }
131✔
180

181
    void setSocketFamily(int family)
182
    {
138✔
183
      add_enum(d_message, Field::socketFamily, family == AF_INET ? 1 : 2);
138✔
184
    }
138✔
185

186
    void setSocketProtocol(TransportProtocol proto)
187
    {
138✔
188
      add_enum(d_message, Field::socketProtocol, static_cast<int32_t>(proto));
138✔
189
    }
138✔
190

191
    void setFrom(const ComboAddress& address)
192
    {
101✔
193
      encodeComboAddress(static_cast<protozero::pbf_tag_type>(Field::from), address);
101✔
194
    }
101✔
195

196
    void setTo(const ComboAddress& address)
197
    {
138✔
198
      encodeComboAddress(static_cast<protozero::pbf_tag_type>(Field::to), address);
138✔
199
    }
138✔
200

201
    void setInBytes(uint64_t len)
202
    {
129✔
203
      add_uint64(d_message, Field::inBytes, len);
129✔
204
    }
129✔
205

206
    void setTime()
207
    {
138✔
208
      timespec timesp{};
138✔
209
      gettime(&timesp, true);
138✔
210

211
      setTime(timesp.tv_sec, timesp.tv_nsec / 1000);
138✔
212
    }
138✔
213

214
    void setTime(time_t sec, uint32_t usec)
215
    {
176✔
216
      // coverity[store_truncates_time_t]
217
      add_uint32(d_message, Field::timeSec, sec);
176✔
218
      add_uint32(d_message, Field::timeUsec, usec);
176✔
219
    }
176✔
220

221
    void setId(uint16_t qid)
222
    {
138✔
223
      add_uint32(d_message, Field::id, ntohs(qid));
138✔
224
    }
138✔
225

226
    void setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass)
227
    {
131✔
228
      protozero::pbf_writer pbf_question{d_message, static_cast<protozero::pbf_tag_type>(Field::question)};
131✔
229
      encodeDNSName(pbf_question, d_buffer, static_cast<protozero::pbf_tag_type>(QuestionField::qName), qname);
131✔
230
      pbf_question.add_uint32(static_cast<protozero::pbf_tag_type>(QuestionField::qType), qtype);
131✔
231
      pbf_question.add_uint32(static_cast<protozero::pbf_tag_type>(QuestionField::qClass), qclass);
131✔
232
    }
131✔
233

234
    void setMeta(const std::string& key, const std::unordered_set<std::string>& stringVal, const std::unordered_set<int64_t>& intVal)
235
    {
97✔
236
      protozero::pbf_writer pbf_meta{d_message, static_cast<protozero::pbf_tag_type>(Field::meta)};
97✔
237
      pbf_meta.add_string(static_cast<protozero::pbf_tag_type>(MetaField::key), key);
97✔
238
      protozero::pbf_writer pbf_meta_value{pbf_meta, static_cast<protozero::pbf_tag_type>(MetaField::value)};
97✔
239
      for (const auto& str : stringVal) {
100✔
240
        pbf_meta_value.add_string(static_cast<protozero::pbf_tag_type>(MetaValueField::stringVal), str);
100✔
241
      }
100✔
242
      for (const auto& val : intVal) {
97✔
243
        pbf_meta_value.add_uint64(static_cast<protozero::pbf_tag_type>(MetaValueField::intVal), val);
5✔
244
      }
5✔
245
    }
97✔
246

247
    void setEDNSSubnet(const Netmask& netmask, uint8_t mask)
248
    {
69✔
249
      encodeNetmask(static_cast<protozero::pbf_tag_type>(Field::originalRequestorSubnet), netmask, mask);
69✔
250
    }
69✔
251

252
    void setRequestorId(const std::string& req)
253
    {
63✔
254
      if (!req.empty()) {
63✔
255
        add_string(d_message, Field::requestorId, req);
8✔
256
      }
8✔
257
    }
63✔
258

259
    void setInitialRequestID(const boost::uuids::uuid& uniqueId)
260
    {
37✔
261
      add_bytes(d_message, Field::initialRequestId, reinterpret_cast<const char*>(uniqueId.begin()), uniqueId.size()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast): it's the API
37✔
262
    }
37✔
263

264
    void setDeviceId(const std::string& deviceId)
265
    {
63✔
266
      if (!deviceId.empty()) {
63✔
267
        add_string(d_message, Field::deviceId, deviceId);
8✔
268
      }
8✔
269
    }
63✔
270

271
    void setNewlyObservedDomain(bool nod)
272
    {
×
273
      add_bool(d_message, Field::newlyObservedDomain, nod);
×
274
    }
×
275

276
    void setDeviceName(const std::string& name)
277
    {
63✔
278
      if (!name.empty()) {
63✔
279
        add_string(d_message, Field::deviceName, name);
8✔
280
      }
8✔
281
    }
63✔
282

283
    void setFromPort(in_port_t port)
284
    {
101✔
285
      add_uint32(d_message, Field::fromPort, port);
101✔
286
    }
101✔
287

288
    void setToPort(in_port_t port)
289
    {
138✔
290
      add_uint32(d_message, Field::toPort, port);
138✔
291
    }
138✔
292

293
    void setWorkerId(uint64_t wid)
294
    {
63✔
295
      add_uint64(d_message, Field::workerId, wid);
63✔
296
    }
63✔
297

298
    void setPacketCacheHit(bool hit)
299
    {
57✔
300
      add_bool(d_message, Field::packetCacheHit, hit);
57✔
301
    }
57✔
302

303
    void setOutgoingQueries(uint32_t num)
304
    {
48✔
305
      add_uint32(d_message, Field::outgoingQueries, num);
48✔
306
    }
48✔
307

308
    void setHeaderFlags(uint16_t flags)
309
    {
26✔
310
      add_uint32(d_message, Field::headerFlags, flags);
26✔
311
    }
26✔
312

313
    void setEDNSVersion(uint32_t version)
314
    {
26✔
315
      add_uint32(d_message, Field::ednsVersion, version);
26✔
316
    }
26✔
317

318
    void setOpenTelemetryData(const std::string& data)
319
    {
×
320
      if (!data.empty()) {
×
321
        add_string(d_message, Field::openTelemetryData, data);
×
322
      }
×
323
    }
×
324

325
    void startResponse()
326
    {
60✔
327
      d_response = protozero::pbf_writer{d_message, static_cast<protozero::pbf_tag_type>(Field::response)};
60✔
328
    }
60✔
329

330
    void commitResponse()
331
    {
60✔
332
      d_response.commit();
60✔
333
    }
60✔
334

335
    void setResponseCode(uint8_t rcode)
336
    {
72✔
337
      d_response.add_uint32(static_cast<protozero::pbf_tag_type>(ResponseField::rcode), rcode);
72✔
338
    }
72✔
339

340
    void setNetworkErrorResponseCode()
341
    {
×
342
      /* special code meaning 'network error', like a timeout */
343
      d_response.add_uint32(static_cast<protozero::pbf_tag_type>(ResponseField::rcode), 65536);
×
344
    }
×
345

346
    void setAppliedPolicy(const std::string& policy)
347
    {
3✔
348
      d_response.add_string(static_cast<protozero::pbf_tag_type>(ResponseField::appliedPolicy), policy);
3✔
349
    }
3✔
350

351
    void addPolicyTags(const std::unordered_set<std::string>& tags)
352
    {
45✔
353
      for (const auto& tag : tags) {
45✔
354
        addPolicyTag(tag);
28✔
355
      }
28✔
356
    }
45✔
357

358
    void addPolicyTag(const string& tag)
359
    {
64✔
360
      d_response.add_string(static_cast<protozero::pbf_tag_type>(ResponseField::tags), tag);
64✔
361
    }
64✔
362

363
    void setQueryTime(uint32_t sec, uint32_t usec)
364
    {
97✔
365
      d_response.add_uint32(static_cast<protozero::pbf_tag_type>(ResponseField::queryTimeSec), sec);
97✔
366
      d_response.add_uint32(static_cast<protozero::pbf_tag_type>(ResponseField::queryTimeUsec), usec);
97✔
367
    }
97✔
368

369
    void addRRsFromPacket(const char* packet, size_t len, bool includeCNAME = false);
370
    void addRR(const DNSName& name, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& blob);
371

372
  protected:
373
    void encodeComboAddress(protozero::pbf_tag_type type, const ComboAddress& address);
374
    void encodeNetmask(protozero::pbf_tag_type type, const Netmask& subnet, uint8_t mask);
375
    static void encodeDNSName(protozero::pbf_writer& pbf, std::string& buffer, protozero::pbf_tag_type type, const DNSName& name);
376

377
    static void add_enum(protozero::pbf_writer& writer, Field type, int32_t value)
378
    {
412✔
379
      writer.add_enum(static_cast<protozero::pbf_tag_type>(type), value);
412✔
380
    }
412✔
381

382
    static void add_bool(protozero::pbf_writer& writer, Field type, bool value)
383
    {
57✔
384
      writer.add_bool(static_cast<protozero::pbf_tag_type>(type), value);
57✔
385
    }
57✔
386

387
    static void add_uint32(protozero::pbf_writer& writer, Field type, uint32_t value)
388
    {
829✔
389
      writer.add_uint32(static_cast<protozero::pbf_tag_type>(type), value);
829✔
390
    }
829✔
391

392
    static void add_uint64(protozero::pbf_writer& writer, Field type, uint64_t value)
393
    {
192✔
394
      writer.add_uint64(static_cast<protozero::pbf_tag_type>(type), value);
192✔
395
    }
192✔
396

397
    static void add_bytes(protozero::pbf_writer& writer, Field type, const char* data, size_t len)
398
    {
306✔
399
      writer.add_bytes(static_cast<protozero::pbf_tag_type>(type), data, len);
306✔
400
    }
306✔
401

402
    static void add_string(protozero::pbf_writer& writer, Field type, const std::string& str)
403
    {
24✔
404
      writer.add_string(static_cast<protozero::pbf_tag_type>(type), str);
24✔
405
    }
24✔
406

407
    // NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes)
408
    std::string& d_buffer;
409
    protozero::pbf_writer d_message;
410
    protozero::pbf_writer d_response;
411
    // NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes)
412
  };
413
};
414
};
415

416
#endif /* DISABLE_PROTOBUF */
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