2 Python interface to cli_mdssvc
4 Copyright (C) Ralph Boehme 2019
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "python/py3compat.h"
24 #include "python/modules.h"
25 #include "lib/util/talloc_stack.h"
26 #include "lib/util/tevent_ntstatus.h"
27 #include "librpc/rpc/rpc_common.h"
28 #include "librpc/rpc/pyrpc_util.h"
29 #include "rpc_client/cli_mdssvc.h"
30 #include "rpc_client/cli_mdssvc_private.h"
32 static PyObject *search_get_results(PyObject *self,
36 TALLOC_CTX *frame = talloc_stackframe();
37 const char * const kwnames[] = {"pipe", NULL};
38 PyObject *pypipe = NULL;
39 PyObject *result = NULL;
40 dcerpc_InterfaceObject *pipe = NULL;
41 struct tevent_req *req = NULL;
42 struct mdscli_search_ctx *search = NULL;
43 uint64_t *cnids = NULL;
50 if (!PyArg_ParseTupleAndKeywords(args,
53 discard_const_p(char *, kwnames),
55 PyErr_SetString(PyExc_RuntimeError, "Failed to parse args");
59 ok = py_check_dcerpc_type(pypipe,
66 pipe = (dcerpc_InterfaceObject *)pypipe;
68 search = pytalloc_get_type(self, struct mdscli_search_ctx);
74 * We must use the async send/recv versions in order to pass the correct
75 * tevent context, here and any other place we call mdscli_*
76 * functions. Using the sync version we would be polling a temporary
77 * event context, but unfortunately the s4 Python RPC bindings dispatch
80 * dcerpc_bh_raw_call_send()
81 * -> dcerpc_request_send()
82 * -> dcerpc_schedule_io_trigger()
83 * -> dcerpc_send_request()
84 * -> tstream_writev_queue_send()
86 * on an hardcoded event context allocated via
88 * py_dcerpc_interface_init_helper()
89 * -> dcerpc_pipe_connect()
92 req = mdscli_get_results_send(frame,
100 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
101 PyErr_SetNTSTATUS(status);
105 status = mdscli_get_results_recv(req, frame, &cnids);
107 if (NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
111 if (!NT_STATUS_IS_OK(status) &&
112 !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_MATCHES))
114 PyErr_SetNTSTATUS(status);
118 result = Py_BuildValue("[]");
120 ncnids = talloc_array_length(cnids);
121 for (i = 0; i < ncnids; i++) {
123 PyObject *pypath = NULL;
125 req = mdscli_get_path_send(frame,
136 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
137 PyErr_SetNTSTATUS(status);
143 status = mdscli_get_path_recv(req, frame, &path);
145 PyErr_NTSTATUS_NOT_OK_RAISE(status);
147 pypath = PyUnicode_FromString(path);
148 if (pypath == NULL) {
155 ret = PyList_Append(result, pypath);
158 PyErr_SetString(PyExc_RuntimeError,
159 "list append failed");
171 static PyObject *search_close(PyObject *self,
175 TALLOC_CTX *frame = talloc_stackframe();
176 const char * const kwnames[] = {"pipe", NULL};
177 PyObject *pypipe = NULL;
178 dcerpc_InterfaceObject *pipe = NULL;
179 struct tevent_req *req = NULL;
180 struct mdscli_search_ctx *search = NULL;
184 if (!PyArg_ParseTupleAndKeywords(args,
187 discard_const_p(char *, kwnames),
189 PyErr_SetString(PyExc_RuntimeError, "Failed to parse args");
193 ok = py_check_dcerpc_type(pypipe,
200 pipe = (dcerpc_InterfaceObject *)pypipe;
202 search = pytalloc_get_type(self, struct mdscli_search_ctx);
203 if (search == NULL) {
207 req = mdscli_close_search_send(frame,
215 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
216 PyErr_SetNTSTATUS(status);
220 status = mdscli_close_search_recv(req);
221 if (!NT_STATUS_IS_OK(status) &&
222 !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_MATCHES))
224 PyErr_SetNTSTATUS(status);
238 static PyMethodDef search_methods[] = {
240 .ml_name = "get_results",
241 .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, search_get_results),
242 .ml_flags = METH_VARARGS|METH_KEYWORDS,
247 .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, search_close),
248 .ml_flags = METH_VARARGS|METH_KEYWORDS,
254 static PyObject *search_new(PyTypeObject *type,
258 TALLOC_CTX *frame = talloc_stackframe();
259 struct mdscli_search_ctx *search = NULL;
260 PyObject *self = NULL;
262 search = talloc_zero(frame, struct mdscli_search_ctx);
263 if (search == NULL) {
269 self = pytalloc_steal(type, search);
274 static PyTypeObject search_type = {
275 .tp_name = "mdscli.ctx.search",
276 .tp_new = search_new,
277 .tp_flags = Py_TPFLAGS_DEFAULT,
278 .tp_doc = "search([....]) -> mdssvc client search context\n",
279 .tp_methods = search_methods,
282 static PyObject *conn_sharepath(PyObject *self,
285 TALLOC_CTX *frame = talloc_stackframe();
286 struct mdscli_ctx *ctx = NULL;
287 char *sharepath = NULL;
288 PyObject *result = NULL;
290 ctx = pytalloc_get_type(self, struct mdscli_ctx);
295 sharepath = mdscli_get_basepath(frame, ctx);
296 if (sharepath == NULL) {
301 result = PyUnicode_FromString(sharepath);
308 static PyObject *conn_search(PyObject *self,
312 TALLOC_CTX *frame = talloc_stackframe();
313 PyObject *pypipe = NULL;
314 dcerpc_InterfaceObject *pipe = NULL;
315 struct mdscli_ctx *ctx = NULL;
316 PyObject *result = NULL;
318 char *basepath = NULL;
319 struct tevent_req *req = NULL;
320 struct mdscli_search_ctx *search = NULL;
321 const char * const kwnames[] = {
322 "pipe", "query", "basepath", NULL
327 if (!PyArg_ParseTupleAndKeywords(args,
330 discard_const_p(char *, kwnames),
334 PyErr_SetString(PyExc_RuntimeError, "Failed to parse args");
338 ok = py_check_dcerpc_type(pypipe,
345 pipe = (dcerpc_InterfaceObject *)pypipe;
347 ctx = pytalloc_get_type(self, struct mdscli_ctx);
352 req = mdscli_search_send(frame,
363 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
364 PyErr_SetNTSTATUS(status);
368 status = mdscli_search_recv(req, frame, &search);
369 PyErr_NTSTATUS_IS_ERR_RAISE(status);
371 result = pytalloc_steal(&search_type, search);
378 static PyObject *conn_disconnect(PyObject *self,
382 TALLOC_CTX *frame = talloc_stackframe();
383 PyObject *pypipe = NULL;
384 dcerpc_InterfaceObject *pipe = NULL;
385 struct mdscli_ctx *ctx = NULL;
386 struct tevent_req *req = NULL;
387 const char * const kwnames[] = {"pipe", NULL};
391 if (!PyArg_ParseTupleAndKeywords(args,
394 discard_const_p(char *, kwnames),
396 PyErr_SetString(PyExc_RuntimeError, "Failed to parse args");
400 ok = py_check_dcerpc_type(pypipe,
407 pipe = (dcerpc_InterfaceObject *)pypipe;
409 ctx = pytalloc_get_type(self, struct mdscli_ctx);
414 req = mdscli_disconnect_send(frame, pipe->ev, ctx);
420 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
421 PyErr_SetNTSTATUS(status);
425 status = mdscli_disconnect_recv(req);
426 PyErr_NTSTATUS_IS_ERR_RAISE(status);
437 static PyMethodDef conn_methods[] = {
439 .ml_name = "sharepath",
440 .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, conn_sharepath),
441 .ml_flags = METH_NOARGS,
442 .ml_doc = "mdscli.conn.sharepath(...) -> get share basepath",
446 .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, conn_search),
447 .ml_flags = METH_VARARGS|METH_KEYWORDS,
448 .ml_doc = "mdscli.conn.search(...) -> run mdssvc query",
451 .ml_name = "disconnect",
452 .ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction, conn_disconnect),
453 .ml_flags = METH_VARARGS|METH_KEYWORDS,
454 .ml_doc = "mdscli.conn.disconnect(...) -> disconnect",
459 static PyObject *conn_new(PyTypeObject *type,
463 TALLOC_CTX *frame = talloc_stackframe();
464 const char * const kwnames[] = { "pipe", "share", "mountpoint", NULL };
465 PyObject *pypipe = NULL;
466 dcerpc_InterfaceObject *pipe = NULL;
467 struct tevent_req *req = NULL;
469 char *mountpoint = NULL;
470 struct mdscli_ctx *ctx = NULL;
471 PyObject *self = NULL;
475 if (!PyArg_ParseTupleAndKeywords(args,
478 discard_const_p(char *, kwnames),
482 PyErr_SetString(PyExc_RuntimeError, "Failed to parse args");
486 ok = py_check_dcerpc_type(pypipe,
493 pipe = (dcerpc_InterfaceObject *)pypipe;
495 req = mdscli_connect_send(frame,
497 pipe->binding_handle,
505 if (!tevent_req_poll_ntstatus(req, pipe->ev, &status)) {
506 PyErr_SetNTSTATUS(status);
510 status = mdscli_connect_recv(req, frame, &ctx);
511 PyErr_NTSTATUS_IS_ERR_RAISE(status);
513 self = pytalloc_steal(type, ctx);
520 static PyTypeObject conn_type = {
521 .tp_name = "mdscli.conn",
523 .tp_flags = Py_TPFLAGS_DEFAULT,
524 .tp_doc = "conn([....]) -> mdssvc connection\n",
525 .tp_methods = conn_methods,
528 static PyMethodDef mdscli_methods[] = {
532 static struct PyModuleDef moduledef = {
533 PyModuleDef_HEAD_INIT,
535 .m_doc = "RPC mdssvc client",
537 .m_methods = mdscli_methods,
540 MODULE_INIT_FUNC(mdscli)
542 TALLOC_CTX *frame = talloc_stackframe();
546 ret = pytalloc_BaseObject_PyType_Ready(&conn_type);
552 ret = pytalloc_BaseObject_PyType_Ready(&search_type);
558 m = PyModule_Create(&moduledef);
564 Py_INCREF(&conn_type);
565 PyModule_AddObject(m, "conn", (PyObject *)&conn_type);
567 Py_INCREF(&search_type);
568 PyModule_AddObject(m, "search", (PyObject *)&search_type);