3 * - RR-type-specific code, and the machinery to call it
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 #include <arpa/inet.h>
29 static adns_status
pa_inaddr(adns_query qu
, int serv
,
30 const byte
*dgram
, int dglen
, int cbyte
, int max
,
32 struct in_addr
*storeto
= datap
;
34 if (max
-cbyte
!= 4) return adns_s_invaliddata
;
35 memcpy(storeto
,dgram
+cbyte
,4);
39 static int dip_inaddr(struct in_addr a
, struct in_addr b
) {
40 /* fixme implement sortlist */
44 static int di_inaddr(const void *datap_a
, const void *datap_b
) {
45 const struct in_addr
*ap
= datap_a
, *bp
= datap_b
;
47 return dip_inaddr(*ap
,*bp
);
50 static adns_status
cs_inaddr(vbuf
*vb
, const void *datap
) {
51 const struct in_addr
*rrp
= datap
, rr
= *rrp
;
54 ia
= inet_ntoa(rr
); assert(ia
);
55 return adns__vbuf_appendstr(vb
,ia
) ? adns_s_ok
: adns_s_nolocalmem
;
58 static adns_status
pap_domain(adns_query qu
, int serv
,
59 const byte
*dgram
, int dglen
, int *cbyte_io
, int max
,
64 st
= adns__parse_domain(qu
->ads
,serv
,qu
,&qu
->vb
,qu
->flags
,
65 dgram
,dglen
, cbyte_io
,max
);
67 if (!qu
->vb
.used
) return adns_s_invaliddata
;
69 dm
= adns__alloc_interim(qu
,qu
->vb
.used
+1);
70 if (!dm
) return adns_s_nolocalmem
;
73 memcpy(dm
,qu
->vb
.buf
,qu
->vb
.used
);
79 static adns_status
pa_domain_raw(adns_query qu
, int serv
,
80 const byte
*dgram
, int dglen
, int cbyte
, int max
,
85 st
= pap_domain(qu
,serv
,dgram
,dglen
,&cbyte
,max
,rrp
);
88 if (cbyte
!= max
) return adns_s_invaliddata
;
92 static adns_status
pa_mx_raw(adns_query qu
, int serv
,
93 const byte
*dgram
, int dglen
, int cbyte
, int max
,
95 adns_rr_intstr
*rrp
= datap
;
99 if (cbyte
+2 > max
) return adns_s_invaliddata
;
102 st
= pap_domain(qu
,serv
,dgram
,dglen
,&cbyte
,max
,&rrp
->str
);
105 if (cbyte
!= max
) return adns_s_invaliddata
;
109 static int di_mx_raw(const void *datap_a
, const void *datap_b
) {
110 const adns_rr_intstr
*ap
= datap_a
, *bp
= datap_b
;
112 if (ap
->i
< bp
->i
) return 0;
113 if (ap
->i
> bp
->i
) return 1;
117 static adns_status
pa_txt(adns_query qu
, int serv
,
118 const byte
*dgram
, int dglen
, int startbyte
, int max
,
120 adns_rr_intstr
**rrp
= datap
, *table
, *te
;
121 int ti
, tc
, cbyte
, l
;
124 if (cbyte
>= max
) return adns_s_invaliddata
;
126 while (cbyte
< max
) {
130 if (cbyte
!= max
) return adns_s_invaliddata
;
132 table
= adns__alloc_interim(qu
,sizeof(*table
)*(tc
+1));
133 if (!table
) return adns_s_nolocalmem
;
135 for (cbyte
=startbyte
, ti
=0, te
=table
; ti
<tc
; ti
++, te
++) {
137 te
->str
= adns__alloc_interim(qu
,l
+1);
138 if (!te
->str
) return adns_s_nolocalmem
;
140 memcpy(te
->str
,dgram
+cbyte
,l
);
143 assert(cbyte
== max
);
152 static int csp_textdata(vbuf
*vb
, const char *dp
, int len
) {
157 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
159 for (cn
=0; cn
<len
; cn
++) {
161 if (ch
>= 32 && ch
<= 126 && ch
!= '"' && ch
!= '\\') {
162 if (!adns__vbuf_append(vb
,&ch
,1)) return 0;
164 sprintf(buf
,"\\%02x",ch
);
165 if (!adns__vbuf_appendstr(vb
,buf
)) return 0;
169 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
173 static int csp_qstring(vbuf
*vb
, const char *dp
) {
174 return csp_textdata(vb
, dp
, strlen(dp
));
177 static adns_status
cs_str(vbuf
*vb
, const void *datap
) {
178 const char *const *rrp
= datap
;
180 return csp_qstring(vb
,*rrp
) ? adns_s_ok
: adns_s_nolocalmem
;
183 static adns_status
cs_intstr(vbuf
*vb
, const void *datap
) {
184 const adns_rr_intstr
*rrp
= datap
;
187 sprintf(buf
,"%u ",rrp
->i
);
188 return (adns__vbuf_appendstr(vb
,buf
) &&
189 csp_qstring(vb
,rrp
->str
)) ? adns_s_ok
: adns_s_nolocalmem
;
192 static adns_status
cs_manyistr(vbuf
*vb
, const void *datap
) {
193 const adns_rr_intstr
*const *rrp
= datap
;
194 const adns_rr_intstr
*current
;
197 for (spc
=0, current
= *rrp
; current
->i
>= 0; current
++) {
199 if (!adns__vbuf_append(vb
," ",1)) goto x_nomem
;
200 if (!csp_textdata(vb
,current
->str
,current
->i
)) goto x_nomem
;
205 return adns_s_nolocalmem
;
208 static void mf_str(adns_query qu
, void *datap
) {
211 adns__makefinal_str(qu
,rrp
);
214 static void mf_intstr(adns_query qu
, void *datap
) {
215 adns_rr_intstr
*rrp
= datap
;
217 adns__makefinal_str(qu
,&rrp
->str
);
220 static void mf_manyistr(adns_query qu
, void *datap
) {
221 adns_rr_intstr
**rrp
= datap
;
222 adns_rr_intstr
*te
, *table
;
226 for (tc
=0, te
= *rrp
; te
->i
>= 0; te
++, tc
++);
228 adns__makefinal_block(qu
,&tablev
,sizeof(*te
)*(tc
+1));
230 for (te
= *rrp
; te
->i
>= 0; te
++)
231 adns__makefinal_str(qu
,&te
->str
);
234 static void mf_flat(adns_query qu
, void *data
) { }
236 #define TYPE_SF(size,func,cp,free) size, pa_##func, mf_##free, cs_##cp
237 #define TYPE_SN(size,func,cp) size, pa_##func, mf_flat, cs_##cp
238 #define TYPESZ_M(member) (sizeof(*((adns_answer*)0)->rrs.member))
239 #define TYPE_MF(memb,parse) TYPE_SF(TYPESZ_M(memb),parse,memb,memb)
240 #define TYPE_MN(memb,parse) TYPE_SN(TYPESZ_M(memb),parse,memb)
242 #define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
243 #define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
246 * ms is M specify member name
247 * or S specify size explicitly
248 * nf is F full memory management, dependent on member name or specified func
249 * N no memory management required
252 static const typeinfo typeinfos
[] = {
253 /* Must be in ascending order of rrtype ! */
254 /* rr type code rrt fmt mem.mgmt member parser comparer */
256 { adns_r_a
, "A", 0, FLAT_MEMB(inaddr
), pa_inaddr
, di_inaddr
},
257 { adns_r_ns_raw
, "NS", "raw", DEEP_MEMB(str
), pa_domain_raw
, 0 },
258 { adns_r_cname
, "CNAME", 0, DEEP_MEMB(str
), pa_domain_raw
, 0 },
260 { adns_r_soa_raw
, "SOA", "raw", DEEP_MEMB(soa
), pa_soa
, 0 },
262 { adns_r_ptr_raw
, "PTR", "raw", DEEP_MEMB(str
), pa_domain_raw
, 0 },
264 { adns_r_hinfo
, "HINFO", 0, DEEP_MEMB(strpair
), pa_hinfo
, 0 },
266 { adns_r_mx_raw
, "MX", "raw", DEEP_MEMB(intstr
), pa_mx_raw
, di_mx_raw
},
267 { adns_r_txt
, "TXT", 0, DEEP_MEMB(manyistr
), pa_txt
, 0 },
269 { adns_r_rp_raw
, "RP", "raw", DEEP_MEMB(strpair
), pa_rp
, 0 },
273 { adns_r_ns
, "NS", "+addr", DEEP_MEMB(dmaddr
), pa_dmaddr
, di_dmaddr
},
274 { adns_r_ptr
, "PTR","checked", DEEP_MEMB(str
), pa_ptr
, 0 },
275 { adns_r_mx
, "MX", "+addr", DEEP_MEMB(intdmaddr
), pa_mx
, di_mx
},
279 { adns_r_soa
, "SOA", "822", DEEP_MEMB(soa
), pa_soa
, 0 },
280 { adns_r_rp
, "RP", "822", DEEP_MEMB(strpair
), pa_rp
, 0 },
284 const typeinfo
*adns__findtype(adns_rrtype type
) {
285 const typeinfo
*begin
, *end
, *mid
;
287 begin
= typeinfos
; end
= typeinfos
+(sizeof(typeinfos
)/sizeof(typeinfo
));
289 while (begin
< end
) {
290 mid
= begin
+ ((end
-begin
)>>1);
291 if (mid
->type
== type
) return mid
;
292 if (type
> mid
->type
) begin
= mid
+1;