2 Unix SMB/CIFS implementation.
4 Python DNS server wrapper
6 Copyright (C) 2015 Andrew Bartlett
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 3 of the License, or
11 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
26 #include "dns_server/dnsserver_common.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "dsdb/common/util.h"
29 #include "librpc/gen_ndr/ndr_dnsp.h"
30 #include "librpc/rpc/pyrpc_util.h"
32 /* FIXME: These should be in a header file somewhere */
33 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
34 if (!py_check_dcerpc_type(py_ldb, "ldb", "Ldb")) { \
35 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
38 ldb = pyldb_Ldb_AsLdbContext(py_ldb);
40 #define PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn) \
41 if (!py_check_dcerpc_type(py_ldb_dn, "ldb", "Dn")) { \
42 PyErr_SetString(py_ldb_get_exception(), "ldb Dn object required"); \
45 dn = pyldb_Dn_AsDn(py_ldb_dn);
47 static PyObject
*py_ldb_get_exception(void)
49 PyObject
*mod
= PyImport_ImportModule("ldb");
53 return PyObject_GetAttrString(mod
, "LdbError");
56 static PyObject
*py_dnsp_DnssrvRpcRecord_get_list(struct dnsp_DnssrvRpcRecord
*records
,
59 PyObject
*py_dns_list
;
61 py_dns_list
= PyList_New(num_records
);
62 if (py_dns_list
== NULL
) {
65 for (i
= 0; i
< num_records
; i
++) {
66 PyObject
*py_dns_record
;
67 py_dns_record
= py_return_ndr_struct("samba.dcerpc.dnsp", "DnssrvRpcRecord", records
, &records
[i
]);
68 PyList_SetItem(py_dns_list
, i
, py_dns_record
);
73 static int py_dnsp_DnssrvRpcRecord_get_array(PyObject
*value
,
75 struct dnsp_DnssrvRpcRecord
**records
,
76 uint16_t *num_records
)
79 struct dnsp_DnssrvRpcRecord
*recs
;
80 PY_CHECK_TYPE(&PyList_Type
, value
, return -1;);
81 recs
= talloc_array(mem_ctx
, struct dnsp_DnssrvRpcRecord
,
82 PyList_GET_SIZE(value
));
87 for (i
= 0; i
< PyList_GET_SIZE(value
); i
++) {
89 PyObject
*item
= PyList_GET_ITEM(value
, i
);
90 type_correct
= py_check_dcerpc_type(item
, "samba.dcerpc.dnsp", "DnssrvRpcRecord");
91 if (type_correct
== false) {
94 if (talloc_reference(mem_ctx
, pytalloc_get_mem_ctx(item
)) == NULL
) {
98 recs
[i
] = *(struct dnsp_DnssrvRpcRecord
*)pytalloc_get_ptr(item
);
101 *num_records
= PyList_GET_SIZE(value
);
105 static PyObject
*py_dsdb_dns_lookup(PyObject
*self
, PyObject
*args
)
107 struct ldb_context
*samdb
;
113 struct dns_server_zone
*zones_list
;
115 struct dnsp_DnssrvRpcRecord
*records
;
116 uint16_t num_records
;
118 if (!PyArg_ParseTuple(args
, "Os", &py_ldb
, &dns_name
)) {
121 PyErr_LDB_OR_RAISE(py_ldb
, samdb
);
123 frame
= talloc_stackframe();
125 status
= dns_common_zones(samdb
, frame
, &zones_list
);
126 if (!NT_STATUS_IS_OK(status
)) {
127 PyErr_SetNTSTATUS(status
);
131 werr
= dns_common_name2dn(samdb
, zones_list
, frame
, dns_name
, &dn
);
132 if (!W_ERROR_IS_OK(werr
)) {
133 PyErr_SetWERROR(werr
);
137 werr
= dns_common_lookup(samdb
,
143 if (!W_ERROR_IS_OK(werr
)) {
144 PyErr_SetWERROR(werr
);
148 return py_dnsp_DnssrvRpcRecord_get_list(records
, num_records
);
151 static PyObject
*py_dsdb_dns_extract(PyObject
*self
, PyObject
*args
)
156 struct ldb_message_element
*dns_el
;
157 struct dnsp_DnssrvRpcRecord
*records
;
158 uint16_t num_records
;
160 if (!PyArg_ParseTuple(args
, "O", &py_dns_el
)) {
164 if (!py_check_dcerpc_type(py_dns_el
, "ldb", "MessageElement")) {
165 PyErr_SetString(py_ldb_get_exception(),
166 "ldb MessageElement object required");
169 dns_el
= pyldb_MessageElement_AsMessageElement(py_dns_el
);
171 frame
= talloc_stackframe();
173 werr
= dns_common_extract(dns_el
,
177 if (!W_ERROR_IS_OK(werr
)) {
178 PyErr_SetWERROR(werr
);
182 return py_dnsp_DnssrvRpcRecord_get_list(records
, num_records
);
185 static PyObject
*py_dsdb_dns_replace(PyObject
*self
, PyObject
*args
)
187 struct ldb_context
*samdb
;
188 PyObject
*py_ldb
, *py_dns_records
;
194 struct dns_server_zone
*zones_list
;
196 struct dnsp_DnssrvRpcRecord
*records
;
197 uint16_t num_records
;
200 * TODO: This is a shocking abuse, but matches what the
201 * internal DNS server does, it should be pushed into
202 * dns_common_replace()
204 static const int serial
= 110;
206 if (!PyArg_ParseTuple(args
, "OsO", &py_ldb
, &dns_name
, &py_dns_records
)) {
209 PyErr_LDB_OR_RAISE(py_ldb
, samdb
);
211 frame
= talloc_stackframe();
213 status
= dns_common_zones(samdb
, frame
, &zones_list
);
214 if (!NT_STATUS_IS_OK(status
)) {
215 PyErr_SetNTSTATUS(status
);
219 werr
= dns_common_name2dn(samdb
, zones_list
, frame
, dns_name
, &dn
);
220 if (!W_ERROR_IS_OK(werr
)) {
221 PyErr_SetWERROR(werr
);
225 ret
= py_dnsp_DnssrvRpcRecord_get_array(py_dns_records
,
227 &records
, &num_records
);
232 werr
= dns_common_replace(samdb
,
235 false, /* Not adding a record */
239 if (!W_ERROR_IS_OK(werr
)) {
240 PyErr_SetWERROR(werr
);
247 static PyObject
*py_dsdb_dns_replace_by_dn(PyObject
*self
, PyObject
*args
)
249 struct ldb_context
*samdb
;
250 PyObject
*py_ldb
, *py_dn
, *py_dns_records
;
255 struct dnsp_DnssrvRpcRecord
*records
;
256 uint16_t num_records
;
259 * TODO: This is a shocking abuse, but matches what the
260 * internal DNS server does, it should be pushed into
261 * dns_common_replace()
263 static const int serial
= 110;
265 if (!PyArg_ParseTuple(args
, "OOO", &py_ldb
, &py_dn
, &py_dns_records
)) {
268 PyErr_LDB_OR_RAISE(py_ldb
, samdb
);
270 PyErr_LDB_DN_OR_RAISE(py_dn
, dn
);
272 frame
= talloc_stackframe();
274 ret
= py_dnsp_DnssrvRpcRecord_get_array(py_dns_records
,
276 &records
, &num_records
);
281 werr
= dns_common_replace(samdb
,
284 false, /* Not adding a record */
288 if (!W_ERROR_IS_OK(werr
)) {
289 PyErr_SetWERROR(werr
);
296 static PyMethodDef py_dsdb_dns_methods
[] = {
298 { "lookup", (PyCFunction
)py_dsdb_dns_lookup
,
299 METH_VARARGS
, "Get the DNS database entries for a DNS name"},
300 { "replace", (PyCFunction
)py_dsdb_dns_replace
,
301 METH_VARARGS
, "Replace the DNS database entries for a DNS name"},
302 { "replace_by_dn", (PyCFunction
)py_dsdb_dns_replace_by_dn
,
303 METH_VARARGS
, "Replace the DNS database entries for a LDB DN"},
304 { "extract", (PyCFunction
)py_dsdb_dns_extract
,
305 METH_VARARGS
, "Return the DNS database entry as a python structure from an Ldb.MessageElement of type dnsRecord"},
309 void initdsdb_dns(void);
311 void initdsdb_dns(void)
315 m
= Py_InitModule3("dsdb_dns", py_dsdb_dns_methods
,
316 "Python bindings for the DNS objects in the directory service databases.");