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) {
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 ||
347 !(data = flx_dns_packet_get_rptr(p)) ||
348 flx_dns_packet_skip(p, rdlength) < 0)
351 *ret_cache_flush = !!(class & MDNS_CACHE_FLUSH);
352 class &= ~ MDNS_CACHE_FLUSH;
354 return flx_record_new_full(name, class, type, data, rdlength, ttl);
357 flxKey* flx_dns_packet_consume_key(flxDnsPacket *p) {
363 if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
364 flx_dns_packet_consume_uint16(p, &type) < 0 ||
365 flx_dns_packet_consume_uint16(p, &class) < 0)
368 class &= ~ MDNS_CACHE_FLUSH;
370 return flx_key_new(name, class, type);
373 guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k) {
379 if (!(t = flx_dns_packet_append_name(p, k->name)) ||
380 !flx_dns_packet_append_uint16(p, k->type) ||
381 !flx_dns_packet_append_uint16(p, k->class))
387 guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cache_flush) {
393 if (!(t = flx_dns_packet_append_name(p, r->key->name)) ||
394 !flx_dns_packet_append_uint16(p, r->key->type) ||
395 !flx_dns_packet_append_uint16(p, cache_flush ? (r->key->class | MDNS_CACHE_FLUSH) : (r->key->class &~ MDNS_CACHE_FLUSH)) ||
396 !flx_dns_packet_append_uint32(p, r->ttl) ||
397 !flx_dns_packet_append_uint16(p, r->size) ||
398 !flx_dns_packet_append_bytes(p, r->data, r->size))