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()
91 req
= mdscli_get_results_send(frame
,
99 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
100 PyErr_SetNTSTATUS(status
);
104 status
= mdscli_get_results_recv(req
, frame
, &cnids
);
105 if (!NT_STATUS_IS_OK(status
) &&
106 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_MATCHES
))
108 PyErr_SetNTSTATUS(status
);
113 result
= Py_BuildValue("[]");
115 ncnids
= talloc_array_length(cnids
);
116 for (i
= 0; i
< ncnids
; i
++) {
118 PyObject
*pypath
= NULL
;
120 req
= mdscli_get_path_send(frame
,
131 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
132 PyErr_SetNTSTATUS(status
);
138 status
= mdscli_get_path_recv(req
, frame
, &path
);
140 PyErr_NTSTATUS_NOT_OK_RAISE(status
);
142 pypath
= PyUnicode_FromString(path
);
143 if (pypath
== NULL
) {
150 ret
= PyList_Append(result
, pypath
);
153 PyErr_SetString(PyExc_RuntimeError
,
154 "list append failed");
166 static PyObject
*search_close(PyObject
*self
,
170 TALLOC_CTX
*frame
= talloc_stackframe();
171 const char * const kwnames
[] = {"pipe", NULL
};
172 PyObject
*pypipe
= NULL
;
173 dcerpc_InterfaceObject
*pipe
= NULL
;
174 struct tevent_req
*req
= NULL
;
175 struct mdscli_search_ctx
*search
= NULL
;
179 if (!PyArg_ParseTupleAndKeywords(args
,
182 discard_const_p(char *, kwnames
),
184 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
188 ok
= py_check_dcerpc_type(pypipe
,
195 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
197 search
= pytalloc_get_type(self
, struct mdscli_search_ctx
);
198 if (search
== NULL
) {
202 req
= mdscli_close_search_send(frame
,
210 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
211 PyErr_SetNTSTATUS(status
);
215 status
= mdscli_close_search_recv(req
);
216 if (!NT_STATUS_IS_OK(status
) &&
217 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_MATCHES
))
219 PyErr_SetNTSTATUS(status
);
233 static PyMethodDef search_methods
[] = {
235 .ml_name
= "get_results",
236 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, search_get_results
),
237 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
242 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, search_close
),
243 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
249 static PyObject
*search_new(PyTypeObject
*type
,
253 TALLOC_CTX
*frame
= talloc_stackframe();
254 struct mdscli_search_ctx
*search
= NULL
;
255 PyObject
*self
= NULL
;
257 search
= talloc_zero(frame
, struct mdscli_search_ctx
);
258 if (search
== NULL
) {
264 self
= pytalloc_steal(type
, search
);
269 static PyTypeObject search_type
= {
270 .tp_name
= "mdscli.ctx.search",
271 .tp_new
= search_new
,
272 .tp_flags
= Py_TPFLAGS_DEFAULT
,
273 .tp_doc
= "search([....]) -> mdssvc client search context\n",
274 .tp_methods
= search_methods
,
277 static PyObject
*conn_sharepath(PyObject
*self
,
280 TALLOC_CTX
*frame
= talloc_stackframe();
281 struct mdscli_ctx
*ctx
= NULL
;
282 char *sharepath
= NULL
;
283 PyObject
*result
= NULL
;
285 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
290 sharepath
= mdscli_get_basepath(frame
, ctx
);
291 if (sharepath
== NULL
) {
296 result
= PyUnicode_FromString(sharepath
);
303 static PyObject
*conn_search(PyObject
*self
,
307 TALLOC_CTX
*frame
= talloc_stackframe();
308 PyObject
*pypipe
= NULL
;
309 dcerpc_InterfaceObject
*pipe
= NULL
;
310 struct mdscli_ctx
*ctx
= NULL
;
311 PyObject
*result
= NULL
;
313 char *basepath
= NULL
;
314 struct tevent_req
*req
= NULL
;
315 struct mdscli_search_ctx
*search
= NULL
;
316 const char * const kwnames
[] = {
317 "pipe", "query", "basepath", NULL
322 if (!PyArg_ParseTupleAndKeywords(args
,
325 discard_const_p(char *, kwnames
),
329 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
333 ok
= py_check_dcerpc_type(pypipe
,
340 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
342 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
347 req
= mdscli_search_send(frame
,
358 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
359 PyErr_SetNTSTATUS(status
);
363 status
= mdscli_search_recv(req
, frame
, &search
);
364 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
366 result
= pytalloc_steal(&search_type
, search
);
373 static PyObject
*conn_disconnect(PyObject
*self
,
377 TALLOC_CTX
*frame
= talloc_stackframe();
378 PyObject
*pypipe
= NULL
;
379 dcerpc_InterfaceObject
*pipe
= NULL
;
380 struct mdscli_ctx
*ctx
= NULL
;
381 struct tevent_req
*req
= NULL
;
382 const char * const kwnames
[] = {"pipe", NULL
};
386 if (!PyArg_ParseTupleAndKeywords(args
,
389 discard_const_p(char *, kwnames
),
391 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
395 ok
= py_check_dcerpc_type(pypipe
,
402 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
404 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
409 req
= mdscli_disconnect_send(frame
, pipe
->ev
, ctx
);
415 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
416 PyErr_SetNTSTATUS(status
);
420 status
= mdscli_disconnect_recv(req
);
421 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
432 static PyMethodDef conn_methods
[] = {
434 .ml_name
= "sharepath",
435 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_sharepath
),
436 .ml_flags
= METH_NOARGS
,
437 .ml_doc
= "mdscli.conn.sharepath(...) -> get share basepath",
441 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_search
),
442 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
443 .ml_doc
= "mdscli.conn.search(...) -> run mdssvc query",
446 .ml_name
= "disconnect",
447 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_disconnect
),
448 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
449 .ml_doc
= "mdscli.conn.disconnect(...) -> disconnect",
454 static PyObject
*conn_new(PyTypeObject
*type
,
458 TALLOC_CTX
*frame
= talloc_stackframe();
459 const char * const kwnames
[] = { "pipe", "share", "mountpoint", NULL
};
460 PyObject
*pypipe
= NULL
;
461 dcerpc_InterfaceObject
*pipe
= NULL
;
462 struct tevent_req
*req
= NULL
;
464 char *mountpoint
= NULL
;
465 struct mdscli_ctx
*ctx
= NULL
;
466 PyObject
*self
= NULL
;
470 if (!PyArg_ParseTupleAndKeywords(args
,
473 discard_const_p(char *, kwnames
),
477 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
481 ok
= py_check_dcerpc_type(pypipe
,
488 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
490 req
= mdscli_connect_send(frame
,
492 pipe
->binding_handle
,
500 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
501 PyErr_SetNTSTATUS(status
);
505 status
= mdscli_connect_recv(req
, frame
, &ctx
);
506 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
508 self
= pytalloc_steal(type
, ctx
);
515 static PyTypeObject conn_type
= {
516 .tp_name
= "mdscli.conn",
518 .tp_flags
= Py_TPFLAGS_DEFAULT
,
519 .tp_doc
= "conn([....]) -> mdssvc connection\n",
520 .tp_methods
= conn_methods
,
523 static PyMethodDef mdscli_methods
[] = {
527 static struct PyModuleDef moduledef
= {
528 PyModuleDef_HEAD_INIT
,
530 .m_doc
= "RPC mdssvc client",
532 .m_methods
= mdscli_methods
,
535 MODULE_INIT_FUNC(mdscli
)
537 TALLOC_CTX
*frame
= talloc_stackframe();
541 ret
= pytalloc_BaseObject_PyType_Ready(&conn_type
);
547 ret
= pytalloc_BaseObject_PyType_Ready(&search_type
);
553 m
= PyModule_Create(&moduledef
);
559 Py_INCREF(&conn_type
);
560 PyModule_AddObject(m
, "conn", (PyObject
*)&conn_type
);
562 Py_INCREF(&search_type
);
563 PyModule_AddObject(m
, "search", (PyObject
*)&search_type
);