jdns_packet_t *jdns_packet_copy(const jdns_packet_t *a) { jdns_packet_t *c = jdns_packet_new(); c->id = a->id; c->opts.qr = a->opts.qr; c->opts.opcode = a->opts.opcode; c->opts.aa = a->opts.aa; c->opts.tc = a->opts.tc; c->opts.rd = a->opts.rd; c->opts.ra = a->opts.ra; c->opts.z = a->opts.z; c->opts.rcode = a->opts.rcode; jdns_list_delete(c->questions); jdns_list_delete(c->answerRecords); jdns_list_delete(c->authorityRecords); jdns_list_delete(c->additionalRecords); c->questions = jdns_list_copy(a->questions); c->answerRecords = jdns_list_copy(a->answerRecords); c->authorityRecords = jdns_list_copy(a->authorityRecords); c->additionalRecords = jdns_list_copy(a->additionalRecords); c->fully_parsed = a->fully_parsed; c->raw_size = a->raw_size; c->raw_data = jdns_copy_array(a->raw_data, a->raw_size); return c; }
static int process_rrsection(jdns_list_t *dest, int count, const unsigned char *data, int size, const unsigned char **bufp) { int n; int offset, at; jdns_string_t *name = 0; const unsigned char *buf; buf = *bufp; for(n = 0; n < count; ++n) { jdns_packet_resource_t *r; offset = buf - data; at = 0; if(!readlabel(data + offset, size - offset, data, size, &at, &name)) goto error; offset += at; // need 10 more bytes if(offset + 10 > size) goto error; buf = data + offset; r = jdns_packet_resource_new(); r->qname = name; name = 0; r->qtype = net2short(&buf); r->qclass = net2short(&buf); r->ttl = net2long(&buf); r->rdlength = net2short(&buf); offset = buf - data; // make sure we have enough for the rdata if(size - offset < r->rdlength) { jdns_packet_resource_delete(r); goto error; } r->rdata = jdns_copy_array(buf, r->rdlength); buf += r->rdlength; jdns_list_insert_value(dest, r, -1); jdns_packet_resource_delete(r); } *bufp = buf; return 1; error: jdns_string_delete(name); return 0; }
jdns_packet_resource_t *jdns_packet_resource_copy(const jdns_packet_resource_t *a) { jdns_packet_resource_t *c = jdns_packet_resource_new(); if(a->qname) c->qname = jdns_string_copy(a->qname); c->qtype = a->qtype; c->qclass = a->qclass; c->ttl = a->ttl; c->rdlength = a->rdlength; c->rdata = jdns_copy_array(a->rdata, a->rdlength); jdns_list_delete(c->writelog); c->writelog = jdns_list_copy(a->writelog); return c; }
int jdns_packet_import(jdns_packet_t **a, const unsigned char *data, int size) { jdns_packet_t *tmp = 0; const unsigned char *buf; // need at least some data if(!data || size == 0) return 0; // header (id + options + item counts) is 12 bytes if(size < 12) goto error; tmp = jdns_packet_new(); buf = data; // id tmp->id = net2short(&buf); // options if(buf[0] & 0x80) // qr is bit 7 tmp->opts.qr = 1; tmp->opts.opcode = (buf[0] & 0x78) >> 3; // opcode is bits 6,5,4,3 if(buf[0] & 0x04) // aa is bit 2 tmp->opts.aa = 1; if(buf[0] & 0x02) // tc is bit 1 tmp->opts.tc = 1; if(buf[0] & 0x01) // rd is bit 0 tmp->opts.rd = 1; if(buf[1] & 0x80) // ra is bit 7 (second byte) tmp->opts.ra = 1; tmp->opts.z = (buf[1] & 0x70) >> 4; // z is bits 6,5,4 tmp->opts.rcode = buf[1] & 0x0f; // rcode is bits 3,2,1,0 buf += 2; // item counts tmp->qdcount = net2short(&buf); tmp->ancount = net2short(&buf); tmp->nscount = net2short(&buf); tmp->arcount = net2short(&buf); // if these fail, we don't count them as errors, since the packet // might have been truncated if(!process_qsection(tmp->questions, tmp->qdcount, data, size, &buf)) goto skip; if(!process_rrsection(tmp->answerRecords, tmp->ancount, data, size, &buf)) goto skip; if(!process_rrsection(tmp->authorityRecords, tmp->nscount, data, size, &buf)) goto skip; if(!process_rrsection(tmp->additionalRecords, tmp->arcount, data, size, &buf)) goto skip; tmp->fully_parsed = 1; skip: // keep the raw data for reference during rdata parsing tmp->raw_size = size; tmp->raw_data = jdns_copy_array(data, size); *a = tmp; return 1; error: jdns_packet_delete(tmp); return 0; }