This file is indexed.

/usr/include/libknot/packet/pkt.h is in libknot-dev 2.6.5-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*  Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*!
 * \file
 *
 * \brief Structure for holding DNS packet data and metadata.
 *
 * \addtogroup libknot
 * @{
 */

#pragma once

#include <stdint.h>
#include <string.h>

#include "libknot/consts.h"
#include "libknot/dname.h"
#include "libknot/mm_ctx.h"
#include "libknot/rrset.h"
#include "libknot/rrtype/opt.h"
#include "libknot/packet/wire.h"
#include "libknot/packet/compr.h"

/* Number of packet sections (ANSWER, AUTHORITY, ADDITIONAL). */
#define KNOT_PKT_SECTIONS 3

/*!
 * \brief Packet flags.
 */
enum {
	KNOT_PF_NULL      = 0 << 0, /*!< No flags. */
	KNOT_PF_FREE      = 1 << 1, /*!< Free with packet. */
	KNOT_PF_NOTRUNC   = 1 << 2, /*!< Don't truncate. */
	KNOT_PF_CHECKDUP  = 1 << 3, /*!< Check for duplicates. */
	KNOT_PF_KEEPWIRE  = 1 << 4, /*!< Keep wireformat untouched when parsing. */
	KNOT_PF_NOCANON   = 1 << 5, /*!< Don't canonicalize rrsets during parsing. */
};

/*!
 * \brief Packet section.
 * Points to RRSet and RRSet info arrays in the packet.
 * This structure is required for random access to packet sections.
 */
typedef struct {
	struct knot_pkt *pkt; /*!< Owner. */
	uint16_t pos;         /*!< Position in the rr/rrinfo fields in packet. */
	uint16_t count;       /*!< Number of RRSets in this section. */
} knot_pktsection_t;

/*!
 * \brief Structure representing a DNS packet.
 */
struct knot_pkt {

	uint8_t *wire;         /*!< Wire format of the packet. */
	size_t size;           /*!< Current wire size of the packet. */
	size_t max_size;       /*!< Maximum allowed size of the packet. */
	size_t parsed;         /*!< Parsed size. */
	uint16_t reserved;     /*!< Reserved space. */
	uint16_t qname_size;   /*!< QNAME size. */
	uint16_t rrset_count;  /*!< Packet RRSet count. */
	uint16_t flags;        /*!< Packet flags. */

	knot_rrset_t *opt_rr;   /*!< OPT RR included in the packet. */
	knot_rrset_t *tsig_rr;  /*!< TSIG RR stored in the packet. */

	/* TSIG RR position in the wire (if parsed from wire). */
	struct {
		uint8_t *pos;
		size_t len;
	} tsig_wire;

	/* Packet sections. */
	knot_section_t current;
	knot_pktsection_t sections[KNOT_PKT_SECTIONS];

	/* Packet RRSet (meta)data. */
	size_t rrset_allocd;
	knot_rrinfo_t *rr_info;
	knot_rrset_t *rr;

	knot_mm_t mm; /*!< Memory allocation context. */

	knot_compr_t compr; /*!< Compression context. */
};

/*!
 * \brief Create new packet over existing memory, or allocate new from memory context.
 *
 * \note Packet is allocated from given memory context.
 *
 * \param wire If NULL, memory of 'len' size shall be allocated.
 *        Otherwise pointer is used for the wire format of the packet.
 * \param len Wire format length.
 * \param mm Memory context (NULL for default).
 * \return New packet or NULL.
 */
knot_pkt_t *knot_pkt_new(void *wire, uint16_t len, knot_mm_t *mm);

/*!
 * \brief Copy packet.
 *
 * \note Current implementation is not very efficient, as it re-parses the wire.
 *
 * \param dst Target packet.
 * \param src Source packet.
 *
 * \return new packet or NULL
 */
int knot_pkt_copy(knot_pkt_t *dst, const knot_pkt_t *src);

/*!
 * \brief Initialized response from query packet.
 *
 * \note Question is not checked, it is expected to be checked already.
 *
 * \param pkt Given packet.
 * \param query Query.
 * \return KNOT_EOK, KNOT_EINVAL, KNOT_ESPACE
 */
int knot_pkt_init_response(knot_pkt_t *pkt, const knot_pkt_t *query);

/*! \brief Clear packet payload and free allocated data. */
void knot_pkt_clear_payload(knot_pkt_t *pkt);

/*! \brief Reinitialize packet for another use. */
void knot_pkt_clear(knot_pkt_t *pkt);

/*! \brief Begone you foul creature of the underworld. */
void knot_pkt_free(knot_pkt_t **pkt);

/*!
 * \brief Reserve an arbitrary amount of space in the packet.
 *
 * \return KNOT_EOK
 * \return KNOT_ERANGE if size can't be reserved
 */
int knot_pkt_reserve(knot_pkt_t *pkt, uint16_t size);

/*!
 * \brief Reclaim reserved size.
 *
 * \return KNOT_EOK
 * \return KNOT_ERANGE if size can't be reclaimed
 */
int knot_pkt_reclaim(knot_pkt_t *pkt, uint16_t size);

/*
 * Packet QUESTION accessors.
 */
/*! \todo Documentation */
uint16_t knot_pkt_question_size(const knot_pkt_t *pkt);

/*! \todo Documentation */
const knot_dname_t *knot_pkt_qname(const knot_pkt_t *pkt);

/*! \todo Documentation */
uint16_t knot_pkt_qtype(const knot_pkt_t *pkt);

/*! \todo Documentation */
uint16_t knot_pkt_qclass(const knot_pkt_t *pkt);

/*
 * Packet writing API.
 */

/*!
 * \brief Begin reading/writing packet section.
 *
 * \note You must proceed in the natural order (ANSWER, AUTHORITY, ADDITIONAL).
 *
 * \param pkt
 * \param section_id
 * \return KNOT_EOK or KNOT_EINVAL
 */
int knot_pkt_begin(knot_pkt_t *pkt, knot_section_t section_id);

/*!
 * \brief Put QUESTION in the packet.
 *
 * \note Since we support QD=1 only, QUESTION is a special type of packet section.
 * \note Must not be used after putting RRsets into the packet.
 *
 * \param pkt
 * \param qname
 * \param qclass
 * \param qtype
 * \return KNOT_EOK or various errors
 */
int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname,
                          uint16_t qclass, uint16_t qtype);

