/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*/
#include <Python.h>
#include <adns.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static PyObject *ErrorObject;
static PyObject *NotReadyError;
static PyObject *LocalError;
static PyObject *RemoteError, *RemoteFailureError, *RemoteTempError,
*RemoteConfigError;
static PyObject *QueryError;
static PyObject *PermanentError, *NXDomainError, *NoDataError;
/* -----------------------------------------------------*/
/* Declarations for objects of type ADNS_State*/
typedef struct {
PyObject_HEAD
adns_state state;
} ADNS_Stateobject;
static PyTypeObject ADNS_Statetype;
/* ----------------------------------------------------------------*/
/* Declarations for objects of type ADNS_Query*/
typedef struct {
PyObject_HEAD
ADNS_Stateobject *s;
adns_query query;
PyObject *answer;
PyObject *exc_type;
PyObject *exc_value;
PyObject *exc_traceback;
} ADNS_Queryobject;
static PyTypeObject ADNS_Querytype;
/* ----------------------------------------------------------------*/
typedef struct {
char *name;
int value;
} _constant_class;
/* int PyModule_AddIntConstant(PyObject *module, const char *name, long value)*/
static PyModuleDef module_iflags = {
PyModuleDef_HEAD_INIT,
"iflags",
"iflags Constants",
-1,
NULL, NULL, NULL, NULL, NULL
};
static _constant_class adns_iflags[] = {
{ "noenv", adns_if_noenv },
{ "noerrprint", adns_if_noerrprint },
{ "noserverwarn", adns_if_noserverwarn },
{ "debug", adns_if_debug },
{ "logpid", adns_if_logpid },
{ "noautosys", adns_if_noautosys },
{ "eintr", adns_if_eintr },
{ "nosigpipe", adns_if_nosigpipe },
{ "checkc_entex", adns_if_checkc_entex },
{ "checkc_freq", adns_if_checkc_freq },
{ NULL, 0 },
};
static PyModuleDef module_qflags = {
PyModuleDef_HEAD_INIT,
"qflags",
"qflags Constants",
-1,
NULL, NULL, NULL, NULL, NULL
};
static _constant_class adns_qflags[] = {
{ "search", adns_qf_search },
{ "usevc", adns_qf_usevc },
{ "owner", adns_qf_owner },
{ "quoteok_query", adns_qf_quoteok_query },
{ "quoteok_cname", adns_qf_quoteok_cname },
{ "quoteok_anshost", adns_qf_quoteok_anshost },
{ "quotefail_cname", adns_qf_quotefail_cname },
{ "cname_loose", adns_qf_cname_loose },
{ "cname_forbid", adns_qf_cname_forbid },
{ "internalmask", adns__qf_internalmask },
{ NULL, 0 },
};
static PyModuleDef module_rr = {
PyModuleDef_HEAD_INIT,
"rr",
"rr Constants",
-1,
NULL, NULL, NULL, NULL, NULL
};
static _constant_class adns_rr[] = {
{ "typemask", adns_rrt_typemask },
{ "deref", adns__qtf_deref },
{ "mail822", adns__qtf_mail822 },
{ "unknown", adns_r_unknown },
{ "none", adns_r_none },
{ "A", adns_r_a },
{ "NSraw", adns_r_ns_raw },
{ "NS", adns_r_ns },
{ "CNAME", adns_r_cname },
{ "SOAraw", adns_r_soa_raw },
{ "SOA", adns_r_soa },
{ "PTRraw", adns_r_ptr_raw },
{ "PTR", adns_r_ptr },
{ "HINFO", adns_r_hinfo },
{ "MXraw", adns_r_mx_raw },
{ "MX", adns_r_mx },
{ "TXT", adns_r_txt },
{ "RPraw", adns_r_rp_raw },
{ "RP", adns_r_rp },
{ "SRVraw", adns_r_srv_raw },
{ "SRV", adns_r_srv },
{ "ADDR", adns_r_addr },
{ NULL, 0 }
};
static PyModuleDef module_status = {
PyModuleDef_HEAD_INIT,
"status",
"status Constants",
-1,
NULL, NULL, NULL, NULL, NULL
};
static _constant_class adns_s[] = {
{ "ok", adns_s_ok },
{ "nomemory", adns_s_nomemory },
{ "unknownrrtype", adns_s_unknownrrtype },
{ "systemfail", adns_s_systemfail },
{ "max_localfail", adns_s_max_localfail },
{ "timeout", adns_s_timeout },
{ "allservfail", adns_s_allservfail },
{ "norecurse", adns_s_norecurse },
{ "invalidresponse", adns_s_invalidresponse },
{ "unknownformat", adns_s_unknownformat },
{ "max_remotefail", adns_s_max_remotefail },
{ "rcodeservfail", adns_s_rcodeservfail },
{ "rcodeformaterror", adns_s_rcodeformaterror },
{ "rcodenotimplemented", adns_s_rcodenotimplemented },
{ "rcoderefused", adns_s_rcoderefused },
{ "rcodeunknown", adns_s_rcodeunknown },
{ "max_tempfail", adns_s_max_tempfail },
{ "inconsistent", adns_s_inconsistent },
{ "prohibitedcname", adns_s_prohibitedcname },
{ "answerdomaininvalid", adns_s_answerdomaininvalid },
{ "answerdomaintoolong", adns_s_answerdomaintoolong },
{ "invaliddata", adns_s_invaliddata },
{ "max_misconfig", adns_s_max_misconfig },
{ "querydomainwrong", adns_s_querydomainwrong },
{ "querydomaininvalid", adns_s_querydomaininvalid },
{ "querydomaintoolong", adns_s_querydomaintoolong },
{ "max_misquery", adns_s_max_misquery },
{ "nxdomain", adns_s_nxdomain },
{ "nodata", adns_s_nodata },
{ "max_permfail", adns_s_max_permfail },
{ NULL, 0 }
};
static PyObject *
interpret_addr(
adns_rr_addr *v
)
{
PyObject *o;
o = Py_BuildValue("is", v->addr.inet.sin_family,
inet_ntoa(v->addr.inet.sin_addr)) ;
return o;
}
static PyObject *
interpret_hostaddr(
adns_rr_hostaddr *hostaddr
)
{
PyObject *o, *addrs;
if (hostaddr->naddrs == -1) {
addrs = Py_None;
Py_INCREF(addrs);
} else {
int i;
addrs = PyTuple_New(hostaddr->naddrs);
for (i=0; i<hostaddr->naddrs; i++) {
adns_rr_addr *v = hostaddr->addrs+i;
PyTuple_SET_ITEM(addrs,i,interpret_addr(v));
}
}
o = Py_BuildValue("siO", hostaddr->host, hostaddr->astatus,
addrs);
Py_DECREF(addrs);
return o;
}
static PyObject *
interpret_answer(
adns_answer *answer
)
{
PyObject *o, *rrs;
int i;
adns_rrtype t = answer->type & adns_rrt_typemask;
adns_rrtype td = answer->type & adns__qtf_deref;
rrs = PyTuple_New(answer->nrrs);
if (!rrs) return NULL;
for (i=0; i<answer->nrrs; i++) {
PyObject *a = NULL;
switch (t) {
case adns_r_a:
if (td) {
a = interpret_addr((answer->rrs.addr+i));
} else {
struct in_addr *v = answer->rrs.inaddr+i;
a = Py_BuildValue("s", inet_ntoa(*v));
}
break;
case adns_r_hinfo:
{
adns_rr_intstrpair *v = \
answer->rrs.intstrpair+i;
a = Py_BuildValue("s#s#", v->array[0].str,
v->array[0].i,
v->array[1].str,
v->array[1].i);
}
break;
case adns_r_mx_raw:
if (td) {
adns_rr_inthostaddr *v = \
answer->rrs.inthostaddr+i;
o = interpret_hostaddr(&v->ha);
a = Py_BuildValue("iO", v->i, o);
Py_DECREF(o);
} else {
adns_rr_intstr *v = answer->rrs.intstr+i;
a = Py_BuildValue("is", v->i, v->str);
}
break;
case adns_r_ptr_raw:
case adns_r_cname:
{
char *(*v) = answer->rrs.str+i;
a = PyBytes_FromString(*v);
}
break;
case adns_r_txt:
{
PyObject *txt;
int array_len = 0;
int ai;
adns_rr_intstr *(*s) = answer->rrs.manyistr+i;
while ((*s)[array_len].i != -1)
array_len++;
if (!(a = PyTuple_New(array_len))) break;
for (ai = 0; ai < array_len; ai++)
{
txt = PyBytes_FromStringAndSize((*s)[ai].str, (*s)[ai].i);
if (!txt) {
Py_DECREF(a);
a = NULL;
break;
}
PyTuple_SET_ITEM(a, ai, txt);
}
}
break;
case adns_r_ns_raw:
if (td) {
a = interpret_hostaddr(answer->rrs.hostaddr+i);
} else {
char *(*v) = answer->rrs.str+i;
a = PyBytes_FromString(*v);
}
break;
case adns_r_soa_raw:
{
adns_rr_soa *v = answer->rrs.soa+i;
a = Py_BuildValue("sslllll", v->mname, v->rname,
v->serial, v->refresh, v->retry,
v->expire, v->minimum);
}
break;
case adns_r_rp:
{
adns_rr_strpair *v = answer->rrs.strpair+i;
a = Py_BuildValue("ss", v->array[0], v->array[1]);
}
break;
case adns_r_srv_raw:
if (td) {
adns_rr_srvha *v = answer->rrs.srvha+i;
o = interpret_hostaddr(&v->ha);
a = Py_BuildValue("iiiO", v->priority, v->weight, v->port, o);
Py_DECREF(o);
} else {
adns_rr_srvraw *v = answer->rrs.srvraw+i;
a = Py_BuildValue("iiis", v->priority, v->weight, v->port,
v->host);
}
break;
default:
a = Py_None;
Py_INCREF(a);
}
if (!a) {
Py_DECREF(rrs);
return NULL;
}
PyTuple_SET_ITEM(rrs, i, a);
}
o = Py_BuildValue("isiO", (int) answer->status, answer->cname,
answer->expires, rrs);
Py_DECREF(rrs);
return o ;
}
static char adns_exception__doc__[] = \
"exception(s)\n\
\n\
Checks the status code of an answer and raises an exception if necessary.\n";
static PyObject*
adns_exception(
PyObject *self,
PyObject *args
)
{
PyObject *e, *m;
adns_status status;
if (!PyArg_ParseTuple(args, "i", &status))
return NULL;
switch (status) {
case adns_s_ok:
Py_INCREF(Py_None);
return Py_None;
case adns_s_nomemory:
return PyErr_NoMemory();
case adns_s_unknownrrtype:
case adns_s_systemfail:
e = LocalError;
break;
case adns_s_timeout:
case adns_s_allservfail:
case adns_s_norecurse:
case adns_s_invalidresponse:
case adns_s_unknownformat:
e = RemoteFailureError;
break;
case adns_s_rcodeservfail:
case adns_s_rcodeformaterror:
case adns_s_rcodenotimplemented:
case adns_s_rcoderefused:
case adns_s_rcodeunknown:
e = RemoteTempError;
break;
case adns_s_inconsistent:
case adns_s_prohibitedcname:
case adns_s_answerdomaininvalid:
case adns_s_invaliddata:
e = RemoteConfigError;
case adns_s_querydomainwrong:
case adns_s_querydomaininvalid:
case adns_s_querydomaintoolong:
e = QueryError;
break;
case adns_s_nxdomain:
e = NXDomainError;
break;
case adns_s_nodata:
e = NoDataError;
break;
default:
e = ErrorObject;
}
if (!(m=Py_BuildValue("is", status,
adns_strerror((adns_status) status))))
return NULL;
PyErr_SetObject(e, m);
Py_DECREF(m);
return NULL;
}
/* ----------------------------------------------------------------*/
static char ADNS_State_synchronous__doc__[] =
"s.synchronous(name,type[,flags]\n\
\n\
Perform a query on name synchronously for RR type, returning the answer.\n\
Answers returned as (status, cname, expires, rrs).\n\
rrs is an n-tuple, each element is a RR. Format varies by\n\
RR and query.\n"
;
static PyObject *
ADNS_State_synchronous(
ADNS_Stateobject *self,
PyObject *args
)
{
char *owner;
adns_rrtype type = 0;
adns_queryflags flags = 0;
adns_answer *answer_r;
int r;
PyObject *o;
if (!PyArg_ParseTuple(args, "si|i", &owner, &type, &flags))
return NULL;
Py_BEGIN_ALLOW_THREADS;
r = adns_synchronous(self->state, owner, type, flags, &answer_r);
Py_END_ALLOW_THREADS;
if (r) {
PyErr_SetString(ErrorObject, strerror(r));
return NULL;
}
o = interpret_answer(answer_r);
free(answer_r);
return o;
}
static char ADNS_State_submit__doc__[] =
"s.submit(name,type[,flags])\n\
\n\
Submit a query. Returns a ADNS_Query object.\n"
;
static ADNS_Queryobject *newADNS_Queryobject(ADNS_Stateobject *state);
static PyObject *
ADNS_State_submit(
ADNS_Stateobject *self,
PyObject *args
)
{
char *owner;
adns_rrtype type = 0;
adns_queryflags flags = 0;
int r;
ADNS_Queryobject *o;
if (!PyArg_ParseTuple(args, "si|i", &owner, &type, &flags))
return NULL;
o = newADNS_Queryobject(self);
Py_BEGIN_ALLOW_THREADS;
r = adns_submit(self->state, owner, type, flags, o, &o->query);
Py_END_ALLOW_THREADS;
if (r) {
PyErr_SetString(ErrorObject, strerror(r));
return NULL;
}
return (PyObject *) o;
}
static char ADNS_State_submit_reverse__doc__[] =
"s.submit_reverse(name,type[,flags])\n\
\n\
Submit a query. Returns a ADNS_Query object.\n\
flags must specify some kind of PTR query."
;
static PyObject *
ADNS_State_submit_reverse(
ADNS_Stateobject *self,
PyObject *args
)
{
char *owner;
struct sockaddr_in addr;
adns_rrtype type = 0;
adns_queryflags flags = 0;
int r;
ADNS_Queryobject *o;
if (!PyArg_ParseTuple(args, "si|i", &owner, &type, &flags))
return NULL;
r = inet_aton(owner, (struct in_addr *) &(addr.sin_addr));
if (!r) {
PyErr_SetString(ErrorObject, "invalid IP address");
return NULL;
}
addr.sin_family = AF_INET;
o = newADNS_Queryobject(self);
Py_BEGIN_ALLOW_THREADS;
r = adns_submit_reverse(self->state, (struct sockaddr *)&addr, type, flags, o, &o->query);
Py_END_ALLOW_THREADS;
if (r) {
PyErr_SetString(ErrorObject, strerror(r));
return NULL;
}
return (PyObject *) o;
}
static char ADNS_State_submit_reverse_any__doc__[] =
"s.submit_reverse_any(name,zone,type[,flags])\n\
\n\
Submit a query. Returns a ADNS_Query object.\n\
zone is in-addr.arpa., etc.\n\
flags must specify some kind of PTR query."
;
static PyObject *
ADNS_State_submit_reverse_any(
ADNS_Stateobject *self,
PyObject *args
)
{
char *owner, *zone;
struct sockaddr_in addr;
adns_rrtype type = 0;
adns_queryflags flags = 0;
int r;
ADNS_Queryobject *o;
if (!PyArg_ParseTuple(args, "ssi|i", &owner, &zone, &type, &flags))
return NULL;
r = inet_aton(owner, &(addr.sin_addr));
if (!r) {
PyErr_SetString(ErrorObject, "invalid IP address");
return NULL;
}
addr.sin_family = AF_INET;
o = newADNS_Queryobject(self);
Py_BEGIN_ALLOW_THREADS;
r = adns_submit_reverse_any(self->state, (struct sockaddr *)&addr, zone, type, flags, o, &o->query);
Py_END_ALLOW_THREADS;
if (r) {
PyErr_SetString(ErrorObject, strerror(r));
return NULL;
}
return (PyObject *) o;
}
static char ADNS_State_allqueries__doc__[] =
"s.allqueries()\n\
\n\
Returns a list of all pending queries.\n"
;
static PyObject *
ADNS_State_allqueries(
ADNS_Stateobject *self,
PyObject *args
)
{
ADNS_Queryobject *o;
adns_query q;
PyObject *l;
if (!PyArg_ParseTuple(args, ""))
return NULL;
if (!(l = PyList_New(0))) return NULL;
for (adns_forallqueries_begin(self->state);
(q = adns_forallqueries_next(self->state, (void *)&o));
) {
if (PyList_Append(l, (PyObject *) o)) {
Py_DECREF(l);
return NULL;
}
}
return l;
}
static char ADNS_State_select__doc__[] =
"s.select(timeout=0)\n\
\n\
Like the select() system call, except it works only on\n\
pending queries, i.e. internally it does:\n\
1) adns_beforeselect\n\
2) select\n\
3) adns_afterselect\n"
;
static PyObject *
ADNS_State_select(
ADNS_Stateobject *self,
PyObject *args
)
{
fd_set rfds, wfds, efds;
int r, maxfd=0;
double ft = 0;
struct timeval **tv_mod, tv_buf, now, timeout;
struct timezone tz;
if (!PyArg_ParseTuple(args, "|d", &ft))
return NULL;
timeout.tv_sec = (int) ft;
timeout.tv_usec = (int) ((ft - timeout.tv_sec) * 1e6);
tv_mod = NULL;
if (gettimeofday(&now, &tz))
return PyErr_SetFromErrno(ErrorObject);
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
adns_beforeselect(self->state, &maxfd, &rfds, &wfds, &efds,
tv_mod, &tv_buf, &now);
Py_BEGIN_ALLOW_THREADS;
r = select(maxfd, &rfds, &wfds, &efds, &timeout);
Py_END_ALLOW_THREADS;
if (r == -1) return PyErr_SetFromErrno(ErrorObject);
if (gettimeofday(&now, &tz))
return PyErr_SetFromErrno(ErrorObject);
adns_afterselect(self->state, maxfd, &rfds, &wfds, &efds, &now);
Py_INCREF(Py_None);
return Py_None;
}
static char ADNS_State_completed__doc__[] =
"s.allqueries()\n\
\n\
Returns a list of all completed queries.\n"
;
static PyObject *
ADNS_State_completed(
ADNS_Stateobject *self,
PyObject *args
)
{
adns_answer *answer_r;
int r;
ADNS_Queryobject *o, *o2;
adns_query q;
PyObject *l;
if (!(l = ADNS_State_select(self, args))) return NULL;
Py_DECREF(l);
if (!(l = PyList_New(0))) return NULL;
for (adns_forallqueries_begin(self->state);
(q = adns_forallqueries_next(self->state, (void *)&o));
) {
r = adns_check(self->state, &q, &answer_r, (void *) &o2);
if (r) {
if (r == EWOULDBLOCK)
continue;
else {
PyErr_SetString(ErrorObject, strerror(r));
PyErr_Fetch(&(o->exc_type),
&(o->exc_value),
&(o->exc_traceback));
continue;
}
}
assert(o == o2);
o->answer = interpret_answer(answer_r);
free(answer_r);
o->query = NULL;
if (PyList_Append(l, (PyObject *) o)) {
Py_DECREF(l);
return NULL;
}
}
return l;
}
static char ADNS_State_globalsystemfailure__doc__[] =
""
;
static PyObject *
ADNS_State_globalsystemfailure(
ADNS_Stateobject *self,
PyObject *args
)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
adns_globalsystemfailure(self->state);
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef ADNS_State_methods[] = {
{"synchronous", (PyCFunction)ADNS_State_synchronous, METH_VARARGS, ADNS_State_synchronous__doc__},
{"submit", (PyCFunction)ADNS_State_submit, METH_VARARGS, ADNS_State_submit__doc__},
{"submit_reverse", (PyCFunction)ADNS_State_submit_reverse, METH_VARARGS, ADNS_State_submit_reverse__doc__},
{"submit_reverse_any", (PyCFunction)ADNS_State_submit_reverse_any, METH_VARARGS, ADNS_State_submit_reverse_any__doc__},
{"allqueries", (PyCFunction)ADNS_State_allqueries, METH_VARARGS, ADNS_State_allqueries__doc__},
{"completed", (PyCFunction)ADNS_State_completed, METH_VARARGS, ADNS_State_completed__doc__},
{"select", (PyCFunction)ADNS_State_select, METH_VARARGS, ADNS_State_select__doc__},
{"globalsystemfailure", (PyCFunction)ADNS_State_globalsystemfailure, METH_VARARGS, ADNS_State_globalsystemfailure__doc__},
{NULL, NULL} /* sentinel*/
};
/* ----------*/
/*
static PyObject *
ADNS_State_getattr(
ADNS_Stateobject *self,
char *name
)
{
// XXXX Add your own getattr code here
// return Py_FindMethod(ADNS_State_methods, (PyObject *)self, name);
// TODO add methods
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
Py_TYPE(self)->tp_name, name);
return NULL;
}
*/
static ADNS_Stateobject *
newADNS_Stateobject(void)
{
ADNS_Stateobject *self;
self = PyObject_New(ADNS_Stateobject, &ADNS_Statetype);
if (self == NULL)
return NULL;
self->state = NULL;
return self;
}
static void
ADNS_State_dealloc(ADNS_Stateobject *self)
{
Py_BEGIN_ALLOW_THREADS;
adns_finish(self->state);
Py_END_ALLOW_THREADS;
Py_INCREF(Py_None);
PyObject_Del(self);
}
static char ADNS_Statetype__doc__[] =
"Contains state information for adns session."
;
static PyTypeObject ADNS_Statetype = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"adns.State", /*tp_name*/
sizeof(ADNS_Stateobject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)ADNS_State_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /*tp_flags*/
ADNS_Statetype__doc__, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
ADNS_State_methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
};
/* End of code for ADNS_State objects*/
/* --------------------------------------------------------*/
static char ADNS_Query_check__doc__[] =
"answer = q.check()\n\
\n\
Check for an answer. Return value same as for\n\
s.synchronous.\n"
;
static PyObject *
ADNS_Query_check(
ADNS_Queryobject *self,
PyObject *args
)
{
adns_answer *answer_r;
int r;
PyObject *o2=(PyObject *)self;
if (!PyArg_ParseTuple(args, ""))
return NULL;
if (self->exc_type) {
PyErr_Restore(self->exc_type, self->exc_value, self->exc_traceback);
self->exc_type = self->exc_value = self->exc_traceback = NULL;
return NULL;
}
if (self->answer) goto ret_answer;
if (!(self->query)) {
PyErr_SetString(ErrorObject, "query invalidated");
return NULL;
}
r = adns_check(self->s->state, &self->query, &answer_r, (void *) &o2);
if (r) {
if (r == EWOULDBLOCK)
PyErr_SetString(NotReadyError, strerror(r));
else {
PyErr_SetString(ErrorObject, strerror(r));
self->query = NULL;
}
return NULL;
}
assert(o2 == (PyObject *) self);
self->answer = interpret_answer(answer_r);
self->query = NULL;
free(answer_r);
ret_answer:
Py_INCREF(self->answer);
return self->answer;
}
static char ADNS_Query_wait__doc__[] =
"answer=q.wait()\n\
\n\
Wait for an answer. Return value same as for\n\
s.synchronous.\n"
;
static PyObject *
ADNS_Query_wait(
ADNS_Queryobject *self,
PyObject *args
)
{
adns_answer *answer_r;
int r;
PyObject *o2=(PyObject *)self;
if (!PyArg_ParseTuple(args, ""))
return NULL;
if (self->exc_type) {
PyErr_Restore(self->exc_type, self->exc_value, self->exc_traceback);
self->exc_type = self->exc_value = self->exc_traceback = NULL;
return NULL;
}
if (self->answer) goto ret_answer;
if (!(self->query)) {
PyErr_SetString(ErrorObject, "query invalidated");
return NULL;
}
Py_BEGIN_ALLOW_THREADS;
r = adns_wait(self->s->state, &self->query, &answer_r, (void *) &o2);
Py_END_ALLOW_THREADS;
if (r) {
if (r == EWOULDBLOCK)
PyErr_SetString(NotReadyError, strerror(r));
else {
PyErr_SetString(ErrorObject, strerror(r));
self->query = NULL;
}
return NULL;
}
assert(o2 == (PyObject *) self);
self->answer = interpret_answer(answer_r);
self->query = NULL;
free(answer_r);
ret_answer:
Py_INCREF(self->answer);
return self->answer;
}
static char ADNS_Query_cancel__doc__[] =
"q.cancel()\n\
\n\
Cancel a pending query.\n"
;
static PyObject *
ADNS_Query_cancel(
ADNS_Queryobject *self,
PyObject *args
)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
if (!(self->query)) {
PyErr_SetString(ErrorObject, "query invalidated");
return NULL;
}
Py_BEGIN_ALLOW_THREADS;
adns_cancel(self->query);
Py_END_ALLOW_THREADS;
Py_INCREF(Py_None);
self->query = NULL;
return Py_None;
}
static struct PyMethodDef ADNS_Query_methods[] = {
{"check", (PyCFunction)ADNS_Query_check, METH_VARARGS, ADNS_Query_check__doc__},
{"wait", (PyCFunction)ADNS_Query_wait, METH_VARARGS, ADNS_Query_wait__doc__},
{"cancel",(PyCFunction)ADNS_Query_cancel,METH_VARARGS, ADNS_Query_cancel__doc__},
{NULL, NULL} /* sentinel*/
};
/* ----------*/
/*
static PyObject *
ADNS_Query_getattr(
ADNS_Queryobject *self,
char *name
)
{
// XXXX Add your own getattr code here
// return Py_FindMethod(ADNS_Query_methods, (PyObject *)self, name);
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
Py_TYPE(self)->tp_name, name);
return NULL;
}
*/
static ADNS_Queryobject *
newADNS_Queryobject(ADNS_Stateobject *state)
{
ADNS_Queryobject *self;
self = PyObject_New(ADNS_Queryobject, &ADNS_Querytype);
if (self == NULL)
return NULL;
Py_INCREF(state);
self->s = state;
self->query = NULL;
self->answer = NULL;
self->exc_type = NULL;
self->exc_value = NULL;
self->exc_traceback = NULL;
return self;
}
static void
ADNS_Query_dealloc(ADNS_Queryobject *self)
{
Py_DECREF(self->s);
Py_XDECREF(self->answer);
Py_XDECREF(self->exc_type);
Py_XDECREF(self->exc_value);
Py_XDECREF(self->exc_traceback);
PyObject_Del(self);
}
static char ADNS_Querytype__doc__[] =
"A query currently being processed by adns."
;
static PyTypeObject ADNS_Querytype = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"adns.Query", /*tp_name*/
sizeof(ADNS_Queryobject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)ADNS_Query_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /*tp_flags*/
ADNS_Querytype__doc__, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
ADNS_Query_methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
};
/* End of code for ADNS_Query objects*/
/* --------------------------------------------------------*/
static char adns_init__doc__[] =
"s=adns.init([initflags,debugfileobj=stderr,configtext=''])\n\
\n\
Initialize an ADNS_State object, which contains state information\n\
used internally by adns."
;
int
_file_converter(
PyObject *obj,
FILE **f
)
{
/* *f = PyFile_AsFile(obj);*/
/* int PyObject_AsFileDescriptor(PyObject *p)*/
*f = fdopen(PyObject_AsFileDescriptor(obj),"a+");
return (*f != NULL);
}
static PyObject *
adns__init(
PyObject *self, /* Not used*/
PyObject *args,
PyObject *kwargs
)
{
static char *kwlist[] = { "flags", "diagfile", "configtext" };
adns_initflags flags = 0;
int status;
FILE *diagfile = NULL;
char *configtext = NULL;
ADNS_Stateobject *s;
/* file is debug file
s=adns.init([initflags,debugfileobj=stderr,configtext=''])
"|iO&s",
| Indicates that the remaining arguments in the Python argument list are optional.
i (int) [int] Convert a Python integer to a plain C int.
O& (object) [converter, anything] Convert a Python object to a C variable through a converter function.
s (string or Unicode) [const char *] Convert a Python string or Unicode object to a C pointer to a character string
*/
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "|iO&s", kwlist,
&flags, _file_converter, &diagfile, &configtext))
return NULL;
if (!(s = newADNS_Stateobject())) return NULL;
if (configtext)
status = adns_init_strcfg(&s->state, flags,
diagfile, configtext);
else
status = adns_init(&s->state, flags, diagfile);
if (status) {
PyErr_SetFromErrno(ErrorObject);
ADNS_State_dealloc(s);
return NULL;
}
return (PyObject *) s;
}
/* List of methods defined in the module*/
static struct PyMethodDef adns_methods[] = {
{"init", (PyCFunction)adns__init, METH_VARARGS|METH_KEYWORDS, adns_init__doc__},
{"exception",(PyCFunction)adns_exception, METH_VARARGS, adns_exception__doc__},
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel*/
};
static char adns_module_documentation[] = "adns python3 module";
static PyObject *
_new_exception(
PyObject *dict,
char *name,
PyObject *base
)
{
PyObject *v;
char longname[256];
sprintf(longname, "adns.%s", name);
if ((v = PyErr_NewException(longname, base, NULL)) == NULL)
return NULL;
if (PyDict_SetItemString(dict, name, v)) return NULL;
return v;
}
static int
_new_constant_class(
PyObject *module,
PyModuleDef *moduledef,
_constant_class *table
)
{
int i;
PyObject * m = PyModule_Create(moduledef);
if (m == NULL)
return -1;
/* int PyModule_AddIntConstant(PyObject *module, const char *name, long value)*/
for (i = 0; table[i].name; i++) {
PyModule_AddIntConstant(m,table[i].name,(long)table[i].value);
/*printf("created %s %ld\n",table[i].name,(long)table[i].value);*/
}
PyModule_AddObject(module, moduledef->m_name, m);
return 0;
}
static struct PyModuleDef module_adns = {
PyModuleDef_HEAD_INIT,
"adns", /* m_name*/
adns_module_documentation, /* m_doc*/
-1, /* m_size*/
adns_methods, /* m_methods*/
NULL, /* m_reload*/
NULL, /* m_traverse*/
NULL, /* m_clear*/
NULL, /* m_free*/
};
/* Initialization function for the module */
PyMODINIT_FUNC
PyInit_adns(void)
{
PyObject *m, *d;
/* Create the module and add the functions*/
m = PyModule_Create(&module_adns);
if (m == NULL)
return NULL;
/*printf("created module adns %s %s\n",__DATE__, __TIME__);*/
/* Initialize object type properly*/
/* maybe not a good idea, because of init values in newADNS_Queryobject*/
/* ADNS_Querytype.tp_new = newADNS_Queryobject; // tp_new is complicated*/
/* no need to create instances from py
ADNS_Querytype.tp_new = PyType_GenericNew;*/
if (PyType_Ready(&ADNS_Querytype) < 0)
return NULL;
Py_INCREF(&ADNS_Querytype);
PyModule_AddObject(m, "Query", (PyObject *)&ADNS_Querytype);
/* ADNS_Statetype.tp_new = newADNS_Stateobject;*/
/*
ADNS_Statetype.tp_new = PyType_GenericNew;*/
if (PyType_Ready(&ADNS_Statetype) < 0)
return NULL;
Py_INCREF(&ADNS_Statetype);
PyModule_AddObject(m, "State", (PyObject *)&ADNS_Statetype);
/* Add some symbolic constants to the module*/
d = PyModule_GetDict(m);
/** Py_INCREF + PyModule_AddObject( ??? - not using the object dict ?*/
ErrorObject = _new_exception(d, "Error", PyExc_ConnectionError);
NotReadyError = _new_exception(d, "NotReady", ErrorObject);
LocalError = _new_exception(d, "LocalError", ErrorObject);
RemoteError = _new_exception(d, "RemoteError", ErrorObject);
RemoteFailureError = _new_exception(d, "RemoteFailureError", RemoteError);
RemoteTempError = _new_exception(d, "RemoteTempError", RemoteError);
RemoteConfigError = _new_exception(d, "RemoteConfigError", RemoteError);
QueryError = _new_exception(d, "QueryError", ErrorObject);
PermanentError = _new_exception(d, "PermanentError", ErrorObject);
NXDomainError = _new_exception(d, "NXDomain", PermanentError);
NoDataError = _new_exception(d, "NoData", PermanentError);
/* XXXX Add constants here*/
/** Py_INCREF + PyModule_AddObject( ??? - not using the object dict ?*/
_new_constant_class(m, &module_iflags, adns_iflags);
_new_constant_class(m, &module_qflags, adns_qflags);
_new_constant_class(m, &module_rr, adns_rr);
_new_constant_class(m, &module_status, adns_s);
/* Check for errors*/
if (PyErr_Occurred())
Py_FatalError("can't initialize module adns");
return m;
}