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 adns_status
pa_txt(adns_query qu
, int serv
,
77 const byte
*dgram
, int dglen
, int cbyte
, int max
,
89 bp
= adns__alloc_interim(qu
,max
+1); if (!bp
) return adns_s_nolocalmem
;
96 static void mf_str(adns_query qu
, void *data
) {
99 adns__makefinal_str(qu
,ddp
);
102 static int csp_qstring(vbuf
*vb
, const char *dp
) {
106 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
108 while ((ch
= *dp
++)) {
109 if (ch
>= 32 && ch
<= 126 && ch
!= '"' && ch
!= '\\') {
110 if (!adns__vbuf_append(vb
,&ch
,1)) return 0;
112 sprintf(buf
,"\\%02x",ch
);
113 if (!adns__vbuf_appendstr(vb
,buf
)) return 0;
117 if (!adns__vbuf_append(vb
,"\"",1)) return 0;
121 static adns_status
cs_str(vbuf
*vb
, const void *data
) {
122 const char *const *dpp
= data
;
124 return csp_qstring(vb
,*dpp
) ? adns_s_ok
: adns_s_nolocalmem
;
127 static void mf_flat(adns_query qu
, void *data
) { }
129 #define TYPE_SF(size,func,cp,free) size, pa_##func, mf_##free, cs_##cp
130 #define TYPE_SN(size,func,cp) size, pa_##func, mf_flat, cs_##cp
131 #define TYPESZ_M(member) (sizeof(((adns_answer*)0)->rrs.member))
132 #define TYPE_MF(memb,parse) TYPE_SF(TYPESZ_M(memb),parse,memb,memb)
133 #define TYPE_MN(memb,parse) TYPE_SN(TYPESZ_M(memb),parse,memb)
135 #define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
136 #define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
139 * ms is M specify member name
140 * or S specify size explicitly
141 * nf is F full memory management, dependent on member name or specified func
142 * N no memory management required
145 static const typeinfo typeinfos
[] = {
146 /* Must be in ascending order of rrtype ! */
147 /* rr type code rrt fmt mem.mgmt member parser */
149 { adns_r_a
, "A", 0, FLAT_MEMB(inaddr
), pa_inaddr
},
150 { adns_r_ns_raw
, "NS", "raw", DEEP_MEMB(str
), pa_domain_raw
},
151 { adns_r_cname
, "CNAME", 0, DEEP_MEMB(str
), pa_domain_raw
},
153 { adns_r_soa_raw
, "SOA", "raw", DEEP_MEMB(soa
), pa_soa
},
155 { adns_r_ptr_raw
, "PTR", "raw", DEEP_MEMB(str
), pa_domain_raw
},
157 { adns_r_hinfo
, "HINFO", 0, DEEP_MEMB(strpair
), pa_hinfo
},
158 { adns_r_mx_raw
, "MX", "raw", DEEP_MEMB(intstr
), pa_mx_raw
},
160 { adns_r_txt
, "TXT", 0, DEEP_MEMB(str
), pa_txt
},
162 { adns_r_rp_raw
, "RP", "raw", DEEP_MEMB(strpair
), pa_rp
},
164 { adns_r_ns
, "NS", "+addr", DEEP_MEMB(dmaddr
), pa_dmaddr
},
165 { adns_r_ptr
, "PTR", "checked", DEEP_MEMB(str
), pa_ptr
},
166 { adns_r_mx
, "MX", "+addr", DEEP_MEMB(intdmaddr
), pa_mx
},
168 { adns_r_soa
, "SOA", "822", DEEP_MEMB(soa
), pa_soa
},
169 { adns_r_rp
, "RP", "822", DEEP_MEMB(strpair
), pa_rp
},
173 const typeinfo
*adns__findtype(adns_rrtype type
) {
174 const typeinfo
*begin
, *end
, *mid
;
176 begin
= typeinfos
; end
= typeinfos
+(sizeof(typeinfos
)/sizeof(typeinfo
));
178 while (begin
< end
) {
179 mid
= begin
+ ((end
-begin
)>>1);
180 if (mid
->type
== type
) return mid
;
181 if (type
> mid
->type
) begin
= mid
+1;