/*!
 * \brief Put RRSet into packet.
 *
 * \note See compr.h for description on how compression hints work.
 * \note Available flags: PF_FREE, KNOT_PF_CHECKDUP, KNOT_PF_NOTRUNC
 *
 * \param pkt
 * \param compr_hint Compression hint, see enum knot_compr_hint or absolute
 *                   position.
 * \param rr Given RRSet.
 * \param flags RRSet flags (set PF_FREE if you want RRSet to be freed with the
 *              packet).
 * \return KNOT_EOK, KNOT_ESPACE, various errors
 */
int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr,
                 uint16_t flags);

/*! \brief Get description of the given packet section. */
const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt,
                                          knot_section_t section_id);

/*! \brief Get RRSet from the packet section. */
const knot_rrset_t *knot_pkt_rr(const knot_pktsection_t *section, uint16_t i);

/*! \brief Get RRSet offset in the packet wire. */
uint16_t knot_pkt_rr_offset(const knot_pktsection_t *section, uint16_t i);

/*
 * Packet parsing API.
 */

/*!
 * \brief Parse both packet question and payload.
 *
 * Parses both QUESTION and all packet sections,
 * includes semantic checks over specific RRs (TSIG, OPT).
 *
 * \note For KNOT_PF_KEEPWIRE see note for \fn knot_pkt_parse_rr
 *
 * \param pkt Given packet.
 * \param flags Parsing flags (allowed KNOT_PF_KEEPWIRE)
 * \return KNOT_EOK, KNOT_EMALF and other errors
 */
int knot_pkt_parse(knot_pkt_t *pkt, unsigned flags);

/*!
 * \brief Parse packet header and a QUESTION section.
 */
int knot_pkt_parse_question(knot_pkt_t *pkt);

/*!
 * \brief Parse single resource record.
 *
 * \note When KNOT_PF_KEEPWIRE is set, TSIG RR is not stripped from the wire
 *       and is processed as any other RR.
 *
 * \param pkt
 * \param flags
 * \return KNOT_EOK, KNOT_EFEWDATA if not enough data or various errors
 */
int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags);

/*!
 * \brief Parse current packet section.
 *
 * \note For KNOT_PF_KEEPWIRE see note for \fn knot_pkt_parse_rr
 *
 * \param pkt
 * \param flags
 * \return KNOT_EOK, KNOT_EFEWDATA if not enough data or various errors
 */
int knot_pkt_parse_section(knot_pkt_t *pkt, unsigned flags);

/*!
 * \brief Parse whole packet payload.
 *
 * \note For KNOT_PF_KEEPWIRE see note for \fn knot_pkt_parse_rr
 *
 * \param pkt
 * \param flags
 * \return KNOT_EOK, KNOT_EFEWDATA if not enough data or various errors
 */
int knot_pkt_parse_payload(knot_pkt_t *pkt, unsigned flags);

/*!
 * \brief Get packet extended RCODE.
 *
 * Extended RCODE is created by considering TSIG RCODE, EDNS RCODE and
 * DNS Header RCODE. (See RFC 6895, Section 2.3).
 *
 * \param pkt Packet to get the response code from.
 *
 * \return Whole extended RCODE (0 if pkt == NULL).
 */
uint16_t knot_pkt_ext_rcode(const knot_pkt_t *pkt);

/*!
 * \brief Get packet extended RCODE name.
 *
 * The packet parameter is important as the name depends on TSIG.
 *
 * \param pkt Packet to get the response code from.
 *
 * \return RCODE name (or empty string if not known).
 */
const char *knot_pkt_ext_rcode_name(const knot_pkt_t *pkt);

/*!
 * \brief Checks if there is an OPT RR in the packet.
 */
static inline bool knot_pkt_has_edns(const knot_pkt_t *pkt)
{
	return pkt != NULL && pkt->opt_rr != NULL;
}

/*!
 * \brief Checks if TSIG is present.
 */
static inline bool knot_pkt_has_tsig(const knot_pkt_t *pkt)
{
	return pkt && pkt->tsig_rr;
}

/*!
 * \brief Checks if DO bit is set in the packet's OPT RR.
 */
static inline bool knot_pkt_has_dnssec(const knot_pkt_t *pkt)
{
	return knot_pkt_has_edns(pkt) && knot_edns_do(pkt->opt_rr);
}

/*!
 * \brief Checks if there is an NSID OPTION in the packet's OPT RR.
 */
static inline bool knot_pkt_has_nsid(const knot_pkt_t *pkt)
{
	return knot_pkt_has_edns(pkt)
	       && knot_edns_has_option(pkt->opt_rr, KNOT_EDNS_OPTION_NSID);
}

/*! @} */