s4: remove ipv6:enabled parameteric option
[Samba.git] / source4 / dns_server / pydns.c
blob63fa80e92b3c65b371ebcfbb1cbf542befd698ad
1 /*
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/>.
22 #include <Python.h>
23 #include "includes.h"
24 #include <pyldb.h>
25 #include <pytalloc.h>
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(PyExc_TypeError, "Ldb connection object required"); \
36 return NULL; \
37 } \
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(PyExc_TypeError, "ldb Dn object required"); \
43 return NULL; \
44 } \
45 dn = pyldb_Dn_AsDn(py_ldb_dn);
47 static PyObject *py_dnsp_DnssrvRpcRecord_get_list(struct dnsp_DnssrvRpcRecord *records,
48 uint16_t num_records)
50 PyObject *py_dns_list;
51 int i;
52 py_dns_list = PyList_New(num_records);
53 if (py_dns_list == NULL) {
54 return NULL;
56 for (i = 0; i < num_records; i++) {
57 PyObject *py_dns_record;
58 py_dns_record = py_return_ndr_struct("samba.dcerpc.dnsp", "DnssrvRpcRecord", records, &records[i]);
59 PyList_SetItem(py_dns_list, i, py_dns_record);
61 return py_dns_list;
64 static int py_dnsp_DnssrvRpcRecord_get_array(PyObject *value,
65 TALLOC_CTX *mem_ctx,
66 struct dnsp_DnssrvRpcRecord **records,
67 uint16_t *num_records)
69 int i;
70 struct dnsp_DnssrvRpcRecord *recs;
71 PY_CHECK_TYPE(&PyList_Type, value, return -1;);
72 recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord,
73 PyList_GET_SIZE(value));
74 if (recs == NULL) {
75 PyErr_NoMemory();
76 return -1;
78 for (i = 0; i < PyList_GET_SIZE(value); i++) {
79 bool type_correct;
80 PyObject *item = PyList_GET_ITEM(value, i);
81 type_correct = py_check_dcerpc_type(item, "samba.dcerpc.dnsp", "DnssrvRpcRecord");
82 if (type_correct == false) {
83 return -1;
85 if (talloc_reference(mem_ctx, pytalloc_get_mem_ctx(item)) == NULL) {
86 PyErr_NoMemory();
87 return -1;
89 recs[i] = *(struct dnsp_DnssrvRpcRecord *)pytalloc_get_ptr(item);
91 *records = recs;
92 *num_records = PyList_GET_SIZE(value);
93 return 0;
96 static PyObject *py_dsdb_dns_lookup(PyObject *self,
97 PyObject *args, PyObject *kwargs)
99 struct ldb_context *samdb;
100 PyObject *py_ldb, *ret, *pydn;
101 PyObject *py_dns_partition = NULL;
102 char *dns_name;
103 TALLOC_CTX *frame;
104 NTSTATUS status;
105 WERROR werr;
106 struct dns_server_zone *zones_list;
107 struct ldb_dn *dn, *dns_partition = NULL;
108 struct dnsp_DnssrvRpcRecord *records;
109 uint16_t num_records;
110 const char * const kwnames[] = { "ldb", "dns_name",
111 "dns_partition", NULL };
113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|O",
114 discard_const_p(char *, kwnames),
115 &py_ldb, &dns_name,
116 &py_dns_partition)) {
117 return NULL;
119 PyErr_LDB_OR_RAISE(py_ldb, samdb);
121 if (py_dns_partition) {
122 PyErr_LDB_DN_OR_RAISE(py_dns_partition,
123 dns_partition);
126 frame = talloc_stackframe();
128 status = dns_common_zones(samdb, frame, dns_partition,
129 &zones_list);
130 if (!NT_STATUS_IS_OK(status)) {
131 talloc_free(frame);
132 PyErr_SetNTSTATUS(status);
133 return NULL;
136 werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
137 if (!W_ERROR_IS_OK(werr)) {
138 talloc_free(frame);
139 PyErr_SetWERROR(werr);
140 return NULL;
143 werr = dns_common_lookup(samdb,
144 frame,
146 &records,
147 &num_records,
148 NULL);
149 if (!W_ERROR_IS_OK(werr)) {
150 talloc_free(frame);
151 PyErr_SetWERROR(werr);
152 return NULL;
155 ret = py_dnsp_DnssrvRpcRecord_get_list(records, num_records);
156 pydn = pyldb_Dn_FromDn(dn);
157 talloc_free(frame);
158 return Py_BuildValue("(OO)", pydn, ret);
161 static PyObject *py_dsdb_dns_extract(PyObject *self, PyObject *args)
163 struct ldb_context *samdb;
164 PyObject *py_dns_el, *ret;
165 PyObject *py_ldb = NULL;
166 TALLOC_CTX *frame;
167 WERROR werr;
168 struct ldb_message_element *dns_el;
169 struct dnsp_DnssrvRpcRecord *records;
170 uint16_t num_records;
172 if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dns_el)) {
173 return NULL;
176 PyErr_LDB_OR_RAISE(py_ldb, samdb);
178 if (!py_check_dcerpc_type(py_dns_el, "ldb", "MessageElement")) {
179 PyErr_SetString(PyExc_TypeError,
180 "ldb MessageElement object required");
181 return NULL;
183 dns_el = pyldb_MessageElement_AsMessageElement(py_dns_el);
185 frame = talloc_stackframe();
187 werr = dns_common_extract(samdb, dns_el,
188 frame,
189 &records,
190 &num_records);
191 if (!W_ERROR_IS_OK(werr)) {
192 talloc_free(frame);
193 PyErr_SetWERROR(werr);
194 return NULL;
197 ret = py_dnsp_DnssrvRpcRecord_get_list(records, num_records);
198 talloc_free(frame);
199 return ret;
202 static PyObject *py_dsdb_dns_replace(PyObject *self, PyObject *args)
204 struct ldb_context *samdb;
205 PyObject *py_ldb, *py_dns_records;
206 char *dns_name;
207 TALLOC_CTX *frame;
208 NTSTATUS status;
209 WERROR werr;
210 int ret;
211 struct dns_server_zone *zones_list;
212 struct ldb_dn *dn;
213 struct dnsp_DnssrvRpcRecord *records;
214 uint16_t num_records;
217 * TODO: This is a shocking abuse, but matches what the
218 * internal DNS server does, it should be pushed into
219 * dns_common_replace()
221 static const int serial = 110;
223 if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &dns_name, &py_dns_records)) {
224 return NULL;
226 PyErr_LDB_OR_RAISE(py_ldb, samdb);
228 frame = talloc_stackframe();
230 status = dns_common_zones(samdb, frame, NULL, &zones_list);
231 if (!NT_STATUS_IS_OK(status)) {
232 PyErr_SetNTSTATUS(status);
233 talloc_free(frame);
234 return NULL;
237 werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
238 if (!W_ERROR_IS_OK(werr)) {
239 PyErr_SetWERROR(werr);
240 talloc_free(frame);
241 return NULL;
244 ret = py_dnsp_DnssrvRpcRecord_get_array(py_dns_records,
245 frame,
246 &records, &num_records);
247 if (ret != 0) {
248 talloc_free(frame);
249 return NULL;
252 werr = dns_common_replace(samdb,
253 frame,
255 false, /* Not adding a record */
256 serial,
257 records,
258 num_records);
259 if (!W_ERROR_IS_OK(werr)) {
260 PyErr_SetWERROR(werr);
261 talloc_free(frame);
262 return NULL;
265 talloc_free(frame);
266 Py_RETURN_NONE;
269 static PyObject *py_dsdb_dns_replace_by_dn(PyObject *self, PyObject *args)
271 struct ldb_context *samdb;
272 PyObject *py_ldb, *py_dn, *py_dns_records;
273 TALLOC_CTX *frame;
274 WERROR werr;
275 int ret;
276 struct ldb_dn *dn;
277 struct dnsp_DnssrvRpcRecord *records;
278 uint16_t num_records;
281 * TODO: This is a shocking abuse, but matches what the
282 * internal DNS server does, it should be pushed into
283 * dns_common_replace()
285 static const int serial = 110;
287 if (!PyArg_ParseTuple(args, "OOO", &py_ldb, &py_dn, &py_dns_records)) {
288 return NULL;
290 PyErr_LDB_OR_RAISE(py_ldb, samdb);
292 PyErr_LDB_DN_OR_RAISE(py_dn, dn);
294 frame = talloc_stackframe();
296 ret = py_dnsp_DnssrvRpcRecord_get_array(py_dns_records,
297 frame,
298 &records, &num_records);
299 if (ret != 0) {
300 talloc_free(frame);
301 return NULL;
304 werr = dns_common_replace(samdb,
305 frame,
307 false, /* Not adding a record */
308 serial,
309 records,
310 num_records);
311 if (!W_ERROR_IS_OK(werr)) {
312 PyErr_SetWERROR(werr);
313 talloc_free(frame);
314 return NULL;
317 talloc_free(frame);
319 Py_RETURN_NONE;
322 static PyMethodDef py_dsdb_dns_methods[] = {
324 { "lookup", (PyCFunction)py_dsdb_dns_lookup,
325 METH_VARARGS|METH_KEYWORDS,
326 "Get the DNS database entries for a DNS name"},
327 { "replace", (PyCFunction)py_dsdb_dns_replace,
328 METH_VARARGS, "Replace the DNS database entries for a DNS name"},
329 { "replace_by_dn", (PyCFunction)py_dsdb_dns_replace_by_dn,
330 METH_VARARGS, "Replace the DNS database entries for a LDB DN"},
331 { "extract", (PyCFunction)py_dsdb_dns_extract,
332 METH_VARARGS, "Return the DNS database entry as a python structure from an Ldb.MessageElement of type dnsRecord"},
333 { NULL }
336 void initdsdb_dns(void);
338 void initdsdb_dns(void)
340 PyObject *m;
342 m = Py_InitModule3("dsdb_dns", py_dsdb_dns_methods,
343 "Python bindings for the DNS objects in the directory service databases.");
344 if (m == NULL)
345 return;