099deb7884ff396ce2826b5c768a94bb30842f68
3 * - parsing assistance functions (mainly for domains inside datagrams)
6 * This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 int vbuf__append_quoted1035(vbuf
*vb
, const byte
*buf
, int len
) {
31 for (i
=0; i
<len
; i
++) {
33 if (ch
== '.' || ch
== '"' || ch
== '(' || ch
== ')' ||
34 ch
== '@' || ch
== ';' || ch
== '$') {
35 sprintf(qbuf
,"\\%c",ch
);
37 } else if (ch
<= ' ' || ch
>= 127) {
38 sprintf(qbuf
,"\\%03o",ch
);
42 if (!adns__vbuf_append(vb
,buf
,i
) || !adns__vbuf_append(vb
,qbuf
,strlen(qbuf
)))
49 void adns__findlabel_start(findlabel_state
*fls
, adns_state ads
,
50 int serv
, adns_query qu
,
51 const byte
*dgram
, int dglen
, int max
,
52 int dmbegin
, int *dmend_rlater
) {
61 fls
->dmend_r
= dmend_rlater
;
64 adns_status
adns__findlabel_next(findlabel_state
*fls
,
65 int *lablen_r
, int *labstart_r
) {
72 if (fls
->cbyte
+2 > fls
->dglen
) goto x_truncated
;
73 if (fls
->cbyte
+2 > fls
->max
) goto x_serverfaulty
;
74 GET_W(fls
->cbyte
,lablen
);
75 if (!(lablen
& 0x0c000)) break;
76 if ((lablen
& 0x0c000) != 0x0c000) return adns_s_unknownreply
;
78 adns__diag(fls
->ads
,fls
->serv
,fls
->qu
,"compressed datagram contains loop");
79 return adns_s_serverfaulty
;
81 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
82 fls
->cbyte
= DNS_HDRSIZE
+(lablen
&0x3fff);
83 fls
->dmend_r
= 0; fls
->max
= fls
->dglen
+1;
86 if (fls
->namelen
) fls
->namelen
++;
87 fls
->namelen
+= lablen
;
88 if (fls
->namelen
> DNS_MAXDOMAIN
) return adns_s_domaintoolong
;
90 if (fls
->cbyte
> fls
->dglen
) goto x_truncated
;
91 if (fls
->cbyte
> fls
->max
) goto x_serverfaulty
;
93 if (fls
->dmend_r
) *(fls
->dmend_r
)= fls
->cbyte
;
95 if (labstart_r
) *labstart_r
= fls
->cbyte
;
104 adns__diag(fls
->ads
,fls
->serv
,fls
->qu
,"label in domain runs beyond end of domain");
105 return adns_s_serverfaulty
;
108 adns_status
adns__parse_domain(adns_state ads
, int serv
, adns_query qu
,
110 const byte
*dgram
, int dglen
, int *cbyte_io
, int max
) {
113 int lablen
, labstart
, i
, ch
;
116 adns__findlabel_start(&fls
,ads
, serv
,qu
, dgram
,dglen
,max
, *cbyte_io
,cbyte_io
);
119 st
= adns__findlabel_next(&fls
,&lablen
,&labstart
);
121 if (lablen
<0) { vb
->used
=0; return adns_s_ok
; }
124 if (!adns__vbuf_append(vb
,".",1)) return adns_s_nolocalmem
;
125 if (flags
& adns_qf_anyquote
) {
126 if (!vbuf__append_quoted1035(vb
,dgram
+labstart
,lablen
))
127 return adns_s_nolocalmem
;
129 if (!ctype_alpha(dgram
[labstart
])) return adns_s_invaliddomain
;
130 for (i
= labstart
+1; i
<labstart
+lablen
; i
++) {
132 if (ch
!= '-' && !ctype_alpha(ch
) && !ctype_digit(ch
))
133 return adns_s_invaliddomain
;
135 if (!adns__vbuf_append(vb
,dgram
+labstart
,lablen
))
136 return adns_s_nolocalmem
;
139 if (!adns__vbuf_append(vb
,"",1)) return adns_s_nolocalmem
;
143 static adns_status
findrr_intern(adns_query qu
, int serv
,
144 const byte
*dgram
, int dglen
, int *cbyte_io
,
145 int *type_r
, int *class_r
, int *rdlen_r
, int *rdstart_r
,
146 const byte
*eo_dgram
, int eo_dglen
, int eo_cbyte
,
148 /* Like adns__findrr_checked, except that the datagram to compare
149 * with can be specified explicitly.
151 * If the caller thinks they know what the owner of the RR ought to
152 * be they can pass in details in eo_*: this is another (or perhaps
153 * the same datagram), and a pointer to where the putative owner
154 * starts in that datagram. In this case *eo_matched_r will be set
155 * to 1 if the datagram matched or 0 if it did not. Either
156 * both eo_dgram and eo_matched_r must both be non-null, or they
157 * must both be null (in which case eo_dglen and eo_cbyte will be ignored).
158 * The eo datagram and contained owner domain MUST be valid and
161 findlabel_state fls
, eo_fls
;
164 int tmp
, rdlen
, mismatch
;
165 int lablen
, labstart
, ch
;
166 int eo_lablen
, eo_labstart
, eo_ch
;
171 adns__findlabel_start(&fls
,qu
->ads
, serv
,qu
, dgram
,dglen
,dglen
,cbyte
,&cbyte
);
173 adns__findlabel_start(&eo_fls
,qu
->ads
, -1,0, eo_dgram
,eo_dglen
,eo_dglen
,eo_cbyte
,0);
180 st
= adns__findlabel_next(&fls
,&lablen
,&labstart
);
182 if (lablen
<0) goto x_truncated
;
185 st
= adns__findlabel_next(&eo_fls
,&eo_lablen
,&eo_labstart
);
186 assert(!st
); assert(eo_lablen
>=0);
187 if (lablen
!= eo_lablen
) mismatch
= 1;
188 while (!mismatch
&& lablen
-- > 0) {
189 ch
= dgram
[labstart
++]; if (ctype_alpha(ch
)) ch
&= ~32;
190 eo_ch
= eo_dgram
[eo_labstart
++]; if (ctype_alpha(eo_ch
)) eo_ch
&= ~32;
191 if (ch
!= eo_ch
) mismatch
= 1;
195 if (eo_matched_r
) *eo_matched_r
= !mismatch
;
197 if (cbyte
+10>dglen
) goto x_truncated
;
198 GET_W(cbyte
,tmp
); *type_r
= tmp
;
199 GET_W(cbyte
,tmp
); *class_r
= tmp
;
200 cbyte
+= 4; /* we skip the TTL */
201 GET_W(cbyte
,rdlen
); if (rdlen_r
) *rdlen_r
= tmp
;
202 if (rdstart_r
) *rdstart_r
= cbyte
;
204 if (cbyte
>dglen
) goto x_truncated
;
213 adns_status
adns__findrr(adns_query qu
, int serv
,
214 const byte
*dgram
, int dglen
, int *cbyte_io
,
215 int *type_r
, int *class_r
, int *rdlen_r
, int *rdstart_r
,
216 int *ownermatchedquery_r
) {
217 if (!ownermatchedquery_r
) {
218 return findrr_intern(qu
,serv
,
219 dgram
,dglen
,cbyte_io
,
220 type_r
,class_r
,rdlen_r
,rdstart_r
,
222 } else if (!qu
->cname_dgram
) {
223 return findrr_intern(qu
,serv
,
224 dgram
,dglen
,cbyte_io
,
225 type_r
,class_r
,rdlen_r
,rdstart_r
,
226 qu
->query_dgram
,qu
->query_dglen
,DNS_HDRSIZE
,
227 ownermatchedquery_r
);
229 return findrr_intern(qu
,serv
,
230 dgram
,dglen
,cbyte_io
,
231 type_r
,class_r
,rdlen_r
,rdstart_r
,
232 qu
->cname_dgram
,qu
->cname_dglen
,qu
->cname_begin
,
233 ownermatchedquery_r
);