diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2009-01-04 22:48:23 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2009-01-04 22:48:23 +0100 |
commit | af744e0954bbe9ddfa2e3da173e79de65e640a4c (patch) | |
tree | 78b98c28e6d54c5339c12f2f942883d5088fda84 | |
parent | ce47b69d8e318bbb3642d27aa0451e2914c92be7 (diff) | |
parent | 2c0faaf5d921fe57a88d3b999067458e8774c6f6 (diff) | |
download | samba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.tar.gz samba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.tar.bz2 samba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
91 files changed, 2515 insertions, 1144 deletions
diff --git a/lib/replace/test/os2_delete.c b/lib/replace/test/os2_delete.c index b45c135355..44efeea08a 100644 --- a/lib/replace/test/os2_delete.c +++ b/lib/replace/test/os2_delete.c @@ -30,7 +30,9 @@ static int test_readdir_os2_delete_ret; static void cleanup(void) { /* I'm a lazy bastard */ - system("rm -rf " TESTDIR); + if (system("rm -rf " TESTDIR)) { + FAILED("system"); + } mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir"); } @@ -118,7 +120,9 @@ int test_readdir_os2_delete(void) rmdir(TESTDIR) == 0 || FAILED("rmdir"); - system("rm -rf " TESTDIR); + if (system("rm -rf " TESTDIR) == -1) { + FAILED("system"); + } return test_readdir_os2_delete_ret; } diff --git a/lib/tevent/config.mk b/lib/tevent/config.mk deleted file mode 100644 index e4fb9a8088..0000000000 --- a/lib/tevent/config.mk +++ /dev/null @@ -1,46 +0,0 @@ -############################## -[MODULE::TEVENT_AIO] -PRIVATE_DEPENDENCIES = LIBAIO_LINUX -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = LIBTEVENT -############################## - -TEVENT_AIO_OBJ_FILES = $(libteventsrcdir)/tevent_aio.o - -############################## -[MODULE::TEVENT_EPOLL] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = LIBTEVENT -############################## - -TEVENT_EPOLL_OBJ_FILES = $(libteventsrcdir)/tevent_epoll.o - -############################## -[MODULE::TEVENT_SELECT] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = LIBTEVENT -############################## - -TEVENT_SELECT_OBJ_FILES = $(libteventsrcdir)/tevent_select.o - -############################## -[MODULE::TEVENT_STANDARD] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = LIBTEVENT -############################## - -TEVENT_STANDARD_OBJ_FILES = $(libteventsrcdir)/tevent_standard.o - -################################################ -# Start SUBSYSTEM LIBTEVENT -[LIBRARY::LIBTEVENT] -PUBLIC_DEPENDENCIES = LIBTALLOC -OUTPUT_TYPE = MERGED_OBJ -CFLAGS = -I../lib/tevent -# -# End SUBSYSTEM LIBTEVENT -################################################ - -LIBTEVENT_OBJ_FILES = $(addprefix $(libteventsrcdir)/, tevent.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o) - -PUBLIC_HEADERS += $(addprefix $(libteventsrcdir)/, tevent.h tevent_internal.h) diff --git a/lib/tevent/configure.ac b/lib/tevent/configure.ac index 22d306b0f6..3cc06a144a 100644 --- a/lib/tevent/configure.ac +++ b/lib/tevent/configure.ac @@ -1,11 +1,8 @@ AC_PREREQ(2.50) -AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) -AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) -AC_DEFUN([SMB_ENABLE], [echo -n ""]) -AC_DEFUN([SMB_EXT_LIB], [echo -n ""]) -AC_INIT(tevent, 0.9.0) +AC_INIT(tevent, 0.9.2) AC_CONFIG_SRCDIR([tevent.c]) AC_CONFIG_HEADER(config.h) + AC_LIBREPLACE_ALL_CHECKS AC_LD_EXPORT_DYNAMIC diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4 index 30105d9bef..ec2ed9cd1f 100644 --- a/lib/tevent/libtevent.m4 +++ b/lib/tevent/libtevent.m4 @@ -1,12 +1,14 @@ dnl find the tevent sources. This is meant to work both for dnl standalone builds, and builds of packages using libtevent + +AC_SUBST(teventdir) + if test x"$teventdir" = "x"; then teventdir="" teventpaths="$srcdir $srcdir/../lib/tevent $srcdir/tevent $srcdir/../tevent" for d in $teventpaths; do if test -f "$d/tevent.c"; then teventdir="$d" - AC_SUBST(teventdir) break; fi done @@ -15,37 +17,32 @@ if test x"$teventdir" = "x"; then fi fi -TEVENT_OBJ="tevent.o tevent_select.o tevent_signal.o tevent_timed.o tevent_standard.o tevent_debug.o tevent_util.o" -AC_LIBREPLACE_NETWORK_CHECKS +TEVENT_OBJ="" +TEVENT_CFLAGS="" +TEVENT_LIBS="" +AC_SUBST(TEVENT_OBJ) +AC_SUBST(TEVENT_CFLAGS) +AC_SUBST(TEVENT_LIBS) + +TEVENT_CFLAGS="-I$teventdir" + +TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o" +TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" -SMB_ENABLE(TEVENT_EPOLL, NO) -SMB_ENABLE(TEVENT_AIO, NO) +tevent_cv_aio_support=no AC_CHECK_HEADERS(sys/epoll.h) AC_CHECK_FUNCS(epoll_create) if test x"$ac_cv_header_sys_epoll_h" = x"yes" -a x"$ac_cv_func_epoll_create" = x"yes"; then TEVENT_OBJ="$TEVENT_OBJ tevent_epoll.o" - SMB_ENABLE(TEVENT_EPOLL,YES) AC_DEFINE(HAVE_EPOLL, 1, [Whether epoll available]) - #TODO: remove HAVE_EVENTS_EPOLL and use HAVE_EPOLL - AC_DEFINE(HAVE_EVENTS_EPOLL, 1, [Whether epoll available]) # check for native Linux AIO interface AC_CHECK_HEADERS(libaio.h) - AC_CHECK_LIB_EXT(aio, AIO_LIBS, io_getevents) + AC_CHECK_LIB_EXT(aio, TEVENT_LIBS, io_getevents) if test x"$ac_cv_header_libaio_h" = x"yes" -a x"$ac_cv_lib_ext_aio_io_getevents" = x"yes";then TEVENT_OBJ="$TEVENT_OBJ tevent_aio.o" - SMB_ENABLE(TEVENT_AIO,YES) + tevent_cv_aio_support=yes AC_DEFINE(HAVE_LINUX_AIO, 1, [Whether Linux AIO is available]) fi fi -AC_SUBST(TEVENT_OBJ) -SMB_EXT_LIB(LIBAIO_LINUX, $AIO_LIBS) - -TEVENT_CFLAGS="-I$teventdir" -AC_SUBST(TEVENT_CFLAGS) - -TEVENT_LIBS="$AIO_LIBS" -AC_SUBST(TEVENT_LIBS) - - diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index a969373738..3d71d78397 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -24,9 +24,9 @@ typedef struct { PyObject_HEAD struct tevent_context *ev_ctx; -} PyEventContextObject; +} PyTEventContextObject; -PyAPI_DATA(PyTypeObject) PyEventContext; +PyAPI_DATA(PyTypeObject) PyTEventContext; static PyObject *py_set_default_backend(PyObject *self, PyObject *args) { @@ -34,13 +34,13 @@ static PyObject *py_set_default_backend(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s", &name)) return NULL; - event_set_default_backend(name); + tevent_set_default_backend(name); return Py_None; } static PyObject *py_backend_list(PyObject *self) { - const char **backends = event_backend_list(NULL); + const char **backends = tevent_backend_list(NULL); PyObject *ret; int i, len; @@ -66,28 +66,28 @@ static PyObject *py_event_ctx_new(PyTypeObject *type, PyObject *args, PyObject * const char *kwnames[] = { "name", NULL }; char *name = NULL; struct tevent_context *ev_ctx; - PyEventContextObject *ret; + PyTEventContextObject *ret; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", (char **)kwnames, &name)) return NULL; if (name == NULL) - ev_ctx = event_context_init(NULL); + ev_ctx = tevent_context_init(NULL); else - ev_ctx = event_context_init_byname(NULL, name); + ev_ctx = tevent_context_init_byname(NULL, name); - ret = (PyEventContextObject *)type->tp_alloc(type, 0); + ret = (PyTEventContextObject *)type->tp_alloc(type, 0); ret->ev_ctx = ev_ctx; return (PyObject *)ret; } -static PyObject *py_event_ctx_loop_once(PyEventContextObject *self) +static PyObject *py_event_ctx_loop_once(PyTEventContextObject *self) { - return PyInt_FromLong(event_loop_once(self->ev_ctx)); + return PyInt_FromLong(tevent_loop_once(self->ev_ctx)); } -static PyObject *py_event_ctx_loop_wait(PyEventContextObject *self) +static PyObject *py_event_ctx_loop_wait(PyTEventContextObject *self) { - return PyInt_FromLong(event_loop_wait(self->ev_ctx)); + return PyInt_FromLong(tevent_loop_wait(self->ev_ctx)); } static PyMethodDef py_event_ctx_methods[] = { @@ -98,16 +98,17 @@ static PyMethodDef py_event_ctx_methods[] = { { NULL } }; -static void py_event_ctx_dealloc(PyEventContextObject * self) +static void py_event_ctx_dealloc(PyTEventContextObject * self) { talloc_free(self->ev_ctx); self->ob_type->tp_free(self); } -PyTypeObject PyEventContext = { - .tp_name = "EventContext", + +PyTypeObject PyTEventContext = { + .tp_name = "TEventContext", .tp_methods = py_event_ctx_methods, - .tp_basicsize = sizeof(PyEventContextObject), + .tp_basicsize = sizeof(PyTEventContextObject), .tp_dealloc = (destructor)py_event_ctx_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = py_event_ctx_new, @@ -117,14 +118,14 @@ void inittevent(void) { PyObject *m; - if (PyType_Ready(&PyEventContext) < 0) + if (PyType_Ready(&PyTEventContext) < 0) return; m = Py_InitModule3("tevent", tevent_methods, "Event management."); if (m == NULL) return; - Py_INCREF(&PyEventContext); - PyModule_AddObject(m, "EventContext", (PyObject *)&PyEventContext); + Py_INCREF(&PyTEventContext); + PyModule_AddObject(m, "TEventContext", (PyObject *)&PyTEventContext); } diff --git a/lib/tevent/samba.m4 b/lib/tevent/samba.m4 new file mode 100644 index 0000000000..89b0b705b4 --- /dev/null +++ b/lib/tevent/samba.m4 @@ -0,0 +1,16 @@ + +teventdir="\$(libteventsrcdir)" +m4_include(../lib/tevent/libtevent.m4) + +SMB_EXT_LIB(LIBTEVENT_EXT, [${TEVENT_LIBS}]) +SMB_ENABLE(LIBTEVENT_EXT) + +SMB_SUBSYSTEM(LIBTEVENT, + [\$(addprefix \$(libteventsrcdir)/, ${TEVENT_OBJ})], + [LIBTEVENT_EXT], + [${TEVENT_CFLAGS}]) + +SMB_MAKE_SETTINGS([ +PUBLIC_HEADERS += \$(addprefix \$(libteventsrcdir)/, tevent.h tevent_internal.h) +]) + diff --git a/lib/tevent/tests.py b/lib/tevent/tests.py index 0ec736b359..bf594a14f6 100644 --- a/lib/tevent/tests.py +++ b/lib/tevent/tests.py @@ -17,15 +17,15 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import tevent as events +import tevent import unittest # Just test the bindings are there and that calling them doesn't crash # anything. -class EventTestCase(unittest.TestCase): +class TEventTestCase(unittest.TestCase): def test_create(self): - self.assertTrue(events.EventContext() is not None) + self.assertTrue(tevent.TEventContext() is not None) def test_loop_wait(self): - self.assertEquals(0, events.EventContext().loop_wait()) + self.assertEquals(0, tevent.TEventContext().loop_wait()) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index ec57c5ad2e..1b811f5fa2 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -81,8 +81,9 @@ static bool test_event_context(struct torture_context *test, /* create a pipe */ pipe(fd); - fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE, + fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ, fde_handler, fd); + tevent_fd_set_auto_close(fde); event_add_timed(ev_ctx, ev_ctx, timeval_current_ofs(2,0), finished_handler, &finished); diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index e45a690c33..5582b583e7 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -41,52 +41,53 @@ handler to get another event. To setup a set of events you first need to create a event_context - structure using the function event_context_init(); This returns a + structure using the function tevent_context_init(); This returns a 'struct tevent_context' that you use in all subsequent calls. After that you can add/remove events that you are interested in - using event_add_*() and talloc_free() + using tevent_add_*() and talloc_free() - Finally, you call event_loop_wait_once() to block waiting for one of the - events to occor or event_loop_wait() which will loop + Finally, you call tevent_loop_wait_once() to block waiting for one of the + events to occor or tevent_loop_wait() which will loop forever. */ #include "replace.h" +#include "system/filesys.h" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" -struct event_ops_list { - struct event_ops_list *next, *prev; +struct tevent_ops_list { + struct tevent_ops_list *next, *prev; const char *name; - const struct event_ops *ops; + const struct tevent_ops *ops; }; /* list of registered event backends */ -static struct event_ops_list *event_backends = NULL; -static char *event_default_backend = NULL; +static struct tevent_ops_list *tevent_backends = NULL; +static char *tevent_default_backend = NULL; /* register an events backend */ -bool event_register_backend(const char *name, const struct event_ops *ops) +bool tevent_register_backend(const char *name, const struct tevent_ops *ops) { - struct event_ops_list *e; + struct tevent_ops_list *e; - for (e = event_backends; e != NULL; e = e->next) { + for (e = tevent_backends; e != NULL; e = e->next) { if (0 == strcmp(e->name, name)) { /* already registered, skip it */ return true; } } - e = talloc(talloc_autofree_context(), struct event_ops_list); + e = talloc(talloc_autofree_context(), struct tevent_ops_list); if (e == NULL) return false; e->name = name; e->ops = ops; - DLIST_ADD(event_backends, e); + DLIST_ADD(tevent_backends, e); return true; } @@ -94,38 +95,39 @@ bool event_register_backend(const char *name, const struct event_ops *ops) /* set the default event backend */ -void event_set_default_backend(const char *backend) +void tevent_set_default_backend(const char *backend) { - if (event_default_backend) free(event_default_backend); - event_default_backend = strdup(backend); + talloc_free(tevent_default_backend); + tevent_default_backend = talloc_strdup(talloc_autofree_context(), + backend); } /* initialise backends if not already done */ -static void event_backend_init(void) +static void tevent_backend_init(void) { - events_select_init(); - events_standard_init(); -#if HAVE_EVENTS_EPOLL - events_epoll_init(); + tevent_select_init(); + tevent_standard_init(); +#ifdef HAVE_EPOLL + tevent_epoll_init(); #endif -#if HAVE_LINUX_AIO - events_aio_init(); +#ifdef HAVE_LINUX_AIO + tevent_aio_init(); #endif } /* list available backends */ -const char **event_backend_list(TALLOC_CTX *mem_ctx) +const char **tevent_backend_list(TALLOC_CTX *mem_ctx) { const char **list = NULL; - struct event_ops_list *e; + struct tevent_ops_list *e; - event_backend_init(); + tevent_backend_init(); - for (e=event_backends;e;e=e->next) { + for (e=tevent_backends;e;e=e->next) { list = ev_str_list_add(list, e->name); } @@ -143,10 +145,10 @@ const char **event_backend_list(TALLOC_CTX *mem_ctx) This function is for allowing third-party-applications to hook in gluecode to their own event loop code, so that they can make async usage of our client libs - NOTE: use event_context_init() inside of samba! + NOTE: use tevent_context_init() inside of samba! */ -static struct tevent_context *event_context_init_ops(TALLOC_CTX *mem_ctx, - const struct event_ops *ops) +static struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops) { struct tevent_context *ev; int ret; @@ -170,22 +172,23 @@ static struct tevent_context *event_context_init_ops(TALLOC_CTX *mem_ctx, call, and all subsequent calls pass this event_context as the first element. Event handlers also receive this as their first argument. */ -struct tevent_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name) +struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, + const char *name) { - struct event_ops_list *e; + struct tevent_ops_list *e; - event_backend_init(); + tevent_backend_init(); if (name == NULL) { - name = event_default_backend; + name = tevent_default_backend; } if (name == NULL) { name = "standard"; } - for (e=event_backends;e;e=e->next) { + for (e=tevent_backends;e;e=e->next) { if (strcmp(name, e->name) == 0) { - return event_context_init_ops(mem_ctx, e->ops); + return tevent_context_init_ops(mem_ctx, e->ops); } } return NULL; @@ -197,42 +200,74 @@ struct tevent_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char call, and all subsequent calls pass this event_context as the first element. Event handlers also receive this as their first argument. */ -struct tevent_context *event_context_init(TALLOC_CTX *mem_ctx) +struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx) { - return event_context_init_byname(mem_ctx, NULL); + return tevent_context_init_byname(mem_ctx, NULL); } /* add a fd based event return NULL on failure (memory allocation error) - if flags contains EVENT_FD_AUTOCLOSE then the fd will be closed when + if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when the returned fd_event context is freed */ -struct tevent_fd *event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, event_fd_handler_t handler, - void *private_data) +struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { - return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data); + return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data, + handler_name, location); } /* add a disk aio event */ -struct aio_event *event_add_aio(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct iocb *iocb, - event_aio_handler_t handler, - void *private_data) +struct tevent_aio *_tevent_add_aio(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct iocb *iocb, + tevent_aio_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { if (ev->ops->add_aio == NULL) return NULL; - return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data); + return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data, + handler_name, location); +} + +/* + set a close function on the fd event +*/ +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + if (!fde) return; + fde->event_ctx->ops->set_fd_close_fn(fde, close_fn); +} + +static void tevent_fd_auto_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data) +{ + close(fd); +} + +void tevent_fd_set_auto_close(struct tevent_fd *fde) +{ + tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn); } /* return the fd event flags */ -uint16_t event_get_fd_flags(struct tevent_fd *fde) +uint16_t tevent_fd_get_flags(struct tevent_fd *fde) { if (!fde) return 0; return fde->event_ctx->ops->get_fd_flags(fde); @@ -241,22 +276,26 @@ uint16_t event_get_fd_flags(struct tevent_fd *fde) /* set the fd event flags */ -void event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags) { if (!fde) return; fde->event_ctx->ops->set_fd_flags(fde, flags); } /* - add a timed event + add a timer event return NULL on failure */ -struct tevent_timer *event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - struct timeval next_event, - event_timed_handler_t handler, - void *private_data) +struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { - return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data); + return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data, + handler_name, location); } /* @@ -266,19 +305,23 @@ struct tevent_timer *event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ return NULL on failure */ -struct signal_event *event_add_signal(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int signum, - int sa_flags, - event_signal_handler_t handler, - void *private_data) +struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { - return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data); + return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, + handler_name, location); } /* do a single event loop using the events defined in ev */ -int event_loop_once(struct tevent_context *ev) +int tevent_loop_once(struct tevent_context *ev) { return ev->ops->loop_once(ev); } @@ -286,25 +329,7 @@ int event_loop_once(struct tevent_context *ev) /* return on failure or (with 0) if all fd events are removed */ -int event_loop_wait(struct tevent_context *ev) +int tevent_loop_wait(struct tevent_context *ev) { return ev->ops->loop_wait(ev); } - -/* - find an event context that is a parent of the given memory context, - or create a new event context as a child of the given context if - none is found - - This should be used in preference to event_context_init() in places - where you would prefer to use the existing event context if possible - (which is most situations) -*/ -struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx) -{ - struct tevent_context *ev = talloc_find_parent_bytype(mem_ctx, struct tevent_context); - if (ev == NULL) { - ev = event_context_init(mem_ctx); - } - return ev; -} diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index f626de9d12..b57d96f5fb 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -33,59 +33,93 @@ struct tevent_aio; struct tevent_signal; /* event handler types */ -typedef void (*tevent_fd_handler_t)(struct tevent_context *, - struct tevent_fd *, - uint16_t , void *); -typedef void (*tevent_timer_handler_t)(struct tevent_context *, - struct tevent_timer *, - struct timeval , void *); -typedef void (*tevent_signal_handler_t)(struct tevent_context *, - struct tevent_signal *, - int , int, void *, void *); -typedef void (*tevent_aio_handler_t)(struct tevent_context *, - struct tevent_aio *, - int, void *); +typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); +typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data); +typedef void (*tevent_timer_handler_t)(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data); +typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data); +typedef void (*tevent_aio_handler_t)(struct tevent_context *ev, + struct tevent_aio *ae, + int ret, + void *private_data); struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); const char **tevent_backend_list(TALLOC_CTX *mem_ctx); void tevent_set_default_backend(const char *backend); -struct tevent_fd *tevent_add_fd(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - tevent_fd_handler_t handler, - void *private_data); - -struct tevent_timer *tevent_add_timer(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct timeval next_event, - tevent_timer_handler_t handler, - void *private_data); - -struct tevent_signal *tevent_add_signal(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - int signum, int sa_flags, - tevent_signal_handler_t handler, - void *private_data); +struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ + _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ + #handler, __location__) + +struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) \ + _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ + #handler, __location__); + +struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ + _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ + #handler, __location__) struct iocb; -struct tevent_aio *tevent_add_aio(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct iocb *iocb, - tevent_aio_handler_t handler, - void *private_data); +struct tevent_aio *_tevent_add_aio(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct iocb *iocb, + tevent_aio_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_add_aio(ev, mem_ctx, iocb, handler, private_data) \ + _tevent_add_aio(ev, mem_ctx, iocb, handler, private_data, \ + #handler, __location__); int tevent_loop_once(struct tevent_context *ev); int tevent_loop_wait(struct tevent_context *ev); +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); +void tevent_fd_set_auto_close(struct tevent_fd *fde); uint16_t tevent_fd_get_flags(struct tevent_fd *fde); void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); /* bits for file descriptor event flags */ #define TEVENT_FD_READ 1 #define TEVENT_FD_WRITE 2 -#define TEVENT_FD_AUTOCLOSE 4 #define TEVENT_FD_WRITEABLE(fde) \ tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_WRITE) @@ -97,10 +131,21 @@ void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); #define TEVENT_FD_NOT_READABLE(fde) \ tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) -/* for now always define the compat symbols */ -#ifndef TEVENT_COMPAT_DEFINES -#define TEVENT_COMPAT_DEFINES 1 -#endif +/* DEBUG */ +enum tevent_debug_level { + TEVENT_DEBUG_FATAL, + TEVENT_DEBUG_ERROR, + TEVENT_DEBUG_WARNING, + TEVENT_DEBUG_TRACE +}; + +int tevent_set_debug(struct tevent_context *ev, + void (*debug)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context); +int tevent_set_debug_stderr(struct tevent_context *ev); #ifdef TEVENT_COMPAT_DEFINES @@ -154,7 +199,6 @@ void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); #define EVENT_FD_READ TEVENT_FD_READ #define EVENT_FD_WRITE TEVENT_FD_WRITE -#define EVENT_FD_AUTOCLOSE TEVENT_FD_AUTOCLOSE #define EVENT_FD_WRITEABLE(fde) \ TEVENT_FD_WRITEABLE(fde) @@ -168,6 +212,18 @@ void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); #define EVENT_FD_NOT_READABLE(fde) \ TEVENT_FD_NOT_READABLE(fde) +#define ev_debug_level tevent_debug_level + +#define EV_DEBUG_FATAL TEVENT_DEBUG_FATAL +#define EV_DEBUG_ERROR TEVENT_DEBUG_ERROR +#define EV_DEBUG_WARNING TEVENT_DEBUG_WARNING +#define EV_DEBUG_TRACE TEVENT_DEBUG_TRACE + +#define ev_set_debug(ev, debug, context) \ + tevent_set_debug(ev, debug, context) + +#define ev_set_debug_stderr(_ev) tevent_set_debug_stderr(ev) + #endif /* TEVENT_COMPAT_DEFINES */ #endif /* __TEVENT_H__ */ diff --git a/lib/tevent/tevent.mk b/lib/tevent/tevent.mk index 6538362a06..be7e298218 100644 --- a/lib/tevent/tevent.mk +++ b/lib/tevent/tevent.mk @@ -1,11 +1,12 @@ -TEVENT_SONAME = libtevent.$(SHLIBEXT).0 -TEVENT_SOLIB = libtevent.$(SHLIBEXT).$(PACKAGE_VERSION) +TEVENT_SOBASE = libtevent.$(SHLIBEXT) +TEVENT_SONAME = $(TEVENT_SOBASE).0 +TEVENT_SOLIB = $(TEVENT_SOBASE).$(PACKAGE_VERSION) TEVENT_STLIB = libtevent.a $(TEVENT_STLIB): $(TEVENT_OBJ) ar -rv $(TEVENT_STLIB) $(TEVENT_OBJ) -libtevent.$(SHLIBEXT): $(TEVENT_SOLIB) +$(TEVENT_SOBASE): $(TEVENT_SOLIB) ln -fs $< $@ $(TEVENT_SONAME): $(TEVENT_SOLIB) @@ -31,7 +32,7 @@ installlibs:: installdirs install:: all installdirs installheaders installlibs $(PYTHON_INSTALL_TARGET) clean:: - rm -f $(TEVENT_SONAME) $(TEVENT_SOLIB) $(TEVENT_STLIB) libtevent.$(SHLIBEXT) + rm -f $(TEVENT_SOBASE) $(TEVENT_SONAME) $(TEVENT_SOLIB) $(TEVENT_STLIB) rm -f tevent.pc rm -f tevent.$(SHLIBEXT) @@ -45,7 +46,7 @@ build-python:: tevent.$(SHLIBEXT) pytevent.o: $(teventdir)/pytevent.c $(CC) $(PICFLAG) -c $(teventdir)/pytevent.c $(CFLAGS) `$(PYTHON_CONFIG) --cflags` -tevent.$(SHLIBEXT): libtevent.$(SHLIBEXT) pytevent.o +tevent.$(SHLIBEXT): $(TEVENT_SOBASE) $(TEVENT_SONAME) pytevent.o $(SHLD) $(SHLD_FLAGS) -o $@ pytevent.o -L. -ltevent `$(PYTHON_CONFIG) --libs` install-python:: build-python diff --git a/lib/tevent/tevent.pc.in b/lib/tevent/tevent.pc.in index afd9fcc279..93d0cf5d8b 100644 --- a/lib/tevent/tevent.pc.in +++ b/lib/tevent/tevent.pc.in @@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: events +Name: tevent Description: An event system library Version: @PACKAGE_VERSION@ Libs: -L${libdir} -ltevent diff --git a/lib/tevent/tevent_aio.c b/lib/tevent/tevent_aio.c index 746e96060b..b15dab3aaf 100644 --- a/lib/tevent/tevent_aio.c +++ b/lib/tevent/tevent_aio.c @@ -30,12 +30,12 @@ this is _very_ experimental code */ -#include "system/filesys.h" #include "replace.h" +#include "system/filesys.h" +#include "system/select.h" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" -#include <sys/epoll.h> #include <libaio.h> #define MAX_AIO_QUEUE_DEPTH 100 @@ -66,11 +66,11 @@ struct aio_event_context { pid_t pid; }; -struct aio_event { +struct tevent_aio { struct tevent_context *event_ctx; struct iocb iocb; void *private_data; - event_aio_handler_t handler; + tevent_aio_handler_t handler; }; /* @@ -79,8 +79,8 @@ struct aio_event { static uint32_t epoll_map_flags(uint16_t flags) { uint32_t ret = 0; - if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); - if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); return ret; } @@ -113,7 +113,8 @@ static void epoll_check_reopen(struct aio_event_context *aio_ev) close(aio_ev->epoll_fd); aio_ev->epoll_fd = epoll_create(MAX_AIO_QUEUE_DEPTH); if (aio_ev->epoll_fd == -1) { - ev_debug(aio_ev->ev, EV_DEBUG_FATAL, "Failed to recreate epoll handle after fork\n"); + tevent_debug(aio_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to recreate epoll handle after fork\n"); return; } aio_ev->pid = getpid(); @@ -146,7 +147,7 @@ static void epoll_add_event(struct aio_event_context *aio_ev, struct tevent_fd * fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -191,7 +192,7 @@ static void epoll_mod_event(struct aio_event_context *aio_ev, struct tevent_fd * epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event); /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -199,8 +200,8 @@ static void epoll_mod_event(struct aio_event_context *aio_ev, struct tevent_fd * static void epoll_change_event(struct aio_event_context *aio_ev, struct tevent_fd *fde) { bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); - bool want_read = (fde->flags & EVENT_FD_READ); - bool want_write= (fde->flags & EVENT_FD_WRITE); + bool want_read = (fde->flags & TEVENT_FD_READ); + bool want_write= (fde->flags & TEVENT_FD_WRITE); if (aio_ev->epoll_fd == -1) return; @@ -260,7 +261,7 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval if (aio_ev->epoll_fd == -1) return -1; if (aio_ev->ev->num_signal_handlers && - common_event_check_signal(aio_ev->ev)) { + tevent_common_check_signal(aio_ev->ev)) { return 0; } @@ -278,14 +279,14 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval if (ret == -EINTR) { if (aio_ev->ev->num_signal_handlers) { - common_event_check_signal(aio_ev->ev); + tevent_common_check_signal(aio_ev->ev); } return 0; } if (ret == 0 && tvalp) { /* we don't care about a possible delay here */ - common_event_loop_timer_delay(aio_ev->ev); + tevent_common_loop_timer_delay(aio_ev->ev); return 0; } @@ -296,8 +297,8 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval switch (finished->aio_lio_opcode) { case IO_CMD_PWRITE: case IO_CMD_PREAD: { - struct aio_event *ae = talloc_get_type(finished->data, - struct aio_event); + struct tevent_aio *ae = talloc_get_type(finished->data, + struct tevent_aio); if (ae) { talloc_set_destructor(ae, NULL); ae->handler(ae->event_ctx, ae, @@ -326,10 +327,10 @@ static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tval epoll_del_event(aio_ev, fde); continue; } - flags |= EVENT_FD_READ; + flags |= TEVENT_FD_READ; } - if (ep->events & EPOLLIN) flags |= EVENT_FD_READ; - if (ep->events & EPOLLOUT) flags |= EVENT_FD_WRITE; + if (ep->events & EPOLLIN) flags |= TEVENT_FD_READ; + if (ep->events & EPOLLOUT) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(aio_ev->ev, fde, flags, fde->private_data); } @@ -398,8 +399,8 @@ static int aio_event_fd_destructor(struct tevent_fd *fde) epoll_del_event(aio_ev, fde); - if (fde->flags & EVENT_FD_AUTOCLOSE) { - close(fde->fd); + if (fde->close_fn) { + fde->close_fn(ev, fde, fde->fd, fde->private_data); fde->fd = -1; } @@ -411,9 +412,11 @@ static int aio_event_fd_destructor(struct tevent_fd *fde) return NULL on failure (memory allocation error) */ static struct tevent_fd *aio_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - event_fd_handler_t handler, - void *private_data) + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data, struct aio_event_context); @@ -428,7 +431,10 @@ static struct tevent_fd *aio_event_add_fd(struct tevent_context *ev, TALLOC_CTX fde->fd = fd; fde->flags = flags; fde->handler = handler; + fde->close_fn = NULL; fde->private_data = private_data; + fde->handler_name = handler_name; + fde->location = location; fde->additional_flags = 0; fde->additional_data = NULL; @@ -441,15 +447,6 @@ static struct tevent_fd *aio_event_add_fd(struct tevent_context *ev, TALLOC_CTX return fde; } - -/* - return the fd event flags -*/ -static uint16_t aio_event_get_fd_flags(struct tevent_fd *fde) -{ - return fde->flags; -} - /* set the fd event flags */ @@ -479,7 +476,7 @@ static int aio_event_loop_once(struct tevent_context *ev) struct aio_event_context); struct timeval tval; - tval = common_event_loop_timer_delay(ev); + tval = tevent_common_loop_timer_delay(ev); if (ev_timeval_is_zero(&tval)) { return 0; } @@ -508,7 +505,7 @@ static int aio_event_loop_wait(struct tevent_context *ev) /* called when a disk IO event needs to be cancelled */ -static int aio_destructor(struct aio_event *ae) +static int aio_destructor(struct tevent_aio *ae) { struct tevent_context *ev = ae->event_ctx; struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data, @@ -520,16 +517,18 @@ static int aio_destructor(struct aio_event *ae) } /* submit an aio disk IO event */ -static struct aio_event *aio_event_add_aio(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct iocb *iocb, - event_aio_handler_t handler, - void *private_data) +static struct tevent_aio *aio_event_add_aio(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct iocb *iocb, + tevent_aio_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data, struct aio_event_context); struct iocb *iocbp; - struct aio_event *ae = talloc(mem_ctx?mem_ctx:ev, struct aio_event); + struct tevent_aio *ae = talloc(mem_ctx?mem_ctx:ev, struct tevent_aio); if (ae == NULL) return NULL; ae->event_ctx = ev; @@ -548,20 +547,21 @@ static struct aio_event *aio_event_add_aio(struct tevent_context *ev, return ae; } -static const struct event_ops aio_event_ops = { +static const struct tevent_ops aio_event_ops = { .context_init = aio_event_context_init, .add_fd = aio_event_add_fd, .add_aio = aio_event_add_aio, - .get_fd_flags = aio_event_get_fd_flags, + .set_fd_close_fn= tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, .set_fd_flags = aio_event_set_fd_flags, - .add_timer = common_event_add_timed, - .add_signal = common_event_add_signal, + .add_timer = tevent_common_add_timer, + .add_signal = tevent_common_add_signal, .loop_once = aio_event_loop_once, .loop_wait = aio_event_loop_wait, }; -bool events_aio_init(void) +bool tevent_aio_init(void) { - return event_register_backend("aio", &aio_event_ops); + return tevent_register_backend("aio", &aio_event_ops); } diff --git a/lib/tevent/tevent_debug.c b/lib/tevent/tevent_debug.c index 4fa58534b4..841446bf6c 100644 --- a/lib/tevent/tevent_debug.c +++ b/lib/tevent/tevent_debug.c @@ -30,10 +30,12 @@ /* this allows the user to choose their own debug function */ -int ev_set_debug(struct tevent_context *ev, - void (*debug)(void *context, enum ev_debug_level level, - const char *fmt, va_list ap), - void *context) +int tevent_set_debug(struct tevent_context *ev, + void (*debug)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context) { ev->debug_ops.debug = debug; ev->debug_ops.context = context; @@ -43,23 +45,26 @@ int ev_set_debug(struct tevent_context *ev, /* debug function for ev_set_debug_stderr */ -void ev_debug_stderr(void *context, enum ev_debug_level level, - const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); -void ev_debug_stderr(void *context, enum ev_debug_level level, - const char *fmt, va_list ap) +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, va_list ap) { - if (level <= EV_DEBUG_WARNING) { + if (level <= TEVENT_DEBUG_WARNING) { vfprintf(stderr, fmt, ap); } } /* convenience function to setup debug messages on stderr - messages of level EV_DEBUG_WARNING and higher are printed + messages of level TEVENT_DEBUG_WARNING and higher are printed */ -int ev_set_debug_stderr(struct tevent_context *ev) +int tevent_set_debug_stderr(struct tevent_context *ev) { - return ev_set_debug(ev, ev_debug_stderr, ev); + return tevent_set_debug(ev, tevent_debug_stderr, ev); } /* @@ -70,7 +75,8 @@ int ev_set_debug_stderr(struct tevent_context *ev) * Applications using the library must decide where to * redirect debugging messages */ -void ev_debug(struct tevent_context *ev, enum ev_debug_level level, const char *fmt, ...) +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) { va_list ap; if (ev->debug_ops.debug == NULL) { diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 1ce666462c..3835774349 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -22,11 +22,10 @@ #include "replace.h" #include "system/filesys.h" -#include "system/network.h" +#include "system/select.h" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" -#include <sys/epoll.h> struct epoll_event_context { /* a pointer back to the generic event_context */ @@ -58,19 +57,19 @@ struct epoll_event_context { */ static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason) { - ev_debug(epoll_ev->ev, EV_DEBUG_FATAL, + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, "%s (%s) - calling abort()\n", reason, strerror(errno)); abort(); } /* - map from EVENT_FD_* to EPOLLIN/EPOLLOUT + map from TEVENT_FD_* to EPOLLIN/EPOLLOUT */ static uint32_t epoll_map_flags(uint16_t flags) { uint32_t ret = 0; - if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); - if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); return ret; } @@ -116,8 +115,8 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) close(epoll_ev->epoll_fd); epoll_ev->epoll_fd = epoll_create(64); if (epoll_ev->epoll_fd == -1) { - ev_debug(epoll_ev->ev, EV_DEBUG_FATAL, - "Failed to recreate epoll handle after fork\n"); + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to recreate epoll handle after fork\n"); return; } epoll_ev->pid = getpid(); @@ -153,7 +152,7 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -176,9 +175,9 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { - ev_debug(epoll_ev->ev, EV_DEBUG_FATAL, - "epoll_del_event failed! probable early close bug (%s)\n", - strerror(errno)); + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "epoll_del_event failed! probable early close bug (%s)\n", + strerror(errno)); } fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; } @@ -201,7 +200,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ } /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -209,8 +208,8 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); - bool want_read = (fde->flags & EVENT_FD_READ); - bool want_write= (fde->flags & EVENT_FD_WRITE); + bool want_read = (fde->flags & TEVENT_FD_READ); + bool want_write= (fde->flags & TEVENT_FD_WRITE); if (epoll_ev->epoll_fd == -1) return; @@ -258,14 +257,14 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval } if (epoll_ev->ev->num_signal_handlers && - common_event_check_signal(epoll_ev->ev)) { + tevent_common_check_signal(epoll_ev->ev)) { return 0; } ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout); if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) { - if (common_event_check_signal(epoll_ev->ev)) { + if (tevent_common_check_signal(epoll_ev->ev)) { return 0; } } @@ -277,7 +276,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval if (ret == 0 && tvalp) { /* we don't care about a possible delay here */ - common_event_loop_timer_delay(epoll_ev->ev); + tevent_common_loop_timer_delay(epoll_ev->ev); return 0; } @@ -293,7 +292,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval if (events[i].events & (EPOLLHUP|EPOLLERR)) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; /* - * if we only wait for EVENT_FD_WRITE, we should not tell the + * if we only wait for TEVENT_FD_WRITE, we should not tell the * event handler about it, and remove the epoll_event, * as we only report errors when waiting for read events, * to match the select() behavior @@ -302,10 +301,10 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval epoll_del_event(epoll_ev, fde); continue; } - flags |= EVENT_FD_READ; + flags |= TEVENT_FD_READ; } - if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ; - if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE; + if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; + if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(epoll_ev->ev, fde, flags, fde->private_data); if (destruction_count != epoll_ev->destruction_count) { @@ -358,8 +357,8 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) epoll_del_event(epoll_ev, fde); - if (fde->flags & EVENT_FD_AUTOCLOSE) { - close(fde->fd); + if (fde->close_fn) { + fde->close_fn(ev, fde, fde->fd, fde->private_data); fde->fd = -1; } @@ -371,9 +370,11 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) return NULL on failure (memory allocation error) */ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - event_fd_handler_t handler, - void *private_data) + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data, struct epoll_event_context); @@ -388,7 +389,10 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT fde->fd = fd; fde->flags = flags; fde->handler = handler; + fde->close_fn = NULL; fde->private_data = private_data; + fde->handler_name = handler_name; + fde->location = location; fde->additional_flags = 0; fde->additional_data = NULL; @@ -401,15 +405,6 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT return fde; } - -/* - return the fd event flags -*/ -static uint16_t epoll_event_get_fd_flags(struct tevent_fd *fde) -{ - return fde->flags; -} - /* set the fd event flags */ @@ -439,7 +434,7 @@ static int epoll_event_loop_once(struct tevent_context *ev) struct epoll_event_context); struct timeval tval; - tval = common_event_loop_timer_delay(ev); + tval = tevent_common_loop_timer_delay(ev); if (ev_timeval_is_zero(&tval)) { return 0; } @@ -465,18 +460,19 @@ static int epoll_event_loop_wait(struct tevent_context *ev) return 0; } -static const struct event_ops epoll_event_ops = { +static const struct tevent_ops epoll_event_ops = { .context_init = epoll_event_context_init, .add_fd = epoll_event_add_fd, - .get_fd_flags = epoll_event_get_fd_flags, + .set_fd_close_fn= tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, .set_fd_flags = epoll_event_set_fd_flags, - .add_timer = common_event_add_timed, - .add_signal = common_event_add_signal, + .add_timer = tevent_common_add_timer, + .add_signal = tevent_common_add_signal, .loop_once = epoll_event_loop_once, .loop_wait = epoll_event_loop_wait, }; -bool events_epoll_init(void) +bool tevent_epoll_init(void) { - return event_register_backend("epoll", &epoll_event_ops); + return tevent_register_backend("epoll", &epoll_event_ops); } diff --git a/lib/tevent/tevent_fd.c b/lib/tevent/tevent_fd.c new file mode 100644 index 0000000000..d450e2168d --- /dev/null +++ b/lib/tevent/tevent_fd.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + + common events code for fd events + + Copyright (C) Stefan Metzmacher 2009 + + 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 "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde) +{ + return fde->flags; +} + +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags) +{ + if (fde->flags == flags) return; + fde->flags = flags; +} + +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + fde->close_fn = close_fn; +} diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 2d6909da36..f29e9c62f5 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -30,7 +30,11 @@ struct tevent_ops { TALLOC_CTX *mem_ctx, int fd, uint16_t flags, tevent_fd_handler_t handler, - void *private_data); + void *private_data, + const char *handler_name, + const char *location); + void (*set_fd_close_fn)(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); uint16_t (*get_fd_flags)(struct tevent_fd *fde); void (*set_fd_flags)(struct tevent_fd *fde, uint16_t flags); @@ -39,19 +43,25 @@ struct tevent_ops { TALLOC_CTX *mem_ctx, struct timeval next_event, tevent_timer_handler_t handler, - void *private_data); + void *private_data, + const char *handler_name, + const char *location); /* disk aio event functions */ struct tevent_aio *(*add_aio)(struct tevent_context *ev, TALLOC_CTX *mem_ctx, struct iocb *iocb, tevent_aio_handler_t handler, - void *private_data); + void *private_data, + const char *handler_name, + const char *location); /* signal functions */ struct tevent_signal *(*add_signal)(struct tevent_context *ev, TALLOC_CTX *mem_ctx, int signum, int sa_flags, tevent_signal_handler_t handler, - void *private_data); + void *private_data, + const char *handler_name, + const char *location); /* loop functions */ int (*loop_once)(struct tevent_context *ev); @@ -62,10 +72,14 @@ struct tevent_fd { struct tevent_fd *prev, *next; struct tevent_context *event_ctx; int fd; - uint16_t flags; /* see EVENT_FD_* flags */ + uint16_t flags; /* see TEVENT_FD_* flags */ tevent_fd_handler_t handler; + tevent_fd_close_fn_t close_fn; /* this is private for the specific handler */ void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; /* this is private for the events_ops implementation */ uint16_t additional_flags; void *additional_data; @@ -78,6 +92,9 @@ struct tevent_timer { tevent_timer_handler_t handler; /* this is private for the specific handler */ void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; /* this is private for the events_ops implementation */ void *additional_data; }; @@ -85,28 +102,26 @@ struct tevent_timer { struct tevent_signal { struct tevent_signal *prev, *next; struct tevent_context *event_ctx; - tevent_signal_handler_t handler; - void *private_data; int signum; int sa_flags; + tevent_signal_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + void *additional_data; }; -/* DEBUG */ -enum ev_debug_level {EV_DEBUG_FATAL, EV_DEBUG_ERROR, - EV_DEBUG_WARNING, EV_DEBUG_TRACE}; - -struct ev_debug_ops { - void (*debug)(void *context, enum ev_debug_level level, +struct tevent_debug_ops { + void (*debug)(void *context, enum tevent_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); void *context; }; -int ev_set_debug(struct tevent_context *ev, - void (*debug)(void *context, enum ev_debug_level level, - const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0), - void *context); -int ev_set_debug_stderr(struct tevent_context *ev); -void ev_debug(struct tevent_context *ev, enum ev_debug_level level, const char *fmt, ...); +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); /* aio event is private to the aio backend */ struct tevent_aio; @@ -128,34 +143,42 @@ struct tevent_context { struct tevent_fd *pipe_fde; /* debugging operations */ - struct ev_debug_ops debug_ops; + struct tevent_debug_ops debug_ops; }; -bool event_register_backend(const char *name, const struct tevent_ops *ops); +bool tevent_register_backend(const char *name, const struct tevent_ops *ops); + +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde); +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags); bool ev_timeval_is_zero(const struct timeval *tv); -struct tevent_timer *common_event_add_timed(struct tevent_context *, - TALLOC_CTX *, - struct timeval, - tevent_timer_handler_t, - void *); -struct timeval common_event_loop_timer_delay(struct tevent_context *); - -struct tevent_signal *common_event_add_signal(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - int signum, - int sa_flags, - tevent_signal_handler_t handler, - void *private_data); -int common_event_check_signal(struct tevent_context *ev); - - -bool events_standard_init(void); -bool events_select_init(void); -#if HAVE_EVENTS_EPOLL -bool events_epoll_init(void); +struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +struct timeval tevent_common_loop_timer_delay(struct tevent_context *); + +struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +int tevent_common_check_signal(struct tevent_context *ev); + +bool tevent_standard_init(void); +bool tevent_select_init(void); +#ifdef HAVE_EPOLL +bool tevent_epoll_init(void); #endif -#if HAVE_LINUX_AIO -bool events_aio_init(void); +#ifdef HAVE_LINUX_AIO +bool tevent_aio_init(void); #endif diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index 3e72ce4943..cf4453f64f 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -103,8 +103,8 @@ static int select_event_fd_destructor(struct tevent_fd *fde) DLIST_REMOVE(select_ev->fd_events, fde); select_ev->destruction_count++; - if (fde->flags & EVENT_FD_AUTOCLOSE) { - close(fde->fd); + if (fde->close_fn) { + fde->close_fn(ev, fde, fde->fd, fde->private_data); fde->fd = -1; } @@ -116,9 +116,11 @@ static int select_event_fd_destructor(struct tevent_fd *fde) return NULL on failure (memory allocation error) */ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - event_fd_handler_t handler, - void *private_data) + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct select_event_context *select_ev = talloc_get_type(ev->additional_data, struct select_event_context); @@ -131,7 +133,10 @@ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_C fde->fd = fd; fde->flags = flags; fde->handler = handler; + fde->close_fn = NULL; fde->private_data = private_data; + fde->handler_name = handler_name; + fde->location = location; fde->additional_flags = 0; fde->additional_data = NULL; @@ -144,31 +149,6 @@ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_C return fde; } - -/* - return the fd event flags -*/ -static uint16_t select_event_get_fd_flags(struct tevent_fd *fde) -{ - return fde->flags; -} - -/* - set the fd event flags -*/ -static void select_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) -{ - struct tevent_context *ev; - struct select_event_context *select_ev; - - if (fde->flags == flags) return; - - ev = fde->event_ctx; - select_ev = talloc_get_type(ev->additional_data, struct select_event_context); - - fde->flags = flags; -} - /* event loop handling using select() */ @@ -189,16 +169,16 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru /* setup any fd events */ for (fde = select_ev->fd_events; fde; fde = fde->next) { - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { FD_SET(fde->fd, &r_fds); } - if (fde->flags & EVENT_FD_WRITE) { + if (fde->flags & TEVENT_FD_WRITE) { FD_SET(fde->fd, &w_fds); } } if (select_ev->ev->num_signal_handlers && - common_event_check_signal(select_ev->ev)) { + tevent_common_check_signal(select_ev->ev)) { return 0; } @@ -206,7 +186,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru if (selrtn == -1 && errno == EINTR && select_ev->ev->num_signal_handlers) { - common_event_check_signal(select_ev->ev); + tevent_common_check_signal(select_ev->ev); return 0; } @@ -216,15 +196,15 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru made readable and that should have removed the event, so this must be a bug. This is a fatal error. */ - ev_debug(select_ev->ev, EV_DEBUG_FATAL, - "ERROR: EBADF on select_event_loop_once\n"); + tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL, + "ERROR: EBADF on select_event_loop_once\n"); select_ev->exit_code = EBADF; return -1; } if (selrtn == 0 && tvalp) { /* we don't care about a possible delay here */ - common_event_loop_timer_delay(select_ev->ev); + tevent_common_loop_timer_delay(select_ev->ev); return 0; } @@ -235,8 +215,8 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru for (fde = select_ev->fd_events; fde; fde = fde->next) { uint16_t flags = 0; - if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ; + if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(select_ev->ev, fde, flags, fde->private_data); if (destruction_count != select_ev->destruction_count) { @@ -258,7 +238,7 @@ static int select_event_loop_once(struct tevent_context *ev) struct select_event_context); struct timeval tval; - tval = common_event_loop_timer_delay(ev); + tval = tevent_common_loop_timer_delay(ev); if (ev_timeval_is_zero(&tval)) { return 0; } @@ -284,19 +264,19 @@ static int select_event_loop_wait(struct tevent_context *ev) return select_ev->exit_code; } -static const struct event_ops select_event_ops = { +static const struct tevent_ops select_event_ops = { .context_init = select_event_context_init, .add_fd = select_event_add_fd, - .get_fd_flags = select_event_get_fd_flags, - .set_fd_flags = select_event_set_fd_flags, - .add_timer = common_event_add_timed, - .add_signal = common_event_add_signal, + .set_fd_close_fn= tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = tevent_common_fd_set_flags, + .add_timer = tevent_common_add_timer, + .add_signal = tevent_common_add_signal, .loop_once = select_event_loop_once, .loop_wait = select_event_loop_wait, }; -bool events_select_init(void) +bool tevent_select_init(void) { - return event_register_backend("select", &select_event_ops); + return tevent_register_backend("select", &select_event_ops); } - diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index bb50480dd7..031845927b 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -19,10 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <signal.h> #include "replace.h" #include "system/filesys.h" -#include "system/select.h" +#include "system/wait.h" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" @@ -46,7 +45,7 @@ struct sigcounter { the poor design of signals means that this table must be static global */ static struct sig_state { - struct signal_event *sig_handlers[NUM_SIGNALS+1]; + struct tevent_signal *sig_handlers[NUM_SIGNALS+1]; struct sigaction *oldact[NUM_SIGNALS+1]; struct sigcounter signal_count[NUM_SIGNALS+1]; struct sigcounter got_signal; @@ -108,7 +107,7 @@ static void signal_handler_info(int signum, siginfo_t *info, void *uctx) /* destroy a signal event */ -static int signal_event_destructor(struct signal_event *se) +static int tevent_signal_destructor(struct tevent_signal *se) { se->event_ctx->num_signal_handlers--; DLIST_REMOVE(sig_state->sig_handlers[se->signum], se); @@ -141,14 +140,16 @@ static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde add a signal event return NULL on failure (memory allocation error) */ -struct signal_event *common_event_add_signal(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - int signum, - int sa_flags, - event_signal_handler_t handler, - void *private_data) +struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { - struct signal_event *se; + struct tevent_signal *se; if (signum >= NUM_SIGNALS) { return NULL; @@ -163,15 +164,18 @@ struct signal_event *common_event_add_signal(struct tevent_context *ev, } } - se = talloc(mem_ctx?mem_ctx:ev, struct signal_event); + se = talloc(mem_ctx?mem_ctx:ev, struct tevent_signal); if (se == NULL) return NULL; se->event_ctx = ev; - se->handler = handler; - se->private_data = private_data; se->signum = signum; se->sa_flags = sa_flags; - + se->handler = handler; + se->private_data = private_data; + se->handler_name = handler_name; + se->location = location; + se->additional_data = NULL; + /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */ if (!talloc_reference(se, sig_state)) { return NULL; @@ -209,7 +213,7 @@ struct signal_event *common_event_add_signal(struct tevent_context *ev, DLIST_ADD(sig_state->sig_handlers[signum], se); - talloc_set_destructor(se, signal_event_destructor); + talloc_set_destructor(se, tevent_signal_destructor); /* we need to setup the pipe hack handler if not already setup */ @@ -220,8 +224,8 @@ struct signal_event *common_event_add_signal(struct tevent_context *ev, ev_set_blocking(sig_state->pipe_hack[0], false); ev_set_blocking(sig_state->pipe_hack[1], false); } - ev->pipe_fde = event_add_fd(ev, ev, sig_state->pipe_hack[0], - EVENT_FD_READ, signal_pipe_handler, NULL); + ev->pipe_fde = tevent_add_fd(ev, ev, sig_state->pipe_hack[0], + TEVENT_FD_READ, signal_pipe_handler, NULL); } ev->num_signal_handlers++; @@ -233,7 +237,7 @@ struct signal_event *common_event_add_signal(struct tevent_context *ev, check if a signal is pending return != 0 if a signal was pending */ -int common_event_check_signal(struct tevent_context *ev) +int tevent_common_check_signal(struct tevent_context *ev) { int i; @@ -242,7 +246,7 @@ int common_event_check_signal(struct tevent_context *ev) } for (i=0;i<NUM_SIGNALS+1;i++) { - struct signal_event *se, *next; + struct tevent_signal *se, *next; struct sigcounter counter = sig_state->signal_count[i]; uint32_t count = sig_count(counter); diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 1c99408b8d..2a292a4c39 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -29,8 +29,7 @@ #include "replace.h" #include "system/filesys.h" -#include "system/network.h" -#include "system/select.h" /* needed for HAVE_EVENTS_EPOLL */ +#include "system/select.h" #include "tevent.h" #include "tevent_util.h" #include "tevent_internal.h" @@ -64,29 +63,29 @@ struct std_event_context { }; /* use epoll if it is available */ -#if HAVE_EVENTS_EPOLL +#if HAVE_EPOLL /* called when a epoll call fails, and we should fallback to using select */ static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason) { - ev_debug(std_ev->ev, EV_DEBUG_FATAL, - "%s (%s) - falling back to select()\n", - reason, strerror(errno)); + tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL, + "%s (%s) - falling back to select()\n", + reason, strerror(errno)); close(std_ev->epoll_fd); std_ev->epoll_fd = -1; talloc_set_destructor(std_ev, NULL); } /* - map from EVENT_FD_* to EPOLLIN/EPOLLOUT + map from TEVENT_FD_* to EPOLLIN/EPOLLOUT */ static uint32_t epoll_map_flags(uint16_t flags) { uint32_t ret = 0; - if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); - if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); return ret; } @@ -130,8 +129,8 @@ static void epoll_check_reopen(struct std_event_context *std_ev) close(std_ev->epoll_fd); std_ev->epoll_fd = epoll_create(64); if (std_ev->epoll_fd == -1) { - ev_debug(std_ev->ev, EV_DEBUG_FATAL, - "Failed to recreate epoll handle after fork\n"); + tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to recreate epoll handle after fork\n"); return; } std_ev->pid = getpid(); @@ -166,7 +165,7 @@ static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd * fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -209,7 +208,7 @@ static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd * } /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } } @@ -217,8 +216,8 @@ static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd * static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde) { bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); - bool want_read = (fde->flags & EVENT_FD_READ); - bool want_write= (fde->flags & EVENT_FD_WRITE); + bool want_read = (fde->flags & TEVENT_FD_READ); + bool want_write= (fde->flags & TEVENT_FD_WRITE); if (std_ev->epoll_fd == -1) return; @@ -266,14 +265,14 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv } if (std_ev->ev->num_signal_handlers && - common_event_check_signal(std_ev->ev)) { + tevent_common_check_signal(std_ev->ev)) { return 0; } ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout); if (ret == -1 && errno == EINTR && std_ev->ev->num_signal_handlers) { - if (common_event_check_signal(std_ev->ev)) { + if (tevent_common_check_signal(std_ev->ev)) { return 0; } } @@ -285,7 +284,7 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv if (ret == 0 && tvalp) { /* we don't care about a possible delay here */ - common_event_loop_timer_delay(std_ev->ev); + tevent_common_loop_timer_delay(std_ev->ev); return 0; } @@ -301,7 +300,7 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv if (events[i].events & (EPOLLHUP|EPOLLERR)) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; /* - * if we only wait for EVENT_FD_WRITE, we should not tell the + * if we only wait for TEVENT_FD_WRITE, we should not tell the * event handler about it, and remove the epoll_event, * as we only report errors when waiting for read events, * to match the select() behavior @@ -310,10 +309,10 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv epoll_del_event(std_ev, fde); continue; } - flags |= EVENT_FD_READ; + flags |= TEVENT_FD_READ; } - if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ; - if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE; + if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; + if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(std_ev->ev, fde, flags, fde->private_data); if (destruction_count != std_ev->destruction_count) { @@ -392,8 +391,8 @@ static int std_event_fd_destructor(struct tevent_fd *fde) epoll_del_event(std_ev, fde); - if (fde->flags & EVENT_FD_AUTOCLOSE) { - close(fde->fd); + if (fde->close_fn) { + fde->close_fn(ev, fde, fde->fd, fde->private_data); fde->fd = -1; } @@ -405,9 +404,11 @@ static int std_event_fd_destructor(struct tevent_fd *fde) return NULL on failure (memory allocation error) */ static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - event_fd_handler_t handler, - void *private_data) + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct std_event_context *std_ev = talloc_get_type(ev->additional_data, struct std_event_context); @@ -422,7 +423,10 @@ static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX fde->fd = fd; fde->flags = flags; fde->handler = handler; + fde->close_fn = NULL; fde->private_data = private_data; + fde->handler_name = handler_name; + fde->location = location; fde->additional_flags = 0; fde->additional_data = NULL; @@ -438,15 +442,6 @@ static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX return fde; } - -/* - return the fd event flags -*/ -static uint16_t std_event_get_fd_flags(struct tevent_fd *fde) -{ - return fde->flags; -} - /* set the fd event flags */ @@ -487,16 +482,16 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva /* setup any fd events */ for (fde = std_ev->fd_events; fde; fde = fde->next) { - if (fde->flags & EVENT_FD_READ) { + if (fde->flags & TEVENT_FD_READ) { FD_SET(fde->fd, &r_fds); } - if (fde->flags & EVENT_FD_WRITE) { + if (fde->flags & TEVENT_FD_WRITE) { FD_SET(fde->fd, &w_fds); } } if (std_ev->ev->num_signal_handlers && - common_event_check_signal(std_ev->ev)) { + tevent_common_check_signal(std_ev->ev)) { return 0; } @@ -504,7 +499,7 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva if (selrtn == -1 && errno == EINTR && std_ev->ev->num_signal_handlers) { - common_event_check_signal(std_ev->ev); + tevent_common_check_signal(std_ev->ev); return 0; } @@ -514,15 +509,15 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva made readable and that should have removed the event, so this must be a bug. This is a fatal error. */ - ev_debug(std_ev->ev, EV_DEBUG_FATAL, - "ERROR: EBADF on std_event_loop_once\n"); + tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL, + "ERROR: EBADF on std_event_loop_once\n"); std_ev->exit_code = EBADF; return -1; } if (selrtn == 0 && tvalp) { /* we don't care about a possible delay here */ - common_event_loop_timer_delay(std_ev->ev); + tevent_common_loop_timer_delay(std_ev->ev); return 0; } @@ -533,8 +528,8 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva for (fde = std_ev->fd_events; fde; fde = fde->next) { uint16_t flags = 0; - if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ; + if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(std_ev->ev, fde, flags, fde->private_data); if (destruction_count != std_ev->destruction_count) { @@ -556,7 +551,7 @@ static int std_event_loop_once(struct tevent_context *ev) struct std_event_context); struct timeval tval; - tval = common_event_loop_timer_delay(ev); + tval = tevent_common_loop_timer_delay(ev); if (ev_timeval_is_zero(&tval)) { return 0; } @@ -588,20 +583,21 @@ static int std_event_loop_wait(struct tevent_context *ev) return std_ev->exit_code; } -static const struct event_ops std_event_ops = { +static const struct tevent_ops std_event_ops = { .context_init = std_event_context_init, .add_fd = std_event_add_fd, - .get_fd_flags = std_event_get_fd_flags, + .set_fd_close_fn= tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, .set_fd_flags = std_event_set_fd_flags, - .add_timer = common_event_add_timed, - .add_signal = common_event_add_signal, + .add_timer = tevent_common_add_timer, + .add_signal = tevent_common_add_signal, .loop_once = std_event_loop_once, .loop_wait = std_event_loop_wait, }; -bool events_standard_init(void) +bool tevent_standard_init(void) { - return event_register_backend("standard", &std_event_ops); + return tevent_register_backend("standard", &std_event_ops); } diff --git a/lib/tevent/tevent_timed.c b/lib/tevent/tevent_timed.c index ce3fc8eb00..dadd360416 100644 --- a/lib/tevent/tevent_timed.c +++ b/lib/tevent/tevent_timed.c @@ -20,11 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sys/time.h> -#include <time.h> #include "replace.h" -#include "system/filesys.h" -#include "system/select.h" +#include "system/time.h" #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" @@ -109,7 +106,7 @@ bool ev_timeval_is_zero(const struct timeval *tv) /* destroy a timed event */ -static int common_event_timed_destructor(struct tevent_timer *te) +static int tevent_common_timed_destructor(struct tevent_timer *te) { struct tevent_context *ev = talloc_get_type(te->event_ctx, struct tevent_context); @@ -117,7 +114,7 @@ static int common_event_timed_destructor(struct tevent_timer *te) return 0; } -static int common_event_timed_deny_destructor(struct tevent_timer *te) +static int tevent_common_timed_deny_destructor(struct tevent_timer *te) { return -1; } @@ -126,10 +123,12 @@ static int common_event_timed_deny_destructor(struct tevent_timer *te) add a timed event return NULL on failure (memory allocation error) */ -struct tevent_timer *common_event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - struct timeval next_event, - event_timed_handler_t handler, - void *private_data) +struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { struct tevent_timer *te, *last_te, *cur_te; @@ -140,6 +139,8 @@ struct tevent_timer *common_event_add_timed(struct tevent_context *ev, TALLOC_CT te->next_event = next_event; te->handler = handler; te->private_data = private_data; + te->handler_name = handler_name; + te->location = location; te->additional_data = NULL; /* keep the list ordered */ @@ -155,7 +156,7 @@ struct tevent_timer *common_event_add_timed(struct tevent_context *ev, TALLOC_CT DLIST_ADD_AFTER(ev->timer_events, te, last_te); - talloc_set_destructor(te, common_event_timed_destructor); + talloc_set_destructor(te, tevent_common_timed_destructor); return te; } @@ -166,7 +167,7 @@ struct tevent_timer *common_event_add_timed(struct tevent_context *ev, TALLOC_CT return the delay untill the next timed event, or zero if a timed event was triggered */ -struct timeval common_event_loop_timer_delay(struct tevent_context *ev) +struct timeval tevent_common_loop_timer_delay(struct tevent_context *ev) { struct timeval current_time = ev_timeval_zero(); struct tevent_timer *te = ev->timer_events; @@ -203,7 +204,7 @@ struct timeval common_event_loop_timer_delay(struct tevent_context *ev) */ /* deny the handler to free the event */ - talloc_set_destructor(te, common_event_timed_deny_destructor); + talloc_set_destructor(te, tevent_common_timed_deny_destructor); /* We need to remove the timer from the list before calling the * handler because in a semi-async inner event loop called from the diff --git a/librpc/gen_ndr/named_pipe_auth.h b/librpc/gen_ndr/named_pipe_auth.h index 87d4bfd712..7ca7444c92 100644 --- a/librpc/gen_ndr/named_pipe_auth.h +++ b/librpc/gen_ndr/named_pipe_auth.h @@ -19,6 +19,7 @@ struct named_pipe_auth_req { }/* [gensize,public] */; union named_pipe_auth_rep_info { + int _dummy_element; }/* [switch_type(uint32)] */; struct named_pipe_auth_rep { diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c index 921af15dae..97f75051b7 100644 --- a/librpc/ndr/ndr_basic.c +++ b/librpc/ndr/ndr_basic.c @@ -757,7 +757,7 @@ _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, ndr->depth++; for (i=0;i<count;i++) { char *idx=NULL; - if (asprintf(&idx, "[%d]", i) == -1) { + if (asprintf(&idx, "[%d]", i) != -1) { ndr_print_uint8(ndr, idx, data[i]); free(idx); } diff --git a/packaging/RHEL/samba.spec.tmpl b/packaging/RHEL/samba.spec.tmpl index 92030fcd6b..f674e8386c 100644 --- a/packaging/RHEL/samba.spec.tmpl +++ b/packaging/RHEL/samba.spec.tmpl @@ -178,12 +178,6 @@ fi make CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE" %{?_smp_mflags} \ all modules pam_smbpass -## build the cifs fs mount helper -cd client -gcc -o mount.cifs $RPM_OPT_FLAGS -D_GNU_SOURCE -Wall -D_GNU_SOURCE -D_LARGEFILE64_SOURCE mount.cifs.c -gcc -o umount.cifs $RPM_OPT_FLAGS -D_GNU_SOURCE -Wall -D_GNU_SOURCE -D_LARGEFILE64_SOURCE umount.cifs.c -cd .. - # Remove some permission bits to avoid to many dependencies cd .. find examples docs -type f | xargs -r chmod -x @@ -238,8 +232,8 @@ install -m644 setup/samba.pamd $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/samba install -m755 setup/smbprint $RPM_BUILD_ROOT%{_bindir} install -m644 setup/smbusers $RPM_BUILD_ROOT%{_sysconfdir}/samba/smbusers install -m644 setup/smb.conf $RPM_BUILD_ROOT%{_sysconfdir}/samba/smb.conf -install -m755 source/client/mount.cifs $RPM_BUILD_ROOT/sbin/mount.cifs -install -m755 source/client/umount.cifs $RPM_BUILD_ROOT/sbin/umount.cifs +install -m755 source/bin/mount.cifs $RPM_BUILD_ROOT/sbin/mount.cifs +install -m755 source/bin/umount.cifs $RPM_BUILD_ROOT/sbin/umount.cifs install -m755 source/script/mksmbpasswd.sh $RPM_BUILD_ROOT%{_bindir} /bin/rm $RPM_BUILD_ROOT%{_sbindir}/*mount.cifs diff --git a/pidl/lib/Parse/Pidl/Samba4/Header.pm b/pidl/lib/Parse/Pidl/Samba4/Header.pm index 94e1efbfe4..0411466c82 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Header.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Header.pm @@ -183,14 +183,20 @@ sub HeaderUnion($$;$) return if (not defined($union->{ELEMENTS})); pidl " {\n"; $tab_depth++; + my $needed = 0; foreach my $e (@{$union->{ELEMENTS}}) { if ($e->{TYPE} ne "EMPTY") { if (! defined $done{$e->{NAME}}) { HeaderElement($e); } $done{$e->{NAME}} = 1; + $needed++; } } + if (!$needed) { + # sigh - some compilers don't like empty structures + pidl tabs()."int _dummy_element;\n"; + } $tab_depth--; pidl "}"; diff --git a/source3/Makefile.in b/source3/Makefile.in index 49f576f507..c13f5ae20a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -930,6 +930,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ + lib/wb_reqtrans.o lib/wbclient.o \ $(LIBNDR_GEN_OBJ0) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ @@ -1029,7 +1030,6 @@ IDMAP_ADEX_OBJ = \ WINBINDD_OBJ1 = \ winbindd/winbindd.o \ - winbindd/winbindd_reqtrans.o \ winbindd/winbindd_user.o \ winbindd/winbindd_group.o \ winbindd/winbindd_util.o \ diff --git a/source3/autogen.sh b/source3/autogen.sh index 61316a8f70..1a33eb22cc 100755 --- a/source3/autogen.sh +++ b/source3/autogen.sh @@ -4,11 +4,11 @@ while true; do case $1 in - (--version-file) + --version-file) VERSION_FILE=$2 shift 2 ;; - (*) + *) break ;; esac diff --git a/source3/client/client.c b/source3/client/client.c index c63921aa1a..529f21ab30 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -78,6 +78,7 @@ static bool showacls = false; bool lowercase = false; static struct sockaddr_storage dest_ss; +static char dest_ss_str[INET6_ADDRSTRLEN]; #define SEPARATORS " \t\n\r" @@ -4043,7 +4044,8 @@ static int process_command_string(const char *cmd_in) /* establish the connection if not already */ if (!cli) { - cli = cli_cm_open(talloc_tos(), NULL, desthost, + cli = cli_cm_open(talloc_tos(), NULL, + have_ip ? dest_ss_str : desthost, service, true, smb_encrypt); if (!cli) { return 1; @@ -4508,7 +4510,8 @@ static int process(const char *base_directory) int rc = 0; cli = cli_cm_open(talloc_tos(), NULL, - desthost, service, true, smb_encrypt); + have_ip ? dest_ss_str : desthost, + service, true, smb_encrypt); if (!cli) { return 1; } @@ -4586,7 +4589,8 @@ static int do_tar_op(const char *base_directory) /* do we already have a connection? */ if (!cli) { cli = cli_cm_open(talloc_tos(), NULL, - desthost, service, true, smb_encrypt); + have_ip ? dest_ss_str : desthost, + service, true, smb_encrypt); if (!cli) return 1; } @@ -4792,8 +4796,7 @@ static int do_message_op(struct user_auth_info *auth_info) exit(1); } have_ip = true; - - cli_cm_set_dest_ss(&dest_ss); + print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss); } break; case 'E': diff --git a/source3/include/async_req.h b/source3/include/async_req.h index 14a30696c4..1b8dbf3346 100644 --- a/source3/include/async_req.h +++ b/source3/include/async_req.h @@ -97,13 +97,6 @@ struct async_req { NTSTATUS status; /** - * @brief The event context we are using - * - * The event context that this async request works on. - */ - struct event_context *event_ctx; - - /** * @brief What to do on completion * * This is used for the user of an async request, fn is called when @@ -122,7 +115,7 @@ struct async_req { } async; }; -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev); +struct async_req *async_req_new(TALLOC_CTX *mem_ctx); char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req); @@ -130,7 +123,8 @@ void async_req_done(struct async_req *req); void async_req_error(struct async_req *req, NTSTATUS status); -bool async_post_status(struct async_req *req, NTSTATUS status); +bool async_post_status(struct async_req *req, struct event_context *ev, + NTSTATUS status); bool async_req_nomem(const void *p, struct async_req *req); @@ -138,4 +132,22 @@ bool async_req_is_error(struct async_req *req, NTSTATUS *status); NTSTATUS async_req_simple_recv(struct async_req *req); +bool async_req_set_timeout(struct async_req *req, struct event_context *ev, + struct timeval to); + +struct async_req *async_wait_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval to); + +NTSTATUS async_wait_recv(struct async_req *req); + +struct async_req_queue; + +struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx); + +bool async_req_enqueue(struct async_req_queue *queue, + struct event_context *ev, + struct async_req *req, + void (*trigger)(struct async_req *req)); + #endif diff --git a/source3/include/async_sock.h b/source3/include/async_sock.h index f0cd5fdaa4..c6f95d64d5 100644 --- a/source3/include/async_sock.h +++ b/source3/include/async_sock.h @@ -24,7 +24,7 @@ ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno); size_t async_syscall_result_size_t(struct async_req *req, int *perrno); -ssize_t async_syscall_result_int(struct async_req *req, int *perrno); +int async_syscall_result_int(struct async_req *req, int *perrno); struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, int fd, const void *buffer, size_t length, @@ -32,9 +32,11 @@ struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev, int fd, void *buffer, size_t length, int flags); -struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len); +struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len); +NTSTATUS async_connect_recv(struct async_req *req, int *perrno); struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, int fd, const void *buffer, size_t length, diff --git a/source3/include/packet.h b/source3/include/packet.h index 05974da8fc..03331da750 100644 --- a/source3/include/packet.h +++ b/source3/include/packet.h @@ -44,12 +44,14 @@ NTSTATUS packet_fd_read_sync(struct packet_context *ctx); * Handle an incoming packet: * Return False if none is available * Otherwise return True and store the callback result in *status + * Callback must either talloc_move or talloc_free buf */ bool packet_handler(struct packet_context *ctx, - bool (*full_req)(const DATA_BLOB *data, + bool (*full_req)(const uint8_t *buf, + size_t available, size_t *length, void *private_data), - NTSTATUS (*callback)(const DATA_BLOB *data, + NTSTATUS (*callback)(uint8_t *buf, size_t length, void *private_data), void *private_data, NTSTATUS *status); diff --git a/source3/include/proto.h b/source3/include/proto.h index e1e98eb125..09f12ceb86 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1457,10 +1457,21 @@ int open_socket_in(int type, int dlevel, const struct sockaddr_storage *psock, bool rebind); -int open_socket_out(int type, - const struct sockaddr_storage *pss, - uint16_t port, - int timeout); +NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, + int timeout, int *pfd); +struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout); +NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd); +struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval wait_time, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout); +NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd); bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs, int timeout, int *fd_index, int *fd); int open_udp_socket(const char *host, int port); @@ -7970,4 +7981,14 @@ NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid); NTSTATUS nss_info_template_init( void ); +/* Misc protos */ + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct wb_context *wb_ctx, bool need_priv, + const struct winbindd_request *wb_req); +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse); +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx); + + #endif /* _PROTO_H_ */ diff --git a/source3/include/smb.h b/source3/include/smb.h index a8a2d98154..7fd4fbb553 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -27,7 +27,7 @@ #define _SMB_H /* logged when starting the various Samba daemons */ -#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2008" +#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2009" #if defined(LARGE_SMB_OFF_T) @@ -369,6 +369,7 @@ struct share_mode_entry; struct uuid; struct named_mutex; struct pcap_cache; +struct wb_context; struct vfs_fsp_data { struct vfs_fsp_data *next; diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c index 159666f15c..ac06df65a3 100644 --- a/source3/lib/async_req.c +++ b/source3/lib/async_req.c @@ -49,7 +49,7 @@ char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req) * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS */ -struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) +struct async_req *async_req_new(TALLOC_CTX *mem_ctx) { struct async_req *result; @@ -58,7 +58,6 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx, struct event_context *ev) return NULL; } result->state = ASYNC_REQ_IN_PROGRESS; - result->event_ctx = ev; result->print = async_req_print; return result; } @@ -135,12 +134,12 @@ static void async_trigger(struct event_context *ev, struct timed_event *te, * conventions, independent of whether the request was actually deferred. */ -bool async_post_status(struct async_req *req, NTSTATUS status) +bool async_post_status(struct async_req *req, struct event_context *ev, + NTSTATUS status) { req->status = status; - if (event_add_timed(req->event_ctx, req, timeval_zero(), - "async_trigger", + if (event_add_timed(ev, req, timeval_zero(), "async_trigger", async_trigger, req) == NULL) { return false; } @@ -195,3 +194,123 @@ NTSTATUS async_req_simple_recv(struct async_req *req) } return NT_STATUS_OK; } + +static void async_req_timedout(struct event_context *ev, + struct timed_event *te, + const struct timeval *now, + void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + TALLOC_FREE(te); + async_req_error(req, NT_STATUS_IO_TIMEOUT); +} + +bool async_req_set_timeout(struct async_req *req, struct event_context *ev, + struct timeval to) +{ + return (event_add_timed(ev, req, + timeval_current_ofs(to.tv_sec, to.tv_usec), + "async_req_timedout", async_req_timedout, req) + != NULL); +} + +struct async_req *async_wait_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval to) +{ + struct async_req *result; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return result; + } + if (!async_req_set_timeout(result, ev, to)) { + TALLOC_FREE(result); + return NULL; + } + return result; +} + +NTSTATUS async_wait_recv(struct async_req *req) +{ + return NT_STATUS_OK; +} + +struct async_queue_entry { + struct async_queue_entry *prev, *next; + struct async_req_queue *queue; + struct async_req *req; + void (*trigger)(struct async_req *req); +}; + +struct async_req_queue { + struct async_queue_entry *queue; +}; + +struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx) +{ + return TALLOC_ZERO_P(mem_ctx, struct async_req_queue); +} + +static int async_queue_entry_destructor(struct async_queue_entry *e) +{ + struct async_req_queue *queue = e->queue; + + DLIST_REMOVE(queue->queue, e); + + if (queue->queue != NULL) { + queue->queue->trigger(queue->queue->req); + } + + return 0; +} + +static void async_req_immediate_trigger(struct event_context *ev, + struct timed_event *te, + const struct timeval *now, + void *priv) +{ + struct async_queue_entry *e = talloc_get_type_abort( + priv, struct async_queue_entry); + + TALLOC_FREE(te); + e->trigger(e->req); +} + +bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev, + struct async_req *req, + void (*trigger)(struct async_req *req)) +{ + struct async_queue_entry *e; + bool busy; + + busy = (queue->queue != NULL); + + e = talloc(req, struct async_queue_entry); + if (e == NULL) { + return false; + } + + e->req = req; + e->trigger = trigger; + e->queue = queue; + + DLIST_ADD_END(queue->queue, e, struct async_queue_entry *); + talloc_set_destructor(e, async_queue_entry_destructor); + + if (!busy) { + struct timed_event *te; + + te = event_add_timed(ev, e, timeval_zero(), + "async_req_immediate_trigger", + async_req_immediate_trigger, + e); + if (te == NULL) { + TALLOC_FREE(e); + return false; + } + } + + return true; +} diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c index 225cc7b195..bb89a1353a 100644 --- a/source3/lib/async_sock.c +++ b/source3/lib/async_sock.c @@ -106,7 +106,7 @@ static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, struct async_req *result; struct async_syscall_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -209,7 +209,7 @@ size_t async_syscall_result_size_t(struct async_req *req, int *perrno) * @retval The return value from the asynchronously called syscall */ -ssize_t async_syscall_result_int(struct async_req *req, int *perrno) +int async_syscall_result_int(struct async_req *req, int *perrno) { struct async_syscall_state *state = talloc_get_type_abort( req->private_data, struct async_syscall_state); @@ -236,7 +236,10 @@ static void async_send_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_send *p = &state->param.param_send; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_SEND); + if (state->syscall_type != ASYNC_SYSCALL_SEND) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = send(p->fd, p->buffer, p->length, p->flags); @@ -300,7 +303,10 @@ static void async_sendall_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_sendall *p = &state->param.param_sendall; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_SENDALL); + if (state->syscall_type != ASYNC_SYSCALL_SENDALL) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent, p->length - p->sent, p->flags); @@ -317,7 +323,10 @@ static void async_sendall_callback(struct event_context *ev, } p->sent += state->result.result_ssize_t; - SMB_ASSERT(p->sent <= p->length); + if (p->sent > p->length) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } if (p->sent == p->length) { TALLOC_FREE(state->fde); @@ -385,7 +394,10 @@ static void async_recv_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_recv *p = &state->param.param_recv; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_RECV); + if (state->syscall_type != ASYNC_SYSCALL_RECV) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, p->flags); @@ -450,7 +462,10 @@ static void async_recvall_callback(struct event_context *ev, req->private_data, struct async_syscall_state); struct param_recvall *p = &state->param.param_recvall; - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_RECVALL); + if (state->syscall_type != ASYNC_SYSCALL_RECVALL) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } state->result.result_ssize_t = recv(p->fd, (char *)p->buffer + p->received, @@ -468,7 +483,10 @@ static void async_recvall_callback(struct event_context *ev, } p->received += state->result.result_ssize_t; - SMB_ASSERT(p->received <= p->length); + if (p->received > p->length) { + async_req_error(req, NT_STATUS_INTERNAL_ERROR); + return; + } if (p->received == p->length) { TALLOC_FREE(state->fde); @@ -517,60 +535,16 @@ NTSTATUS recvall_recv(struct async_req *req) return async_req_simple_recv(req); } -/** - * fde event handler for connect(2) - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the connect - * @param[in] flags Indicate read/writeability of the socket - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_connect_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_connect *p = &state->param.param_connect; - - SMB_ASSERT(state->syscall_type == ASYNC_SYSCALL_CONNECT); - - TALLOC_FREE(state->fde); - - /* - * Stevens, Network Programming says that if there's a - * successful connect, the socket is only writable. Upon an - * error, it's both readable and writable. - */ - if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) - == (EVENT_FD_READ|EVENT_FD_WRITE)) { - int sockerr; - socklen_t err_len = sizeof(sockerr); - - if (getsockopt(p->fd, SOL_SOCKET, SO_ERROR, - (void *)&sockerr, &err_len) == 0) { - errno = sockerr; - } - - state->sys_errno = errno; - - DEBUG(10, ("connect returned %s\n", strerror(errno))); - - sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags); - - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - sys_fcntl_long(p->fd, F_SETFL, p->old_sockflags); - - state->result.result_int = 0; - state->sys_errno = 0; +struct async_connect_state { + int fd; + int result; + int sys_errno; + long old_sockflags; +}; - async_req_done(req); -} +static void async_connect_connected(struct event_context *ev, + struct fd_event *fde, uint16_t flags, + void *priv); /** * @brief async version of connect(2) @@ -585,47 +559,46 @@ static void async_connect_callback(struct event_context *ev, * connect in an async state. This will be reset when the request is finished. */ -struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len) +struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, const struct sockaddr *address, + socklen_t address_len) { struct async_req *result; - struct async_syscall_state *state; - struct param_connect *p; + struct async_connect_state *state; + struct fd_event *fde; + NTSTATUS status; - result = async_syscall_new(mem_ctx, ev, ASYNC_SYSCALL_CONNECT, &state); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } - p = &state->param.param_connect; + state = talloc(result, struct async_connect_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; /** * We have to set the socket to nonblocking for async connect(2). Keep * the old sockflags around. */ - p->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); + state->fd = fd; + state->sys_errno = 0; - if (p->old_sockflags == -1) { - if (async_post_status(result, map_nt_error_from_unix(errno))) { - return result; - } - TALLOC_FREE(result); - return NULL; + state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); + if (state->old_sockflags == -1) { + goto post_errno; } - set_blocking(fd, true); + set_blocking(fd, false); - state->result.result_int = connect(fd, address, address_len); - - if (state->result.result_int == 0) { + state->result = connect(fd, address, address_len); + if (state->result == 0) { state->sys_errno = 0; - if (async_post_status(result, NT_STATUS_OK)) { - return result; - } - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + status = NT_STATUS_OK; + goto post_status; } /** @@ -640,31 +613,93 @@ struct async_req *async_connect(TALLOC_CTX *mem_ctx, struct event_context *ev, errno == EISCONN || #endif errno == EAGAIN || errno == EINTR)) { + goto post_errno; + } - state->sys_errno = errno; - - if (async_post_status(result, map_nt_error_from_unix(errno))) { - return result; - } - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE, + async_connect_connected, result); + if (fde == NULL) { + status = NT_STATUS_NO_MEMORY; + goto post_status; } + return result; - state->fde = event_add_fd(ev, state, fd, - EVENT_FD_READ | EVENT_FD_WRITE, - async_connect_callback, result); - if (state->fde == NULL) { - sys_fcntl_long(fd, F_SETFL, p->old_sockflags); - TALLOC_FREE(result); - return NULL; + post_errno: + state->sys_errno = errno; + status = map_nt_error_from_unix(state->sys_errno); + post_status: + sys_fcntl_long(fd, F_SETFL, state->old_sockflags); + if (!async_post_status(result, ev, status)) { + goto fail; } - result->private_data = state; + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +/** + * fde event handler for connect(2) + * @param[in] ev The event context that sent us here + * @param[in] fde The file descriptor event associated with the connect + * @param[in] flags Indicate read/writeability of the socket + * @param[in] priv private data, "struct async_req *" in this case + */ - state->param.param_connect.fd = fd; - state->param.param_connect.address = address; - state->param.param_connect.address_len = address_len; +static void async_connect_connected(struct event_context *ev, + struct fd_event *fde, uint16_t flags, + void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + struct async_connect_state *state = talloc_get_type_abort( + req->private_data, struct async_connect_state); - return result; + TALLOC_FREE(fde); + + /* + * Stevens, Network Programming says that if there's a + * successful connect, the socket is only writable. Upon an + * error, it's both readable and writable. + */ + if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) + == (EVENT_FD_READ|EVENT_FD_WRITE)) { + int sockerr; + socklen_t err_len = sizeof(sockerr); + + if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR, + (void *)&sockerr, &err_len) == 0) { + errno = sockerr; + } + + state->sys_errno = errno; + + DEBUG(10, ("connect returned %s\n", strerror(errno))); + + sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); + async_req_error(req, map_nt_error_from_unix(state->sys_errno)); + return; + } + + state->sys_errno = 0; + async_req_done(req); } +NTSTATUS async_connect_recv(struct async_req *req, int *perrno) +{ + struct async_connect_state *state = talloc_get_type_abort( + req->private_data, struct async_connect_state); + NTSTATUS status; + + sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); + + *perrno = state->sys_errno; + + if (async_req_is_error(req, &status)) { + return status; + } + if (state->sys_errno == 0) { + return NT_STATUS_OK; + } + return map_nt_error_from_unix(state->sys_errno); +} diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index 8d97606b85..75a513312e 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -155,17 +155,17 @@ static NTSTATUS ctdbd_connect(TALLOC_CTX *mem_ctx, * Do we have a complete ctdb packet in the queue? */ -static bool ctdb_req_complete(const DATA_BLOB *data, +static bool ctdb_req_complete(const uint8_t *buf, size_t available, size_t *length, void *private_data) { uint32 msglen; - if (data->length < sizeof(msglen)) { + if (available < sizeof(msglen)) { return False; } - msglen = *((uint32 *)data->data); + msglen = *((uint32 *)buf); DEBUG(10, ("msglen = %d\n", msglen)); @@ -176,12 +176,12 @@ static bool ctdb_req_complete(const DATA_BLOB *data, cluster_fatal("ctdbd protocol error\n"); } - if (data->length >= msglen) { - *length = msglen; - return True; + if (available < msglen) { + return false; } - return False; + *length = msglen; + return true; } /* @@ -220,16 +220,13 @@ struct req_pull_state { * Pull a ctdb request out of the incoming packet queue */ -static NTSTATUS ctdb_req_pull(const DATA_BLOB *data, +static NTSTATUS ctdb_req_pull(uint8_t *buf, size_t length, void *private_data) { struct req_pull_state *state = (struct req_pull_state *)private_data; - state->req = data_blob_talloc(state->mem_ctx, data->data, - data->length); - if (state->req.data == NULL) { - return NT_STATUS_NO_MEMORY; - } + state->req.data = talloc_move(state->mem_ctx, &buf); + state->req.length = length; return NT_STATUS_OK; } @@ -497,7 +494,7 @@ NTSTATUS ctdbd_messaging_connection(TALLOC_CTX *mem_ctx, /* * Packet handler to receive and handle a ctdb message */ -static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, +static NTSTATUS ctdb_handle_message(uint8_t *buf, size_t length, void *private_data) { struct ctdbd_connection *conn = talloc_get_type_abort( @@ -505,11 +502,12 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, struct ctdb_req_message *msg; struct messaging_rec *msg_rec; - msg = (struct ctdb_req_message *)data->data; + msg = (struct ctdb_req_message *)buf; if (msg->hdr.operation != CTDB_REQ_MESSAGE) { DEBUG(0, ("Received async msg of type %u, discarding\n", msg->hdr.operation)); + TALLOC_FREE(buf); return NT_STATUS_INVALID_PARAMETER; } @@ -519,6 +517,7 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, DEBUG(10, ("received CTDB_SRVID_RELEASE_IP\n")); conn->release_ip_handler((const char *)msg->data, conn->release_ip_priv); + TALLOC_FREE(buf); return NT_STATUS_OK; } @@ -540,6 +539,8 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, */ message_send_all(conn->msg_ctx, MSG_SMB_UNLOCK, NULL, 0, NULL); + TALLOC_FREE(buf); + return NT_STATUS_OK; } @@ -548,17 +549,20 @@ static NTSTATUS ctdb_handle_message(const DATA_BLOB *data, if (msg->srvid != sys_getpid() && msg->srvid != MSG_SRVID_SAMBA) { DEBUG(0,("Got unexpected message with srvid=%llu\n", (unsigned long long)msg->srvid)); + TALLOC_FREE(buf); return NT_STATUS_OK; } - if (!(msg_rec = ctdb_pull_messaging_rec(NULL, data->length, msg))) { + if (!(msg_rec = ctdb_pull_messaging_rec(NULL, length, msg))) { DEBUG(10, ("ctdb_pull_messaging_rec failed\n")); + TALLOC_FREE(buf); return NT_STATUS_NO_MEMORY; } messaging_dispatch_rec(conn->msg_ctx, msg_rec); TALLOC_FREE(msg_rec); + TALLOC_FREE(buf); return NT_STATUS_OK; } @@ -1025,7 +1029,7 @@ struct ctdbd_traverse_state { * Handle a traverse record coming in on the ctdbd connection */ -static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, +static NTSTATUS ctdb_traverse_handler(uint8_t *buf, size_t length, void *private_data) { struct ctdbd_traverse_state *state = @@ -1035,11 +1039,11 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, struct ctdb_rec_data *d; TDB_DATA key, data; - m = (struct ctdb_req_message *)blob->data; + m = (struct ctdb_req_message *)buf; - if (blob->length < sizeof(*m) || m->hdr.length != blob->length) { - DEBUG(0, ("Got invalid message of length %d\n", - (int)blob->length)); + if (length < sizeof(*m) || m->hdr.length != length) { + DEBUG(0, ("Got invalid message of length %d\n", (int)length)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } @@ -1047,6 +1051,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, if (m->datalen < sizeof(uint32_t) || m->datalen != d->length) { DEBUG(0, ("Got invalid traverse data of length %d\n", (int)m->datalen)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } @@ -1063,6 +1068,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, if (data.dsize < sizeof(struct ctdb_ltdb_header)) { DEBUG(0, ("Got invalid ltdb header length %d\n", (int)data.dsize)); + TALLOC_FREE(buf); return NT_STATUS_UNEXPECTED_IO_ERROR; } data.dsize -= sizeof(struct ctdb_ltdb_header); @@ -1072,6 +1078,7 @@ static NTSTATUS ctdb_traverse_handler(const DATA_BLOB *blob, state->fn(key, data, state->private_data); } + TALLOC_FREE(buf); return NT_STATUS_OK; } diff --git a/source3/lib/ldb/include/ldb.h b/source3/lib/ldb/include/ldb.h index 0a745742d9..3891c1c6a3 100644 --- a/source3/lib/ldb/include/ldb.h +++ b/source3/lib/ldb/include/ldb.h @@ -991,7 +991,7 @@ int ldb_search(struct ldb_context *ldb, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_result **res); + const char * const *attrs, struct ldb_result **_res); /* * a useful search function where you can easily define the expression and diff --git a/source3/lib/ldb/tools/ldbadd.c b/source3/lib/ldb/tools/ldbadd.c index 4dde2a1ef5..155395e065 100644 --- a/source3/lib/ldb/tools/ldbadd.c +++ b/source3/lib/ldb/tools/ldbadd.c @@ -35,8 +35,6 @@ #include "ldb/include/includes.h" #include "ldb/tools/cmdline.h" -static int failures; - static void usage(void) { printf("Usage: ldbadd <options> <ldif...>\n"); @@ -53,7 +51,8 @@ static void usage(void) /* add records from an opened file */ -static int process_file(struct ldb_context *ldb, FILE *f, int *count) +static int process_file(struct ldb_context *ldb, FILE *f, int *count, + int *failures) { struct ldb_ldif *ldif; int ret = LDB_SUCCESS; @@ -71,7 +70,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); - failures++; + (*failures)++; } else { (*count)++; } @@ -86,7 +85,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) int main(int argc, const char **argv) { struct ldb_context *ldb; - int i, ret=0, count=0; + int i, ret=0, count=0, failures=0; struct ldb_cmdline *options; ldb_global_init(); @@ -96,7 +95,7 @@ int main(int argc, const char **argv) options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { - ret = process_file(ldb, stdin, &count); + ret = process_file(ldb, stdin, &count, &failures); } else { for (i=0;i<options->argc;i++) { const char *fname = options->argv[i]; @@ -106,7 +105,7 @@ int main(int argc, const char **argv) perror(fname); exit(1); } - ret = process_file(ldb, f, &count); + ret = process_file(ldb, f, &count, &failures); fclose(f); } } diff --git a/source3/lib/ldb/tools/ldbmodify.c b/source3/lib/ldb/tools/ldbmodify.c index 368b4cf996..f12387a8f6 100644 --- a/source3/lib/ldb/tools/ldbmodify.c +++ b/source3/lib/ldb/tools/ldbmodify.c @@ -35,8 +35,6 @@ #include "ldb/include/includes.h" #include "ldb/tools/cmdline.h" -static int failures; - static void usage(void) { printf("Usage: ldbmodify <options> <ldif...>\n"); @@ -52,7 +50,8 @@ static void usage(void) /* process modifies for one file */ -static int process_file(struct ldb_context *ldb, FILE *f, int *count) +static int process_file(struct ldb_context *ldb, FILE *f, int *count, + int *failures) { struct ldb_ldif *ldif; int ret = LDB_SUCCESS; @@ -73,7 +72,7 @@ static int process_file(struct ldb_context *ldb, FILE *f, int *count) if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); - failures++; + (*failures)++; } else { (*count)++; } @@ -87,6 +86,7 @@ int main(int argc, const char **argv) { struct ldb_context *ldb; int count=0; + int failures=0; int i, ret=LDB_SUCCESS; struct ldb_cmdline *options; @@ -97,7 +97,7 @@ int main(int argc, const char **argv) options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { - ret = process_file(ldb, stdin, &count); + ret = process_file(ldb, stdin, &count, &failures); } else { for (i=0;i<options->argc;i++) { const char *fname = options->argv[i]; @@ -107,7 +107,7 @@ int main(int argc, const char **argv) perror(fname); exit(1); } - ret = process_file(ldb, f, &count); + ret = process_file(ldb, f, &count, &failures); } } diff --git a/source3/lib/packet.c b/source3/lib/packet.c index e4cab6ba87..ef28bf9f62 100644 --- a/source3/lib/packet.c +++ b/source3/lib/packet.c @@ -120,33 +120,43 @@ NTSTATUS packet_fd_read_sync(struct packet_context *ctx) } bool packet_handler(struct packet_context *ctx, - bool (*full_req)(const DATA_BLOB *data, + bool (*full_req)(const uint8_t *buf, + size_t available, size_t *length, - void *private_data), - NTSTATUS (*callback)(const DATA_BLOB *data, - void *private_data), - void *private_data, - NTSTATUS *status) + void *priv), + NTSTATUS (*callback)(uint8_t *buf, size_t length, + void *priv), + void *priv, NTSTATUS *status) { size_t length; - DATA_BLOB data; + uint8_t *buf; - if (!full_req(&ctx->in, &length, private_data)) { + if (!full_req(ctx->in.data, ctx->in.length, &length, priv)) { return False; } - SMB_ASSERT(length <= ctx->in.length); - - data = data_blob(ctx->in.data, length); - - memmove(ctx->in.data, ctx->in.data + length, - ctx->in.length - length); - ctx->in.length -= length; + if (length > ctx->in.length) { + *status = NT_STATUS_INTERNAL_ERROR; + return true; + } - *status = callback(&data, private_data); + if (length == ctx->in.length) { + buf = ctx->in.data; + ctx->in.data = NULL; + ctx->in.length = 0; + } else { + buf = (uint8_t *)TALLOC_MEMDUP(ctx, ctx->in.data, length); + if (buf == NULL) { + *status = NT_STATUS_NO_MEMORY; + return true; + } - data_blob_free(&data); + memmove(ctx->in.data, ctx->in.data + length, + ctx->in.length - length); + ctx->in.length -= length; + } + *status = callback(buf, length, priv); return True; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index d23758ad6a..e913b35d60 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -707,10 +707,6 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt) Write data to a fd. ****************************************************************************/ -/**************************************************************************** - Write data to a fd. -****************************************************************************/ - ssize_t write_data(int fd, const char *buffer, size_t N) { ssize_t ret; @@ -948,102 +944,319 @@ int open_socket_in(int type, return( res ); } +struct open_socket_out_state { + int fd; + struct event_context *ev; + struct sockaddr_storage ss; + socklen_t salen; + uint16_t port; + int wait_nsec; +}; + +static void open_socket_out_connected(struct async_req *subreq); + +static int open_socket_out_state_destructor(struct open_socket_out_state *s) +{ + if (s->fd != -1) { + close(s->fd); + } + return 0; +} + /**************************************************************************** Create an outgoing socket. timeout is in milliseconds. **************************************************************************/ -int open_socket_out(int type, - const struct sockaddr_storage *pss, - uint16_t port, - int timeout) +struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout) { char addr[INET6_ADDRSTRLEN]; - struct sockaddr_storage sock_out = *pss; - int res,ret; - int connect_loop = 10; - int increment = 10; + struct async_req *result, *subreq; + struct open_socket_out_state *state; + NTSTATUS status; - /* create a socket to write to */ - res = socket(pss->ss_family, type, 0); - if (res == -1) { - DEBUG(0,("socket error (%s)\n", strerror(errno))); - return -1; + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; } + state = talloc(result, struct open_socket_out_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->ev = ev; + state->ss = *pss; + state->port = port; + state->wait_nsec = 10000; + state->salen = -1; - if (type != SOCK_STREAM) { - return res; + state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0); + if (state->fd == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + talloc_set_destructor(state, open_socket_out_state_destructor); + + if (!async_req_set_timeout(result, ev, timeval_set(0, timeout*1000))) { + goto fail; } #if defined(HAVE_IPV6) if (pss->ss_family == AF_INET6) { - struct sockaddr_in6 *psa6 = (struct sockaddr_in6 *)&sock_out; + struct sockaddr_in6 *psa6; + psa6 = (struct sockaddr_in6 *)&state->ss; psa6->sin6_port = htons(port); - if (psa6->sin6_scope_id == 0 && - IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) { - setup_linklocal_scope_id((struct sockaddr *)&sock_out); + if (psa6->sin6_scope_id == 0 + && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) { + setup_linklocal_scope_id( + (struct sockaddr *)&(state->ss)); } + state->salen = sizeof(struct sockaddr_in6); } #endif if (pss->ss_family == AF_INET) { - struct sockaddr_in *psa = (struct sockaddr_in *)&sock_out; + struct sockaddr_in *psa; + psa = (struct sockaddr_in *)&state->ss; psa->sin_port = htons(port); + state->salen = sizeof(struct sockaddr_in); } - /* set it non-blocking */ - set_blocking(res,false); + print_sockaddr(addr, sizeof(addr), &state->ss); + DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port)); - print_sockaddr(addr, sizeof(addr), &sock_out); - DEBUG(3,("Connecting to %s at port %u\n", - addr, - (unsigned int)port)); + subreq = async_connect_send(state, state->ev, state->fd, + (struct sockaddr *)&state->ss, + state->salen); + if ((subreq == NULL) + || !async_req_set_timeout(subreq, state->ev, + timeval_set(0, state->wait_nsec))) { + status = NT_STATUS_NO_MEMORY; + goto post_status; + } + subreq->async.fn = open_socket_out_connected; + subreq->async.priv = result; + return result; - /* and connect it to the destination */ - connect_again: + post_status: + if (!async_post_status(result, ev, status)) { + goto fail; + } + return result; + fail: + TALLOC_FREE(result); + return NULL; +} - ret = sys_connect(res, (struct sockaddr *)&sock_out); +static void open_socket_out_connected(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_state); + NTSTATUS status; + int sys_errno; - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && (connect_loop < timeout) ) { - smb_msleep(connect_loop); - timeout -= connect_loop; - connect_loop += increment; - if (increment < 250) { - /* After 8 rounds we end up at a max of 255 msec */ - increment *= 1.5; - } - goto connect_again; + status = async_connect_recv(subreq, &sys_errno); + TALLOC_FREE(subreq); + if (NT_STATUS_IS_OK(status)) { + async_req_done(req); + return; } - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%u\n", - addr, - (unsigned int)port)); - close(res); - return -1; + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) + || (sys_errno == EINPROGRESS) + || (sys_errno == EALREADY) + || (sys_errno == EAGAIN)) { + + /* + * retry + */ + + if (state->wait_nsec < 250000) { + state->wait_nsec *= 1.5; + } + + subreq = async_connect_send(state, state->ev, state->fd, + (struct sockaddr *)&state->ss, + state->salen); + if (async_req_nomem(subreq, req)) { + return; + } + if (!async_req_set_timeout(subreq, state->ev, + timeval_set(0, state->wait_nsec))) { + async_req_error(req, NT_STATUS_NO_MEMORY); + return; + } + subreq->async.fn = open_socket_out_connected; + subreq->async.priv = req; + return; } #ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; + if (sys_errno == EISCONN) { + async_req_done(req); + return; } #endif - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - addr, - (unsigned int)port, - strerror(errno))); - close(res); - return -1; + /* real error */ + async_req_error(req, map_nt_error_from_unix(sys_errno)); +} + +NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) +{ + struct open_socket_out_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *pfd = state->fd; + state->fd = -1; + return NT_STATUS_OK; +} + +NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, + int timeout, int *pfd) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = event_context_init(frame); + if (ev == NULL) { + goto fail; } - /* set it blocking again */ - set_blocking(res,true); + req = open_socket_out_send(frame, ev, pss, port, timeout); + if (req == NULL) { + goto fail; + } + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } - return res; + status = open_socket_out_recv(req, pfd); + fail: + TALLOC_FREE(frame); + return status; +} + +struct open_socket_out_defer_state { + struct event_context *ev; + struct sockaddr_storage ss; + uint16_t port; + int timeout; + int fd; +}; + +static void open_socket_out_defer_waited(struct async_req *subreq); +static void open_socket_out_defer_connected(struct async_req *subreq); + +struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct timeval wait_time, + const struct sockaddr_storage *pss, + uint16_t port, + int timeout) +{ + struct async_req *result, *subreq; + struct open_socket_out_defer_state *state; + NTSTATUS status; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct open_socket_out_defer_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->ev = ev; + state->ss = *pss; + state->port = port; + state->timeout = timeout; + + subreq = async_wait_send(state, ev, wait_time); + if (subreq == NULL) { + status = NT_STATUS_NO_MEMORY; + goto post_status; + } + subreq->async.fn = open_socket_out_defer_waited; + subreq->async.priv = result; + return result; + + post_status: + if (!async_post_status(result, ev, status)) { + goto fail; + } + return result; + fail: + TALLOC_FREE(result); + return NULL; +} + +static void open_socket_out_defer_waited(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + status = async_wait_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = open_socket_out_send(state, state->ev, &state->ss, + state->port, state->timeout); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = open_socket_out_defer_connected; + subreq->async.priv = req; +} + +static void open_socket_out_defer_connected(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + status = open_socket_out_recv(subreq, &state->fd); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + +NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd) +{ + struct open_socket_out_defer_state *state = talloc_get_type_abort( + req->private_data, struct open_socket_out_defer_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *pfd = state->fd; + state->fd = -1; + return NT_STATUS_OK; } /******************************************************************* diff --git a/source3/winbindd/winbindd_reqtrans.c b/source3/lib/wb_reqtrans.c index ea16c5f81e..1f5f181aa1 100644 --- a/source3/winbindd/winbindd_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -20,7 +20,7 @@ */ #include "includes.h" -#include "winbindd.h" +#include "winbindd/winbindd.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -43,7 +43,7 @@ struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct req_read_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -205,7 +205,7 @@ struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct req_write_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -304,7 +304,7 @@ struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct resp_read_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -458,7 +458,7 @@ struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, struct async_req *result, *subreq; struct resp_write_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { return NULL; } @@ -540,146 +540,3 @@ NTSTATUS wb_resp_write_recv(struct async_req *req) { return async_req_simple_recv(req); } - -struct wb_trans_state { - struct event_context *ev; - struct timed_event *te; - int fd; - struct winbindd_response *wb_resp; - size_t reply_max_extra_data; -}; - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv); -static void wb_trans_sent(struct async_req *req); -static void wb_trans_received(struct async_req *req); - -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, - struct winbindd_request *wb_req, - struct timeval timeout, - size_t reply_max_extra_data) -{ - struct async_req *result, *subreq; - struct wb_trans_state *state; - - result = async_req_new(mem_ctx, ev); - if (result == NULL) { - return NULL; - } - - state = talloc(result, struct wb_trans_state); - if (state == NULL) { - goto nomem; - } - result->private_data = state; - - state->ev = ev; - state->fd = fd; - state->reply_max_extra_data = reply_max_extra_data; - - state->te = event_add_timed( - ev, state, - timeval_current_ofs(timeout.tv_sec, timeout.tv_usec), - "wb_trans_timeout", wb_trans_timeout, result); - if (state->te == NULL) { - goto nomem; - } - - subreq = wb_req_write_send(state, state->ev, state->fd, wb_req); - if (subreq == NULL) { - goto nomem; - } - subreq->async.fn = wb_trans_sent; - subreq->async.priv = result; - - return result; - - nomem: - TALLOC_FREE(result); - return NULL; -} - -static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - - TALLOC_FREE(state->te); - async_req_error(req, NT_STATUS_IO_TIMEOUT); -} - -static void wb_trans_sent(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - status = wb_req_write_recv(subreq); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - subreq = wb_resp_read_send(state, state->ev, state->fd); - if (async_req_nomem(subreq, req)) { - return; - } - - subreq->async.fn = wb_trans_received; - subreq->async.priv = req; -}; - -static void wb_trans_received(struct async_req *subreq) -{ - struct async_req *req = talloc_get_type_abort( - subreq->async.priv, struct async_req); - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - TALLOC_FREE(state->te); - - status = wb_resp_read_recv(subreq, state, &state->wb_resp); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); - return; - } - - async_req_done(req); -} - -NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp) -{ - struct wb_trans_state *state = talloc_get_type_abort( - req->private_data, struct wb_trans_state); - NTSTATUS status; - - if (async_req_is_error(req, &status)) { - return status; - } - *presp = talloc_move(mem_ctx, &state->wb_resp); - return NT_STATUS_OK; -} - -struct wb_trans_queue_state { - struct wb_trans_queue_state *prev, *next; - struct wb_trans_queue *queue; - struct winbindd_request *req; -}; - -struct wb_trans_queue { - int fd; - struct timeval timeout; - size_t max_resp_extra_data; - struct wb_trans_queue_state *queued_requests; -}; diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c new file mode 100644 index 0000000000..d58c934c07 --- /dev/null +++ b/source3/lib/wbclient.c @@ -0,0 +1,774 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async winbind requests + Copyright (C) Volker Lendecke 2008 + + 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 "includes.h" +#include "winbindd/winbindd.h" +#include "winbindd/winbindd_proto.h" + +static int make_nonstd_fd(int fd) +{ + int i; + int sys_errno = 0; + int fds[3]; + int num_fds = 0; + + if (fd == -1) { + return -1; + } + while (fd < 3) { + fds[num_fds++] = fd; + fd = dup(fd); + if (fd == -1) { + sys_errno = errno; + break; + } + } + for (i=0; i<num_fds; i++) { + close(fds[i]); + } + if (fd == -1) { + errno = sys_errno; + } + return fd; +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY + Set close on exec also. +****************************************************************************/ + +static int make_safe_fd(int fd) +{ + int result, flags; + int new_fd = make_nonstd_fd(fd); + + if (new_fd == -1) { + goto fail; + } + + /* Socket should be nonblocking. */ + +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if ((flags = fcntl(new_fd, F_GETFL)) == -1) { + goto fail; + } + + flags |= FLAG_TO_SET; + if (fcntl(new_fd, F_SETFL, flags) == -1) { + goto fail; + } + +#undef FLAG_TO_SET + + /* Socket should be closed on exec() */ +#ifdef FD_CLOEXEC + result = flags = fcntl(new_fd, F_GETFD, 0); + if (flags >= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + goto fail; + } +#endif + return new_fd; + + fail: + if (new_fd != -1) { + int sys_errno = errno; + close(new_fd); + errno = sys_errno; + } + return -1; +} + +static bool winbind_closed_fd(int fd) +{ + struct timeval tv; + fd_set r_fds; + + if (fd == -1) { + return true; + } + + FD_ZERO(&r_fds); + FD_SET(fd, &r_fds); + ZERO_STRUCT(tv); + + if ((select(fd+1, &r_fds, NULL, NULL, &tv) == -1) + || FD_ISSET(fd, &r_fds)) { + return true; + } + + return false; +} + +struct wb_context { + struct async_req_queue *queue; + int fd; + bool is_priv; +}; + +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) +{ + struct wb_context *result; + + result = talloc(mem_ctx, struct wb_context); + if (result == NULL) { + return NULL; + } + result->queue = async_req_queue_init(result); + if (result->queue == NULL) { + TALLOC_FREE(result); + return NULL; + } + result->fd = -1; + return result; +} + +static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct wb_context *wb_ctx, + const char *dir) +{ + struct async_req *req; + struct sockaddr_un sunaddr; + struct stat st; + char *path = NULL; + NTSTATUS status; + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + /* Connect to socket */ + + path = talloc_asprintf(talloc_tos(), "%s/%s", dir, + WINBINDD_SOCKET_NAME); + if (path == NULL) { + goto nomem; + } + + sunaddr.sun_family = AF_UNIX; + strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)); + TALLOC_FREE(path); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if ((lstat(sunaddr.sun_path, &st) == -1) + || !S_ISSOCK(st.st_mode) + || (st.st_uid != 0 && st.st_uid != geteuid())) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto post_status; + } + + wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0)); + if (wb_ctx->fd == -1) { + status = map_nt_error_from_unix(errno); + goto post_status; + } + + req = async_connect_send(mem_ctx, ev, wb_ctx->fd, + (struct sockaddr *)&sunaddr, + sizeof(sunaddr)); + if (req == NULL) { + goto nomem; + } + if (!async_req_set_timeout(req, ev, timeval_set(30, 0))) { + TALLOC_FREE(req); + goto nomem; + } + + return req; + + nomem: + status = NT_STATUS_NO_MEMORY; + post_status: + req = async_req_new(mem_ctx); + if (req == NULL) { + return NULL; + } + if (async_post_status(req, ev, status)) { + return req; + } + TALLOC_FREE(req); + return NULL; +} + +static NTSTATUS wb_connect_recv(struct async_req *req) +{ + int dummy; + + return async_connect_recv(req, &dummy); +} + +static struct winbindd_request *winbindd_request_copy( + TALLOC_CTX *mem_ctx, + const struct winbindd_request *req) +{ + struct winbindd_request *result; + + result = (struct winbindd_request *)TALLOC_MEMDUP( + mem_ctx, req, sizeof(struct winbindd_request)); + if (result == NULL) { + return NULL; + } + + if (result->extra_len == 0) { + return result; + } + + result->extra_data.data = (char *)TALLOC_MEMDUP( + result, result->extra_data.data, result->extra_len); + if (result->extra_data.data == NULL) { + TALLOC_FREE(result); + return NULL; + } + return result; +} + +struct wb_int_trans_state { + struct event_context *ev; + int fd; + struct winbindd_request *wb_req; + struct winbindd_response *wb_resp; +}; + +static void wb_int_trans_write_done(struct async_req *subreq); +static void wb_int_trans_read_done(struct async_req *subreq); + +static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_request *wb_req) +{ + struct async_req *result; + struct async_req *subreq; + struct wb_int_trans_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_int_trans_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + if (winbind_closed_fd(fd)) { + if (!async_post_status(result, ev, + NT_STATUS_PIPE_DISCONNECTED)) { + goto fail; + } + return result; + } + + state->ev = ev; + state->fd = fd; + state->wb_req = wb_req; + + state->wb_req->length = sizeof(struct winbindd_request); + state->wb_req->pid = getpid(); + + subreq = wb_req_write_send(state, state->ev, state->fd, state->wb_req); + if (subreq == NULL) { + goto fail; + } + subreq->async.fn = wb_int_trans_write_done; + subreq->async.priv = result; + + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void wb_int_trans_write_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + status = wb_req_write_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = wb_resp_read_send(state, state->ev, state->fd); + if (subreq == NULL) { + async_req_error(req, NT_STATUS_NO_MEMORY); + } + subreq->async.fn = wb_int_trans_read_done; + subreq->async.priv = req; +} + +static void wb_int_trans_read_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + status = wb_resp_read_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +static NTSTATUS wb_int_trans_recv(struct async_req *req, + TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse) +{ + struct wb_int_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_int_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +static const char *winbindd_socket_dir(void) +{ +#ifdef SOCKET_WRAPPER + const char *env_dir; + + env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); + if (env_dir) { + return env_dir; + } +#endif + + return WINBINDD_SOCKET_DIR; +} + +struct wb_open_pipe_state { + struct wb_context *wb_ctx; + struct event_context *ev; + bool need_priv; + struct winbindd_request wb_req; +}; + +static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq); +static void wb_open_pipe_ping_done(struct async_req *subreq); +static void wb_open_pipe_getpriv_done(struct async_req *subreq); +static void wb_open_pipe_connect_priv_done(struct async_req *subreq); + +static struct async_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct wb_context *wb_ctx, + bool need_priv) +{ + struct async_req *result; + struct async_req *subreq; + struct wb_open_pipe_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_open_pipe_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->wb_ctx = wb_ctx; + state->ev = ev; + state->need_priv = need_priv; + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + subreq = wb_connect_send(state, ev, wb_ctx, winbindd_socket_dir()); + if (subreq == NULL) { + goto fail; + } + + subreq->async.fn = wb_open_pipe_connect_nonpriv_done; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + NTSTATUS status; + + status = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + state->wb_ctx->is_priv = true; + async_req_error(req, status); + return; + } + + ZERO_STRUCT(state->wb_req); + state->wb_req.cmd = WINBINDD_INTERFACE_VERSION; + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + &state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_ping_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_ping_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + struct winbindd_response *wb_resp; + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (!state->need_priv) { + async_req_done(req); + return; + } + + state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR; + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + &state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_getpriv_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_getpriv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + struct winbindd_response *wb_resp = NULL; + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + + subreq = wb_connect_send(state, state->ev, state->wb_ctx, + (char *)wb_resp->extra_data.data); + TALLOC_FREE(wb_resp); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_open_pipe_connect_priv_done; + subreq->async.priv = req; +} + +static void wb_open_pipe_connect_priv_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_open_pipe_state *state = talloc_get_type_abort( + req->private_data, struct wb_open_pipe_state); + NTSTATUS status; + + status = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + state->wb_ctx->is_priv = true; + async_req_done(req); +} + +static NTSTATUS wb_open_pipe_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct wb_trans_state { + struct wb_trans_state *prev, *next; + struct wb_context *wb_ctx; + struct event_context *ev; + struct winbindd_request *wb_req; + struct winbindd_response *wb_resp; + int num_retries; + bool need_priv; +}; + +static void wb_trans_connect_done(struct async_req *subreq); +static void wb_trans_done(struct async_req *subreq); +static void wb_trans_retry_wait_done(struct async_req *subreq); + +static void wb_trigger_trans(struct async_req *req) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + struct async_req *subreq; + + if ((state->wb_ctx->fd == -1) + || (state->need_priv && !state->wb_ctx->is_priv)) { + + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_connect_done; + subreq->async.priv = req; + return; + } + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_done; + subreq->async.priv = req; +} + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct wb_context *wb_ctx, bool need_priv, + const struct winbindd_request *wb_req) +{ + struct async_req *result; + struct wb_trans_state *state; + + result = async_req_new(mem_ctx); + if (result == NULL) { + return NULL; + } + state = talloc(result, struct wb_trans_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->wb_ctx = wb_ctx; + state->ev = ev; + state->wb_req = winbindd_request_copy(state, wb_req); + if (state->wb_req == NULL) { + goto fail; + } + state->num_retries = 10; + state->need_priv = need_priv; + + if (!async_req_enqueue(wb_ctx->queue, ev, result, wb_trigger_trans)) { + goto fail; + } + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static bool wb_trans_retry(struct async_req *req, + struct wb_trans_state *state, + NTSTATUS status) +{ + struct async_req *subreq; + + if (NT_STATUS_IS_OK(status)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) + || NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + /* + * Winbind not around or we can't connect to the pipe. Fail + * immediately. + */ + async_req_error(req, status); + return true; + } + + state->num_retries -= 1; + if (state->num_retries == 0) { + async_req_error(req, status); + return true; + } + + /* + * The transfer as such failed, retry after one second + */ + + if (state->wb_ctx->fd != -1) { + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + } + + subreq = async_wait_send(state, state->ev, timeval_set(1, 0)); + if (async_req_nomem(subreq, req)) { + return true; + } + + subreq->async.fn = wb_trans_retry_wait_done; + subreq->async.priv = req; + return true; +} + +static void wb_trans_retry_wait_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = async_wait_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + async_req_error(req, status); + return; + } + + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = wb_trans_connect_done; + subreq->async.priv = req; +} + +static void wb_trans_connect_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_open_pipe_recv(subreq); + TALLOC_FREE(subreq); + + if (wb_trans_retry(req, state, status)) { + return; + } + + subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, + state->wb_req); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_trans_done; + subreq->async.priv = req; +} + +static void wb_trans_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_int_trans_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + + if (wb_trans_retry(req, state, status)) { + return; + } + + async_req_done(req); +} + +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 5032ffd14c..7cdfbc58a4 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -425,21 +425,28 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context, if (!use_tcp) { sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT); - + if (sock == -1) { + int rc = errno; + SAFE_FREE(ap_req.data); + krb5_auth_con_free(context, auth_context); + DEBUG(1,("failed to open kpasswd socket to %s " + "(%s)\n", kdc_host, strerror(errno))); + return ADS_ERROR_SYSTEM(rc); + } } else { - - sock = open_socket_out(SOCK_STREAM, &addr, DEFAULT_KPASSWD_PORT, - LONG_CONNECT_TIMEOUT); + NTSTATUS status; + status = open_socket_out(&addr, DEFAULT_KPASSWD_PORT, + LONG_CONNECT_TIMEOUT, &sock); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(ap_req.data); + krb5_auth_con_free(context, auth_context); + DEBUG(1,("failed to open kpasswd socket to %s " + "(%s)\n", kdc_host, + nt_errstr(status))); + return ADS_ERROR_NT(status); + } } - if (sock == -1) { - int rc = errno; - SAFE_FREE(ap_req.data); - krb5_auth_con_free(context, auth_context); - DEBUG(1,("failed to open kpasswd socket to %s (%s)\n", - kdc_host, strerror(errno))); - return ADS_ERROR_SYSTEM(rc); - } addr_len = sizeof(remote_addr); if (getpeername(sock, (struct sockaddr *)&remote_addr, &addr_len) != 0) { close(sock); diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 82a919455a..a1fcf8eb07 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -435,7 +435,7 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, req->async = tmp_reqs; req->num_async += 1; - req->async[req->num_async-1] = async_req_new(mem_ctx, ev); + req->async[req->num_async-1] = async_req_new(mem_ctx); if (req->async[req->num_async-1] == NULL) { DEBUG(0, ("async_req_new failed\n")); req->num_async -= 1; diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 5892bdc859..6ddc249c04 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1494,17 +1494,17 @@ bool cli_session_request(struct cli_state *cli, */ uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); struct in_addr dest_ip; + NTSTATUS status; /* SESSION RETARGET */ putip((char *)&dest_ip,cli->inbuf+4); in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip); - cli->fd = open_socket_out(SOCK_STREAM, - &cli->dest_ss, - port, - LONG_CONNECT_TIMEOUT); - if (cli->fd == -1) + status = open_socket_out(&cli->dest_ss, port, + LONG_CONNECT_TIMEOUT, &cli->fd); + if (!NT_STATUS_IS_OK(status)) { return False; + } DEBUG(3,("Retargeted\n")); @@ -1533,6 +1533,78 @@ bool cli_session_request(struct cli_state *cli, return(True); } +static void smb_sock_connected(struct async_req *req) +{ + int *pfd = (int *)req->async.priv; + int fd; + NTSTATUS status; + + status = open_socket_out_defer_recv(req, &fd); + if (NT_STATUS_IS_OK(status)) { + *pfd = fd; + } +} + +static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss, + uint16_t *port, int timeout, int *pfd) +{ + struct event_context *ev; + struct async_req *r139, *r445; + int fd139 = -1; + int fd445 = -1; + NTSTATUS status; + + if (*port != 0) { + return open_socket_out(pss, *port, timeout, pfd); + } + + ev = event_context_init(talloc_tos()); + if (ev == NULL) { + return NT_STATUS_NO_MEMORY; + } + + r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0), + pss, 445, timeout); + r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000), + pss, 139, timeout); + if ((r445 == NULL) || (r139 == NULL)) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + r445->async.fn = smb_sock_connected; + r445->async.priv = &fd445; + r139->async.fn = smb_sock_connected; + r139->async.priv = &fd139; + + while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE) + && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) { + event_loop_once(ev); + } + + if ((fd139 != -1) && (fd445 != -1)) { + close(fd139); + fd139 = -1; + } + + if (fd445 != -1) { + *port = 445; + *pfd = fd445; + status = NT_STATUS_OK; + goto done; + } + if (fd139 != -1) { + *port = 139; + *pfd = fd139; + status = NT_STATUS_OK; + goto done; + } + + status = open_socket_out_defer_recv(r445, &fd445); + done: + TALLOC_FREE(ev); + return status; +} + /**************************************************************************** Open the client sockets. ****************************************************************************/ @@ -1587,16 +1659,11 @@ NTSTATUS cli_connect(struct cli_state *cli, if (getenv("LIBSMB_PROG")) { cli->fd = sock_exec(getenv("LIBSMB_PROG")); } else { - /* try 445 first, then 139 */ - uint16_t port = cli->port?cli->port:445; - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, - port, cli->timeout); - if (cli->fd == -1 && cli->port == 0) { - port = 139; - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ss, - port, cli->timeout); - } - if (cli->fd != -1) { + uint16_t port = cli->port; + NTSTATUS status; + status = open_smb_socket(&cli->dest_ss, &port, + cli->timeout, &cli->fd); + if (NT_STATUS_IS_OK(status)) { cli->port = port; } } diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 4597e63c98..ac68700fd0 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -54,8 +54,6 @@ static void cm_set_password(const char *newpass); static int port; static int name_type = 0x20; -static bool have_ip; -static struct sockaddr_storage dest_ss; static struct client_connection *connections; @@ -133,8 +131,11 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, } sharename = servicename; if (*sharename == '\\') { - server = sharename+2; - sharename = strchr_m(server,'\\'); + sharename += 2; + if (server == NULL) { + server = sharename; + } + sharename = strchr_m(sharename,'\\'); if (!sharename) { return NULL; } @@ -151,8 +152,6 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, again: zero_sockaddr(&ss); - if (have_ip) - ss = dest_ss; /* have to open a new connection */ if (!(c=cli_initialise()) || (cli_set_port(c, port) != port)) { @@ -550,15 +549,6 @@ void cli_cm_set_fallback_after_kerberos(void) cm_creds.fallback_after_kerberos = true; } -/**************************************************************************** -****************************************************************************/ - -void cli_cm_set_dest_ss(struct sockaddr_storage *pss) -{ - dest_ss = *pss; - have_ip = true; -} - /********************************************************************** split a dfs path into the server, share name, and extrapath components **********************************************************************/ diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index b33d0f0938..1d5582e61d 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -278,7 +278,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_pull_state *state; int i; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto failed; } @@ -302,7 +302,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->top_req = 0; if (size == 0) { - if (!async_post_status(result, NT_STATUS_OK)) { + if (!async_post_status(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -843,7 +843,7 @@ static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, struct async_req *subreq; struct cli_writeall_state *state; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto fail; } @@ -969,7 +969,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_push_state *state; int i; - result = async_req_new(mem_ctx, ev); + result = async_req_new(mem_ctx); if (result == NULL) { goto failed; } @@ -1034,7 +1034,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } if (i == 0) { - if (!async_post_status(result, NT_STATUS_OK)) { + if (!async_post_status(result, ev, NT_STATUS_OK)) { goto failed; } return result; diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 16b3b10925..af3f7b0dd5 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -1,7 +1,7 @@ /* Samba share mode database library external interface library. Used by non-Samba products needing access to the Samba share mode db. - + Copyright (C) Jeremy Allison 2005 - 2006 sharemodes_procid functions (C) Copyright (C) Volker Lendecke 2005 @@ -9,17 +9,17 @@ ** NOTE! The following LGPL license applies to this module only. ** This does NOT imply that all of Samba is released ** under the LGPL - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This library 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>. */ @@ -92,16 +92,16 @@ int smb_share_mode_db_close(struct smbdb_ctx *db_ctx) return ret; } -static TDB_DATA get_locking_key(uint64_t dev, uint64_t ino) +static TDB_DATA get_locking_key(struct locking_key *lk, uint64_t dev, + uint64_t ino) { - static struct locking_key lk; TDB_DATA ld; - memset(&lk, '\0', sizeof(struct locking_key)); - lk.dev = (SMB_DEV_T)dev; - lk.inode = (SMB_INO_T)ino; - ld.dptr = (uint8 *)&lk; - ld.dsize = sizeof(lk); + memset(lk, '\0', sizeof(*lk)); + lk->dev = (SMB_DEV_T)dev; + lk->inode = (SMB_INO_T)ino; + ld.dptr = (uint8 *)lk; + ld.dsize = sizeof(*lk); return ld; } @@ -113,14 +113,17 @@ int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino) { - return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(dev, ino)); + struct locking_key lk; + return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino)); } - + int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx, uint64_t dev, uint64_t ino) { - return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino)); + struct locking_key lk; + return tdb_chainunlock(db_ctx->smb_tdb, + get_locking_key(&lk, dev, ino)); } /* @@ -172,6 +175,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, struct smb_share_mode_entry **pp_list, unsigned char *p_delete_on_close) { + struct locking_key lk; TDB_DATA db_data; struct smb_share_mode_entry *list = NULL; int num_share_modes = 0; @@ -183,7 +187,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, *pp_list = NULL; *p_delete_on_close = 0; - db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(dev, ino)); + db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino)); if (!db_data.dptr) { return 0; } @@ -258,7 +262,8 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, const char *filename) /* Must be relative utf8 path. */ { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; @@ -371,7 +376,8 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, const struct smb_share_mode_entry *del_entry) { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; @@ -473,7 +479,8 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx, const struct smb_share_mode_entry *new_entry) { TDB_DATA db_data; - TDB_DATA locking_key = get_locking_key(dev, ino); + struct locking_key lk; + TDB_DATA locking_key = get_locking_key(&lk, dev, ino); int num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ struct share_mode_entry *shares = NULL; diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index a4a317d905..a86d39948d 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -1,8 +1,8 @@ /* * Unix SMB/CIFS implementation. * - * This file began with some code from source3/smbd/open.c and modified it to - * work with ifs_createfile. + * This file began with some code from source3/smbd/open.c and has been + * modified it work with ifs_createfile. * * ifs_createfile is a CIFS-specific syscall for opening/files and * directories. It adds support for: @@ -459,7 +459,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(req, conn, fname, req->vuid, fsp); + return print_fsp_open(req, conn, fname, req->vuid, fsp, psbuf); } if (!parent_dirname(talloc_tos(), fname, &parent_dir, &newname)) { diff --git a/source3/modules/vfs_smb_traffic_analyzer.c b/source3/modules/vfs_smb_traffic_analyzer.c index 63cc904bed..3ac5a4971b 100644 --- a/source3/modules/vfs_smb_traffic_analyzer.c +++ b/source3/modules/vfs_smb_traffic_analyzer.c @@ -78,6 +78,7 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle, for (res = ailist; res; res = res->ai_next) { struct sockaddr_storage ss; + NTSTATUS status; if (!res->ai_addr || res->ai_addrlen == 0) { continue; @@ -86,8 +87,8 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle, ZERO_STRUCT(ss); memcpy(&ss, res->ai_addr, res->ai_addrlen); - sockfd = open_socket_out(SOCK_STREAM, &ss, port, 10000); - if (sockfd != -1) { + status = open_socket_out(&ss, port, 10000, &sockfd); + if (NT_STATUS_IS_OK(status)) { break; } } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 274c79904e..cb0ba47572 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4630,7 +4630,7 @@ static void free_one_parameter_by_snum(int snum, struct parm_struct parm) { void *parm_ptr; - if (parm.ptr == NULL); { + if (parm.ptr == NULL) { return; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a2d334230d..3fd31e2867 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2618,9 +2618,8 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, goto fail; } - result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60); - if (result->trans.sock.fd == -1) { - status = map_nt_error_from_unix(errno); + status = open_socket_out(&addr, port, 60, &result->trans.sock.fd); + if (!NT_STATUS_IS_OK(status)) { goto fail; } diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 1cff95dcab..7d1f824234 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -105,8 +105,7 @@ static bool pipe_init_outgoing_data(pipes_struct *p) static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, const char *pipe_name, const char *client_address, - struct auth_serversupplied_info *server_info, - uint16_t vuid) + struct auth_serversupplied_info *server_info) { pipes_struct *p; @@ -1125,8 +1124,7 @@ NTSTATUS np_open(struct smb_request *smb_req, const char *name, p = make_internal_rpc_pipe_p(fsp->fake_file_handle, name, conn->client_address, - conn->server_info, - smb_req->vuid); + conn->server_info); fsp->fake_file_handle->type = FAKE_FILE_TYPE_NAMED_PIPE; fsp->fake_file_handle->private_data = p; diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 5199363fc3..a7916ef794 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -65,13 +65,8 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.0, - [], - [ - m4_include(../lib/tevent/libtevent.m4) - SMB_INCLUDE_MK(../lib/tevent/config.mk) - AC_CONFIG_FILES(../lib/tevent/tevent.pc) - ] +SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.2, + [],[m4_include(../lib/tevent/samba.m4)] ) SMB_INCLUDE_MK(../lib/tevent/python.mk) @@ -114,8 +109,6 @@ SMB_INCLUDE_MK(lib/ldb/python.mk) SMB_ENABLE(swig_ldb,YES) m4_include(lib/tls/config.m4) -teventdir="../lib/tevent" -m4_include(../lib/tevent/libtevent.m4) dnl m4_include(auth/kerberos/config.m4) m4_include(auth/gensec/config.m4) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8466e84179..67e6067b26 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -284,7 +284,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd, if (CVAL(lenbuf,0) == 0 && min_recv_size && - smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */ + smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */ !srv_is_signing_active()) { return receive_smb_raw_talloc_partial_read( diff --git a/source3/torture/nbio.c b/source3/torture/nbio.c index 81d0eb816b..a010c80985 100644 --- a/source3/torture/nbio.c +++ b/source3/torture/nbio.c @@ -111,7 +111,9 @@ static void sigsegv(int sig) printf("segv at line %d\n", line_count); slprintf(line, sizeof(line), "/usr/X11R6/bin/xterm -e gdb /proc/%d/exe %d", (int)getpid(), (int)getpid()); - system(line); + if (system(line) == -1) { + printf("system() failed\n"); + } exit(1); } @@ -280,10 +282,16 @@ static void delete_fn(const char *mnt, file_info *finfo, const char *name, void n = SMB_STRDUP(name); n[strlen(n)-1] = 0; - asprintf(&s, "%s%s", n, finfo->name); + if (asprintf(&s, "%s%s", n, finfo->name) == -1) { + printf("asprintf failed\n"); + return; + } if (finfo->mode & aDIR) { char *s2; - asprintf(&s2, "%s\\*", s); + if (asprintf(&s2, "%s\\*", s) == -1) { + printf("asprintf failed\n"); + return; + } cli_list(c, s2, aDIR, delete_fn, NULL); nb_rmdir(s); } else { @@ -297,7 +305,10 @@ static void delete_fn(const char *mnt, file_info *finfo, const char *name, void void nb_deltree(const char *dname) { char *mask; - asprintf(&mask, "%s\\*", dname); + if (asprintf(&mask, "%s\\*", dname) == -1) { + printf("asprintf failed\n"); + return; + } total_deleted = 0; cli_list(c, mask, aDIR, delete_fn, NULL); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 63942da2e5..8a1a61e79a 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -1213,7 +1213,9 @@ static bool run_tcon2_test(int dummy) printf("starting tcon2 test\n"); - asprintf(&service, "\\\\%s\\%s", host, share); + if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) { + return false; + } status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum); @@ -5280,8 +5282,13 @@ static bool run_local_rbtree(int dummy) for (i=0; i<1000; i++) { char *key, *value; - asprintf(&key, "key%ld", random()); - asprintf(&value, "value%ld", random()); + if (asprintf(&key, "key%ld", random()) == -1) { + goto done; + } + if (asprintf(&value, "value%ld", random()) == -1) { + SAFE_FREE(key); + goto done; + } if (!rbt_testval(db, key, value)) { SAFE_FREE(key); @@ -5290,7 +5297,10 @@ static bool run_local_rbtree(int dummy) } SAFE_FREE(value); - asprintf(&value, "value%ld", random()); + if (asprintf(&value, "value%ld", random()) == -1) { + SAFE_FREE(key); + goto done; + } if (!rbt_testval(db, key, value)) { SAFE_FREE(key); @@ -5483,6 +5493,70 @@ static bool run_local_memcache(int dummy) return ret; } +static void wbclient_done(struct async_req *req) +{ + NTSTATUS status; + struct winbindd_response *wb_resp; + int *i = (int *)req->async.priv; + + status = wb_trans_recv(req, req, &wb_resp); + TALLOC_FREE(req); + *i += 1; + d_printf("wb_trans_recv %d returned %s\n", *i, nt_errstr(status)); +} + +static bool run_local_wbclient(int dummy) +{ + struct event_context *ev; + struct wb_context **wb_ctx; + struct winbindd_request wb_req; + bool result = false; + int i, j; + + BlockSignals(True, SIGPIPE); + + ev = event_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + + wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, torture_numops); + if (wb_ctx == NULL) { + goto fail; + } + + ZERO_STRUCT(wb_req); + wb_req.cmd = WINBINDD_PING; + + for (i=0; i<torture_numops; i++) { + wb_ctx[i] = wb_context_init(ev); + if (wb_ctx[i] == NULL) { + goto fail; + } + for (j=0; j<5; j++) { + struct async_req *req; + req = wb_trans_send(ev, ev, wb_ctx[i], + (j % 2) == 0, &wb_req); + if (req == NULL) { + goto fail; + } + req->async.fn = wbclient_done; + req->async.priv = &i; + } + } + + i = 0; + + while (i < 5 * torture_numops) { + event_loop_once(ev); + } + + result = true; + fail: + TALLOC_FREE(ev); + return result; +} + static double create_procs(bool (*fn)(int), bool *result) { int i, status; @@ -5642,6 +5716,7 @@ static struct { { "LOCAL-RBTREE", run_local_rbtree, 0}, { "LOCAL-MEMCACHE", run_local_memcache, 0}, { "LOCAL-STREAM-NAME", run_local_stream_name, 0}, + { "LOCAL-WBCLIENT", run_local_wbclient, 0}, {NULL, NULL, 0}}; diff --git a/source3/torture/utable.c b/source3/torture/utable.c index 7032cea99b..e36b0388c4 100644 --- a/source3/torture/utable.c +++ b/source3/torture/utable.c @@ -84,7 +84,11 @@ bool torture_utable(int dummy) d_printf("Failed to create valid.dat - %s", strerror(errno)); return False; } - write(fd, valid, 0x10000); + if (write(fd, valid, 0x10000) != 0x10000) { + d_printf("Failed to create valid.dat - %s", strerror(errno)); + close(fd); + return false; + } close(fd); d_printf("wrote valid.dat\n"); diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c index 1e22a40201..1fdea818d6 100644 --- a/source3/utils/smbfilter.c +++ b/source3/utils/smbfilter.c @@ -141,10 +141,11 @@ static bool send_smb(int fd, char *buffer) static void filter_child(int c, struct sockaddr_storage *dest_ss) { - int s; + NTSTATUS status; + int s = -1; /* we have a connection from a new client, now connect to the server */ - s = open_socket_out(SOCK_STREAM, dest_ss, 445, LONG_CONNECT_TIMEOUT); + status = open_socket_out(dest_ss, 445, LONG_CONNECT_TIMEOUT, &s); if (s == -1) { char addr[INET6_ADDRSTRLEN]; diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index 6be55ef03c..ca07f230ab 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -735,6 +735,17 @@ NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id) maps[0] = id; maps[1] = NULL; + /* + * Always give passdb a chance first + */ + + dom = idmap_init_passdb_domain(NULL); + if ((dom != NULL) + && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps)) + && id->status == ID_MAPPED) { + return NT_STATUS_OK; + } + dom = idmap_find_domain(domname); if (dom == NULL) { return NT_STATUS_NONE_MAPPED; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 92ce1f9850..3869ac5771 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -88,15 +88,6 @@ struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, struct winbindd_response *wb_resp); NTSTATUS wb_resp_write_recv(struct async_req *req); -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, - struct winbindd_request *wb_req, - struct timeval timeout, - size_t reply_max_extra_data); -NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, - struct winbindd_response **presp); - /* The following definitions come from winbindd/winbindd_ads.c */ diff --git a/source4/auth/kerberos/config.mk b/source4/auth/kerberos/config.mk index b724b8df37..822bf398a7 100644 --- a/source4/auth/kerberos/config.mk +++ b/source4/auth/kerberos/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM KERBEROS [SUBSYSTEM::KERBEROS] PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 NDR_KRB5PAC samba_socket LIBCLI_RESOLVE -PRIVATE_DEPENDENCIES = ASN1_UTIL auth_sam_reply LIBPACKET LIBNDR +PRIVATE_DEPENDENCIES = ASN1_UTIL auth_sam_reply LIBTEVENT LIBPACKET LIBNDR # End SUBSYSTEM KERBEROS ################################# diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c index 2f0a2317a0..6e885842f3 100644 --- a/source4/auth/kerberos/krb5_init_context.c +++ b/source4/auth/kerberos/krb5_init_context.c @@ -22,11 +22,11 @@ #include "includes.h" #include "system/kerberos.h" +#include <tevent.h> #include "auth/kerberos/kerberos.h" #include "lib/socket/socket.h" #include "lib/stream/packet.h" #include "system/network.h" -#include "lib/events/events.h" #include "param/param.h" #include "libcli/resolve/resolve.h" @@ -159,9 +159,9 @@ static void smb_krb5_socket_send(struct smb_krb5_socket *smb_krb5) if (!NT_STATUS_IS_OK(status)) return; - EVENT_FD_READABLE(smb_krb5->fde); + TEVENT_FD_READABLE(smb_krb5->fde); - EVENT_FD_NOT_WRITEABLE(smb_krb5->fde); + TEVENT_FD_NOT_WRITEABLE(smb_krb5->fde); return; } @@ -175,22 +175,22 @@ static void smb_krb5_socket_handler(struct tevent_context *ev, struct tevent_fd struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); switch (smb_krb5->hi->proto) { case KRB5_KRBHST_UDP: - if (flags & EVENT_FD_READ) { + if (flags & TEVENT_FD_READ) { smb_krb5_socket_recv(smb_krb5); return; } - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { smb_krb5_socket_send(smb_krb5); return; } /* not reached */ return; case KRB5_KRBHST_TCP: - if (flags & EVENT_FD_READ) { + if (flags & TEVENT_FD_READ) { packet_recv(smb_krb5->packet); return; } - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { packet_queue_run(smb_krb5->packet); return; } @@ -284,24 +284,24 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, * drop) and mark as AUTOCLOSE along with the fde */ /* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */ - smb_krb5->fde = event_add_fd(ev, smb_krb5->sock, - socket_get_fd(smb_krb5->sock), - EVENT_FD_READ|EVENT_FD_AUTOCLOSE, - smb_krb5_socket_handler, smb_krb5); + smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock, + socket_get_fd(smb_krb5->sock), + TEVENT_FD_READ, + smb_krb5_socket_handler, smb_krb5); /* its now the job of the event layer to close the socket */ + tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn); socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE); - event_add_timed(ev, smb_krb5, - timeval_current_ofs(timeout, 0), - smb_krb5_request_timeout, smb_krb5); + tevent_add_timer(ev, smb_krb5, + timeval_current_ofs(timeout, 0), + smb_krb5_request_timeout, smb_krb5); - smb_krb5->status = NT_STATUS_OK; smb_krb5->reply = data_blob(NULL, 0); switch (hi->proto) { case KRB5_KRBHST_UDP: - EVENT_FD_WRITEABLE(smb_krb5->fde); + TEVENT_FD_WRITEABLE(smb_krb5->fde); smb_krb5->request = send_blob; break; case KRB5_KRBHST_TCP: @@ -329,7 +329,7 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, return EINVAL; } while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { - if (event_loop_once(ev) != 0) { + if (tevent_loop_once(ev) != 0) { talloc_free(smb_krb5); return EINVAL; } diff --git a/source4/build/m4/public.m4 b/source4/build/m4/public.m4 index 5be4189e06..e51a8ac146 100644 --- a/source4/build/m4/public.m4 +++ b/source4/build/m4/public.m4 @@ -155,6 +155,14 @@ SMB_INFO_ENABLES="$SMB_INFO_ENABLES \$enabled{$1} = \"$2\";" ]) +dnl SMB_MAKE_SETTINGS(text) +AC_DEFUN([SMB_MAKE_SETTINGS], +[ +MAKE_SETTINGS="$MAKE_SETTINGS +$1 +" +]) + dnl SMB_WRITE_MAKEVARS(path, skip_vars) AC_DEFUN([SMB_WRITE_MAKEVARS], [ diff --git a/source4/configure.ac b/source4/configure.ac index debdc39d58..6c8fb0efc2 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -60,13 +60,8 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.0, - [], - [ - m4_include(../lib/tevent/libtevent.m4) - SMB_INCLUDE_MK(../lib/tevent/config.mk) - AC_CONFIG_FILES(../lib/tevent/tevent.pc) - ] +SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent >= 0.9.2, + [],[m4_include(../lib/tevent/samba.m4)] ) SMB_INCLUDE_MK(../lib/tevent/python.mk) diff --git a/source4/headermap.txt b/source4/headermap.txt index d5e70a7304..c27ec2f2de 100644 --- a/source4/headermap.txt +++ b/source4/headermap.txt @@ -49,11 +49,8 @@ param/share.h: share.h ../lib/util/util_tdb.h: util_tdb.h ../lib/util/util_ldb.h: util_ldb.h ../lib/util/wrap_xattr.h: wrap_xattr.h -lib/events/events.h: events/events.h -lib/events/events_internal.h: events/events_internal.h libcli/ldap/ldap_ndr.h: ldap_ndr.h lib/events/events.h: events.h -lib/events/events_internal.h: events_internal.h ../lib/tevent/tevent.h: tevent.h ../lib/tevent/tevent_internal.h: tevent_internal.h auth/session.h: samba/session.h diff --git a/source4/lib/events/config.mk b/source4/lib/events/config.mk index a1b2cd218a..c07a21bc75 100644 --- a/source4/lib/events/config.mk +++ b/source4/lib/events/config.mk @@ -4,4 +4,4 @@ CFLAGS = -Ilib/events LIBEVENTS_OBJ_FILES = $(addprefix $(libeventssrcdir)/, tevent_s4.o) -PUBLIC_HEADERS += $(addprefix $(libeventssrcdir)/, events.h events_internal.h) +PUBLIC_HEADERS += $(addprefix $(libeventssrcdir)/, events.h) diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h index 698ff2919b..1b2dbde32b 100644 --- a/source4/lib/events/events.h +++ b/source4/lib/events/events.h @@ -3,5 +3,5 @@ #define TEVENT_COMPAT_DEFINES 1 #include <../lib/tevent/tevent.h> struct tevent_context *s4_event_context_init(TALLOC_CTX *mem_ctx); -struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx); +struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx) _DEPRECATED_; #endif /* __LIB_EVENTS_H__ */ diff --git a/source4/lib/events/events_internal.h b/source4/lib/events/events_internal.h deleted file mode 100644 index 055bfe1a92..0000000000 --- a/source4/lib/events/events_internal.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __LIB_EVENTS_INTERNAL_H__ -#define __LIB_EVENTS_INTERNAL_H__ -#define TEVENT_COMPAT_DEFINES 1 -#include <../lib/tevent/tevent_internal.h> -#endif /* __LIB_EVENTS_INTERNAL_H__ */ diff --git a/source4/lib/events/tevent_s4.c b/source4/lib/events/tevent_s4.c index b3de7e667a..34a34a8e0b 100644 --- a/source4/lib/events/tevent_s4.c +++ b/source4/lib/events/tevent_s4.c @@ -17,38 +17,37 @@ */ #include "includes.h" -#include <events.h> -#include <events_internal.h> +#include "lib/events/events.h" /* this is used to catch debug messages from events */ -static void ev_wrap_debug(void *context, enum ev_debug_level level, +static void ev_wrap_debug(void *context, enum tevent_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); -static void ev_wrap_debug(void *context, enum ev_debug_level level, +static void ev_wrap_debug(void *context, enum tevent_debug_level level, const char *fmt, va_list ap) { int samba_level = -1; char *s = NULL; switch (level) { - case EV_DEBUG_FATAL: + case TEVENT_DEBUG_FATAL: samba_level = 0; break; - case EV_DEBUG_ERROR: + case TEVENT_DEBUG_ERROR: samba_level = 1; break; - case EV_DEBUG_WARNING: + case TEVENT_DEBUG_WARNING: samba_level = 2; break; - case EV_DEBUG_TRACE: + case TEVENT_DEBUG_TRACE: samba_level = 5; break; }; vasprintf(&s, fmt, ap); if (!s) return; - DEBUG(samba_level, ("events: %s\n", s)); + DEBUG(samba_level, ("tevent: %s\n", s)); free(s); } @@ -63,10 +62,27 @@ struct tevent_context *s4_event_context_init(TALLOC_CTX *mem_ctx) { struct tevent_context *ev; - ev = event_context_init_byname(mem_ctx, NULL); + ev = tevent_context_init_byname(mem_ctx, NULL); if (ev) { - ev_set_debug(ev, ev_wrap_debug, NULL); + tevent_set_debug(ev, ev_wrap_debug, NULL); } return ev; } +/* + find an event context that is a parent of the given memory context, + or create a new event context as a child of the given context if + none is found + + This should be used in preference to event_context_init() in places + where you would prefer to use the existing event context if possible + (which is most situations) +*/ +struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx) +{ + struct tevent_context *ev = talloc_find_parent_bytype(mem_ctx, struct tevent_context); + if (ev == NULL) { + ev = tevent_context_init(mem_ctx); + } + return ev; +} diff --git a/source4/lib/registry/pyregistry.c b/source4/lib/registry/pyregistry.c index 2d2f2fb685..357305c4de 100644 --- a/source4/lib/registry/pyregistry.c +++ b/source4/lib/registry/pyregistry.c @@ -357,7 +357,7 @@ static PyObject *py_open_ldb_file(PyObject *self, PyObject *args, PyObject *kwar session_info = NULL; /* FIXME */ result = reg_open_ldb_file(NULL, location, session_info, credentials, - event_context_init(NULL), lp_ctx, &key); + tevent_context_init(NULL), lp_ctx, &key); PyErr_WERROR_IS_ERR_RAISE(result); return py_talloc_import(&PyHiveKey, key); diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index a869ed4440..4cbcb09a10 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -543,7 +543,7 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key, if (vk->data_length & 0x80000000) { vk->data_length &=~0x80000000; - data->data = (uint8_t *)&vk->data_offset; + data->data = talloc_memdup(ctx, (uint8_t *)&vk->data_offset, vk->data_length); data->length = vk->data_length; } else { *data = hbin_get(regf, vk->data_offset); @@ -2045,7 +2045,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, struct tdr_pull *pull; int i; - regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); + regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data); regf->iconv_convenience = iconv_convenience; diff --git a/source4/lib/registry/tools/common.c b/source4/lib/registry/tools/common.c index c9f1248bf8..d997cb0fde 100644 --- a/source4/lib/registry/tools/common.c +++ b/source4/lib/registry/tools/common.c @@ -51,7 +51,7 @@ struct registry_key *reg_common_open_file(const char *path, struct registry_context *h = NULL; WERROR error; - error = reg_open_hive(NULL, path, NULL, creds, ev_ctx, lp_ctx, &hive_root); + error = reg_open_hive(ev_ctx, path, NULL, creds, ev_ctx, lp_ctx, &hive_root); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s': %s \n", diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index cca009a0e2..948ed49312 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -55,13 +55,16 @@ static void print_tree(int level, struct registry_key *p, &keyname, NULL, NULL)); i++) { - SMB_ASSERT(strlen(keyname) > 0); + + SMB_ASSERT(strlen(keyname) > 0); if (!W_ERROR_IS_OK(reg_open_key(mem_ctx, p, keyname, &subkey))) - continue; + continue; + print_tree(level+1, subkey, (fullpath && strlen(name))? - talloc_asprintf(mem_ctx, "%s\\%s", - name, keyname): - keyname, fullpath, novals); + talloc_asprintf(mem_ctx, "%s\\%s", + name, keyname): + keyname, fullpath, novals); + talloc_free(subkey); } talloc_free(mem_ctx); diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 26cdac99a3..9d30e0a77e 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -37,6 +37,15 @@ static int socket_destructor(struct socket_context *sock) return 0; } +_PUBLIC_ void socket_tevent_fd_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data) +{ + /* this might be the socket_wrapper swrap_close() */ + close(fd); +} + _PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops, struct socket_context **new_sock, enum socket_type type, uint32_t flags) diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 7a27e3070b..e9338127c4 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -21,6 +21,7 @@ #define _SAMBA_SOCKET_H struct tevent_context; +struct tevent_fd; struct socket_context; enum socket_type { @@ -205,6 +206,11 @@ NTSTATUS socket_connect_multi(TALLOC_CTX *mem_ctx, const char *server_address, void set_socket_options(int fd, const char *options); void socket_set_flags(struct socket_context *socket, unsigned flags); +void socket_tevent_fd_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data); + extern bool testnonblock; #endif /* _SAMBA_SOCKET_H */ diff --git a/source4/libcli/ldap/config.mk b/source4/libcli/ldap/config.mk index 2e50596dad..11157c5b63 100644 --- a/source4/libcli/ldap/config.mk +++ b/source4/libcli/ldap/config.mk @@ -1,5 +1,5 @@ [SUBSYSTEM::LIBCLI_LDAP] -PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBEVENTS LIBPACKET +PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTEVENT LIBPACKET PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE samba_socket NDR_SAMR LIBTLS ASN1_UTIL \ LDAP_ENCODE LIBNDR LP_RESOLVE gensec diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index 18784135cc..e30d5032fb 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -23,10 +23,10 @@ */ #include "includes.h" +#include <tevent.h> +#include "lib/socket/socket.h" #include "../lib/util/asn1.h" #include "../lib/util/dlinklist.h" -#include "lib/events/events.h" -#include "lib/socket/socket.h" #include "libcli/ldap/ldap.h" #include "libcli/ldap/ldap_proto.h" #include "libcli/ldap/ldap_client.h" @@ -229,11 +229,11 @@ static void ldap_io_handler(struct tevent_context *ev, struct tevent_fd *fde, { struct ldap_connection *conn = talloc_get_type(private_data, struct ldap_connection); - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { packet_queue_run(conn->packet); if (!tls_enabled(conn->sock)) return; } - if (flags & EVENT_FD_READ) { + if (flags & TEVENT_FD_READ) { ldap_read_io_handler(private_data, flags); } } @@ -387,14 +387,15 @@ static void ldap_connect_got_sock(struct composite_context *ctx, struct ldap_connection *conn) { /* setup a handler for events on this socket */ - conn->event.fde = event_add_fd(conn->event.event_ctx, conn->sock, - socket_get_fd(conn->sock), - EVENT_FD_READ | EVENT_FD_AUTOCLOSE, ldap_io_handler, conn); + conn->event.fde = tevent_add_fd(conn->event.event_ctx, conn->sock, + socket_get_fd(conn->sock), + TEVENT_FD_READ, ldap_io_handler, conn); if (conn->event.fde == NULL) { composite_error(ctx, NT_STATUS_INTERNAL_ERROR); return; } + tevent_fd_set_close_fn(conn->event.fde, socket_tevent_fd_close_fn); socket_set_flags(conn->sock, SOCKET_FLAG_NOCLOSE); talloc_steal(conn, conn->sock); @@ -621,8 +622,8 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn, req->state = LDAP_REQUEST_DONE; /* we can't call the async callback now, as it isn't setup, so call it as next event */ - event_add_timed(conn->event.event_ctx, req, timeval_zero(), - ldap_request_complete, req); + tevent_add_timer(conn->event.event_ctx, req, timeval_zero(), + ldap_request_complete, req); return req; } @@ -630,17 +631,17 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn, DLIST_ADD(conn->pending, req); /* put a timeout on the request */ - req->time_event = event_add_timed(conn->event.event_ctx, req, - timeval_current_ofs(conn->timeout, 0), - ldap_request_timeout, req); + req->time_event = tevent_add_timer(conn->event.event_ctx, req, + timeval_current_ofs(conn->timeout, 0), + ldap_request_timeout, req); return req; failed: req->status = status; req->state = LDAP_REQUEST_ERROR; - event_add_timed(conn->event.event_ctx, req, timeval_zero(), - ldap_request_complete, req); + tevent_add_timer(conn->event.event_ctx, req, timeval_zero(), + ldap_request_complete, req); return req; } @@ -653,7 +654,7 @@ failed: _PUBLIC_ NTSTATUS ldap_request_wait(struct ldap_request *req) { while (req->state < LDAP_REQUEST_DONE) { - if (event_loop_once(req->conn->event.event_ctx) != 0) { + if (tevent_loop_once(req->conn->event.event_ctx) != 0) { req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; break; } @@ -768,7 +769,7 @@ _PUBLIC_ NTSTATUS ldap_result_n(struct ldap_request *req, int n, struct ldap_mes NT_STATUS_HAVE_NO_MEMORY(req); while (req->state < LDAP_REQUEST_DONE && n >= req->num_replies) { - if (event_loop_once(req->conn->event.event_ctx) != 0) { + if (tevent_loop_once(req->conn->event.event_ctx) != 0) { return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } } diff --git a/source4/ntvfs/posix/config.m4 b/source4/ntvfs/posix/config.m4 index fe1997b437..a6f79dfbb3 100644 --- a/source4/ntvfs/posix/config.m4 +++ b/source4/ntvfs/posix/config.m4 @@ -30,8 +30,7 @@ if test x"$ac_cv_func_ext_blkid_get_cache" = x"yes"; then SMB_ENABLE(BLKID,YES) fi -AC_CHECK_HEADERS(libaio.h) SMB_ENABLE(pvfs_aio,NO) -if test x"$ac_cv_header_libaio_h" = x"yes"; then +if test x"$tevent_cv_aio_support" = x"yes"; then SMB_ENABLE(pvfs_aio,YES) fi diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index ec1cdf3659..1d7949214a 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -29,7 +29,7 @@ pvfs_acl_nfs4_OBJ_FILES = $(ntvfssrcdir)/posix/pvfs_acl_nfs4.o ################################################ [SUBSYSTEM::pvfs_aio] -PRIVATE_DEPENDENCIES = LIBTEVENT LIBAIO_LINUX +PRIVATE_DEPENDENCIES = LIBTEVENT LIBTEVENT_EXT ################################################ pvfs_aio_OBJ_FILES = $(ntvfssrcdir)/posix/pvfs_aio.o diff --git a/source4/ntvfs/sysdep/inotify.c b/source4/ntvfs/sysdep/inotify.c index f7aa91dd0e..42aac0b097 100644 --- a/source4/ntvfs/sysdep/inotify.c +++ b/source4/ntvfs/sysdep/inotify.c @@ -23,8 +23,8 @@ #include "includes.h" #include "system/filesys.h" +#include <tevent.h> #include "ntvfs/sysdep/sys_notify.h" -#include "lib/events/events.h" #include "../lib/util/dlinklist.h" #include "libcli/raw/smb.h" #include "param/param.h" @@ -249,8 +249,11 @@ static void inotify_handler(struct tevent_context *ev, struct tevent_fd *fde, static NTSTATUS inotify_setup(struct sys_notify_context *ctx) { struct inotify_private *in; + struct tevent_fd *fde; + in = talloc(ctx, struct inotify_private); NT_STATUS_HAVE_NO_MEMORY(in); + in->fd = inotify_init(); if (in->fd == -1) { DEBUG(0,("Failed to init inotify - %s\n", strerror(errno))); @@ -263,8 +266,19 @@ static NTSTATUS inotify_setup(struct sys_notify_context *ctx) ctx->private_data = in; /* add a event waiting for the inotify fd to be readable */ - event_add_fd(ctx->ev, in, in->fd, EVENT_FD_READ|EVENT_FD_AUTOCLOSE, inotify_handler, in); - + fde = tevent_add_fd(ctx->ev, in, in->fd, + TEVENT_FD_READ, inotify_handler, in); + if (!fde) { + if (errno == 0) { + errno = ENOMEM; + } + DEBUG(0,("Failed to tevent_add_fd() - %s\n", strerror(errno))); + talloc_free(in); + return map_nt_error_from_unix(errno); + } + + tevent_fd_set_auto_close(fde); + return NT_STATUS_OK; } diff --git a/source4/selftest/tests.sh b/source4/selftest/tests.sh index 0a5bdf62cd..56cbacbdaf 100755 --- a/source4/selftest/tests.sh +++ b/source4/selftest/tests.sh @@ -401,7 +401,7 @@ plantest "samr.python" dc $SUBUNITRUN samba.tests.dcerpc.sam plantest "dcerpc.bare.python" dc $SUBUNITRUN samba.tests.dcerpc.bare plantest "unixinfo.python" dc $SUBUNITRUN samba.tests.dcerpc.unix plantest "samdb.python" none $SUBUNITRUN samba.tests.samdb -plantest "events.python" none PYTHONPATH="$PYTHONPATH:../lib/tevent" $SUBUNITRUN tests +plantest "tevent.python" none PYTHONPATH="$PYTHONPATH:../lib/tevent" $SUBUNITRUN tests plantest "messaging.python" none PYTHONPATH="$PYTHONPATH:lib/messaging/tests" $SUBUNITRUN bindings plantest "samba3sam.python" none PYTHONPATH="$PYTHONPATH:dsdb/samdb/ldb_modules/tests" $SUBUNITRUN samba3sam plantest "subunit.python" none $SUBUNITRUN subunit diff --git a/source4/smbd/config.mk b/source4/smbd/config.mk index e0b09f4b8c..a76d10cbe7 100644 --- a/source4/smbd/config.mk +++ b/source4/smbd/config.mk @@ -2,7 +2,7 @@ [SUBSYSTEM::service] PRIVATE_DEPENDENCIES = \ - LIBEVENTS MESSAGING samba_socket NDR_NAMED_PIPE_AUTH + LIBTEVENT MESSAGING samba_socket NDR_NAMED_PIPE_AUTH service_OBJ_FILES = $(addprefix $(smbdsrcdir)/, \ service.o \ @@ -21,6 +21,7 @@ $(eval $(call proto_header_template,$(smbdsrcdir)/pidfile.h,$(PIDFILE_OBJ_FILES: [BINARY::samba] INSTALLDIR = SBINDIR PRIVATE_DEPENDENCIES = \ + LIBEVENTS \ process_model \ service \ LIBSAMBA-HOSTCONFIG \ diff --git a/source4/smbd/server.c b/source4/smbd/server.c index c1683a48dc..df970661f1 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -266,7 +266,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ umask(0); DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING)); - DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2008\n")); + DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2009\n")); if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); @@ -323,7 +323,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ if (opt_interactive) { /* terminate when stdin goes away */ - stdin_event_flags = EVENT_FD_READ; + stdin_event_flags = TEVENT_FD_READ; } else { /* stay alive forever */ stdin_event_flags = 0; @@ -333,15 +333,15 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif - event_add_fd(event_ctx, event_ctx, 0, stdin_event_flags, - server_stdin_handler, - discard_const(binary_name)); + tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags, + server_stdin_handler, + discard_const(binary_name)); if (max_runtime) { - event_add_timed(event_ctx, event_ctx, - timeval_current_ofs(max_runtime, 0), - max_runtime_handler, - discard_const(binary_name)); + tevent_add_timer(event_ctx, event_ctx, + timeval_current_ofs(max_runtime, 0), + max_runtime_handler, + discard_const(binary_name)); } DEBUG(0,("%s: using '%s' process model\n", binary_name, model)); @@ -354,7 +354,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ /* wait for events - this is where smbd sits for most of its life */ - event_loop_wait(event_ctx); + tevent_loop_wait(event_ctx); /* as everything hangs off this event context, freeing it should initiate a clean shutdown of all services */ diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c index 94fd501ffe..02b71de7c3 100644 --- a/source4/smbd/service_named_pipe.c +++ b/source4/smbd/service_named_pipe.c @@ -20,7 +20,7 @@ */ #include "includes.h" -#include "lib/events/events.h" +#include <tevent.h> #include "lib/socket/socket.h" #include "smbd/service.h" #include "param/param.h" @@ -49,7 +49,7 @@ static void named_pipe_handover_connection(void *private_data) private_data, struct named_pipe_connection); struct stream_connection *conn = pipe_conn->connection; - EVENT_FD_NOT_WRITEABLE(conn->event.fde); + TEVENT_FD_NOT_WRITEABLE(conn->event.fde); if (!NT_STATUS_IS_OK(pipe_conn->status)) { stream_terminate_connection(conn, nt_errstr(pipe_conn->status)); @@ -64,7 +64,7 @@ static void named_pipe_handover_connection(void *private_data) talloc_free(pipe_conn); /* we're now ready to start receiving events on this stream */ - EVENT_FD_READABLE(conn->event.fde); + TEVENT_FD_READABLE(conn->event.fde); /* * hand over to the real pipe implementation, diff --git a/source4/smbd/service_stream.c b/source4/smbd/service_stream.c index ef98919f93..6dff01f4f3 100644 --- a/source4/smbd/service_stream.c +++ b/source4/smbd/service_stream.c @@ -21,8 +21,8 @@ */ #include "includes.h" +#include <tevent.h> #include "process_model.h" -#include "lib/events/events.h" #include "lib/socket/socket.h" #include "smbd/service.h" #include "smbd/service_stream.h" @@ -72,7 +72,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char * * and we don't want to read or write to the connection... */ - event_set_fd_flags(srv_conn->event.fde, 0); + tevent_fd_set_flags(srv_conn->event.fde, 0); return; } @@ -88,9 +88,9 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char static void stream_io_handler(struct stream_connection *conn, uint16_t flags) { conn->processing++; - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { conn->ops->send_handler(conn, flags); - } else if (flags & EVENT_FD_READ) { + } else if (flags & TEVENT_FD_READ) { conn->ops->recv_handler(conn, flags); } conn->processing--; @@ -144,9 +144,14 @@ NTSTATUS stream_new_connection_merge(struct tevent_context *ev, srv_conn->msg_ctx = msg_ctx; srv_conn->event.ctx = ev; srv_conn->lp_ctx = lp_ctx; - srv_conn->event.fde = event_add_fd(ev, srv_conn, socket_get_fd(sock), - EVENT_FD_READ, - stream_io_handler_fde, srv_conn); + srv_conn->event.fde = tevent_add_fd(ev, srv_conn, socket_get_fd(sock), + TEVENT_FD_READ, + stream_io_handler_fde, srv_conn); + if (!srv_conn->event.fde) { + talloc_free(srv_conn); + return NT_STATUS_NO_MEMORY; + } + *_srv_conn = srv_conn; return NT_STATUS_OK; } @@ -179,14 +184,19 @@ static void stream_new_connection(struct tevent_context *ev, srv_conn->ops = stream_socket->ops; srv_conn->event.ctx = ev; srv_conn->lp_ctx = lp_ctx; - srv_conn->event.fde = event_add_fd(ev, srv_conn, socket_get_fd(sock), - 0, stream_io_handler_fde, srv_conn); if (!socket_check_access(sock, "smbd", lp_hostsallow(NULL, lp_default_service(lp_ctx)), lp_hostsdeny(NULL, lp_default_service(lp_ctx)))) { stream_terminate_connection(srv_conn, "denied by access rules"); return; } + srv_conn->event.fde = tevent_add_fd(ev, srv_conn, socket_get_fd(sock), + 0, stream_io_handler_fde, srv_conn); + if (!srv_conn->event.fde) { + stream_terminate_connection(srv_conn, "tevent_add_fd() failed"); + return; + } + /* setup to receive internal messages on this connection */ srv_conn->msg_ctx = messaging_init(srv_conn, lp_messaging_path(srv_conn, lp_ctx), @@ -214,7 +224,7 @@ static void stream_new_connection(struct tevent_context *ev, talloc_free(s); /* we're now ready to start receiving events on this stream */ - EVENT_FD_READABLE(srv_conn->event.fde); + TEVENT_FD_READABLE(srv_conn->event.fde); /* call the server specific accept code */ stream_socket->ops->accept_connection(srv_conn); @@ -258,6 +268,7 @@ NTSTATUS stream_setup_socket(struct tevent_context *event_context, NTSTATUS status; struct stream_socket *stream_socket; struct socket_address *socket_address; + struct tevent_fd *fde; int i; stream_socket = talloc_zero(event_context, struct stream_socket); @@ -322,20 +333,24 @@ NTSTATUS stream_setup_socket(struct tevent_context *event_context, return status; } - /* By specifying EVENT_FD_AUTOCLOSE below, we indicate that we - * will close the socket using the events system. This avoids - * nasty interactions with waiting for talloc to close the socket. */ - - socket_set_flags(stream_socket->sock, SOCKET_FLAG_NOCLOSE); - /* Add the FD from the newly created socket into the event * subsystem. it will call the accept handler whenever we get * new connections */ - event_add_fd(event_context, stream_socket->sock, - socket_get_fd(stream_socket->sock), - EVENT_FD_READ|EVENT_FD_AUTOCLOSE, - stream_accept_handler, stream_socket); + fde = tevent_add_fd(event_context, stream_socket->sock, + socket_get_fd(stream_socket->sock), + TEVENT_FD_READ, + stream_accept_handler, stream_socket); + if (!fde) { + DEBUG(0,("Failed to setup fd event\n")); + talloc_free(stream_socket); + return NT_STATUS_NO_MEMORY; + } + + /* we let events system to the close on the socket. This avoids + * nasty interactions with waiting for talloc to close the socket. */ + tevent_fd_set_close_fn(fde, socket_tevent_fd_close_fn); + socket_set_flags(stream_socket->sock, SOCKET_FLAG_NOCLOSE); stream_socket->private = talloc_reference(stream_socket, private); stream_socket->ops = stream_ops; diff --git a/source4/smbd/service_task.c b/source4/smbd/service_task.c index 34ce755b93..d3951a4a9a 100644 --- a/source4/smbd/service_task.c +++ b/source4/smbd/service_task.c @@ -21,7 +21,6 @@ #include "includes.h" #include "process_model.h" -#include "lib/events/events.h" #include "smbd/service.h" #include "smbd/service_task.h" #include "lib/messaging/irpc.h" diff --git a/source4/torture/util_smb.c b/source4/torture/util_smb.c index f88a641059..732b84af73 100644 --- a/source4/torture/util_smb.c +++ b/source4/torture/util_smb.c @@ -656,7 +656,10 @@ double torture_create_procs(struct torture_context *tctx, pid_t mypid = getpid(); srandom(((int)mypid) ^ ((int)time(NULL))); - asprintf(&myname, "CLIENT%d", i); + if (asprintf(&myname, "CLIENT%d", i) == -1) { + printf("asprintf failed\n"); + return -1; + } lp_set_cmdline(tctx->lp_ctx, "netbios name", myname); free(myname); diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c index 637cf10bb7..5953474c52 100644 --- a/source4/winbind/wb_init_domain.c +++ b/source4/winbind/wb_init_domain.c @@ -402,8 +402,7 @@ static void init_domain_recv_samr(struct composite_context *ctx) talloc_steal(state->domain->libnet_ctx->samr.pipe, state->domain->samr_binding); state->domain->libnet_ctx->samr.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; state->domain->libnet_ctx->samr.name = state->domain->info->name; - state->domain->libnet_ctx->samr.sid = dom_sid_dup(state->ctx, - state->domain->info->sid); + state->domain->libnet_ctx->samr.sid = state->domain->info->sid; composite_done(state->ctx); } diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c index 6cad76b08b..6af92668a3 100644 --- a/source4/winbind/wb_samba3_cmd.c +++ b/source4/winbind/wb_samba3_cmd.c @@ -115,7 +115,7 @@ NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call) { const char *path = s3call->wbconn->listen_socket->service->priv_socket_path; s3call->response.result = WINBINDD_OK; - WBSRV_SAMBA3_SET_STRING(s3call->response.extra_data.data, path); + s3call->response.extra_data.data = discard_const(path); s3call->response.length += strlen(path) + 1; return NT_STATUS_OK; |