adns-ruby 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +2 -0
- data/COPYING +271 -0
- data/README +35 -0
- data/examples/a.rb +21 -0
- data/examples/cname.rb +21 -0
- data/examples/mx.rb +21 -0
- data/examples/ns.rb +21 -0
- data/examples/ptr.rb +22 -0
- data/examples/soa.rb +21 -0
- data/examples/srv.rb +21 -0
- data/examples/txt.rb +21 -0
- data/ext/adns/extconf.rb +4 -0
- data/ext/adns/mod_adns.c +998 -0
- data/lib/adns.rb +6 -0
- metadata +77 -0
data/examples/txt.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
# This file is part of adns-ruby library
|
|
3
|
+
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'adns'
|
|
6
|
+
require 'pp'
|
|
7
|
+
|
|
8
|
+
domain=""
|
|
9
|
+
if ARGV.length != 1
|
|
10
|
+
$stderr.puts "usage: #{__FILE__} <domain>"
|
|
11
|
+
exit -1
|
|
12
|
+
else
|
|
13
|
+
domain = ARGV[0]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
puts '* initializing adns..'
|
|
17
|
+
adns = ADNS::State.new
|
|
18
|
+
puts "* resolving TXT record of domain #{domain}.."
|
|
19
|
+
q = adns.submit(domain, ADNS::RR::TXT)
|
|
20
|
+
pp q.wait()
|
|
21
|
+
puts "query status: #{ADNS::status_to_s(q.check[:status])}"
|
data/ext/adns/extconf.rb
ADDED
data/ext/adns/mod_adns.c
ADDED
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Ruby interface to GNU adns asynchronous DNS client library.
|
|
3
|
+
* Copyright (C) 2013 Purushottam Tuladhar <purshottam.tuladhar@gmail.com>
|
|
4
|
+
*
|
|
5
|
+
* This program is free software; you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
|
7
|
+
* the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
* (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU General Public License for more details.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
#include <adns.h>
|
|
17
|
+
#include <ruby.h>
|
|
18
|
+
|
|
19
|
+
#include <errno.h>
|
|
20
|
+
#include <fcntl.h>
|
|
21
|
+
#include <string.h>
|
|
22
|
+
#include <sys/time.h>
|
|
23
|
+
#include <arpa/inet.h>
|
|
24
|
+
#include <sys/select.h>
|
|
25
|
+
#include <netinet/in.h>
|
|
26
|
+
|
|
27
|
+
#define VERSION "0.3"
|
|
28
|
+
#define CSTR2STR(cstr) ((cstr) ? rb_str_new2(cstr) : rb_str_new2(""))
|
|
29
|
+
#define CSTR2SYM(cstr) (rb_str_intern(CSTR2STR(cstr)))
|
|
30
|
+
#define CHECK_TYPE(v,t) (Check_Type(v, t))
|
|
31
|
+
#define DEFAULT_DIAG_FILEMODE "w"
|
|
32
|
+
|
|
33
|
+
typedef struct {
|
|
34
|
+
adns_state ads;
|
|
35
|
+
FILE *diagfile;
|
|
36
|
+
} rb_adns_state_t;
|
|
37
|
+
|
|
38
|
+
typedef struct {
|
|
39
|
+
adns_query adq;
|
|
40
|
+
rb_adns_state_t *rb_ads_r;
|
|
41
|
+
VALUE answer;
|
|
42
|
+
} rb_adns_query_t;
|
|
43
|
+
|
|
44
|
+
static VALUE mADNS; /* ADNS */
|
|
45
|
+
static VALUE mADNS__cState; /* ADNS::State */
|
|
46
|
+
static VALUE mADNS__cQuery; /* ADNS::Query */
|
|
47
|
+
static VALUE mADNS__mRR; /* ADNS::RR */
|
|
48
|
+
static VALUE mADNS__mStatus; /* ADNS::Status */
|
|
49
|
+
static VALUE mADNS__mIF; /* ADNS::IF */
|
|
50
|
+
static VALUE mADNS__mQF; /* ADNS::QF */
|
|
51
|
+
static VALUE mADNS__eError; /* ADNS::Error */
|
|
52
|
+
static VALUE mADNS__eLocalError; /* ADNS::LocalError */
|
|
53
|
+
static VALUE mADNS__eRemoteError; /* ADNS::RemoteError */
|
|
54
|
+
static VALUE mADNS__eQueryError; /* ADNS::QueryError */
|
|
55
|
+
static VALUE maDNS__ePermanentError;/* ADNS::PermanentError */
|
|
56
|
+
static VALUE mADNS__eNotReadyError; /* ADNS::NotReadyError */
|
|
57
|
+
|
|
58
|
+
static void adns_select_timeout(rb_adns_state_t *rb_ads_r, double t)
|
|
59
|
+
{
|
|
60
|
+
/*
|
|
61
|
+
* select call on adns query IO rather than file descriptors.
|
|
62
|
+
*/
|
|
63
|
+
struct timeval **tv_mod = NULL, tv_buf, timeout, now;
|
|
64
|
+
int nfds, maxfds = 0;
|
|
65
|
+
fd_set rfds, wfds, efds;
|
|
66
|
+
int ecode;
|
|
67
|
+
|
|
68
|
+
timeout.tv_sec = t;
|
|
69
|
+
timeout.tv_usec = 0;
|
|
70
|
+
ecode = gettimeofday(&now, NULL);
|
|
71
|
+
if (ecode == -1)
|
|
72
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
73
|
+
FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
|
|
74
|
+
adns_beforeselect(rb_ads_r->ads, &maxfds, &rfds, &wfds, &efds,
|
|
75
|
+
tv_mod, &tv_buf, &now);
|
|
76
|
+
ecode = select(maxfds, &rfds, &wfds, &efds, &timeout);
|
|
77
|
+
if (ecode == -1)
|
|
78
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
79
|
+
ecode = gettimeofday(&now, NULL);
|
|
80
|
+
if (ecode == -1)
|
|
81
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
82
|
+
adns_afterselect(rb_ads_r->ads, maxfds, &rfds, &wfds, &efds, &now);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* call-seq: status_to_s(status) => String
|
|
87
|
+
*
|
|
88
|
+
* Convert adns status code to string representation.
|
|
89
|
+
*/
|
|
90
|
+
static VALUE mADNS__status_to_s(VALUE self, VALUE a1)
|
|
91
|
+
{
|
|
92
|
+
adns_status status;
|
|
93
|
+
const char *s;
|
|
94
|
+
|
|
95
|
+
CHECK_TYPE(a1, T_FIXNUM);
|
|
96
|
+
status = FIX2INT(a1);
|
|
97
|
+
s = adns_strerror(status);
|
|
98
|
+
return CSTR2STR(s);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* call-seq: status_to_ss(status) => String
|
|
103
|
+
*
|
|
104
|
+
* Convert adns status code to short abbreviation string representation.
|
|
105
|
+
*/
|
|
106
|
+
static VALUE mADNS__status_to_ss(VALUE self, VALUE a1)
|
|
107
|
+
{
|
|
108
|
+
adns_status status;
|
|
109
|
+
const char *s;
|
|
110
|
+
|
|
111
|
+
CHECK_TYPE(a1, T_FIXNUM);
|
|
112
|
+
status = FIX2INT(a1);
|
|
113
|
+
s = adns_errabbrev(status);
|
|
114
|
+
return CSTR2STR(s);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void __rdata_modify(VALUE data)
|
|
118
|
+
{
|
|
119
|
+
struct RData *data_r = (struct RData *)data;
|
|
120
|
+
long data_len = sizeof(data_r->data);
|
|
121
|
+
VALUE *ptr = ALLOC_N(VALUE, data_len);
|
|
122
|
+
MEMCPY(ptr, data_r->data, VALUE, data_len);
|
|
123
|
+
}
|
|
124
|
+
#define RDATA_MODIFY(d) (__rdata_modify(d))
|
|
125
|
+
|
|
126
|
+
static VALUE parse_adns_rr_addr(adns_rr_addr *addr_r)
|
|
127
|
+
{
|
|
128
|
+
const char *addr_str = inet_ntoa(addr_r->addr.inet.sin_addr);
|
|
129
|
+
if (!addr_str)
|
|
130
|
+
return CSTR2STR("");
|
|
131
|
+
else
|
|
132
|
+
return CSTR2STR(addr_str);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static VALUE parse_adns_rr_hostaddr(adns_rr_hostaddr *hostaddr_r)
|
|
136
|
+
{
|
|
137
|
+
VALUE rb_hostaddr = rb_hash_new();
|
|
138
|
+
VALUE host_k = CSTR2SYM("host");
|
|
139
|
+
VALUE host_v = CSTR2STR(hostaddr_r->host);
|
|
140
|
+
VALUE status_k = CSTR2SYM("status");
|
|
141
|
+
VALUE status_v = INT2FIX(hostaddr_r->astatus);
|
|
142
|
+
VALUE addrs_k = CSTR2SYM("addr");
|
|
143
|
+
VALUE addrs_v = rb_ary_new();
|
|
144
|
+
int idx;
|
|
145
|
+
|
|
146
|
+
if (hostaddr_r->naddrs > 0)
|
|
147
|
+
for (idx=0; idx < hostaddr_r->naddrs; idx++)
|
|
148
|
+
rb_ary_store(addrs_v, idx, parse_adns_rr_addr(hostaddr_r->addrs+idx));
|
|
149
|
+
|
|
150
|
+
rb_hash_aset(rb_hostaddr, host_k, host_v);
|
|
151
|
+
rb_hash_aset(rb_hostaddr, status_k, status_v);
|
|
152
|
+
rb_hash_aset(rb_hostaddr, addrs_k, addrs_v);
|
|
153
|
+
|
|
154
|
+
return rb_hostaddr;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
static VALUE parse_adns_rr_soa(adns_rr_soa *soa_r)
|
|
159
|
+
{
|
|
160
|
+
VALUE rb_soa = rb_hash_new();
|
|
161
|
+
VALUE mname_k = CSTR2SYM("mname");
|
|
162
|
+
VALUE mname_v = CSTR2STR(soa_r->mname);
|
|
163
|
+
VALUE rname_k = CSTR2SYM("rname");
|
|
164
|
+
VALUE rname_v = CSTR2STR(soa_r->rname);
|
|
165
|
+
VALUE serial_k = CSTR2SYM("serial");
|
|
166
|
+
VALUE serial_v = INT2FIX(soa_r->serial);
|
|
167
|
+
VALUE refresh_k = CSTR2SYM("refresh");
|
|
168
|
+
VALUE refresh_v = INT2FIX(soa_r->refresh);
|
|
169
|
+
VALUE retry_k = CSTR2SYM("retry");
|
|
170
|
+
VALUE retry_v = INT2FIX(soa_r->retry);
|
|
171
|
+
VALUE minimum_k = CSTR2SYM("minimum");
|
|
172
|
+
VALUE mimimum_v = INT2FIX(soa_r->minimum);
|
|
173
|
+
|
|
174
|
+
rb_hash_aset(rb_soa, mname_k, mname_v);
|
|
175
|
+
rb_hash_aset(rb_soa, rname_k, rname_v);
|
|
176
|
+
rb_hash_aset(rb_soa, serial_k, serial_v);
|
|
177
|
+
rb_hash_aset(rb_soa, refresh_k, refresh_v);
|
|
178
|
+
rb_hash_aset(rb_soa, retry_k, retry_v);
|
|
179
|
+
rb_hash_aset(rb_soa, minimum_k, mimimum_v);
|
|
180
|
+
|
|
181
|
+
return rb_soa;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
static VALUE parse_adns_rr_srv(adns_rr_srvraw *srvraw_r, adns_rr_srvha *srvha_r)
|
|
186
|
+
{
|
|
187
|
+
VALUE rb_srv = rb_hash_new();
|
|
188
|
+
VALUE priority_k = CSTR2SYM("priority"), priority_v;
|
|
189
|
+
VALUE weight_k = CSTR2SYM("weight"), weight_v;
|
|
190
|
+
VALUE port_k = CSTR2SYM("port"), port_v;
|
|
191
|
+
VALUE host_k = CSTR2SYM("host"), host_v;
|
|
192
|
+
VALUE addrs_k = CSTR2SYM("addrs"), addrs_v;
|
|
193
|
+
|
|
194
|
+
if (srvraw_r)
|
|
195
|
+
{
|
|
196
|
+
priority_v = INT2FIX(srvraw_r->priority);
|
|
197
|
+
weight_v = INT2FIX(srvraw_r->weight);
|
|
198
|
+
port_v = INT2FIX(srvraw_r->port);
|
|
199
|
+
host_v = CSTR2STR(srvraw_r->host);
|
|
200
|
+
rb_hash_aset(rb_srv, host_k, host_v);
|
|
201
|
+
}
|
|
202
|
+
else if (srvha_r)
|
|
203
|
+
{
|
|
204
|
+
priority_v = INT2FIX(srvha_r->priority);
|
|
205
|
+
weight_v = INT2FIX(srvha_r->weight);
|
|
206
|
+
port_v = INT2FIX(srvha_r->port);
|
|
207
|
+
addrs_v = parse_adns_rr_hostaddr(&srvha_r->ha);
|
|
208
|
+
rb_hash_aset(rb_srv, addrs_k, addrs_v);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
rb_hash_aset(rb_srv, priority_k, priority_v);
|
|
212
|
+
rb_hash_aset(rb_srv, weight_k, weight_v);
|
|
213
|
+
rb_hash_aset(rb_srv, port_k, port_v);
|
|
214
|
+
|
|
215
|
+
return rb_srv;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
static VALUE parse_adns_answer(adns_answer *answer_r)
|
|
220
|
+
{
|
|
221
|
+
VALUE rb_answer = rb_ary_new2(answer_r->nrrs);;
|
|
222
|
+
adns_rrtype t = answer_r->type & adns_rrt_typemask;
|
|
223
|
+
adns_rrtype t_dref = answer_r->type & adns__qtf_deref;
|
|
224
|
+
int idx, ecode;
|
|
225
|
+
|
|
226
|
+
if (answer_r->nrrs == 0)
|
|
227
|
+
/* something went wrong! */
|
|
228
|
+
return rb_answer;
|
|
229
|
+
|
|
230
|
+
for (idx=0; idx < answer_r->nrrs; idx++)
|
|
231
|
+
{
|
|
232
|
+
VALUE v; /* record specific value */
|
|
233
|
+
|
|
234
|
+
/* A, ADDR RECORD */
|
|
235
|
+
if (t == adns_r_a)
|
|
236
|
+
if (t_dref)
|
|
237
|
+
v = parse_adns_rr_addr(answer_r->rrs.addr+idx);
|
|
238
|
+
else
|
|
239
|
+
{
|
|
240
|
+
const char *addr_buf;
|
|
241
|
+
struct in_addr *inaddr_r = answer_r->rrs.inaddr+idx;
|
|
242
|
+
addr_buf = inet_ntoa(*inaddr_r);
|
|
243
|
+
if (ecode)
|
|
244
|
+
v = CSTR2STR("");
|
|
245
|
+
else
|
|
246
|
+
v = CSTR2STR(addr_buf);
|
|
247
|
+
}
|
|
248
|
+
/* NS, NS_RAW RECORD */
|
|
249
|
+
else if (t == adns_r_ns_raw)
|
|
250
|
+
if (t_dref)
|
|
251
|
+
v = parse_adns_rr_hostaddr(answer_r->rrs.hostaddr+idx);
|
|
252
|
+
else
|
|
253
|
+
v = CSTR2STR(answer_r->rrs.str[idx]);
|
|
254
|
+
/* CNAME, PTR, PTR_RAW RECORD */
|
|
255
|
+
else if (t == adns_r_cname ||
|
|
256
|
+
t == adns_r_ptr ||
|
|
257
|
+
t == adns_r_ptr_raw)
|
|
258
|
+
v = CSTR2STR(answer_r->rrs.str[idx]);
|
|
259
|
+
/* SOA, SOA_RAW RECORD */
|
|
260
|
+
else if (t == adns_r_soa_raw)
|
|
261
|
+
v = parse_adns_rr_soa(answer_r->rrs.soa+idx);
|
|
262
|
+
/* HINFO RECORD */
|
|
263
|
+
else if (t == adns_r_hinfo)
|
|
264
|
+
{
|
|
265
|
+
adns_rr_intstrpair *intstrpair_r = answer_r->rrs.intstrpair+idx;
|
|
266
|
+
const char *str1 = intstrpair_r->array[0].str;
|
|
267
|
+
const char *str2 = intstrpair_r->array[1].str;
|
|
268
|
+
v = rb_ary_new();
|
|
269
|
+
VALUE v1 = rb_ary_new();
|
|
270
|
+
VALUE v2 = rb_ary_new();
|
|
271
|
+
|
|
272
|
+
rb_ary_store(v1, 0, INT2FIX(intstrpair_r->array[0].i));
|
|
273
|
+
rb_ary_store(v1, 1, str1 ? CSTR2STR(str1) : CSTR2STR(""));
|
|
274
|
+
rb_ary_store(v2, 0, INT2FIX(intstrpair_r->array[1].i));
|
|
275
|
+
rb_ary_store(v2, 1, str2 ? CSTR2STR(str2) : CSTR2STR(""));
|
|
276
|
+
rb_ary_store(v, 0, v1);
|
|
277
|
+
rb_ary_store(v, 1, v2);
|
|
278
|
+
}
|
|
279
|
+
/* MX, MX_RAW RECORD */
|
|
280
|
+
else if (t == adns_r_mx_raw)
|
|
281
|
+
{
|
|
282
|
+
v = rb_hash_new();
|
|
283
|
+
VALUE preference_k = CSTR2SYM("preference"), preference_v;
|
|
284
|
+
|
|
285
|
+
if (t_dref) {
|
|
286
|
+
adns_rr_inthostaddr *inthostaddr_r = answer_r->rrs.inthostaddr+idx;
|
|
287
|
+
preference_v = INT2FIX(inthostaddr_r->i);
|
|
288
|
+
v = parse_adns_rr_hostaddr(&inthostaddr_r->ha);
|
|
289
|
+
} else {
|
|
290
|
+
adns_rr_intstr *intstr_r = answer_r->rrs.intstr+idx;
|
|
291
|
+
preference_v = INT2FIX(intstr_r->i);
|
|
292
|
+
VALUE host_k = CSTR2SYM("host");
|
|
293
|
+
VALUE host_v = CSTR2STR(intstr_r->str);
|
|
294
|
+
rb_hash_aset(v, host_k, host_v);
|
|
295
|
+
}
|
|
296
|
+
rb_hash_aset(v, preference_k, preference_v);
|
|
297
|
+
}
|
|
298
|
+
/* TXT RECORD */
|
|
299
|
+
else if (t == adns_r_txt)
|
|
300
|
+
{
|
|
301
|
+
adns_rr_intstr *intstr_r = answer_r->rrs.manyistr[idx];
|
|
302
|
+
v = CSTR2STR(intstr_r->str);
|
|
303
|
+
}
|
|
304
|
+
/* RP RP_RAW RECORD */
|
|
305
|
+
else if (t == adns_r_rp)
|
|
306
|
+
{
|
|
307
|
+
adns_rr_strpair *strpair_r = answer_r->rrs.strpair+idx;
|
|
308
|
+
v = rb_ary_new2(2);
|
|
309
|
+
rb_ary_store(v, 0, CSTR2STR(strpair_r->array[0]));
|
|
310
|
+
rb_ary_store(v, 1, CSTR2STR(strpair_r->array[1]));
|
|
311
|
+
}
|
|
312
|
+
/* SRV, SRV_RAW RECORD */
|
|
313
|
+
else if (t == adns_r_srv)
|
|
314
|
+
{
|
|
315
|
+
if (t_dref) {
|
|
316
|
+
adns_rr_srvraw *srvraw_r = answer_r->rrs.srvraw+idx;
|
|
317
|
+
v = parse_adns_rr_srv(srvraw_r, NULL);
|
|
318
|
+
} else {
|
|
319
|
+
adns_rr_srvha *srvha_r = answer_r->rrs.srvha+idx;
|
|
320
|
+
v = parse_adns_rr_srv(NULL, srvha_r);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/* UNKNOWN RECORD */
|
|
324
|
+
else
|
|
325
|
+
v = rb_hash_new();
|
|
326
|
+
/* push value to answer array */
|
|
327
|
+
rb_ary_store(rb_answer, idx, v);
|
|
328
|
+
}
|
|
329
|
+
return rb_answer;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
static VALUE cQuery_init(VALUE self)
|
|
333
|
+
{
|
|
334
|
+
return self;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
static void cQuery_mark(void *ptr)
|
|
338
|
+
{
|
|
339
|
+
rb_adns_query_t *rb_adq_r = (rb_adns_query_t *)ptr;
|
|
340
|
+
rb_gc_mark(rb_adq_r->answer);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static void cQuery_free(void *ptr)
|
|
344
|
+
{
|
|
345
|
+
rb_adns_query_t *rb_adq_r = (rb_adns_query_t *)ptr;
|
|
346
|
+
rb_adq_r->rb_ads_r = NULL;
|
|
347
|
+
rb_adq_r->adq = NULL;
|
|
348
|
+
rb_adq_r->answer = Qnil;
|
|
349
|
+
(void) free(rb_adq_r);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/*
|
|
353
|
+
* call-seq: check => Hash or raises ADNS::NotReadyError
|
|
354
|
+
*
|
|
355
|
+
* Check pending asynchronous request and retrieve answer or raises ADNS::NotReadyError, if request is still pending.
|
|
356
|
+
*/
|
|
357
|
+
static VALUE cQuery_check(VALUE self)
|
|
358
|
+
{
|
|
359
|
+
rb_adns_query_t *rb_adq_r;
|
|
360
|
+
adns_answer *answer_r;
|
|
361
|
+
int ecode;
|
|
362
|
+
|
|
363
|
+
Data_Get_Struct(self, rb_adns_query_t, rb_adq_r);
|
|
364
|
+
if (rb_adq_r->answer != Qnil)
|
|
365
|
+
return rb_adq_r->answer;
|
|
366
|
+
if (!rb_adq_r->adq)
|
|
367
|
+
rb_raise(mADNS__eQueryError, "invalid query");
|
|
368
|
+
ecode = adns_check(rb_adq_r->rb_ads_r->ads, &rb_adq_r->adq, &answer_r, NULL);
|
|
369
|
+
if (ecode)
|
|
370
|
+
{
|
|
371
|
+
if (ecode == EWOULDBLOCK)
|
|
372
|
+
rb_raise(mADNS__eNotReadyError, strerror(ecode));
|
|
373
|
+
else
|
|
374
|
+
{
|
|
375
|
+
rb_adq_r->adq = NULL;
|
|
376
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
rb_adq_r->answer = rb_hash_new();
|
|
380
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("type"), INT2FIX(answer_r->type));
|
|
381
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("owner"), CSTR2STR(answer_r->owner));
|
|
382
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("status"), INT2FIX(answer_r->status));
|
|
383
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("expires"), INT2FIX(answer_r->expires));
|
|
384
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("answer"), parse_adns_answer(answer_r));
|
|
385
|
+
rb_adq_r->adq = NULL; /* mark query as completed, thus making it invalid */
|
|
386
|
+
return rb_adq_r->answer;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/*
|
|
390
|
+
* call-seq: wait() => Hash
|
|
391
|
+
*
|
|
392
|
+
* Wait until answer is received.
|
|
393
|
+
*/
|
|
394
|
+
static VALUE cQuery_wait(int argc, VALUE argv[], VALUE self)
|
|
395
|
+
{
|
|
396
|
+
rb_adns_query_t *rb_adq_r;
|
|
397
|
+
adns_answer *answer_r;
|
|
398
|
+
int ecode;
|
|
399
|
+
|
|
400
|
+
Data_Get_Struct(self, rb_adns_query_t, rb_adq_r);
|
|
401
|
+
if (rb_adq_r->answer != Qnil)
|
|
402
|
+
return rb_adq_r->answer;
|
|
403
|
+
if (!rb_adq_r->adq)
|
|
404
|
+
rb_raise(mADNS__eQueryError, "query invalidated");
|
|
405
|
+
ecode = adns_wait(rb_adq_r->rb_ads_r->ads, &rb_adq_r->adq, &answer_r, NULL);
|
|
406
|
+
if (ecode)
|
|
407
|
+
{
|
|
408
|
+
rb_adq_r->adq = NULL;
|
|
409
|
+
rb_adq_r->answer = Qnil;
|
|
410
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
411
|
+
}
|
|
412
|
+
rb_adq_r->answer = rb_hash_new();
|
|
413
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("type"), INT2FIX(answer_r->type));
|
|
414
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("owner"), CSTR2STR(answer_r->owner));
|
|
415
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("status"), INT2FIX(answer_r->status));
|
|
416
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("expires"), INT2FIX(answer_r->expires));
|
|
417
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("answer"), parse_adns_answer(answer_r));
|
|
418
|
+
rb_adq_r->adq = NULL;
|
|
419
|
+
return rb_adq_r->answer;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/*
|
|
423
|
+
* call-seq: cancel() => nil
|
|
424
|
+
*
|
|
425
|
+
* Cancel current pending asynchronous request.
|
|
426
|
+
*/
|
|
427
|
+
static VALUE cQuery_cancel(VALUE self)
|
|
428
|
+
{
|
|
429
|
+
rb_adns_query_t *rb_adq_r;
|
|
430
|
+
int ecode;
|
|
431
|
+
|
|
432
|
+
Data_Get_Struct(self, rb_adns_query_t, rb_adq_r);
|
|
433
|
+
if (!rb_adq_r->adq)
|
|
434
|
+
rb_raise(mADNS__eQueryError, "query invalidated");
|
|
435
|
+
(void) adns_cancel(rb_adq_r->adq);
|
|
436
|
+
cQuery_free((void *)rb_adq_r);
|
|
437
|
+
return Qnil;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
/*
|
|
442
|
+
* call-seq: submit(domain, type[, qflags]) => ADNS::Query instance
|
|
443
|
+
*
|
|
444
|
+
* Submit asynchronous request to resolve domain <domain> of record type <type> using optional query flags <qflags>.
|
|
445
|
+
*/
|
|
446
|
+
static VALUE cState_submit(int argc, VALUE argv[], VALUE self)
|
|
447
|
+
{
|
|
448
|
+
rb_adns_query_t *rb_adq_r = ALLOC(rb_adns_query_t);
|
|
449
|
+
const char *owner;
|
|
450
|
+
adns_rrtype type;
|
|
451
|
+
adns_queryflags qflags = adns_qf_owner;
|
|
452
|
+
VALUE query; /* return instance */
|
|
453
|
+
int ecode;
|
|
454
|
+
|
|
455
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_adq_r->rb_ads_r);
|
|
456
|
+
if (argc < 2)
|
|
457
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
|
|
458
|
+
else if (argc > 3)
|
|
459
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 3)", argc);
|
|
460
|
+
CHECK_TYPE(argv[0], T_STRING); /* DOMAIN */
|
|
461
|
+
CHECK_TYPE(argv[1], T_FIXNUM); /* RR */
|
|
462
|
+
if (argc == 3)
|
|
463
|
+
CHECK_TYPE(argv[2], T_FIXNUM); /* QFlags */
|
|
464
|
+
owner = STR2CSTR(argv[0]);
|
|
465
|
+
type = FIX2INT(argv[1]);
|
|
466
|
+
if (argc == 3)
|
|
467
|
+
qflags |= FIX2INT(argv[2]);
|
|
468
|
+
rb_adq_r->answer = Qnil;
|
|
469
|
+
query = Data_Wrap_Struct(mADNS__cQuery, cQuery_mark, cQuery_free, rb_adq_r);
|
|
470
|
+
ecode = adns_submit(rb_adq_r->rb_ads_r->ads, owner, type, qflags, (void *)query, &rb_adq_r->adq);
|
|
471
|
+
if (ecode)
|
|
472
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
473
|
+
rb_obj_call_init(query, 0, 0);
|
|
474
|
+
return query;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/*
|
|
478
|
+
* call-seq: submit_reverse(ipaddr, type[, qflags]) => ADNS::Query object
|
|
479
|
+
*
|
|
480
|
+
* Submit asynchronous request to reverse lookup address <ipaddr> using optional query flags <qflags>.
|
|
481
|
+
* Note: <type> can only be ADNS::RR::PTR or ADNS::RR::PTR_RAW
|
|
482
|
+
*/
|
|
483
|
+
static VALUE cState_submit_reverse(int argc, VALUE argv[], VALUE self)
|
|
484
|
+
{
|
|
485
|
+
VALUE query; /* return instance */
|
|
486
|
+
rb_adns_query_t *rb_adq_r = ALLOC(rb_adns_query_t);
|
|
487
|
+
const char *owner;
|
|
488
|
+
struct sockaddr_in addr;
|
|
489
|
+
adns_rrtype type;
|
|
490
|
+
adns_queryflags qflags = adns_qf_owner;
|
|
491
|
+
int idx, ecode;
|
|
492
|
+
|
|
493
|
+
if (argc < 2)
|
|
494
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
|
|
495
|
+
if (argc > 3)
|
|
496
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 2)", argc);
|
|
497
|
+
CHECK_TYPE(argv[0], T_STRING);
|
|
498
|
+
CHECK_TYPE(argv[1], T_FIXNUM);
|
|
499
|
+
if (argc == 3)
|
|
500
|
+
CHECK_TYPE(argv[2], T_FIXNUM);
|
|
501
|
+
owner = STR2CSTR(argv[0]);
|
|
502
|
+
type = FIX2INT(argv[1]);
|
|
503
|
+
if (argc == 3)
|
|
504
|
+
qflags |= FIX2INT(argv[2]);
|
|
505
|
+
switch(type)
|
|
506
|
+
{
|
|
507
|
+
case adns_r_ptr:
|
|
508
|
+
case adns_r_ptr_raw:
|
|
509
|
+
break;
|
|
510
|
+
default:
|
|
511
|
+
rb_raise(rb_eArgError, "invalid record type (PTR or PTR_RAW record expected)");
|
|
512
|
+
}
|
|
513
|
+
addr.sin_family = AF_INET;
|
|
514
|
+
ecode = inet_aton(owner, &addr.sin_addr);
|
|
515
|
+
if (ecode == -1)
|
|
516
|
+
rb_raise(mADNS__eQueryError, "invalid ip address");
|
|
517
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_adq_r->rb_ads_r);
|
|
518
|
+
rb_adq_r->answer = Qnil;
|
|
519
|
+
query = Data_Wrap_Struct(mADNS__cQuery, cQuery_mark, cQuery_free, rb_adq_r);
|
|
520
|
+
rb_obj_call_init(query, 0, 0);
|
|
521
|
+
ecode = adns_submit_reverse(rb_adq_r->rb_ads_r->ads, (struct sockaddr *) &addr,
|
|
522
|
+
type, qflags, (void *)query, &rb_adq_r->adq);
|
|
523
|
+
if (ecode)
|
|
524
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
525
|
+
return query;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/*
|
|
529
|
+
* call-seq: submit_reverse_any(ip_addr, type[, qflags]) => ADNS::Query instance
|
|
530
|
+
*
|
|
531
|
+
* Submit asynchronous request to reverse lookup address <ipaddr> using optional query flags <qflags>.
|
|
532
|
+
* Note: <type> can any resource record.
|
|
533
|
+
*/
|
|
534
|
+
static VALUE cState_submit_reverse_any(int argc, VALUE argv[], VALUE self)
|
|
535
|
+
{
|
|
536
|
+
VALUE query; /* return instance */
|
|
537
|
+
rb_adns_query_t *rb_adq_r = ALLOC(rb_adns_query_t);
|
|
538
|
+
const char *owner;
|
|
539
|
+
struct sockaddr_in addr;
|
|
540
|
+
const char *zone; /* in-addr.arpa or any other reverse zones */
|
|
541
|
+
adns_rrtype type = adns_r_none;
|
|
542
|
+
adns_queryflags qflags = adns_qf_owner;
|
|
543
|
+
int idx, ecode;
|
|
544
|
+
|
|
545
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_adq_r->rb_ads_r);
|
|
546
|
+
if (argc < 3)
|
|
547
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 3)", argc);
|
|
548
|
+
if (argc > 4)
|
|
549
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 4)", argc);
|
|
550
|
+
CHECK_TYPE(argv[0], T_STRING); /* IP */
|
|
551
|
+
CHECK_TYPE(argv[1], T_STRING); /* Zone */
|
|
552
|
+
CHECK_TYPE(argv[2], T_FIXNUM); /* RR */
|
|
553
|
+
if (argc == 4)
|
|
554
|
+
CHECK_TYPE(argv[3], T_FIXNUM); /* )); */
|
|
555
|
+
owner = STR2CSTR(argv[0]);
|
|
556
|
+
zone = STR2CSTR(argv[1]);
|
|
557
|
+
type = FIX2INT(argv[2]);
|
|
558
|
+
if (argc == 4)
|
|
559
|
+
qflags |= FIX2INT(argv[3]);
|
|
560
|
+
addr.sin_family = AF_INET;
|
|
561
|
+
ecode = inet_aton(owner, &addr.sin_addr);
|
|
562
|
+
if (ecode == 0)
|
|
563
|
+
rb_raise(mADNS__eQueryError, "invalid ip address");
|
|
564
|
+
rb_adq_r->answer = Qnil;
|
|
565
|
+
query = Data_Wrap_Struct(mADNS__cQuery, cQuery_mark, cQuery_free, rb_adq_r);
|
|
566
|
+
rb_obj_call_init(query, 0, 0);
|
|
567
|
+
ecode = adns_submit_reverse_any(rb_adq_r->rb_ads_r->ads, (struct sockaddr*)&addr,
|
|
568
|
+
zone, type, qflags, (void *)query, &rb_adq_r->adq);
|
|
569
|
+
if (ecode)
|
|
570
|
+
rb_raise(mADNS__eError, strerror(ecode));
|
|
571
|
+
return query;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/*
|
|
575
|
+
* call-seq: completed() => Array
|
|
576
|
+
*
|
|
577
|
+
* Returns an array of all the completed (ADNS::Query) queries submitted using ADNS::State.submit_*() methods.
|
|
578
|
+
*/
|
|
579
|
+
static VALUE cState_completed_queries(int argc, VALUE argv[], VALUE self)
|
|
580
|
+
{
|
|
581
|
+
VALUE a1, query_list = rb_ary_new();
|
|
582
|
+
VALUE query_ctx; /* ADNS::Query context passed from one of the submit_* */
|
|
583
|
+
rb_adns_state_t *rb_ads_r;
|
|
584
|
+
rb_adns_query_t *rb_adq_r;
|
|
585
|
+
adns_query adq;
|
|
586
|
+
adns_answer *answer_r;
|
|
587
|
+
double timeout;
|
|
588
|
+
int ecode;
|
|
589
|
+
|
|
590
|
+
if (argc == 1)
|
|
591
|
+
{
|
|
592
|
+
a1 = argv[0];
|
|
593
|
+
CHECK_TYPE(a1, T_FLOAT);
|
|
594
|
+
}
|
|
595
|
+
else
|
|
596
|
+
a1 = rb_float_new(0.0);
|
|
597
|
+
timeout = (double) RFLOAT_VALUE(a1);
|
|
598
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_ads_r);
|
|
599
|
+
(void) adns_select_timeout(rb_ads_r, timeout);
|
|
600
|
+
for (adns_forallqueries_begin(rb_ads_r->ads);
|
|
601
|
+
(adq = adns_forallqueries_next(rb_ads_r->ads, 0)) != 0;)
|
|
602
|
+
{
|
|
603
|
+
ecode = adns_check(rb_ads_r->ads, &adq, &answer_r, (void **)&query_ctx);
|
|
604
|
+
if (ecode)
|
|
605
|
+
if (ecode == EWOULDBLOCK)
|
|
606
|
+
continue;
|
|
607
|
+
Data_Get_Struct(query_ctx, rb_adns_query_t, rb_adq_r);
|
|
608
|
+
rb_adq_r->answer = rb_hash_new();
|
|
609
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("type"), INT2FIX(answer_r->type));
|
|
610
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("owner"), CSTR2STR(answer_r->owner));
|
|
611
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("status"), INT2FIX(answer_r->status));
|
|
612
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("expires"), INT2FIX(answer_r->expires));
|
|
613
|
+
rb_hash_aset(rb_adq_r->answer, CSTR2SYM("answer"), parse_adns_answer(answer_r));
|
|
614
|
+
rb_adq_r->adq = NULL;
|
|
615
|
+
free(answer_r);
|
|
616
|
+
rb_ary_push(query_list, query_ctx);
|
|
617
|
+
}
|
|
618
|
+
return query_list;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/*
|
|
622
|
+
* call-seq: synchronous(domain, type[, qflags]) => Hash
|
|
623
|
+
*
|
|
624
|
+
* Submit synchronous request to resolve domain <domain> of record type <type> using optional query flags <qflags>.
|
|
625
|
+
*/
|
|
626
|
+
static VALUE cState_synchronous(int argc, VALUE argv[], VALUE self)
|
|
627
|
+
{
|
|
628
|
+
VALUE answer = rb_hash_new(); /* return instance */
|
|
629
|
+
rb_adns_state_t *rb_ads_r;
|
|
630
|
+
adns_answer *answer_r;
|
|
631
|
+
adns_queryflags qflags = adns_qf_owner;
|
|
632
|
+
adns_rrtype type = adns_r_none;
|
|
633
|
+
const char *owner;
|
|
634
|
+
int ecode;
|
|
635
|
+
|
|
636
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_ads_r);
|
|
637
|
+
if (argc < 2)
|
|
638
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
|
|
639
|
+
if (argc > 3)
|
|
640
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 3)", argc);
|
|
641
|
+
CHECK_TYPE(argv[0], T_STRING); /* DOMAIN */
|
|
642
|
+
CHECK_TYPE(argv[1], T_FIXNUM); /* RR */
|
|
643
|
+
if (argc == 3)
|
|
644
|
+
CHECK_TYPE(argv[2], T_FIXNUM); /* QFlags */
|
|
645
|
+
owner = STR2CSTR(argv[0]);
|
|
646
|
+
type = FIX2INT(argv[1]);
|
|
647
|
+
if (argc == 3)
|
|
648
|
+
qflags |= FIX2INT(argv[2]);
|
|
649
|
+
ecode = adns_synchronous(rb_ads_r->ads, owner, type, qflags, &answer_r);
|
|
650
|
+
if (ecode)
|
|
651
|
+
rb_raise(mADNS__eError, adns_strerror(ecode));
|
|
652
|
+
/* populate return hash */
|
|
653
|
+
rb_hash_aset(answer, CSTR2SYM("type"), INT2FIX(answer_r->type));
|
|
654
|
+
rb_hash_aset(answer, CSTR2SYM("owner"), CSTR2STR(answer_r->owner));
|
|
655
|
+
rb_hash_aset(answer, CSTR2SYM("status"), INT2FIX(answer_r->status));
|
|
656
|
+
rb_hash_aset(answer, CSTR2SYM("expires"), INT2FIX(answer_r->expires));
|
|
657
|
+
rb_hash_aset(answer, CSTR2SYM("answer"), Qnil);
|
|
658
|
+
if (answer_r->nrrs == 0)
|
|
659
|
+
return answer;
|
|
660
|
+
else
|
|
661
|
+
rb_hash_aset(answer, CSTR2SYM("answer"), parse_adns_answer(answer_r));
|
|
662
|
+
return answer;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/*
|
|
666
|
+
* call-seq: global_system_failure() => nil
|
|
667
|
+
*
|
|
668
|
+
* Call this function, If serious problem(s) occurs with adns library.
|
|
669
|
+
* All currently outstanding queries will be made to fail with ADNS::Status::SystemFail
|
|
670
|
+
* status code and adns library will close any stream sockets it has open since inception.
|
|
671
|
+
*/
|
|
672
|
+
static VALUE cState_global_system_failure(VALUE self)
|
|
673
|
+
{
|
|
674
|
+
rb_adns_state_t *rb_ads_r;
|
|
675
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_ads_r);
|
|
676
|
+
(void) adns_globalsystemfailure(rb_ads_r->ads);
|
|
677
|
+
return Qnil;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
static VALUE cState_initialize(int argc, VALUE argv[], VALUE self)
|
|
681
|
+
{
|
|
682
|
+
return self;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
static void cState_free(void *ptr)
|
|
686
|
+
{
|
|
687
|
+
rb_adns_state_t *rb_ads_r = (rb_adns_state_t *) ptr;
|
|
688
|
+
(void) adns_finish(rb_ads_r->ads);
|
|
689
|
+
if (rb_ads_r->diagfile)
|
|
690
|
+
(void) fclose(rb_ads_r->diagfile);
|
|
691
|
+
free(rb_ads_r);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
static void cState_mark(void *ptr)
|
|
695
|
+
{
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/*
|
|
700
|
+
* call-seq: new([iflags, filename, filemode]) => ADNS::State object
|
|
701
|
+
*
|
|
702
|
+
* Create new ADNS::State object and initialize adns library using optional initialization
|
|
703
|
+
* flags <iflags>, debug log to filename <filename> (*only available if ADNS::IF::DEBUG flag is given*),
|
|
704
|
+
* debug log filemode <filemode>.
|
|
705
|
+
*/
|
|
706
|
+
static VALUE cState_new(int argc, VALUE argv[], VALUE self)
|
|
707
|
+
{
|
|
708
|
+
VALUE state; /* return instance */
|
|
709
|
+
rb_adns_state_t *rb_ads_r = ALLOC(rb_adns_state_t);
|
|
710
|
+
rb_ads_r->ads = NULL;
|
|
711
|
+
rb_ads_r->diagfile = NULL;
|
|
712
|
+
adns_initflags iflags = adns_if_none;
|
|
713
|
+
const char *fname, *fmode;
|
|
714
|
+
|
|
715
|
+
if (argc > 3)
|
|
716
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 3)", argc);
|
|
717
|
+
if (argc >= 1)
|
|
718
|
+
{
|
|
719
|
+
CHECK_TYPE(argv[0], T_FIXNUM);
|
|
720
|
+
iflags |= FIX2INT(argv[0]);
|
|
721
|
+
if (argc >= 2)
|
|
722
|
+
{
|
|
723
|
+
CHECK_TYPE(argv[1], T_STRING);
|
|
724
|
+
fname = STR2CSTR(argv[1]);
|
|
725
|
+
if (argc == 3)
|
|
726
|
+
{
|
|
727
|
+
CHECK_TYPE(argv[2], T_STRING);
|
|
728
|
+
fmode = STR2CSTR(argv[2]);
|
|
729
|
+
} else
|
|
730
|
+
fmode = DEFAULT_DIAG_FILEMODE;
|
|
731
|
+
rb_ads_r->diagfile = fopen(fname, fmode);
|
|
732
|
+
if (!rb_ads_r->diagfile)
|
|
733
|
+
rb_raise(rb_eIOError, "%s - %s", strerror(errno), fname);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
adns_init(&rb_ads_r->ads, iflags, rb_ads_r->diagfile);
|
|
737
|
+
state = Data_Wrap_Struct(mADNS__cState, cState_mark, cState_free, rb_ads_r);
|
|
738
|
+
rb_obj_call_init(state, 0, 0);
|
|
739
|
+
return state;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/*
|
|
743
|
+
* call-seq: new2(configtext, [iflags, filename, filemode]) => ADNS::State object
|
|
744
|
+
*
|
|
745
|
+
* Create new ADNS::State object and initialize adns library using resolve.conf style
|
|
746
|
+
* configuration text and optional initialization
|
|
747
|
+
* flags <iflags>, debug log to filename <filename> (*only available if ADNS::IF::DEBUG flag is given*),
|
|
748
|
+
* debug log filemode <filemode>.
|
|
749
|
+
*/
|
|
750
|
+
static VALUE cState_new2(int argc, VALUE argv[], VALUE self)
|
|
751
|
+
{
|
|
752
|
+
VALUE state; /* return instance */
|
|
753
|
+
rb_adns_state_t *rb_ads_r = ALLOC(rb_adns_state_t);
|
|
754
|
+
rb_ads_r->ads = NULL;
|
|
755
|
+
rb_ads_r->diagfile = NULL;
|
|
756
|
+
adns_initflags iflags = adns_if_none;
|
|
757
|
+
const char *fname, *fmode, *cfgtxt;
|
|
758
|
+
|
|
759
|
+
if (argc > 4)
|
|
760
|
+
rb_raise(rb_eArgError, "excess number of arguments (%d for 3)", argc);
|
|
761
|
+
if (argc >= 1)
|
|
762
|
+
{
|
|
763
|
+
CHECK_TYPE(argv[0], T_STRING);
|
|
764
|
+
cfgtxt = STR2CSTR(argv[0]);
|
|
765
|
+
if (argc >= 2)
|
|
766
|
+
{
|
|
767
|
+
CHECK_TYPE(argv[1], T_FIXNUM);
|
|
768
|
+
iflags |= FIX2INT(argv[1]);
|
|
769
|
+
}
|
|
770
|
+
if (argc >= 3)
|
|
771
|
+
{
|
|
772
|
+
CHECK_TYPE(argv[2], T_STRING);
|
|
773
|
+
fname = STR2CSTR(argv[2]);
|
|
774
|
+
if (argc == 4)
|
|
775
|
+
{
|
|
776
|
+
CHECK_TYPE(argv[3], T_STRING);
|
|
777
|
+
fmode = STR2CSTR(argv[3]);
|
|
778
|
+
} else
|
|
779
|
+
fmode = DEFAULT_DIAG_FILEMODE;
|
|
780
|
+
rb_ads_r->diagfile = fopen(fname, fmode);
|
|
781
|
+
if (!rb_ads_r->diagfile)
|
|
782
|
+
rb_raise(rb_eIOError, "%s - %s", strerror(errno), fname);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
adns_init_strcfg(&rb_ads_r->ads, iflags, rb_ads_r->diagfile, cfgtxt);
|
|
786
|
+
state = Data_Wrap_Struct(mADNS__cState, cState_mark, cState_free, rb_ads_r);
|
|
787
|
+
rb_obj_call_init(state, 0, 0);
|
|
788
|
+
return state;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/*
|
|
792
|
+
* call-seq: finish() => nil
|
|
793
|
+
*
|
|
794
|
+
* Finish all the outstanding queries associated with the ADNS::State instance.
|
|
795
|
+
*/
|
|
796
|
+
static VALUE cState_finish(VALUE self)
|
|
797
|
+
{
|
|
798
|
+
rb_adns_state_t *rb_ads_r;
|
|
799
|
+
Data_Get_Struct(self, rb_adns_state_t, rb_ads_r);
|
|
800
|
+
(void) adns_finish(rb_ads_r->ads);
|
|
801
|
+
return Qnil;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/*
|
|
805
|
+
* = ADNS Module
|
|
806
|
+
*
|
|
807
|
+
* === Classes
|
|
808
|
+
* * ADNS::State
|
|
809
|
+
* * ADNS::Query
|
|
810
|
+
* * ADNS::Error
|
|
811
|
+
* * ADNS::LocalError
|
|
812
|
+
* * ADNS::RemoteError
|
|
813
|
+
* * ADNS::QueryError
|
|
814
|
+
* * ADNS::NotReadyError
|
|
815
|
+
*
|
|
816
|
+
* === Class methods
|
|
817
|
+
* * ADNS::status_to_s
|
|
818
|
+
* * ADNS::status_to_ss
|
|
819
|
+
*
|
|
820
|
+
* === Modules
|
|
821
|
+
* * ADNS::RR - resource record types constant collection module.
|
|
822
|
+
* * ADNS::QF - adns query flags constant collection module.
|
|
823
|
+
* * ADNS::IF - adns initialization flags constant collections module.
|
|
824
|
+
* * ADNS::Status - adns status code constant collection module.
|
|
825
|
+
*
|
|
826
|
+
* === Usage Example
|
|
827
|
+
* ==== Asynchronous
|
|
828
|
+
* require 'rubygems';
|
|
829
|
+
* require 'adns';
|
|
830
|
+
* require 'pp';
|
|
831
|
+
* adns = ADNS::State.new();
|
|
832
|
+
* query = adns.submit("rubygems.org", ADNS::RR:NS);
|
|
833
|
+
* pp query.wait();
|
|
834
|
+
*
|
|
835
|
+
* ==== Synchronous
|
|
836
|
+
* require 'rubygems'
|
|
837
|
+
* require 'adns';
|
|
838
|
+
* require 'pp';
|
|
839
|
+
* adns = ADNS::State.new();
|
|
840
|
+
* pp adns.synchronous('rubygems', ADNS::RR::MX);
|
|
841
|
+
*
|
|
842
|
+
*/
|
|
843
|
+
void Init_adns(void)
|
|
844
|
+
{
|
|
845
|
+
/*
|
|
846
|
+
* Document-module: ADNS
|
|
847
|
+
* ADNS module provides bindings to GNU adns resolver library.
|
|
848
|
+
*/
|
|
849
|
+
mADNS = rb_define_module("ADNS");
|
|
850
|
+
rb_define_module_function(mADNS, "status_to_s", mADNS__status_to_s, 1);
|
|
851
|
+
rb_define_module_function(mADNS, "status_to_ss", mADNS__status_to_ss, 1);
|
|
852
|
+
rb_define_const(mADNS, "VERSION", CSTR2STR(VERSION));
|
|
853
|
+
|
|
854
|
+
/*
|
|
855
|
+
* Document-class: ADNS::State
|
|
856
|
+
* ADNS::State class defines asychronous/synchronous methods to submit/check the query.
|
|
857
|
+
*/
|
|
858
|
+
mADNS__cState = rb_define_class_under(mADNS, "State", rb_cObject);
|
|
859
|
+
rb_define_module_function(mADNS__cState, "new", cState_new, -1);
|
|
860
|
+
rb_define_module_function(mADNS__cState, "new2", cState_new2, -1);
|
|
861
|
+
rb_define_method(mADNS__cState, "initialize", cState_initialize, -1);
|
|
862
|
+
rb_define_method(mADNS__cState, "synchronous", cState_synchronous, -1);
|
|
863
|
+
rb_define_method(mADNS__cState, "submit", cState_submit, -1);
|
|
864
|
+
rb_define_method(mADNS__cState, "submit_reverse", cState_submit_reverse, -1);
|
|
865
|
+
rb_define_method(mADNS__cState, "submit_reverse_any", cState_submit_reverse_any, -1);
|
|
866
|
+
rb_define_method(mADNS__cState, "completed_queries", cState_completed_queries, -1);
|
|
867
|
+
rb_define_method(mADNS__cState, "global_system_failure", cState_global_system_failure, -1);
|
|
868
|
+
|
|
869
|
+
/*
|
|
870
|
+
* Document-class: ADNS::Query
|
|
871
|
+
* ADNS::Query class defines asychronous/synchronous methods to check the query
|
|
872
|
+
* submitted using one of the ADNS::State.submit* methods.
|
|
873
|
+
*/
|
|
874
|
+
mADNS__cQuery = rb_define_class_under(mADNS, "Query", rb_cObject);
|
|
875
|
+
rb_define_method(mADNS__cQuery, "initialize", cQuery_init, 0);
|
|
876
|
+
rb_define_method(mADNS__cQuery, "check", cQuery_check, 0);
|
|
877
|
+
rb_define_method(mADNS__cQuery, "wait", cQuery_wait, -1);
|
|
878
|
+
rb_define_method(mADNS__cQuery, "cancel", cQuery_cancel, 0);
|
|
879
|
+
|
|
880
|
+
/*
|
|
881
|
+
* Document-module: ADNS::RR
|
|
882
|
+
* Module defines collection of adns resource records.
|
|
883
|
+
*/
|
|
884
|
+
mADNS__mRR = rb_define_module_under(mADNS, "RR");
|
|
885
|
+
rb_define_const(mADNS__mRR, "UNKNOWN", INT2FIX(adns_r_unknown));
|
|
886
|
+
rb_define_const(mADNS__mRR, "NONE", INT2FIX(adns_r_none));
|
|
887
|
+
rb_define_const(mADNS__mRR, "A", INT2FIX(adns_r_a));
|
|
888
|
+
rb_define_const(mADNS__mRR, "NS_RAW", INT2FIX(adns_r_ns_raw));
|
|
889
|
+
rb_define_const(mADNS__mRR, "NS", INT2FIX(adns_r_ns));
|
|
890
|
+
rb_define_const(mADNS__mRR, "CNAME", INT2FIX(adns_r_cname));
|
|
891
|
+
rb_define_const(mADNS__mRR, "SOA_RAW", INT2FIX(adns_r_soa_raw));
|
|
892
|
+
rb_define_const(mADNS__mRR, "SOA", INT2FIX(adns_r_soa));
|
|
893
|
+
rb_define_const(mADNS__mRR, "PTR_RAW", INT2FIX(adns_r_ptr_raw));
|
|
894
|
+
rb_define_const(mADNS__mRR, "PTR", INT2FIX(adns_r_ptr));
|
|
895
|
+
rb_define_const(mADNS__mRR, "HINFO", INT2FIX(adns_r_hinfo));
|
|
896
|
+
rb_define_const(mADNS__mRR, "MX_RAW", INT2FIX(adns_r_mx_raw));
|
|
897
|
+
rb_define_const(mADNS__mRR, "MX", INT2FIX(adns_r_mx));
|
|
898
|
+
rb_define_const(mADNS__mRR, "TXT", INT2FIX(adns_r_txt));
|
|
899
|
+
rb_define_const(mADNS__mRR, "RP_RAW", INT2FIX(adns_r_rp_raw));
|
|
900
|
+
rb_define_const(mADNS__mRR, "RP", INT2FIX(adns_r_rp));
|
|
901
|
+
rb_define_const(mADNS__mRR, "SRV", INT2FIX(adns_r_srv));
|
|
902
|
+
rb_define_const(mADNS__mRR, "SRV_RAW", INT2FIX(adns_r_srv_raw));
|
|
903
|
+
|
|
904
|
+
/*
|
|
905
|
+
* Document-module: ADNS::Status
|
|
906
|
+
* Module defines collection of adns status code.
|
|
907
|
+
*/
|
|
908
|
+
mADNS__mStatus = rb_define_module_under(mADNS, "Status");
|
|
909
|
+
rb_define_const(mADNS__mStatus, "OK", INT2FIX(adns_s_ok));
|
|
910
|
+
|
|
911
|
+
// ADNS::LocalError
|
|
912
|
+
rb_define_const(mADNS__mStatus, "NoMemory", INT2FIX(adns_s_nomemory));
|
|
913
|
+
rb_define_const(mADNS__mStatus, "UnknownRRType", INT2FIX(adns_s_unknownrrtype));
|
|
914
|
+
rb_define_const(mADNS__mStatus, "SystemFail", INT2FIX(adns_s_systemfail));
|
|
915
|
+
|
|
916
|
+
// ADNS::RemoteError
|
|
917
|
+
rb_define_const(mADNS__mStatus, "Timeout", INT2FIX(adns_s_timeout));
|
|
918
|
+
rb_define_const(mADNS__mStatus, "AllServFail", INT2FIX(adns_s_allservfail));
|
|
919
|
+
rb_define_const(mADNS__mStatus, "NoRecurse", INT2FIX(adns_s_norecurse));
|
|
920
|
+
rb_define_const(mADNS__mStatus, "InvalidResponse", INT2FIX(adns_s_invalidresponse));
|
|
921
|
+
rb_define_const(mADNS__mStatus, "UnknownFormat", INT2FIX(adns_s_unknownformat));
|
|
922
|
+
rb_define_const(mADNS__mStatus, "RcodeServFail", INT2FIX(adns_s_rcodeservfail));
|
|
923
|
+
rb_define_const(mADNS__mStatus, "RcodeFormatError", INT2FIX(adns_s_rcodeformaterror));
|
|
924
|
+
rb_define_const(mADNS__mStatus, "RcodeNotImplemented", INT2FIX(adns_s_rcodenotimplemented));
|
|
925
|
+
rb_define_const(mADNS__mStatus, "RcodeRefused", INT2FIX(adns_s_rcoderefused));
|
|
926
|
+
rb_define_const(mADNS__mStatus, "RcodeUnknown", INT2FIX(adns_s_rcodeunknown));
|
|
927
|
+
rb_define_const(mADNS__mStatus, "Inconsistent", INT2FIX(adns_s_inconsistent));
|
|
928
|
+
rb_define_const(mADNS__mStatus, "ProhibitedCNAME", INT2FIX(adns_s_prohibitedcname));
|
|
929
|
+
rb_define_const(mADNS__mStatus, "AnswerDomainInvalid", INT2FIX(adns_s_answerdomaininvalid));
|
|
930
|
+
rb_define_const(mADNS__mStatus, "InvalidData", INT2FIX(adns_s_invaliddata));
|
|
931
|
+
|
|
932
|
+
// ADNS::QueryError
|
|
933
|
+
rb_define_const(mADNS__mStatus, "QueryDomainWrong", INT2FIX(adns_s_querydomainwrong));
|
|
934
|
+
rb_define_const(mADNS__mStatus, "QueryDomainInvalid", INT2FIX(adns_s_querydomaininvalid));
|
|
935
|
+
rb_define_const(mADNS__mStatus, "QueryDomainTooLong", INT2FIX(adns_s_querydomaintoolong));
|
|
936
|
+
|
|
937
|
+
// ADNS::PermanentError
|
|
938
|
+
rb_define_const(mADNS__mStatus, "NXDomain", INT2FIX(adns_s_nxdomain));
|
|
939
|
+
rb_define_const(mADNS__mStatus, "NoData", INT2FIX(adns_s_nodata));
|
|
940
|
+
|
|
941
|
+
/*
|
|
942
|
+
* Document-module: ADNS::IF
|
|
943
|
+
* Module defines collection of adns init flags.
|
|
944
|
+
*/
|
|
945
|
+
mADNS__mIF = rb_define_module_under(mADNS, "IF");
|
|
946
|
+
rb_define_const(mADNS__mIF, "NONE", INT2FIX(adns_if_none));
|
|
947
|
+
rb_define_const(mADNS__mIF, "NOENV", INT2FIX(adns_if_noenv));
|
|
948
|
+
rb_define_const(mADNS__mIF, "NOERRPRINT", INT2FIX(adns_if_noerrprint));
|
|
949
|
+
rb_define_const(mADNS__mIF, "NOSERVWarn", INT2FIX(adns_if_noserverwarn));
|
|
950
|
+
rb_define_const(mADNS__mIF, "DEBUG", INT2FIX(adns_if_debug));
|
|
951
|
+
rb_define_const(mADNS__mIF, "LOGPID", INT2FIX(adns_if_logpid));
|
|
952
|
+
rb_define_const(mADNS__mIF, "NOAUTOSYS", INT2FIX(adns_if_noautosys));
|
|
953
|
+
rb_define_const(mADNS__mIF, "EINTR", INT2FIX(adns_if_eintr));
|
|
954
|
+
rb_define_const(mADNS__mIF, "NOSIGPIPE", INT2FIX(adns_if_nosigpipe));
|
|
955
|
+
rb_define_const(mADNS__mIF, "CHECKC_ENTEX", INT2FIX(adns_if_checkc_entex));
|
|
956
|
+
rb_define_const(mADNS__mIF, "CHECKC_FREQ", INT2FIX(adns_if_checkc_freq));
|
|
957
|
+
|
|
958
|
+
/*
|
|
959
|
+
* Document-module: ADNS::QF
|
|
960
|
+
* Module defines collection of adns query flags.
|
|
961
|
+
*/
|
|
962
|
+
mADNS__mQF = rb_define_module_under(mADNS, "QF");
|
|
963
|
+
rb_define_const(mADNS__mQF, "NONE", INT2FIX(adns_qf_none));
|
|
964
|
+
rb_define_const(mADNS__mQF, "SEARCH", INT2FIX(adns_qf_search));
|
|
965
|
+
rb_define_const(mADNS__mQF, "USEVC", INT2FIX(adns_qf_usevc));
|
|
966
|
+
rb_define_const(mADNS__mQF, "OWNER", INT2FIX(adns_qf_owner));
|
|
967
|
+
rb_define_const(mADNS__mQF, "QUOTEOK_QUERY", INT2FIX(adns_qf_quoteok_query));
|
|
968
|
+
rb_define_const(mADNS__mQF, "QUOTEOK_CNAME", INT2FIX(adns_qf_quoteok_cname));
|
|
969
|
+
rb_define_const(mADNS__mQF, "QUOTEOK_ANSHOST", INT2FIX(adns_qf_quoteok_anshost));
|
|
970
|
+
rb_define_const(mADNS__mQF, "QUOTEFAIL_CNAME", INT2FIX(adns_qf_quotefail_cname));
|
|
971
|
+
rb_define_const(mADNS__mQF, "CNAME_LOOSE", INT2FIX(adns_qf_cname_loose));
|
|
972
|
+
rb_define_const(mADNS__mQF, "CNAME_FORBID", INT2FIX(adns_qf_cname_forbid));
|
|
973
|
+
|
|
974
|
+
/*
|
|
975
|
+
* Document-class: ADNS::Error
|
|
976
|
+
*/
|
|
977
|
+
mADNS__eError = rb_define_class_under(mADNS, "Error", rb_eException);
|
|
978
|
+
/*
|
|
979
|
+
* Document-class: ADNS::LocalError
|
|
980
|
+
*/
|
|
981
|
+
mADNS__eLocalError = rb_define_class_under(mADNS, "LocalError", mADNS__eError);
|
|
982
|
+
/*
|
|
983
|
+
* Document-class: ADNS::RemoteError
|
|
984
|
+
*/
|
|
985
|
+
mADNS__eRemoteError = rb_define_class_under(mADNS, "RemoteError", mADNS__eError);
|
|
986
|
+
/*
|
|
987
|
+
* Document-class: ADNS::QueryError
|
|
988
|
+
*/
|
|
989
|
+
mADNS__eQueryError = rb_define_class_under(mADNS, "QueryError", mADNS__eError);
|
|
990
|
+
/*
|
|
991
|
+
* Document-class: ADNS::PermanentError
|
|
992
|
+
*/
|
|
993
|
+
maDNS__ePermanentError = rb_define_class_under(mADNS, "PermanentError", mADNS__eError);
|
|
994
|
+
/*
|
|
995
|
+
* Document-class: ADNS::NotReadyError
|
|
996
|
+
*/
|
|
997
|
+
mADNS__eNotReadyError = rb_define_class_under(mADNS, "NotReadyError", mADNS__eError);
|
|
998
|
+
}
|