-#include "internal.h"
-
-typedef enum {
- rcode_noerror,
- rcode_formaterror,
- rcode_servfail,
- rcode_nxdomain,
- rcode_notimp,
- rcode_refused
-} dns_rcode;
-
-#define GETIL_B(cb) (dgram[*(cb)++])
-#define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
-#define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))
-
-static void vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len) {
- char qbuf[10];
- int i;
-
- while (len) {
- qbuf[0]= 0;
- for (i=0; i<len; i++) {
- ch= buf[i];
- if (ch == '.' || ch == '"' || ch == '(' || ch == ')' ||
- ch == '@' || ch == ';' || ch == '$') {
- sprintf(qbuf,"\\%c",ch);
- break;
- } else if (ch <= ' ' || ch >= 127) {
- sprintf(qbuf,"\\%03o",ch);
- break;
- }
- }
- if (!adns__vbuf_append(vb,buf,i) || !adns__vbuf_append(vb,qbuf,strlen(qbuf)))
- return adns_s_nolocalmem;
- buf+= i; len-= i;
- }
-}
-
-static adns_status get_domain_perm(adns_state ads, adns_query qu, int serv,
- const byte *dgram, int dglen,
- int *cbyte_io, int max, char **domain_r) {
- /* Returns 0 for OK (*domain_r set) or truncated (*domain_r null)
- * or any other adns_s_* value.
- */
- int cbyte, sused, lablen;
-
- /* If we follow a pointer we set cbyte_io to 0 to indicate that
- * we've lost our original starting and ending points; we don't
- * put the end of the pointed-to thing into the original *cbyte_io.
- */
- cbyte= *cbyte_io;
- sused= qu->ans.used;
- *domain_r= 0;
- for (;;) {
- if (cbyte>=max) goto x_truncated;
- lablen= GET_B(cbyte);
- if (!lablen) break;
- if (lablen&0x0c000) {
- if ((lablen&0x0c000) != 0x0c0000) return adns_s_unknownreply;
- if (cbyte_io) { *cbyte_io= cbyte; cbyte_io= 0; }
- cbyte= (lablen&0x3fff) + DNS_HDR_SIZE;
- max= dglen;
- continue;
- }
- if (cbyte+lablen>=max) bgoto x_truncated;
- if (qu->ans.used != sused)
- if (!adns__vbuf_append(&qu->ans,".",1)) return adns_s_nolocalmem;
- if (qu->flags & adns_qf_anyquote) {
- if (!vbuf__append_quoted1035(&qu->ans,dgram+cbyte,lablen))
- return adns_s_nolocalmem;
- } else {
- if (!ctype_isalpha(dgram[cbyte])) return adns_s_invaliddomain;
- for (i= cbyte+1; i<cbyte+lablen; i++) {
- ch= dgram[cbyte];
- if (ch != '-' && !ctype_isalpha(ch) && !ctype_isdigit(ch))
- return adns_s_invaliddomain;
- }
- if (!adns__vbuf_append(&qu->ans,dgram+cbyte,lablen))
- return adns_s_nolocalmem;
- }
- }
- if (cbyte_io) *cbyte_io= cbyte;
- if (!adns__vbuf_append(&qu->ans,"",1)) return adns_s_nolocalmem;
- *domain_r= qu->ans.buf+sused;
- return adns_s_ok;