summaryrefslogtreecommitdiff
path: root/source4/dns_server/pydns.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2015-09-22 12:11:04 +1200
committerAndrew Bartlett <abartlet@samba.org>2015-10-26 05:11:21 +0100
commit87cd68c1dc0427521061f8febbcc18d73e21ab18 (patch)
treebcd38df96c246ee691e254cdf8559b4ae2eda1a4 /source4/dns_server/pydns.c
parent0504065948eec9bd65296d5956b5863d9af06e41 (diff)
downloadsamba-87cd68c1dc0427521061f8febbcc18d73e21ab18.tar.gz
dns_server: Add a python module directly accessing DNS records in sam.ldb
Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'source4/dns_server/pydns.c')
-rw-r--r--source4/dns_server/pydns.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/source4/dns_server/pydns.c b/source4/dns_server/pydns.c
new file mode 100644
index 00000000000..1fad6922ed0
--- /dev/null
+++ b/source4/dns_server/pydns.c
@@ -0,0 +1,225 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Python DNS server wrapper
+
+ Copyright (C) 2015 Andrew Bartlett
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "includes.h"
+#include <pyldb.h>
+#include <pytalloc.h>
+#include "dns_server/dnsserver_common.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include "librpc/rpc/pyrpc_util.h"
+
+/* FIXME: These should be in a header file somewhere */
+#define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
+ if (!py_check_dcerpc_type(py_ldb, "ldb", "Ldb")) { \
+ PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
+ return NULL; \
+ } \
+ ldb = pyldb_Ldb_AsLdbContext(py_ldb);
+
+static PyObject *py_ldb_get_exception(void)
+{
+ PyObject *mod = PyImport_ImportModule("ldb");
+ if (mod == NULL)
+ return NULL;
+
+ return PyObject_GetAttrString(mod, "LdbError");
+}
+
+static PyObject *py_dnsp_DnssrvRpcRecord_get_list(struct dnsp_DnssrvRpcRecord *records,
+ uint16_t num_records)
+{
+ PyObject *py_dns_list;
+ int i;
+ py_dns_list = PyList_New(num_records);
+ if (py_dns_list == NULL) {
+ return NULL;
+ }
+ for (i = 0; i < num_records; i++) {
+ PyObject *py_dns_record;
+ py_dns_record = py_return_ndr_struct("samba.dcerpc.dnsp", "DnssrvRpcRecord", records, &records[i]);
+ PyList_SetItem(py_dns_list, i, py_dns_record);
+ }
+ return py_dns_list;
+}
+
+static int py_dnsp_DnssrvRpcRecord_get_array(PyObject *value,
+ TALLOC_CTX *mem_ctx,
+ struct dnsp_DnssrvRpcRecord **records,
+ uint16_t *num_records)
+{
+ int i;
+ struct dnsp_DnssrvRpcRecord *recs;
+ PY_CHECK_TYPE(&PyList_Type, value, return -1;);
+ recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord,
+ PyList_GET_SIZE(value));
+ if (recs == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ for (i = 0; i < PyList_GET_SIZE(value); i++) {
+ bool type_correct;
+ PyObject *item = PyList_GET_ITEM(value, i);
+ type_correct = py_check_dcerpc_type(item, "samba.dcerpc.dnsp", "DnssrvRpcRecord");
+ if (type_correct == false) {
+ return -1;
+ }
+ if (talloc_reference(mem_ctx, pytalloc_get_mem_ctx(item)) == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ recs[i] = *(struct dnsp_DnssrvRpcRecord *)pytalloc_get_ptr(item);
+ }
+ *records = recs;
+ *num_records = PyList_GET_SIZE(value);
+ return 0;
+}
+
+static PyObject *py_dsdb_dns_lookup(PyObject *self, PyObject *args)
+{
+ struct ldb_context *samdb;
+ PyObject *py_ldb;
+ char *dns_name;
+ TALLOC_CTX *frame;
+ NTSTATUS status;
+ WERROR werr;
+ struct dns_server_zone *zones_list;
+ struct ldb_dn *dn;
+ struct dnsp_DnssrvRpcRecord *records;
+ uint16_t num_records;
+
+ if (!PyArg_ParseTuple(args, "Os", &py_ldb, &dns_name)) {
+ return NULL;
+ }
+ PyErr_LDB_OR_RAISE(py_ldb, samdb);
+
+ frame = talloc_stackframe();
+
+ status = dns_common_zones(samdb, frame, &zones_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+
+ werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
+ if (!W_ERROR_IS_OK(werr)) {
+ PyErr_SetWERROR(werr);
+ return NULL;
+ }
+
+ werr = dns_common_lookup(samdb,
+ frame,
+ dn,
+ &records,
+ &num_records,
+ NULL);
+ if (!W_ERROR_IS_OK(werr)) {
+ PyErr_SetWERROR(werr);
+ return NULL;
+ }
+
+ return py_dnsp_DnssrvRpcRecord_get_list(records, num_records);
+}
+
+static PyObject *py_dsdb_dns_replace(PyObject *self, PyObject *args)
+{
+ struct ldb_context *samdb;
+ PyObject *py_ldb, *py_dns_records;
+ char *dns_name;
+ TALLOC_CTX *frame;
+ NTSTATUS status;
+ WERROR werr;
+ int ret;
+ struct dns_server_zone *zones_list;
+ struct ldb_dn *dn;
+ struct dnsp_DnssrvRpcRecord *records;
+ uint16_t num_records;
+
+ /*
+ * TODO: This is a shocking abuse, but matches what the
+ * internal DNS server does, it should be pushed into
+ * dns_common_replace()
+ */
+ static const int serial = 110;
+
+ if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &dns_name, &py_dns_records)) {
+ return NULL;
+ }
+ PyErr_LDB_OR_RAISE(py_ldb, samdb);
+
+ frame = talloc_stackframe();
+
+ status = dns_common_zones(samdb, frame, &zones_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+
+ werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
+ if (!W_ERROR_IS_OK(werr)) {
+ PyErr_SetWERROR(werr);
+ return NULL;
+ }
+
+ ret = py_dnsp_DnssrvRpcRecord_get_array(py_dns_records,
+ frame,
+ &records, &num_records);
+ if (ret != 0) {
+ return NULL;
+ }
+
+ werr = dns_common_replace(samdb,
+ frame,
+ dn,
+ false, /* Not adding a record */
+ serial,
+ records,
+ num_records);
+ if (!W_ERROR_IS_OK(werr)) {
+ PyErr_SetWERROR(werr);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef py_dsdb_dns_methods[] = {
+
+ { "lookup", (PyCFunction)py_dsdb_dns_lookup,
+ METH_VARARGS, "Get the DNS database entries for a DNS name"},
+ { "replace", (PyCFunction)py_dsdb_dns_replace,
+ METH_VARARGS, "Replace the DNS database entries for a DNS name"},
+ { NULL }
+};
+
+void initdsdb_dns(void);
+
+void initdsdb_dns(void)
+{
+ PyObject *m;
+
+ m = Py_InitModule3("dsdb_dns", py_dsdb_dns_methods,
+ "Python bindings for the DNS objects in the directory service databases.");
+ if (m == NULL)
+ return;
+}