:param opt_list_out: :class:`edns_option`. EDNS option list to append options to.
:param region: :class:`regional`
-.. function:: register_inplace_cb_reply(py_cb, env)
+.. function:: inplace_cb_query(qinfo, flags, qstate, addr, zone, region)
+
+ Function prototype for callback functions used in
+ `register_inplace_cb_query`_.
+
+ :param qinfo: :class:`query_info`
+ :param flags: query flags (integer)
+ :param qstate: :class:`module_qstate`
+ :param addr: :class:`sockaddr_storage`
+ :param zone: zone name in wire format (bytes)
+ :param region: :class:`regional`
+
+.. function:: register_inplace_cb_reply(py_cb, env, id)
Register py_cb as an inplace reply callback function.
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
:param env: :class:`module_env`
+ :param id: Module ID.
:return: True on success, False otherwise
:rtype: boolean
-.. function:: register_inplace_cb_reply_cache(py_cb, env)
+.. function:: register_inplace_cb_reply_cache(py_cb, env, id)
Register py_cb as an inplace reply_cache callback function.
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
:param env: :class:`module_env`
+ :param id: Module ID.
:return: True on success, False otherwise
:rtype: boolean
-.. function:: register_inplace_cb_reply_local(py_cb, env)
+.. function:: register_inplace_cb_reply_local(py_cb, env, id)
Register py_cb as an inplace reply_local callback function.
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
:param env: :class:`module_env`
+ :param id: Module ID.
:return: True on success, False otherwise
:rtype: boolean
-.. function:: register_inplace_cb_reply_servfail(py_cb, env)
+.. function:: register_inplace_cb_reply_servfail(py_cb, env, id)
Register py_cb as an inplace reply_servfail callback function.
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
:param env: :class:`module_env`
+ :param id: Module ID.
:return: True on success, False otherwise
:rtype: boolean
+.. function:: register_inplace_cb_query(py_cb, env, id)
+
+ Register py_cb as an inplace query callback function.
+
+ :param py_cb: Python function that follows `inplace_cb_query`_'s prototype. **Must** be callable.
+ :param env: :class:`module_env`
+ :param id: Module ID.
+ :return: True on success, False otherwise
+ :rtype: boolean
Logging
-------
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+ #include <netdb.h>
+ #include <sys/un.h>
#include <stdarg.h>
#include "config.h"
#include "util/log.h"
}
/* ************************************************************************************ *
- Structure mesh_state
+ Structure sockaddr_storage
* ************************************************************************************ */
-struct mesh_state {
- struct mesh_reply* reply_list;
-};
-struct mesh_reply {
- struct mesh_reply* next;
- struct comm_reply query_reply;
-};
+struct sockaddr_storage {};
-struct comm_reply {
+%inline %{
+ static size_t _sockaddr_storage_len(const struct sockaddr_storage *ss) {
+ if (ss == NULL) {
+ return 0;
+ }
-};
+ switch (ss->ss_family) {
+ case AF_INET: return sizeof(struct sockaddr_in);
+ case AF_INET6: return sizeof(struct sockaddr_in6);
+ case AF_UNIX: return sizeof(struct sockaddr_un);
+ default:
+ return 0;
+ }
+ }
-%inline %{
+ PyObject *_sockaddr_storage_family(const struct sockaddr_storage *ss) {
+ if (ss == NULL) {
+ return Py_None;
+ }
+
+ switch (ss->ss_family) {
+ case AF_INET: return PyUnicode_FromString("ip4");
+ case AF_INET6: return PyUnicode_FromString("ip6");
+ case AF_UNIX: return PyUnicode_FromString("unix");
+ default:
+ return Py_None;
+ }
+ }
+
+ PyObject *_sockaddr_storage_addr(const struct sockaddr_storage *ss) {
+ if (ss == NULL) {
+ return Py_None;
+ }
+
+ const struct sockaddr *sa = (struct sockaddr *)ss;
+ size_t sa_len = _sockaddr_storage_len(ss);
+ if (sa_len == 0) {
+ return Py_None;
+ }
+
+ char name[NI_MAXHOST] = {0};
+ if (getnameinfo(sa, sa_len, name, sizeof(name), NULL, 0, NI_NUMERICHOST) != 0) {
+ return Py_None;
+ }
+
+ return PyUnicode_FromString(name);
+ }
+
+ PyObject *_sockaddr_storage_raw_addr(const struct sockaddr_storage *ss) {
+ if (ss == NULL) {
+ return Py_None;
+ }
+
+ size_t sa_len = _sockaddr_storage_len(ss);
+ if (sa_len == 0) {
+ return Py_None;
+ }
+
+ if (ss->ss_family == AF_INET) {
+ const struct sockaddr_in *sa = (struct sockaddr_in *)ss;
+ const struct in_addr *raw = (struct in_addr *)&sa->sin_addr;
+ return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
+ }
+
+ if (ss->ss_family == AF_INET6) {
+ const struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss;
+ const struct in6_addr *raw = (struct in6_addr *)&sa->sin6_addr;
+ return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
+ }
+
+ if (ss->ss_family == AF_UNIX) {
+ const struct sockaddr_un *sa = (struct sockaddr_un *)ss;
+ return PyBytes_FromString(sa->sun_path);
+ }
- PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
- char dest[64];
- reply_addr2str(reply, dest, 64);
- if (dest[0] == 0)
return Py_None;
- return PyBytes_FromString(dest);
- }
+ }
- PyObject* _comm_reply_family_get(struct comm_reply* reply) {
+ PyObject *_sockaddr_storage_port(const struct sockaddr_storage *ss) {
+ if (ss == NULL) {
+ return Py_None;
+ }
- int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
+ if (ss->ss_family == AF_INET) {
+ const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
+ return PyInt_FromLong(ntohs(sa4->sin_port));
+ }
- switch(af) {
- case AF_INET: return PyBytes_FromString("ip4");
- case AF_INET6: return PyBytes_FromString("ip6");
- case AF_UNIX: return PyBytes_FromString("unix");
+ if (ss->ss_family == AF_INET6) {
+ const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
+ return PyInt_FromLong(ntohs(sa6->sin6_port));
}
return Py_None;
- }
+ }
- PyObject* _comm_reply_port_get(struct comm_reply* reply) {
- uint16_t port;
- port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
- return PyInt_FromLong(port);
- }
+ PyObject *_sockaddr_storage_flowinfo(const struct sockaddr_storage *ss) {
+ if (ss == NULL || ss->ss_family != AF_INET6) {
+ return Py_None;
+ }
+
+ const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
+ return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
+ }
+
+ PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
+ if (ss == NULL || ss->ss_family != AF_INET6) {
+ return Py_None;
+ }
+ const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
+ return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
+ }
%}
+%extend sockaddr_storage {
+ %pythoncode %{
+ def _family_get(self): return _sockaddr_storage_family(self)
+ __swig_getmethods__["family"] = _family_get
+ if _newclass: family = _swig_property(_family_get)
+
+ def _addr_get(self): return _sockaddr_storage_addr(self)
+ __swig_getmethods__["addr"] = _addr_get
+ if _newclass: addr = _swig_property(_addr_get)
+
+ def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
+ __swig_getmethods__["raw_addr"] = _raw_addr_get
+ if _newclass: raw_addr = _swig_property(_raw_addr_get)
+
+ def _port_get(self): return _sockaddr_storage_port(self)
+ __swig_getmethods__["port"] = _port_get
+ if _newclass: port = _swig_property(_port_get)
+
+ def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
+ __swig_getmethods__["flowinfo"] = _flowinfo_get
+ if _newclass: flowinfo = _swig_property(_flowinfo_get)
+
+ def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
+ __swig_getmethods__["scope_id"] = _scope_id_get
+ if _newclass: scope_id = _swig_property(_scope_id_get)
+ %}
+}
+
+/* ************************************************************************************ *
+ Structure mesh_state
+ * ************************************************************************************ */
+struct mesh_state {
+ struct mesh_reply* reply_list;
+};
+
+struct mesh_reply {
+ struct mesh_reply* next;
+ struct comm_reply query_reply;
+};
+
+%rename(_addr) comm_reply::addr;
+struct comm_reply {
+ struct sockaddr_storage addr;
+};
+
%extend comm_reply {
%pythoncode %{
- def _addr_get(self): return _comm_reply_addr_get(self)
+ def _addr_get(self): return _sockaddr_storage_addr(self._addr)
__swig_getmethods__["addr"] = _addr_get
if _newclass:addr = _swig_property(_addr_get)
- def _port_get(self): return _comm_reply_port_get(self)
+ def _port_get(self): return _sockaddr_storage_port(self._addr)
__swig_getmethods__["port"] = _port_get
if _newclass:port = _swig_property(_port_get)
- def _family_get(self): return _comm_reply_family_get(self)
+ def _family_get(self): return _sockaddr_storage_family(self._addr)
__swig_getmethods__["family"] = _family_get
if _newclass:family = _swig_property(_family_get)
%}
return python_inplace_cb_register(inplace_cb_reply_servfail,
py_cb, env, id);
}
+
+ int python_inplace_cb_query_generic(
+ struct query_info* qinfo, uint16_t flags, struct module_qstate* qstate,
+ struct sockaddr_storage* addr, socklen_t addrlen,
+ uint8_t* zone, size_t zonelen, struct regional* region, int id,
+ void* python_callback)
+ {
+ int res = 0;
+ PyObject *func = python_callback;
+
+ PyGILState_STATE gstate = PyGILState_Ensure();
+
+ PyObject *py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
+ PyObject *py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
+ PyObject *py_addr = SWIG_NewPointerObj((void *) addr, SWIGTYPE_p_sockaddr_storage, 0);
+ PyObject *py_zone = PyBytes_FromStringAndSize((const char *)zone, zonelen);
+ PyObject *py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
+
+ PyObject *py_args = Py_BuildValue("(OiOOOO)", py_qinfo, flags, py_qstate, py_addr, py_zone, py_region);
+ PyObject *py_kwargs = Py_BuildValue("{}");
+ PyObject *result = PyObject_Call(func, py_args, py_kwargs);
+ if (result) {
+ res = PyInt_AsLong(result);
+ }
+
+ Py_XDECREF(py_qinfo);
+ Py_XDECREF(py_qstate);
+ Py_XDECREF(py_addr);
+ Py_XDECREF(py_zone);
+ Py_XDECREF(py_region);
+
+ Py_XDECREF(py_args);
+ Py_XDECREF(py_kwargs);
+ Py_XDECREF(result);
+
+ PyGILState_Release(gstate);
+
+ return res;
+ }
+
+ static int register_inplace_cb_query(PyObject* py_cb,
+ struct module_env* env, int id)
+ {
+ int ret = inplace_cb_register(python_inplace_cb_query_generic,
+ inplace_cb_query, (void*) py_cb, env, id);
+ if (ret) Py_INCREF(py_cb);
+ return ret;
+ }
%}
/* C declarations */
int inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
struct module_env* env, int id);
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
struct module_env* env, int id);
+static int register_inplace_cb_query(PyObject *py_cb,
+ struct module_env* env, int id);