diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/messaging/pymessaging.c | 352 |
1 files changed, 3 insertions, 349 deletions
diff --git a/source4/lib/messaging/pymessaging.c b/source4/lib/messaging/pymessaging.c index 5813001319..ba9770da34 100644 --- a/source4/lib/messaging/pymessaging.c +++ b/source4/lib/messaging/pymessaging.c @@ -25,20 +25,15 @@ #include "libcli/util/pyerrors.h" #include "librpc/rpc/pyrpc_util.h" #include "librpc/ndr/libndr.h" -#include "lib/messaging/irpc.h" #include "lib/messaging/messaging.h" #include "lib/events/events.h" #include "cluster/cluster.h" #include "param/param.h" #include "param/pyparam.h" -#include "librpc/gen_ndr/ndr_irpc.h" #include "librpc/rpc/dcerpc.h" +#include "librpc/gen_ndr/server_id.h" PyAPI_DATA(PyTypeObject) messaging_Type; -PyAPI_DATA(PyTypeObject) irpc_ClientConnectionType; - -/* FIXME: This prototype should be in py_irpc.h, or shared otherwise */ -extern const struct PyNdrRpcMethodDef py_ndr_irpc_methods[]; static bool server_id_from_py(PyObject *object, struct server_id *server_id) { @@ -143,7 +138,7 @@ static PyObject *py_messaging_send(PyObject *self, PyObject *args, PyObject *kwa data.length = length; - if (!server_id_from_py(target, &server)) + if (!server_id_from_py(target, &server)) return NULL; status = messaging_send(iface->msg_ctx, server, msg_type, &data); @@ -217,44 +212,6 @@ static PyObject *py_messaging_deregister(PyObject *self, PyObject *args, PyObjec Py_RETURN_NONE; } -static PyObject *py_messaging_add_name(PyObject *self, PyObject *args, PyObject *kwargs) -{ - messaging_Object *iface = (messaging_Object *)self; - NTSTATUS status; - char *name; - const char *kwnames[] = { "name", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:add_name", - discard_const_p(char *, kwnames), &name)) { - return NULL; - } - - status = irpc_add_name(iface->msg_ctx, name); - if (NT_STATUS_IS_ERR(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - Py_RETURN_NONE; -} - - -static PyObject *py_messaging_remove_name(PyObject *self, PyObject *args, PyObject *kwargs) -{ - messaging_Object *iface = (messaging_Object *)self; - char *name; - const char *kwnames[] = { "name", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:remove_name", - discard_const_p(char *, kwnames), &name)) { - return NULL; - } - - irpc_remove_name(iface->msg_ctx, name); - - Py_RETURN_NONE; -} - static PyMethodDef py_messaging_methods[] = { { "send", (PyCFunction)py_messaging_send, METH_VARARGS|METH_KEYWORDS, "S.send(target, msg_type, data) -> None\nSend a message" }, @@ -262,8 +219,6 @@ static PyMethodDef py_messaging_methods[] = { "S.register(callback, msg_type=None) -> msg_type\nRegister a message handler" }, { "deregister", (PyCFunction)py_messaging_deregister, METH_VARARGS|METH_KEYWORDS, "S.deregister(callback, msg_type) -> None\nDeregister a message handler" }, - { "add_name", (PyCFunction)py_messaging_add_name, METH_VARARGS|METH_KEYWORDS, "S.add_name(name) -> None\nListen on another name" }, - { "remove_name", (PyCFunction)py_messaging_remove_name, METH_VARARGS|METH_KEYWORDS, "S.remove_name(name) -> None\nStop listening on a name" }, { NULL, NULL, 0, NULL } }; @@ -285,7 +240,7 @@ static PyGetSetDef py_messaging_getset[] = { PyTypeObject messaging_Type = { PyObject_HEAD_INIT(NULL) 0, - .tp_name = "irpc.Messaging", + .tp_name = "messaging.Messaging", .tp_basicsize = sizeof(messaging_Object), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_new = py_messaging_connect, @@ -297,318 +252,17 @@ PyTypeObject messaging_Type = { "If no path is specified, the default path from smb.conf will be used." }; - -/* - state of a irpc 'connection' -*/ -typedef struct { - PyObject_HEAD - TALLOC_CTX *mem_ctx; - const char *server_name; - struct server_id *dest_ids; - struct messaging_context *msg_ctx; - struct tevent_context *ev; -} irpc_ClientConnectionObject; - -/* - setup a context for talking to a irpc server - example: - status = irpc.connect("smb_server"); -*/ - -PyObject *py_irpc_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs) -{ - const char *kwnames[] = { "server", "own_id", "messaging_path", NULL }; - char *server; - const char *messaging_path = NULL; - PyObject *own_id = Py_None; - irpc_ClientConnectionObject *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oz:connect", - discard_const_p(char *, kwnames), &server, &own_id, &messaging_path)) { - return NULL; - } - - ret = PyObject_New(irpc_ClientConnectionObject, &irpc_ClientConnectionType); - if (ret == NULL) - return NULL; - - ret->mem_ctx = talloc_new(NULL); - - ret->server_name = server; - - ret->ev = s4_event_context_init(ret->mem_ctx); - - if (messaging_path == NULL) { - messaging_path = lpcfg_messaging_path(ret->mem_ctx, - py_default_loadparm_context(ret->mem_ctx)); - } else { - messaging_path = talloc_strdup(ret->mem_ctx, messaging_path); - } - - if (own_id != Py_None) { - struct server_id server_id; - - if (!server_id_from_py(own_id, &server_id)) - return NULL; - - ret->msg_ctx = messaging_init(ret->mem_ctx, - messaging_path, - server_id, - ret->ev); - } else { - ret->msg_ctx = messaging_client_init(ret->mem_ctx, - messaging_path, - ret->ev); - } - - if (ret->msg_ctx == NULL) { - PyErr_SetString(PyExc_RuntimeError, "irpc_connect unable to create a messaging context"); - talloc_free(ret->mem_ctx); - return NULL; - } - - ret->dest_ids = irpc_servers_byname(ret->msg_ctx, ret->mem_ctx, ret->server_name); - if (ret->dest_ids == NULL || ret->dest_ids[0].id == 0) { - talloc_free(ret->mem_ctx); - PyErr_SetNTSTATUS(NT_STATUS_OBJECT_NAME_NOT_FOUND); - return NULL; - } else { - return (PyObject *)ret; - } -} - -typedef struct { - PyObject_HEAD - TALLOC_CTX *mem_ctx; - struct tevent_context *ev; - struct tevent_req **reqs; - void **ptrs; - int count; - int current; - py_data_unpack_fn unpack_fn; -} irpc_ResultObject; - - -static PyObject *irpc_result_next(irpc_ResultObject *iterator) -{ - NTSTATUS status; - bool ok; - - if (iterator->current >= iterator->count) { - PyErr_SetString(PyExc_StopIteration, "No more results"); - return NULL; - } - - ok = tevent_req_poll(iterator->reqs[iterator->current], iterator->ev); - if (!ok) { - status = map_nt_error_from_unix(errno); - PyErr_SetNTSTATUS(status); - return NULL; - } - - status = dcerpc_binding_handle_call_recv(iterator->reqs[iterator->current]); - TALLOC_FREE(iterator->reqs[iterator->current]); - iterator->current++; - if (!NT_STATUS_IS_OK(status)) { - PyErr_SetNTSTATUS(status); - return NULL; - } - - return iterator->unpack_fn(iterator->ptrs[iterator->current-1]); -} - -static PyObject *irpc_result_len(irpc_ResultObject *self) -{ - return PyLong_FromLong(self->count); -} - -static PyMethodDef irpc_result_methods[] = { - { "__len__", (PyCFunction)irpc_result_len, METH_NOARGS, - "Number of elements returned"}, - { NULL } -}; - -static void irpc_result_dealloc(PyObject *self) -{ - talloc_free(((irpc_ResultObject *)self)->mem_ctx); - PyObject_Del(self); -} - -PyTypeObject irpc_ResultIteratorType = { - PyObject_HEAD_INIT(NULL) 0, - .tp_name = "irpc.ResultIterator", - .tp_basicsize = sizeof(irpc_ResultObject), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_iternext = (iternextfunc)irpc_result_next, - .tp_iter = PyObject_SelfIter, - .tp_methods = irpc_result_methods, - .tp_dealloc = irpc_result_dealloc, -}; - -static PyObject *py_irpc_call(irpc_ClientConnectionObject *p, struct PyNdrRpcMethodDef *method_def, PyObject *args, PyObject *kwargs) -{ - void *ptr; - void **ptrs; - struct tevent_req **reqs; - int i, count; - NTSTATUS status; - TALLOC_CTX *mem_ctx = talloc_new(NULL); - irpc_ResultObject *ret; - size_t struct_size = method_def->table->calls[method_def->opnum].struct_size; - - /* allocate the C structure */ - ptr = talloc_zero_size(mem_ctx, struct_size); - if (ptr == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - /* convert the mpr object into a C structure */ - if (!method_def->pack_in_data(args, kwargs, ptr)) { - talloc_free(mem_ctx); - return NULL; - } - - for (count=0;p->dest_ids[count].id;count++) /* noop */ ; - - /* we need to make a call per server */ - reqs = talloc_array(mem_ctx, struct tevent_req *, count); - if (reqs == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - ptrs = talloc_array(mem_ctx, void *, count); - if (ptrs == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - /* make the actual calls */ - for (i=0;i<count;i++) { - struct dcerpc_binding_handle *irpc_handle; - - irpc_handle = irpc_binding_handle(reqs, p->msg_ctx, - p->dest_ids[i], - &ndr_table_irpc); - if (irpc_handle == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - ptrs[i] = talloc_size(mem_ctx, struct_size); - if (ptrs[i] == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - memcpy(ptrs[i], ptr, struct_size); - - reqs[i] = dcerpc_binding_handle_call_send(reqs, - p->ev, - irpc_handle, - NULL, - &ndr_table_irpc, - method_def->opnum, - ptrs[i], ptrs[i]); - if (reqs[i] == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - } - - ret = PyObject_New(irpc_ResultObject, &irpc_ResultIteratorType); - ret->mem_ctx = mem_ctx; - ret->ev = p->ev; - ret->reqs = reqs; - ret->ptrs = ptrs; - ret->count = count; - ret->current = 0; - ret->unpack_fn = method_def->unpack_out_data; - - return (PyObject *)ret; -done: - talloc_free(mem_ctx); - PyErr_SetNTSTATUS(status); - return NULL; -} - -static PyObject *py_irpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs) -{ - irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self; - struct PyNdrRpcMethodDef *md = wrapped; - - return py_irpc_call(iface, md, args, kwargs); -} - -static void py_irpc_dealloc(PyObject *self) -{ - irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self; - talloc_free(iface->mem_ctx); - PyObject_Del(self); -} - -PyTypeObject irpc_ClientConnectionType = { - PyObject_HEAD_INIT(NULL) 0, - .tp_name = "irpc.ClientConnection", - .tp_basicsize = sizeof(irpc_ClientConnectionObject), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_new = py_irpc_connect, - .tp_dealloc = py_irpc_dealloc, - .tp_doc = "ClientConnection(server, own_id=None, messaging_path=None)\n" \ - "Create a new IRPC client connection to communicate with the servers in the specified path.\n" \ - "If no path is specified, the default path from smb.conf will be used." -}; - -static bool irpc_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds) -{ - int i; - for (i = 0; mds[i].name; i++) { - PyObject *ret; - struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1); - - wb->name = discard_const_p(char, mds[i].name); - wb->flags = PyWrapperFlag_KEYWORDS; - wb->wrapper = (wrapperfunc)py_irpc_call_wrapper; - wb->doc = discard_const_p(char, mds[i].doc); - - ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i])); - - PyDict_SetItemString(ifacetype->tp_dict, mds[i].name, - (PyObject *)ret); - } - - return true; -} - void initmessaging(void) { PyObject *mod; - PyObject *dep_irpc; - - dep_irpc = PyImport_ImportModule("samba.dcerpc.irpc"); - if (dep_irpc == NULL) - return; - - if (PyType_Ready(&irpc_ClientConnectionType) < 0) - return; if (PyType_Ready(&messaging_Type) < 0) return; - if (PyType_Ready(&irpc_ResultIteratorType) < 0) - return; - - if (!irpc_AddNdrRpcMethods(&irpc_ClientConnectionType, py_ndr_irpc_methods)) - return; - mod = Py_InitModule3("messaging", NULL, "Internal RPC"); if (mod == NULL) return; - Py_INCREF((PyObject *)&irpc_ClientConnectionType); - PyModule_AddObject(mod, "ClientConnection", (PyObject *)&irpc_ClientConnectionType); - Py_INCREF((PyObject *)&messaging_Type); PyModule_AddObject(mod, "Messaging", (PyObject *)&messaging_Type); } |