7 flxDnsPacket* flx_dns_packet_new(guint max_size) {
11 max_size = FLX_DNS_PACKET_MAX_SIZE;
12 else if (max_size < FLX_DNS_PACKET_HEADER_SIZE)
13 max_size = FLX_DNS_PACKET_HEADER_SIZE;
15 p = g_malloc(sizeof(flxDnsPacket) + max_size);
16 p->size = p->rindex = FLX_DNS_PACKET_HEADER_SIZE;
17 p->max_size = max_size;
19 memset(FLX_DNS_PACKET_DATA(p), 0, p->size);
23 flxDnsPacket* flx_dns_packet_new_query(guint max_size) {
26 p = flx_dns_packet_new(max_size);
27 flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
31 flxDnsPacket* flx_dns_packet_new_response(guint max_size) {
34 p = flx_dns_packet_new(max_size);
35 flx_dns_packet_set_field(p, DNS_FIELD_FLAGS, DNS_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
39 void flx_dns_packet_free(flxDnsPacket *p) {
44 void flx_dns_packet_set_field(flxDnsPacket *p, guint index, guint16 v) {
46 g_assert(index < FLX_DNS_PACKET_HEADER_SIZE);
48 ((guint16*) FLX_DNS_PACKET_DATA(p))[index] = g_htons(v);
51 guint16 flx_dns_packet_get_field(flxDnsPacket *p, guint index) {
53 g_assert(index < FLX_DNS_PACKET_HEADER_SIZE);
55 return g_ntohs(((guint16*) FLX_DNS_PACKET_DATA(p))[index]);
58 guint8* flx_dns_packet_append_name(flxDnsPacket *p, const gchar *name) {
68 guint n = strcspn(name, ".");
72 if (!(d = flx_dns_packet_extend(p, n+1)))
93 if (!(d = flx_dns_packet_extend(p, 1)))
101 p->size = saved_size;
105 guint8* flx_dns_packet_append_uint16(flxDnsPacket *p, guint16 v) {
109 if (!(d = flx_dns_packet_extend(p, sizeof(guint16))))
112 *((guint16*) d) = g_htons(v);
116 guint8 *flx_dns_packet_append_uint32(flxDnsPacket *p, guint32 v) {
120 if (!(d = flx_dns_packet_extend(p, sizeof(guint32))))
123 *((guint32*) d) = g_htonl(v);
128 guint8 *flx_dns_packet_append_bytes(flxDnsPacket *p, gconstpointer b, guint l) {
135 if (!(d = flx_dns_packet_extend(p, l)))
142 guint8 *flx_dns_packet_extend(flxDnsPacket *p, guint l) {
147 if (p->size+l > p->max_size)
150 d = FLX_DNS_PACKET_DATA(p) + p->size;
156 guint8 *flx_dns_packet_append_name_compressed(flxDnsPacket *p, const gchar *name, guint8 *prev) {
162 return flx_dns_packet_append_name(p, name);
164 k = prev - FLX_DNS_PACKET_DATA(p);
165 if (k < 0 || k >= 0x4000 || (guint) k >= p->size)
166 return flx_dns_packet_append_name(p, name);
168 if (!(d = (guint16*) flx_dns_packet_extend(p, sizeof(guint16))))
171 *d = g_htons((0xC000 | k));
175 gint flx_dns_packet_check_valid(flxDnsPacket *p) {
182 flags = flx_dns_packet_get_field(p, DNS_FIELD_FLAGS);
184 if (flags & DNS_FLAG_OPCODE || flags & DNS_FLAG_RCODE)
190 gint flx_dns_packet_is_query(flxDnsPacket *p) {
193 return !(flx_dns_packet_get_field(p, DNS_FIELD_FLAGS) & DNS_FLAG_QR);
196 static gint consume_labels(flxDnsPacket *p, guint index, gchar *ret_name, guint l) {
200 g_assert(p && ret_name && l);
205 if (index+1 > p->size)
208 n = FLX_DNS_PACKET_DATA(p)[index];
221 } else if (n <= 63) {
222 /* Uncompressed label */
227 if (index + n > p->size)
230 if ((guint) n + 1 > l)
239 memcpy(ret_name, FLX_DNS_PACKET_DATA(p) + index, n);
246 } else if ((n & 0xC0) == 0xC0) {
247 /* Compressed label */
249 if (index+2 > p->size)
252 index = ((guint) (FLX_DNS_PACKET_DATA(p)[index] & ~0xC0)) << 8 | FLX_DNS_PACKET_DATA(p)[index+1];
263 gint flx_dns_packet_consume_name(flxDnsPacket *p, gchar *ret_name, guint l) {
266 if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0)
273 gint flx_dns_packet_consume_uint16(flxDnsPacket *p, guint16 *ret_v) {
277 if (p->rindex + sizeof(guint16) > p->size)
280 *ret_v = g_ntohs(*((guint16*) (FLX_DNS_PACKET_DATA(p) + p->rindex)));
281 p->rindex += sizeof(guint16);
286 gint flx_dns_packet_consume_uint32(flxDnsPacket *p, guint32 *ret_v) {
290 if (p->rindex + sizeof(guint32) > p->size)
293 *ret_v = g_ntohl(*((guint32*) (FLX_DNS_PACKET_DATA(p) + p->rindex)));
294 p->rindex += sizeof(guint32);
299 gint flx_dns_packet_consume_bytes(flxDnsPacket *p, gpointer ret_data, guint l) {
304 if (p->rindex + l > p->size)
307 memcpy(ret_data, FLX_DNS_PACKET_DATA(p) + p->rindex, l);
313 gconstpointer flx_dns_packet_get_rptr(flxDnsPacket *p) {
316 if (p->rindex >= p->size)
319 return FLX_DNS_PACKET_DATA(p) + p->rindex;
322 gint flx_dns_packet_skip(flxDnsPacket *p, guint length) {
325 if (p->rindex + length > p->size)
332 flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_flush) {
333 gchar name[257], buf[257+6];
340 g_assert(ret_cache_flush);
342 if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
343 flx_dns_packet_consume_uint16(p, &type) < 0 ||
344 flx_dns_packet_consume_uint16(p, &class) < 0 ||
345 flx_dns_packet_consume_uint32(p, &ttl) < 0 ||
346 flx_dns_packet_consume_uint16(p, &rdlength) < 0)
350 case FLX_DNS_TYPE_PTR:
351 case FLX_DNS_TYPE_CNAME:
352 if (flx_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
356 rdlength = strlen(buf);
359 case FLX_DNS_TYPE_SRV: {
360 const guint8 *t = flx_dns_packet_get_rptr(p);
362 if (flx_dns_packet_skip(p, 6) < 0)
367 if (flx_dns_packet_consume_name(p, buf+6, sizeof(buf)-6) < 0)
371 rdlength = 6 + strlen(buf+6);
376 if (!(data = flx_dns_packet_get_rptr(p)) ||
377 flx_dns_packet_skip(p, rdlength) < 0)
383 *ret_cache_flush = !!(class & MDNS_CACHE_FLUSH);
384 class &= ~ MDNS_CACHE_FLUSH;
386 return flx_record_new_full(name, class, type, data, rdlength, ttl);
389 flxKey* flx_dns_packet_consume_key(flxDnsPacket *p) {
395 if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
396 flx_dns_packet_consume_uint16(p, &type) < 0 ||
397 flx_dns_packet_consume_uint16(p, &class) < 0)
400 class &= ~ MDNS_CACHE_FLUSH;
402 return flx_key_new(name, class, type);
405 guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k) {
411 if (!(t = flx_dns_packet_append_name(p, k->name)) ||
412 !flx_dns_packet_append_uint16(p, k->type) ||
413 !flx_dns_packet_append_uint16(p, k->class))
419 guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cache_flush) {
425 if (!(t = flx_dns_packet_append_name(p, r->key->name)) ||
426 !flx_dns_packet_append_uint16(p, r->key->type) ||
427 !flx_dns_packet_append_uint16(p, cache_flush ? (r->key->class | MDNS_CACHE_FLUSH) : (r->key->class &~ MDNS_CACHE_FLUSH)) ||
428 !flx_dns_packet_append_uint32(p, r->ttl))
431 switch (r->key->type) {
433 case FLX_DNS_TYPE_PTR:
434 case FLX_DNS_TYPE_CNAME: {
437 g_assert((size_t) r->size+1 <= sizeof(ptr_name));
438 memcpy(ptr_name, r->data, r->size);
439 ptr_name[r->size] = 0;
441 if (!flx_dns_packet_append_uint16(p, strlen(ptr_name)) ||
442 !flx_dns_packet_append_name(p, ptr_name))
448 case FLX_DNS_TYPE_SRV: {
451 g_assert(r->size >= 6 && (size_t) r->size-6+1 <= sizeof(name));
452 memcpy(name, r->data+6, r->size-6);
455 if (!flx_dns_packet_append_uint16(p, strlen(name+6)) ||
456 !flx_dns_packet_append_bytes(p, r->data, 6) ||
457 !flx_dns_packet_append_name(p, name))
464 if (!flx_dns_packet_append_uint16(p, r->size) ||
465 !flx_dns_packet_append_bytes(p, r->data, r->size))