static int dns_parse_a(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result, unsigned dsize) { struct dns_rr_a *ret; struct dns_parse p; struct dns_rr rr; int r; /* first, validate and count number of addresses */ dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) if (rr.dnsrr_dsz != dsize) return DNS_E_PROTOCOL; if (r < 0) return DNS_E_PROTOCOL; else if (!p.dnsp_nrr) return DNS_E_NODATA; ret = malloc(sizeof(*ret) + dsize * p.dnsp_nrr + dns_stdrr_size(&p)); if (!ret) return DNS_E_NOMEM; ret->dnsa_nrr = p.dnsp_nrr; ret->dnsa_addr = (unsigned char*)(ret+1); /* copy the RRs */ for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) memcpy(ret->dnsa_addr + dsize * r, rr.dnsrr_dptr, dsize); dns_stdrr_finish((struct dns_rr_null *)ret, (char *)(ret->dnsa_addr + dsize * p.dnsp_nrr), &p); *result = ret; return 0; }
int dns_parse_srv(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_srv *ret; struct dns_parse p; struct dns_rr rr; int r, l; char *sp; dnsc_t srv[DNS_MAXDN]; assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_SRV); /* first, validate the answer and count size of the result */ l = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { cur = rr.dnsrr_dptr + 6; r = dns_getdn(pkt, &cur, end, srv, sizeof(srv)); if (r <= 0 || cur != rr.dnsrr_dend) return DNS_E_PROTOCOL; l += dns_dntop_size(srv); } if (r < 0) return DNS_E_PROTOCOL; if (!p.dnsp_nrr) return DNS_E_NODATA; /* next, allocate and set up result */ l += dns_stdrr_size(&p); ret = malloc(sizeof(*ret) + sizeof(struct dns_srv) * p.dnsp_nrr + l); if (!ret) return DNS_E_NOMEM; ret->dnssrv_nrr = p.dnsp_nrr; ret->dnssrv_srv = (struct dns_srv *)(ret+1); /* and 3rd, fill in result, finally */ sp = (char*)(ret->dnssrv_srv + p.dnsp_nrr); for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) { ret->dnssrv_srv[r].name = sp; cur = rr.dnsrr_dptr; ret->dnssrv_srv[r].priority = dns_get16(cur); ret->dnssrv_srv[r].weight = dns_get16(cur+2); ret->dnssrv_srv[r].port = dns_get16(cur+4); cur += 6; dns_getdn(pkt, &cur, end, srv, sizeof(srv)); sp += dns_dntop(srv, sp, DNS_MAXNAME); } dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p); *result = ret; return 0; }