GNUnet 0.22.2
dnsparser.c File Reference

helper library to parse DNS packets. More...

#include "platform.h"
#include "gnunet_util_lib.h"
Include dependency graph for dnsparser.c:

Go to the source code of this file.

Functions

int GNUNET_DNSPARSER_check_label (const char *label)
 Check if a label in UTF-8 format can be coded into valid IDNA. More...
 
int GNUNET_DNSPARSER_check_name (const char *name)
 Check if a label in UTF-8 format can be coded into valid IDNA. More...
 
void GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa)
 Free SOA information record. More...
 
void GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert)
 Free CERT information record. More...
 
void GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv)
 Free SRV information record. More...
 
void GNUNET_DNSPARSER_free_uri (struct GNUNET_DNSPARSER_UriRecord *uri)
 Free URI information record. More...
 
void GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx)
 Free MX information record. More...
 
void GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r)
 Free the given DNS record. More...
 
static char * parse_name (const char *udp_payload, size_t udp_payload_length, size_t *off, unsigned int depth)
 Parse name inside of a DNS query or record. More...
 
char * GNUNET_DNSPARSER_parse_name (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse name inside of a DNS query or record. More...
 
int GNUNET_DNSPARSER_parse_query (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Query *q)
 Parse a DNS query entry. More...
 
struct GNUNET_DNSPARSER_SoaRecordGNUNET_DNSPARSER_parse_soa (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse a DNS SOA record. More...
 
struct GNUNET_DNSPARSER_MxRecordGNUNET_DNSPARSER_parse_mx (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse a DNS MX record. More...
 
struct GNUNET_DNSPARSER_SrvRecordGNUNET_DNSPARSER_parse_srv (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse a DNS SRV record. More...
 
struct GNUNET_DNSPARSER_UriRecordGNUNET_DNSPARSER_parse_uri (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse a DNS URI record. More...
 
struct GNUNET_DNSPARSER_CertRecordGNUNET_DNSPARSER_parse_cert (const char *udp_payload, size_t udp_payload_length, size_t *off)
 Parse a DNS CERT record. More...
 
int GNUNET_DNSPARSER_parse_record (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Record *r)
 Parse a DNS record entry. More...
 
struct GNUNET_DNSPARSER_PacketGNUNET_DNSPARSER_parse (const char *udp_payload, size_t udp_payload_length)
 Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation. More...
 
struct GNUNET_DNSPARSER_RecordGNUNET_DNSPARSER_duplicate_record (const struct GNUNET_DNSPARSER_Record *r)
 Duplicate (deep-copy) the given DNS record. More...
 
struct GNUNET_DNSPARSER_SoaRecordGNUNET_DNSPARSER_duplicate_soa_record (const struct GNUNET_DNSPARSER_SoaRecord *r)
 Duplicate (deep-copy) the given DNS record. More...
 
struct GNUNET_DNSPARSER_CertRecordGNUNET_DNSPARSER_duplicate_cert_record (const struct GNUNET_DNSPARSER_CertRecord *r)
 Duplicate (deep-copy) the given DNS record. More...
 
struct GNUNET_DNSPARSER_MxRecordGNUNET_DNSPARSER_duplicate_mx_record (const struct GNUNET_DNSPARSER_MxRecord *r)
 Duplicate (deep-copy) the given DNS record. More...
 
struct GNUNET_DNSPARSER_SrvRecordGNUNET_DNSPARSER_duplicate_srv_record (const struct GNUNET_DNSPARSER_SrvRecord *r)
 Duplicate (deep-copy) the given DNS record. More...
 
struct GNUNET_DNSPARSER_UriRecordGNUNET_DNSPARSER_duplicate_uri_record (const struct GNUNET_DNSPARSER_UriRecord *r)
 Duplicate (deep-copy) the given DNS record. More...
 
void GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p)
 Free memory taken by a packet. More...
 
int GNUNET_DNSPARSER_builder_add_name (char *dst, size_t dst_len, size_t *off, const char *name)
 Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as necessary. More...
 
int GNUNET_DNSPARSER_builder_add_query (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_Query *query)
 Add a DNS query to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_builder_add_mx (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
 Add an MX record to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_builder_add_cert (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_CertRecord *cert)
 Add a CERT record to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_builder_add_soa (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
 Add an SOA record to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_builder_add_srv (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
 Add an SRV record to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_builder_add_uri (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_UriRecord *uri)
 Add an URI record to the UDP packet at the given location. More...
 
static int add_record (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_Record *record)
 Add a DNS record to the UDP packet at the given location. More...
 
int GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
 Given a DNS packet p, generate the corresponding UDP payload. More...
 
char * GNUNET_DNSPARSER_bin_to_hex (const void *data, size_t data_size)
 Convert a block of binary data to HEX. More...
 
size_t GNUNET_DNSPARSER_hex_to_bin (const char *hex, void *data)
 Convert a HEX string to block of binary data. More...
 

Detailed Description

helper library to parse DNS packets.

Author
Philipp Toelke
Christian Grothoff

Definition in file dnsparser.c.

Function Documentation

◆ parse_name()

static char * parse_name ( const char *  udp_payload,
size_t  udp_payload_length,
size_t *  off,
unsigned int  depth 
)
static

Parse name inside of a DNS query or record.

Parameters
udp_payloadentire UDP payload
udp_payload_lengthlength of udp_payload
offpointer to the offset of the name to parse in the udp_payload (to be incremented by the size of the name)
depthcurrent depth of our recursion (to prevent stack overflow)
Returns
name as 0-terminated C string on success, NULL if the payload is malformed

Definition at line 233 of file dnsparser.c.

237{
238 const uint8_t *input = (const uint8_t *) udp_payload;
239 char *ret;
240 char *tmp;
241 char *xstr;
242 uint8_t len;
243 size_t xoff;
244 char *utf8;
245 Idna_rc rc;
246
247 ret = GNUNET_strdup ("");
248 while (1)
249 {
250 if (*off >= udp_payload_length)
251 {
252 GNUNET_break_op (0);
253 goto error;
254 }
255 len = input[*off];
256 if (0 == len)
257 {
258 (*off)++;
259 break;
260 }
261 if (len < 64)
262 {
263 if (*off + 1 + len > udp_payload_length)
264 {
265 GNUNET_break_op (0);
266 goto error;
267 }
268 GNUNET_asprintf (&tmp, "%.*s", (int) len, &udp_payload[*off + 1]);
269 if (IDNA_SUCCESS !=
270 (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED)))
271 {
273 _ ("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
274 tmp,
275 idna_strerror (rc));
276 GNUNET_free (tmp);
277 GNUNET_asprintf (&tmp,
278 "%s%.*s.",
279 ret,
280 (int) len,
281 &udp_payload[*off + 1]);
282 }
283 else
284 {
285 GNUNET_free (tmp);
286 GNUNET_asprintf (&tmp, "%s%s.", ret, utf8);
287 free (utf8);
288 }
290 ret = tmp;
291 *off += 1 + len;
292 }
293 else if ((64 | 128) == (len & (64 | 128)))
294 {
295 if (depth > 32)
296 {
297 GNUNET_break_op (0);
298 goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */
299 }
300 /* pointer to string */
301 if (*off + 1 > udp_payload_length)
302 {
303 GNUNET_break_op (0);
304 goto error;
305 }
306 xoff = ((len - (64 | 128)) << 8) + input[*off + 1];
307 xstr = parse_name (udp_payload, udp_payload_length, &xoff, depth + 1);
308 if (NULL == xstr)
309 {
310 GNUNET_break_op (0);
311 goto error;
312 }
313 GNUNET_asprintf (&tmp, "%s%s.", ret, xstr);
315 GNUNET_free (xstr);
316 ret = tmp;
317 if (strlen (ret) > udp_payload_length)
318 {
319 GNUNET_break_op (0);
320 goto error; /* we are looping (building an infinite string) */
321 }
322 *off += 2;
323 /* pointers always terminate names */
324 break;
325 }
326 else
327 {
328 /* neither pointer nor inline string, not supported... */
329 GNUNET_break_op (0);
330 goto error;
331 }
332 }
333 if (0 < strlen (ret))
334 ret[strlen (ret) - 1] = '\0'; /* eat tailing '.' */
335 return ret;
336error:
337 GNUNET_break_op (0);
339 return NULL;
340}
static char * parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off, unsigned int depth)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:233
static int ret
Final status code.
Definition: gnunet-arm.c:93
#define GNUNET_log(kind,...)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_free(ptr)
Wrapper around free.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178

References _, GNUNET_asprintf(), GNUNET_break_op, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_strdup, parse_name(), and ret.

Referenced by GNUNET_DNSPARSER_parse_name(), and parse_name().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_record()

static int add_record ( char *  dst,
size_t  dst_len,
size_t *  off,
const struct GNUNET_DNSPARSER_Record record 
)
static

Add a DNS record to the UDP packet at the given location.

Parameters
dstwhere to write the query
dst_lennumber of bytes in dst
offpointer to offset where to write the query (increment by bytes used) must not be changed if there is an error
recordrecord to write
Returns
GNUNET_SYSERR if record is invalid GNUNET_NO if record did not fit GNUNET_OK if record was added to dst

Definition at line 1293 of file dnsparser.c.

1297{
1298 int ret;
1299 size_t start;
1300 size_t pos;
1301 struct GNUNET_TUN_DnsRecordLine rl;
1302
1303 if (dst_len < sizeof(struct GNUNET_TUN_DnsRecordLine))
1304 return GNUNET_NO;
1305 start = *off;
1307 dst,
1308 dst_len - sizeof(struct GNUNET_TUN_DnsRecordLine),
1309 off,
1310 record->name);
1311 if (GNUNET_OK != ret)
1312 return ret;
1313 /* '*off' is now the position where we will need to write the record line */
1314
1315 pos = *off + sizeof(struct GNUNET_TUN_DnsRecordLine);
1316 switch (record->type)
1317 {
1319 ret = GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &pos, record->data.mx);
1320 break;
1321
1323 ret =
1324 GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &pos, record->data.cert);
1325 break;
1326
1328 ret =
1329 GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &pos, record->data.soa);
1330 break;
1331
1336 dst_len,
1337 &pos,
1338 record->data.hostname);
1339 break;
1341 ret =
1342 GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &pos, record->data.srv);
1343 break;
1345 ret =
1346 GNUNET_DNSPARSER_builder_add_uri (dst, dst_len, &pos, record->data.uri);
1347 break;
1348 default:
1349 if ( (pos + record->data.raw.data_len < pos) ||
1350 (pos + record->data.raw.data_len > dst_len) )
1351 {
1352 ret = GNUNET_NO;
1353 break;
1354 }
1355 GNUNET_memcpy (&dst[pos], record->data.raw.data, record->data.raw.data_len);
1356 pos += record->data.raw.data_len;
1357 ret = GNUNET_OK;
1358 break;
1359 }
1360 if (GNUNET_OK != ret)
1361 {
1362 *off = start;
1363 return GNUNET_NO;
1364 }
1365
1366 if (pos - (*off + sizeof(struct GNUNET_TUN_DnsRecordLine)) > UINT16_MAX)
1367 {
1368 /* record data too long */
1369 *off = start;
1370 return GNUNET_NO;
1371 }
1372 rl.type = htons (record->type);
1373 rl.dns_traffic_class = htons (record->dns_traffic_class);
1374 rl.ttl = htonl (
1376 / 1000LL / 1000LL); /* in seconds */
1377 rl.data_len = htons (
1378 (uint16_t) (pos - (*off + sizeof(struct GNUNET_TUN_DnsRecordLine))));
1379 GNUNET_memcpy (&dst[*off], &rl, sizeof(struct GNUNET_TUN_DnsRecordLine));
1380 *off = pos;
1381 return GNUNET_OK;
1382}
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
#define GNUNET_DNSPARSER_TYPE_URI
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:985
int GNUNET_DNSPARSER_builder_add_cert(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_CertRecord *cert)
Add a CERT record to the UDP packet at the given location.
Definition: dnsparser.c:1129
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_CERT
#define GNUNET_DNSPARSER_TYPE_PTR
#define GNUNET_DNSPARSER_TYPE_NS
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition: dnsparser.c:1177
#define GNUNET_DNSPARSER_TYPE_CNAME
int GNUNET_DNSPARSER_builder_add_mx(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
Add an MX record to the UDP packet at the given location.
Definition: dnsparser.c:1099
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition: dnsparser.c:1218
int GNUNET_DNSPARSER_builder_add_uri(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_UriRecord *uri)
Add an URI record to the UDP packet at the given location.
Definition: dnsparser.c:1255
#define GNUNET_DNSPARSER_TYPE_MX
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_NO
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:406
uint64_t rel_value_us
The actual value.
General DNS record prefix.

References GNUNET_TUN_DnsRecordLine::data_len, GNUNET_TUN_DnsRecordLine::dns_traffic_class, GNUNET_DNSPARSER_builder_add_cert(), GNUNET_DNSPARSER_builder_add_mx(), GNUNET_DNSPARSER_builder_add_name(), GNUNET_DNSPARSER_builder_add_soa(), GNUNET_DNSPARSER_builder_add_srv(), GNUNET_DNSPARSER_builder_add_uri(), GNUNET_DNSPARSER_TYPE_CERT, GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_NS, GNUNET_DNSPARSER_TYPE_PTR, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_DNSPARSER_TYPE_URI, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_TIME_absolute_get_remaining(), record(), GNUNET_TIME_Relative::rel_value_us, ret, start, GNUNET_TUN_DnsRecordLine::ttl, and GNUNET_TUN_DnsRecordLine::type.

Referenced by GNUNET_DNSPARSER_pack().

Here is the call graph for this function:
Here is the caller graph for this function: