5 int vbuf__append_quoted1035(vbuf
*vb
, const byte
*buf
, int len
) {
11 for (i
=0; i
<len
; i
++) {
13 if (ch
== '.' || ch
== '"' || ch
== '(' || ch
== ')' ||
14 ch
== '@' || ch
== ';' || ch
== '$') {
15 sprintf(qbuf
,"\\%c",ch
);
17 } else if (ch
<= ' ' || ch
>= 127) {
18 sprintf(qbuf
,"\\%03o",ch
);
22 if (!adns__vbuf_append(vb
,buf
,i
) || !adns__vbuf_append(vb
,qbuf
,strlen(qbuf
)))
29 void adns__findlabel_start(findlabel_state
*fls
,
30 adns_state ads
, int serv
,
31 const byte
*dgram
, int dglen
, int max
,
32 int dmbegin
, int *dmend_rlater
) {
40 fls
->dmend_r
= dmend_rlater
;
41 fls
->namelen_r
= namelen_rlater
;
44 adns_status
adns__findlabel_next(findlabel_state fls
,
45 int *lablen_r
, int *labstart_r
) {
51 if (fls
->cbyte
> fls
->dglen
) goto x_truncated
;
52 if (fls
->cbyte
> fls
->max
) goto x_serverfaulty
;
53 GET_W(fls
->cbyte
-2,lablen
);
54 if (!(lablen
& 0x0c000)) break;
55 if ((lablen
& 0x0c000) != 0x0c000) return adns_s_unknownreply
;
57 adns__diag(ads
,fls
->serv
,fls
->qu
,"compressed datagram contains loop");
58 return adns_s_serverfaulty
;
60 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
61 fls
->cbyte
= DNS_HDRSIZE
+(lablen
&0x3fff);
62 fls
->dmend_r
= 0; fls
->max
= fls
->dglen
+1;
65 if (fls
->namelen
) fls
->namelen
++;
66 fls
->namelen
+= lablen
;
67 if (fls
->namelen
> DNS_MAXDOMAIN
) return adns_s_domaintoolong
;
69 if (fls
->cbyte
> fls
->dglen
) goto x_truncated
;
70 if (fls
->cbyte
> fls
->max
) goto x_serverfaulty
;
72 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
73 if (fls
->namelen_r
) *(fls
->namelen_r
)= fls
->namelen
;
75 if (labstart_r
) *labstart_r
= fls
->cbyte
;
84 adns__diag(ads
,fls
->serv
,fls
->qu
,"label in domain runs beyond end of domain");
85 return adns_s_serverfaulty
;
88 adns_status
adns__parse_domain(adns_state ads
, int serv
, vbuf
*vb
, int flags
,
89 const byte
*dgram
, int dglen
,
90 int *cbyte_io
, int max
) {
93 int cbyte
, lablen
, labstart
, namelen
, i
, ch
;
96 ands__findlabel_start(&fls
,ads
,serv
, dgram
,dglen
,max
, *cbyte_io
,cbyte_io
);
99 st
= adns__findlabel_next(&fls
,&lablen
,&labstart
);
101 if (lablen
<0) { vb
->used
=0; return adns_s_ok
; }
104 if (!adns__vbuf_append(&qu
->ans
,".",1)) return adns_s_nolocalmem
;
105 if (flags
& adns_qf_anyquote
) {
106 if (!vbuf__append_quoted1035(&qu
->ans
,dgram
+labstart
,lablen
))
107 return adns_s_nolocalmem
;
109 if (!ctype_alpha(dgram
[labstart
])) return adns_s_invaliddomain
;
110 for (i
= labstart
+1; i
<labstart
+lablen
; i
++) {
112 if (ch
!= '-' && !ctype_alpha(ch
) && !ctype_digit(ch
))
113 return adns_s_invaliddomain
;
115 if (!adns__vbuf_append(&qu
->ans
,dgram
+labstart
,lablen
))
116 return adns_s_nolocalmem
;
119 if (!adns__vbuf_append(&qu
->ans
,"",1)) return adns_s_nolocalmem
;
123 const char *adns__diag_domain(adns_state ads
, int serv
, adns_query qu
, vbuf
*vb
,
124 int flags
, const byte
*dgram
, int dglen
, int cbyte
) {
127 st
= adns__parse_domain(ads
,serv
,vb
,qu
->flags
, dgram
,dglen
, &cbyte
,dglen
);
128 if (st
== adns_s_nomemory
) {
129 return "<cannot report domain... out of memory>";
133 if (!(adns__vbuf_appendstr(vb
,"<bad format... ") &&
134 adns__vbuf_appendstr(vb
,adns_strerror(st
)) &&
135 adns__vbuf_appendstr(vb
,">") &&
136 adns__vbuf_append(vb
,"",1))) {
137 return "<cannot report bad format... out of memory>";
141 adns__vbuf_appendstr(vb
,"<truncated ...>");
142 adns__vbuf_append(vb
,"",1);
147 adns_status
adns__findrr(adns_state ads
, int serv
,
148 const byte
*dgram
, int dglen
, int *cbyte_io
,
149 int *type_r
, int *class_r
, int *rdlen_r
, int *rdstart_r
,
150 const byte
*eo_dgram
, int eo_dglen
, int eo_cbyte
,
152 /* Finds the extent and some of the contents of an RR in a datagram
153 * and does some checks. The datagram is *dgram, length dglen, and
154 * the RR starts at *cbyte_io (which is updated afterwards to point
155 * to the end of the RR).
157 * The type, class and RRdata length and start are returned iff
158 * the corresponding pointer variables are not null. type_r and
159 * class_r may not be null.
161 * If the caller thinks they know what the owner of the RR ought to
162 * be they can pass in details in eo_*: this is another (or perhaps
163 * the same datagram), and a pointer to where the putative owner
164 * starts in that datagram. In this case *eo_matched_r will be set
165 * to 1 if the datagram matched or 0 if it did not. Either
166 * both eo_dgram and eo_matched_r must both be non-null, or they
167 * must both be null (in which case eo_dglen and eo_cbyte will be ignored).
168 * The eo datagram and contained owner domain MUST be valid and
171 * If there is truncation then *type_r will be set to -1 and
172 * *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be
175 * If an error is returned then *type_r will be undefined too.
177 findlabel_state fls
, eo_fls
;
180 int tmp
, rdlen
, mismatch
;
181 int max
, lablen
, labstart
, namelen
, ch
;
182 int eo_max
, eo_lablen
, eo_labstart
, eo_namelen
, eo_ch
;
187 ands__findlabel_start(&fls
,ads
,serv
, dgram
,dglen
,dglen
,cbyte
,&cbyte
);
189 ands__findlabel_start(&eo_fls
,ads
,serv
, eo_dgram
,eo_dglen
,eo_dglen
,eo_cbyte
,0);
196 st
= adns__findlabel_next(&fls
,&lablen
,&labstart
);
198 if (lablen
<0) goto x_truncated
;
201 st
= adns__findlabel_next(&eo_fls
,&eo_lablen
,&eo_labstart
);
202 assert(!st
); assert(eo_lablen
>=0);
203 if (lablen
!= eo_lablen
) mismatch
= 1;
204 while (!mismatch
&& lablen
-- > 0) {
205 ch
= dgram
[labstart
++]; if (ctype_alpha(ch
)) ch
&= ~32;
206 eo_ch
= eo_dgram
[eo_labstart
++]; if (ctype_alpha(eo_ch
)) eo_ch
&= ~32;
207 if (ch
!= eo_ch
) mismatch
= 1;
211 if (eo_matched_r
) *eo_matched_r
= !mismatch
;
213 if (cbyte
+10>dglen
) goto x_truncated
;
214 GET_W(cbyte
,tmp
); *type_r
= tmp
;
215 GET_W(cbyte
,tmp
); *class_r
= tmp
;
216 cbyte
+= 4; /* we skip the TTL */
217 GET_W(cbyte
,rdlen
); if (rdlen_r
) *rdlen_r
= tmp
;
218 if (rdstart_r
) *rdstart_r
= cbyte
;
220 if (cbyte
>dglen
) goto x_truncated
;