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
*dr
= store_r
;
34 if (max
-cbyte
!= 4) return adns_s_invaliddata
;
35 memcpy(dr
,dgram
+cbyte
,4);
39 static adns_status
cs_inaddr(vbuf
*vb
, const void *data
) {
40 const struct in_addr
*dp
= data
;
43 ia
= inet_ntoa(*dp
); assert(ia
);
44 return adns__vbuf_appendstr(vb
,ia
) ? adns_s_ok
: adns_s_nolocalmem
;
47 static adns_status
pa_domain_raw(adns_query qu
, int serv
,
48 const byte
*dgram
, int dglen
, int cbyte
, int max
,
56 st
= adns__parse_domain(qu
->ads
,serv
,qu
,&vb
,qu
->flags
,
57 dgram
,dglen
, &cbyte
,max
);
60 dp
= adns__alloc_interim(qu
,vb
.used
+1);
61 if (!dp
) { st
= adns_s_nolocalmem
; goto x_error
; }
64 memcpy(dp
,vb
.buf
,vb
.used
);
66 if (cbyte
!= max
) { st
= adns_s_invaliddata
; goto x_error
; }
76 static void mf_str(adns_query qu
, void *data
) {
79 adns__makefinal_str(qu
,ddp
);
82 static int csp_qstring(vbuf
*vb
, const char *dp
) {
86 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
89 if (ch
>= 32 && ch
<= 126 && ch
!= '"' && ch
!= '\\') {
90 if (!adns__vbuf_append(vb
,&ch
,1)) return 0;
92 sprintf(buf
,"\\%02x",ch
);
93 if (!adns__vbuf_appendstr(vb
,buf
)) return 0;
97 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
101 static adns_status
cs_str(vbuf
*vb
, const void *data
) {
102 const char *const *dpp
= data
;
104 return csp_qstring(vb
,*dpp
) ? adns_s_ok
: adns_s_nolocalmem
;
107 static void mf_flat(adns_query qu
, void *data
) { }
109 #define TYPE_SF(size,func,cp,free) size, pa_##func, mf_##free, cs_##cp
110 #define TYPE_SN(size,func,cp) size, pa_##func, mf_flat, cs_##cp
111 #define TYPESZ_M(member) (sizeof(((adns_answer*)0)->rrs.member))
112 #define TYPE_MF(memb,parse) TYPE_SF(TYPESZ_M(memb),parse,memb,memb)
113 #define TYPE_MN(memb,parse) TYPE_SN(TYPESZ_M(memb),parse,memb)
115 #define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
116 #define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
119 * ms is M specify member name
120 * or S specify size explicitly
121 * nf is F full memory management, dependent on member name or specified func
122 * N no memory management required
125 static const typeinfo typeinfos
[] = {
126 /* Must be in ascending order of rrtype ! */
127 /* rr type code rrt fmt mem.mgmt member parser */
129 { adns_r_a
, "A", 0, FLAT_MEMB(inaddr
), pa_inaddr
},
130 { adns_r_ns_raw
, "NS", "raw", DEEP_MEMB(str
), pa_domain_raw
},
131 { adns_r_cname
, "CNAME", 0, DEEP_MEMB(str
), pa_domain_raw
},
133 { adns_r_soa_raw
, "SOA", "raw", DEEP_MEMB(soa
), pa_soa
},
135 { adns_r_ptr_raw
, "PTR", "raw", DEEP_MEMB(str
), pa_domain_raw
},
137 { adns_r_hinfo
, "HINFO", 0, DEEP_MEMB(strpair
), pa_hinfo
},
138 { adns_r_mx_raw
, "MX", "raw", DEEP_MEMB(intstr
), pa_mx_raw
},
139 { adns_r_txt
, "TXT", 0, DEEP_MEMB(manystr
), pa_txt
},
140 { adns_r_rp_raw
, "RP", "raw", DEEP_MEMB(strpair
), pa_rp
},
142 { adns_r_ns
, "NS", "+addr", DEEP_MEMB(dmaddr
), pa_dmaddr
},
143 { adns_r_ptr
, "PTR", "checked", DEEP_MEMB(str
), pa_ptr
},
144 { adns_r_mx
, "MX", "+addr", DEEP_MEMB(intdmaddr
), pa_mx
},
146 { adns_r_soa
, "SOA", "822", DEEP_MEMB(soa
), pa_soa
},
147 { adns_r_rp
, "RP", "822", DEEP_MEMB(strpair
), pa_rp
},
151 const typeinfo
*adns__findtype(adns_rrtype type
) {
152 const typeinfo
*begin
, *end
, *mid
;
154 begin
= typeinfos
; end
= typeinfos
+(sizeof(typeinfos
)/sizeof(typeinfo
));
156 while (begin
< end
) {
157 mid
= begin
+ ((end
-begin
)>>1);
158 if (mid
->type
== type
) return mid
;
159 if (type
> mid
->type
) begin
= mid
+1;