int d_a_p(dns_pkt_a * dpa, char *buf, int limitlen) { int offset, rdlen; uint16_t u; int i; if ((rdlen = nametolbl(dpa->name, buf)) == -1) return -1; offset = rdlen; if (offset + 10 > limitlen) err_intret(ERR_DNSPLB); buf += offset; u = htons(dpa->type); memcpy(buf, &u, 2); buf += 2; offset += 2; u = htons(dpa->cl); memcpy(buf, &u, 2); buf += 2; offset += 2; i = htonl(dpa->ttl); memcpy(buf, &i, 4); buf += 4; offset += 4; if (dpa->type == T_A) { if (offset + dpa->rdlength > limitlen) err_intret(ERR_DNSPLB); memcpy(buf + 2, dpa->rdata, dpa->rdlength); offset += dpa->rdlength; } else if (dpa->type == T_MX) { memcpy(buf + 2, dpa->rdata, 2); if ((rdlen = nametolbl(dpa->rdata + 2, buf + 4)) == -1) { error(err_str); err_ret(ERR_DNSMDA, -1); } offset += rdlen + 2; if (offset > limitlen) err_ret(ERR_DNSPLB, -1); dpa->rdlength = rdlen + 2; } else { if ((rdlen = nametolbl(dpa->rdata, buf + 2)) == -1) { error(err_str); err_ret(ERR_DNSMDA, -1); } offset += rdlen; if (offset > limitlen) err_ret(ERR_DNSPLB, -1); dpa->rdlength = rdlen; } u = htons(dpa->rdlength); memcpy(buf, &u, 2); offset += 2; return offset; }
/* * This is a main function: takes the pkt-buf and translate * it in structured data. * It cares about dns_pkt allocations. * * Returns: * -1 on E_INTRPRT * 0 if pkt must be discarded. * Number of bytes read otherwise */ int d_u(char *buf, int pktlen, dns_pkt ** dpp) { dns_pkt *dp; int offset = 0, res; char *crow; crow = buf; /* Controls pkt consistency: we must at least read pkt headers */ if (pktlen < DNS_HDR_SZ) err_ret(ERR_DNSMDP, 0); *dpp = dp = create_dns_pkt(); /* Writes headers */ offset += d_hdr_u(buf, &(dp->pkt_hdr)); if (pktlen > DNS_MAX_SZ) /* If pkt is too long: the headers are written, * so we can reply with E_INTRPRT */ err_intret(ERR_DNSPLB); crow += offset; /* Writes qsts */ if (dp->pkt_hdr.qdcount) { if ((res = d_qsts_u(buf, crow, dp, pktlen - offset)) == -1) { error(err_str); err_intret(ERR_DNSMDP); } offset += res; crow += res; } if (dp->pkt_hdr.ancount) { if ((res = d_as_u(buf, crow, &(dp->pkt_answ), pktlen - offset, DP_ANCOUNT(dp))) == -1) { error(err_str); err_intret(ERR_DNSMDP); } offset += res; } /*crow+=res; if ((res=dpkttoas(buf,crow,&(dp->pkt_auth),pktlen-offset,DP_NSCOUNT(dp)))==-1) return -1; offset+=res; crow+=res; if ((res=dpkttoas(buf,crow,&(dp->pkt_add),pktlen-offset,DP_ARCOUNT(dp)))==-1) return -1; */ return offset; }
/* * like d_qs_u. count is the number of section to read. * -1 on error. Bytes readed otherwise. */ int d_as_u(char *start_buf,char *buf,dns_pkt_a **dpa,int limit_len,int count) { int offset=0,res; int i; if (!count) return 0; for(i=0;i<count;i++) { if ((res=d_a_u(start_buf,buf+offset,dpa,limit_len-offset))==-1) { error(err_str); err_intret(ERR_DNSMDD); } offset+=res; } return offset; }
/* * The behavior of this function is in all similar to dpkttoqst. * Returns -1 on error. Bytes readed otherwise. */ int d_a_u(char *start_buf, char *buf, dns_pkt_a ** dpa_orig, int limit_len) { int count, rdlen; dns_pkt_a *dpa; uint16_t s; uint32_t ui; dpa = dns_add_a(dpa_orig); /* get name */ if ((count = lbltoname(buf, start_buf, dpa->name, limit_len)) == -1) { error(err_str); err_ret(ERR_DNSMDD, -1); } buf += count; /* Now we have to write 2+2+4+2 bytes */ if (count + 10 > limit_len) err_ret(ERR_DNSPLB, -1); memcpy(&s, buf, 2); dpa->type = ntohs(s); count += 2; buf += 2; memcpy(&s, buf, 2); dpa->cl = ntohs(s); count += 2; buf += 2; memcpy(&ui, buf, 4); dpa->ttl = ntohl(ui); count += 4; buf += 4; memcpy(&s, buf, 2); dpa->rdlength = ntohs(s); count += 2; buf += 2; rdlen = dpa->rdlength; if (rdlen > DNS_MAX_HNAME_LEN) err_ret(ERR_DNSMDD, -1); /* Now we have to write dpa->rdlength bytes */ if (count + rdlen > limit_len) err_ret(ERR_DNSPLB, -1); if (dpa->type == T_A) { memcpy(dpa->rdata, buf, rdlen); /* 32bit address */ count += rdlen; } else if (dpa->type == T_AAAA) { memcpy(dpa->rdata, buf, rdlen); /* 128bit address */ count += rdlen; } else if (dpa->type == T_MX) { memcpy(dpa->rdata, buf, 2); if ((ui = lbltoname(buf + 2, start_buf, dpa->rdata + 2, rdlen - 2)) == -1) { error(err_str); err_ret(ERR_DNSMDD, -1); } if (rdlen != ui + 2) { debug(DBG_NORMAL, "In d_a_u(): rdlen (%d) differs from readed bytes (%d).", rdlen, ui + 2); err_ret(ERR_DNSMDD, -1); } count += 2 + ui; } else { if ((ui = lbltoname(buf, start_buf, dpa->rdata, rdlen)) == -1) { error(err_str); err_intret(ERR_DNSMDD); } if (rdlen != ui) { debug(DBG_NORMAL, "In d_a_u(): rdlen (%d) differs from readed bytes (%d).", rdlen, ui); err_ret(ERR_DNSMDD, -1); } count += ui; } return count; }