3 * - parsing assistance functions (mainly for domains inside datagrams)
7 * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
9 * It is part of adns, which is
10 * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
11 * Copyright (C) 1999 Tony Finch <dot@dotat.at>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 int vbuf__append_quoted1035(vbuf
*vb
, const byte
*buf
, int len
) {
36 for (i
=0; i
<len
; i
++) {
38 if (ch
== '.' || ch
== '"' || ch
== '(' || ch
== ')' ||
39 ch
== '@' || ch
== ';' || ch
== '$' || ch
== '\\') {
40 sprintf(qbuf
,"\\%c",ch
);
42 } else if (ch
<= ' ' || ch
>= 127) {
43 sprintf(qbuf
,"\\%03o",ch
);
47 if (!adns__vbuf_append(vb
,buf
,i
) || !adns__vbuf_append(vb
,qbuf
,strlen(qbuf
)))
56 void adns__findlabel_start(findlabel_state
*fls
, adns_state ads
,
57 int serv
, adns_query qu
,
58 const byte
*dgram
, int dglen
, int max
,
59 int dmbegin
, int *dmend_rlater
) {
68 fls
->dmend_r
= dmend_rlater
;
71 adns_status
adns__findlabel_next(findlabel_state
*fls
,
72 int *lablen_r
, int *labstart_r
) {
73 int lablen
, jumped
, jumpto
;
79 if (fls
->cbyte
>= fls
->dglen
) goto x_truncated
;
80 if (fls
->cbyte
>= fls
->max
) goto x_badresponse
;
81 GET_B(fls
->cbyte
,lablen
);
82 if (!(lablen
& 0x0c0)) break;
83 if ((lablen
& 0x0c0) != 0x0c0) return adns_s_unknownformat
;
85 adns__diag(fls
->ads
,fls
->serv
,fls
->qu
,"compressed datagram contains loop");
86 return adns_s_invalidresponse
;
88 if (fls
->cbyte
>= fls
->dglen
) goto x_truncated
;
89 if (fls
->cbyte
>= fls
->max
) goto x_badresponse
;
90 GET_B(fls
->cbyte
,jumpto
);
91 jumpto
|= (lablen
&0x3f)<<8;
92 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
94 fls
->dmend_r
= 0; fls
->max
= fls
->dglen
+1;
96 if (labstart_r
) *labstart_r
= fls
->cbyte
;
98 if (fls
->namelen
) fls
->namelen
++;
99 fls
->namelen
+= lablen
;
100 if (fls
->namelen
> DNS_MAXDOMAIN
) return adns_s_answerdomaintoolong
;
102 if (fls
->cbyte
> fls
->dglen
) goto x_truncated
;
103 if (fls
->cbyte
> fls
->max
) goto x_badresponse
;
105 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
108 /*if (labstart_r) fprintf(stderr,"label %d >%.*s<\n",lablen,lablen,fls->dgram+*labstart_r);*/
116 adns__diag(fls
->ads
,fls
->serv
,fls
->qu
,"label in domain runs beyond end of domain");
117 return adns_s_invalidresponse
;
120 adns_status
adns__parse_domain(adns_state ads
, int serv
, adns_query qu
,
121 vbuf
*vb
, adns_queryflags flags
,
122 const byte
*dgram
, int dglen
, int *cbyte_io
, int max
) {
125 adns__findlabel_start(&fls
,ads
, serv
,qu
, dgram
,dglen
,max
, *cbyte_io
,cbyte_io
);
127 return adns__parse_domain_more(&fls
,ads
,qu
, vb
,flags
,dgram
);
130 adns_status
adns__parse_domain_more(findlabel_state
*fls
, adns_state ads
,
131 adns_query qu
, vbuf
*vb
, parsedomain_flags flags
,
133 int lablen
, labstart
, i
, ch
, first
;
138 st
= adns__findlabel_next(fls
,&lablen
,&labstart
);
140 if (lablen
<0) { vb
->used
=0; return adns_s_ok
; }
145 if (!adns__vbuf_append(vb
,".",1)) return adns_s_nomemory
;
147 if (flags
& pdf_quoteok
) {
148 if (!vbuf__append_quoted1035(vb
,dgram
+labstart
,lablen
))
149 return adns_s_nomemory
;
152 if (!ctype_alpha(ch
) && !ctype_digit(ch
)) return adns_s_answerdomaininvalid
;
153 for (i
= labstart
+1; i
<labstart
+lablen
; i
++) {
155 if (ch
!= '-' && !ctype_alpha(ch
) && !ctype_digit(ch
))
156 return adns_s_answerdomaininvalid
;
158 if (!adns__vbuf_append(vb
,dgram
+labstart
,lablen
))
159 return adns_s_nomemory
;
162 if (!adns__vbuf_append(vb
,"",1)) return adns_s_nomemory
;
166 adns_status
adns__findrr_anychk(adns_query qu
, int serv
,
167 const byte
*dgram
, int dglen
, int *cbyte_io
,
168 int *type_r
, int *class_r
, unsigned long *ttl_r
,
169 int *rdlen_r
, int *rdstart_r
,
170 const byte
*eo_dgram
, int eo_dglen
, int eo_cbyte
,
172 findlabel_state fls
, eo_fls
;
175 int tmp
, rdlen
, mismatch
;
177 int lablen
, labstart
, ch
;
178 int eo_lablen
, eo_labstart
, eo_ch
;
183 adns__findlabel_start(&fls
,qu
->ads
, serv
,qu
, dgram
,dglen
,dglen
,cbyte
,&cbyte
);
185 adns__findlabel_start(&eo_fls
,qu
->ads
, -1,0, eo_dgram
,eo_dglen
,eo_dglen
,eo_cbyte
,0);
192 st
= adns__findlabel_next(&fls
,&lablen
,&labstart
);
194 if (lablen
<0) goto x_truncated
;
197 st
= adns__findlabel_next(&eo_fls
,&eo_lablen
,&eo_labstart
);
198 assert(!st
); assert(eo_lablen
>=0);
199 if (lablen
!= eo_lablen
) mismatch
= 1;
200 while (!mismatch
&& eo_lablen
-- > 0) {
201 ch
= dgram
[labstart
++]; if (ctype_alpha(ch
)) ch
&= ~32;
202 eo_ch
= eo_dgram
[eo_labstart
++]; if (ctype_alpha(eo_ch
)) eo_ch
&= ~32;
203 if (ch
!= eo_ch
) mismatch
= 1;
208 if (eo_matched_r
) *eo_matched_r
= !mismatch
;
210 if (cbyte
+10>dglen
) goto x_truncated
;
211 GET_W(cbyte
,tmp
); *type_r
= tmp
;
212 GET_W(cbyte
,tmp
); *class_r
= tmp
;
215 if (ttl
> MAXTTLBELIEVE
) ttl
= MAXTTLBELIEVE
;
218 GET_W(cbyte
,rdlen
); if (rdlen_r
) *rdlen_r
= rdlen
;
219 if (rdstart_r
) *rdstart_r
= cbyte
;
221 if (cbyte
>dglen
) goto x_truncated
;
230 adns_status
adns__findrr(adns_query qu
, int serv
,
231 const byte
*dgram
, int dglen
, int *cbyte_io
,
232 int *type_r
, int *class_r
, unsigned long *ttl_r
,
233 int *rdlen_r
, int *rdstart_r
,
234 int *ownermatchedquery_r
) {
235 if (!ownermatchedquery_r
) {
236 return adns__findrr_anychk(qu
,serv
,
237 dgram
,dglen
,cbyte_io
,
238 type_r
,class_r
,ttl_r
,rdlen_r
,rdstart_r
,
240 } else if (!qu
->cname_dgram
) {
241 return adns__findrr_anychk(qu
,serv
,
242 dgram
,dglen
,cbyte_io
,
243 type_r
,class_r
,ttl_r
,rdlen_r
,rdstart_r
,
244 qu
->query_dgram
,qu
->query_dglen
,DNS_HDRSIZE
,
245 ownermatchedquery_r
);
247 return adns__findrr_anychk(qu
,serv
,
248 dgram
,dglen
,cbyte_io
,
249 type_r
,class_r
,ttl_r
,rdlen_r
,rdstart_r
,
250 qu
->cname_dgram
,qu
->cname_dglen
,qu
->cname_begin
,
251 ownermatchedquery_r
);