diff options
37 files changed, 706 insertions, 459 deletions
diff --git a/docs-xml/manpages-3/smbclient.1.xml b/docs-xml/manpages-3/smbclient.1.xml index e2662cc08d..188ff11bb0 100644 --- a/docs-xml/manpages-3/smbclient.1.xml +++ b/docs-xml/manpages-3/smbclient.1.xml @@ -13,7 +13,7 @@ <refnamediv> <refname>smbclient</refname> - <refpurpose>ftp-like client to access SMB/CIFS resources + <refpurpose>ftp-like client to access SMB/CIFS resources on servers</refpurpose> </refnamediv> @@ -30,6 +30,7 @@ <arg choice="opt">-m maxprotocol</arg> <arg choice="opt">-A authfile</arg> <arg choice="opt">-N</arg> + <arg choice="opt">-g</arg> <arg choice="opt">-i scope</arg> <arg choice="opt">-O <socket options></arg> <arg choice="opt">-p port</arg> @@ -39,7 +40,7 @@ <arg choice="opt">-P</arg> <arg choice="opt">-c <command></arg> </cmdsynopsis> - + <cmdsynopsis> <command>smbclient</command> <arg choice="req">servicename</arg> @@ -54,6 +55,7 @@ <arg choice="opt">-m maxprotocol</arg> <arg choice="opt">-A authfile</arg> <arg choice="opt">-N</arg> + <arg choice="opt">-g</arg> <arg choice="opt">-l log-basename</arg> <arg choice="opt">-I destinationIP</arg> <arg choice="opt">-E</arg> @@ -233,7 +235,7 @@ on your WfWg PCs if you want them to always be able to receive messages. </para></listitem> </varlistentry> - + <varlistentry> <term>-p port</term> <listitem><para>This number is the TCP port number that will be used @@ -241,19 +243,27 @@ TCP port number for an SMB/CIFS server is 139, which is the default. </para></listitem> </varlistentry> - + + <varlistentry> + <term>-g</term> + <listitem><para>This parameter provides combined with + <parameter>-L</parameter> easy parseable output that allows processing + with utilities such as grep and cut. + </para></listitem> + </varlistentry> + <varlistentry> <term>-P</term> <listitem><para> Make queries to the external server using the machine account of the local server. </para></listitem> </varlistentry> - + &stdarg.help; - + <varlistentry> <term>-I IP-address</term> - <listitem><para><replaceable>IP address</replaceable> is the address of the server to connect to. + <listitem><para><replaceable>IP address</replaceable> is the address of the server to connect to. It should be specified in standard "a.b.c.d" notation. </para> <para>Normally the client would attempt to locate a named diff --git a/examples/perfcounter/perfcountd.init b/examples/perfcounter/perfcountd.init index 683e91395b..0beff96227 100755 --- a/examples/perfcounter/perfcountd.init +++ b/examples/perfcounter/perfcountd.init @@ -21,17 +21,17 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin -killproc() +killproc() { pid=`ps aux | grep $1 | egrep -v '(grep|perfcountd)' | awk '{print $2}'` - if [ "$pid" != "" ]; then + if [ x"$pid" != "x" ]; then kill $pid fi } -# Start/stop processes +# Start/stop processes -case "$1" +case "$1" in start) /opt/samba/bin/perfcount -d -f /var/lib/samba/perfmon 2> /dev/null @@ -47,7 +47,7 @@ stop) status) pid=`ps aux | grep perfcount | egrep -v '(grep|perfcountd)' | awk '{print $2}'` - if [ "$pid" == "" ]; then + if [ x"$pid" = "x" ]; then echo "Dead!" exit 2; fi diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h index fe3da81791..0b3e74492c 100644 --- a/nsswitch/winbind_struct_protocol.h +++ b/nsswitch/winbind_struct_protocol.h @@ -484,31 +484,4 @@ struct winbindd_response { } extra_data; }; -struct WINBINDD_MEMORY_CREDS { - struct WINBINDD_MEMORY_CREDS *next, *prev; - const char *username; /* lookup key. */ - uid_t uid; - int ref_count; - size_t len; - uint8_t *nt_hash; /* Base pointer for the following 2 */ - uint8_t *lm_hash; - char *pass; -}; - -struct WINBINDD_CCACHE_ENTRY { - struct WINBINDD_CCACHE_ENTRY *next, *prev; - const char *principal_name; - const char *ccname; - const char *service; - const char *username; - const char *realm; - struct WINBINDD_MEMORY_CREDS *cred_ptr; - int ref_count; - uid_t uid; - time_t create_time; - time_t renew_until; - time_t refresh_time; - struct timed_event *event; -}; - #endif diff --git a/source3/Makefile.in b/source3/Makefile.in index c13f5ae20a..d938b94ee0 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -359,7 +359,8 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \ lib/iconv.o lib/pam_errors.o intl/lang_tdb.o lib/conn_tdb.o \ lib/adt_tree.o lib/gencache.o \ - lib/module.o lib/events.o lib/ldap_escape.o @CHARSET_STATIC@ \ + lib/module.o lib/events.o @LIBTEVENT_OBJ0@ \ + lib/ldap_escape.o @CHARSET_STATIC@ \ lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o \ libads/krb5_errs.o lib/system_smbd.o lib/audit.o $(LIBNDR_OBJ) \ lib/file_id.o lib/idmap_cache.o diff --git a/source3/client/client.c b/source3/client/client.c index 529f21ab30..c40c04e9c6 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1353,6 +1353,11 @@ static int cmd_mget(void) do_list(mget_mask, attribute, do_mget, false, true); } + if (mget_mask == NULL) { + d_printf("nothing to mget\n"); + return 0; + } + if (!*mget_mask) { mget_mask = talloc_asprintf(ctx, "%s*", diff --git a/source3/configure.in b/source3/configure.in index fc3cb261d4..6727181e1c 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -31,6 +31,15 @@ for obj in ${TALLOC_OBJ}; do done AC_SUBST(LIBTALLOC_OBJ0) +m4_include(../lib/tevent/libtevent.m4) + +LIBTEVENT_OBJ0="" +for obj in ${TEVENT_OBJ}; do + LIBTEVENT_OBJ0="${LIBTEVENT_OBJ0} ${teventdir}/${obj}" +done +AC_SUBST(LIBTEVENT_OBJ0) +LIBS="${LIBS} ${TEVENT_LIBS}" + # TODO: These should come from m4_include(lib/tdb/libtdb.m4) # but currently this fails: things have to get merged from s4. tdbdir="../lib/tdb" @@ -50,6 +59,7 @@ AC_SUBST(LIBTDB_OBJ0) SAMBA_CPPFLAGS="-Iinclude -I${srcdir-.}/include -I. -I${srcdir-.}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/../lib/replace" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TALLOC_CFLAGS}" +SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TEVENT_CFLAGS}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TDB_CFLAGS}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/libaddns" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/librpc" diff --git a/source3/include/event.h b/source3/include/event.h index 0465fae471..93112a86fa 100644 --- a/source3/include/event.h +++ b/source3/include/event.h @@ -18,7 +18,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* bits for file descriptor event flags */ -#define EVENT_FD_READ 1 -#define EVENT_FD_WRITE 2 +#define TEVENT_COMPAT_DEFINES +#include <tevent.h> + +#undef event_context_init +#define event_context_init(mem_ctx) s3_tevent_context_init(mem_ctx) + +/* The following definitions come from lib/events.c */ + +void event_fd_set_writeable(struct fd_event *fde); +void event_fd_set_not_writeable(struct fd_event *fde); +void event_fd_set_readable(struct fd_event *fde); +void event_fd_set_not_readable(struct fd_event *fde); +bool event_add_to_select_args(struct event_context *event_ctx, + const struct timeval *now, + fd_set *read_fds, fd_set *write_fds, + struct timeval *timeout, int *maxfd); +bool run_events(struct event_context *event_ctx, + int selrtn, fd_set *read_fds, fd_set *write_fds); +struct timeval *get_timed_events_timeout(struct event_context *event_ctx, + struct timeval *to_ret); +void event_context_reinit(struct event_context *ev); +void dump_event_list(struct event_context *event_ctx); +struct tevent_context *s3_tevent_context_init(TALLOC_CTX *mem_ctx); diff --git a/source3/include/includes.h b/source3/include/includes.h index 64be27336d..8b0ff71c4e 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -574,6 +574,8 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "../talloc/talloc.h" +#include "event.h" + #include "../lib/util/data_blob.h" #include "../lib/util/time.h" #include "../lib/util/asn1.h" @@ -642,7 +644,6 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx); #include "nsswitch/winbind_client.h" #include "spnego.h" #include "rpc_client.h" -#include "event.h" #include "dbwrap.h" #include "packet.h" #include "ctdbd_conn.h" diff --git a/source3/include/proto.h b/source3/include/proto.h index 09f12ceb86..22183118e2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -501,46 +501,6 @@ void display_set_stderr(void); NTSTATUS map_nt_error_from_unix(int unix_error); int map_errno_from_nt_status(NTSTATUS status); -/* The following definitions come from lib/events.c */ - -struct timed_event *event_add_timed(struct event_context *event_ctx, - TALLOC_CTX *mem_ctx, - struct timeval when, - const char *event_name, - void (*handler)(struct event_context *event_ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data), - void *private_data); -struct fd_event *event_add_fd(struct event_context *event_ctx, - TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - void (*handler)(struct event_context *event_ctx, - struct fd_event *event, - uint16 flags, - void *private_data), - void *private_data); -void event_fd_set_writeable(struct fd_event *fde); -void event_fd_set_not_writeable(struct fd_event *fde); -void event_fd_set_readable(struct fd_event *fde); -void event_fd_set_not_readable(struct fd_event *fde); -bool event_add_to_select_args(struct event_context *event_ctx, - const struct timeval *now, - fd_set *read_fds, fd_set *write_fds, - struct timeval *timeout, int *maxfd); -bool events_pending(struct event_context *event_ctx); -bool run_events(struct event_context *event_ctx, - int selrtn, fd_set *read_fds, fd_set *write_fds); -struct timeval *get_timed_events_timeout(struct event_context *event_ctx, - struct timeval *to_ret); -int event_loop_once(struct event_context *ev); -struct event_context *event_context_init(TALLOC_CTX *mem_ctx); -int set_event_dispatch_time(struct event_context *event_ctx, - const char *event_name, struct timeval when); -int cancel_named_event(struct event_context *event_ctx, - const char *event_name); -void dump_event_list(struct event_context *event_ctx); - /* The following definitions come from lib/fault.c */ void fault_setup(void (*fn)(void *)); void dump_core_setup(const char *progname); @@ -1183,6 +1143,7 @@ int set_blocking(int fd, bool set); void smb_msleep(unsigned int t); void become_daemon(bool Fork, bool no_process_group); bool reinit_after_fork(struct messaging_context *msg_ctx, + struct event_context *ev_ctx, bool parent_longlived); bool yesno(const char *p); void *malloc_(size_t size); diff --git a/source3/include/smb.h b/source3/include/smb.h index 7fd4fbb553..9f6a6f02d7 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -361,9 +361,6 @@ struct fd_handle { unsigned long gen_id; }; -struct event_context; -struct fd_event; -struct timed_event; struct idle_event; struct share_mode_entry; struct uuid; diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c index ac06df65a3..13b64ba79a 100644 --- a/source3/lib/async_req.c +++ b/source3/lib/async_req.c @@ -103,12 +103,12 @@ void async_req_error(struct async_req *req, NTSTATUS status) * @brief Timed event callback * @param[in] ev Event context * @param[in] te The timed event - * @param[in] now current time + * @param[in] now zero time * @param[in] priv The async request to be finished */ static void async_trigger(struct event_context *ev, struct timed_event *te, - const struct timeval *now, void *priv) + struct timeval now, void *priv) { struct async_req *req = talloc_get_type_abort(priv, struct async_req); @@ -139,7 +139,7 @@ bool async_post_status(struct async_req *req, struct event_context *ev, { req->status = status; - if (event_add_timed(ev, req, timeval_zero(), "async_trigger", + if (event_add_timed(ev, req, timeval_zero(), async_trigger, req) == NULL) { return false; } @@ -197,7 +197,7 @@ NTSTATUS async_req_simple_recv(struct async_req *req) static void async_req_timedout(struct event_context *ev, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *priv) { struct async_req *req = talloc_get_type_abort( @@ -211,7 +211,7 @@ bool async_req_set_timeout(struct async_req *req, struct event_context *ev, { return (event_add_timed(ev, req, timeval_current_ofs(to.tv_sec, to.tv_usec), - "async_req_timedout", async_req_timedout, req) + async_req_timedout, req) != NULL); } @@ -268,7 +268,7 @@ static int async_queue_entry_destructor(struct async_queue_entry *e) static void async_req_immediate_trigger(struct event_context *ev, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *priv) { struct async_queue_entry *e = talloc_get_type_abort( @@ -303,7 +303,6 @@ bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev, struct timed_event *te; te = event_add_timed(ev, e, timeval_zero(), - "async_req_immediate_trigger", async_req_immediate_trigger, e); if (te == NULL) { diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index 75a513312e..c94ef802c4 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -200,7 +200,7 @@ struct deferred_msg_state { static void deferred_message_dispatch(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct deferred_msg_state *state = talloc_get_type_abort( @@ -383,7 +383,6 @@ static NTSTATUS ctdb_read_req(struct ctdbd_connection *conn, uint32 reqid, evt = event_add_timed(conn->msg_ctx->event_ctx, conn->msg_ctx->event_ctx, timeval_zero(), - "deferred_message_dispatch", deferred_message_dispatch, msg_state); if (evt == NULL) { diff --git a/source3/lib/events.c b/source3/lib/events.c index 8bbc9497ac..be2fdcb68f 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -19,52 +19,19 @@ */ #include "includes.h" +#include <tevent_internal.h> -struct timed_event { - struct timed_event *next, *prev; - struct event_context *event_ctx; - struct timeval when; - const char *event_name; - void (*handler)(struct event_context *event_ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data); - void *private_data; +struct s3_event_context { + struct tevent_context *ev; + struct tevent_fd *fd_events; }; -struct fd_event { - struct fd_event *prev, *next; - struct event_context *event_ctx; - int fd; - uint16_t flags; /* see EVENT_FD_* flags */ - void (*handler)(struct event_context *event_ctx, - struct fd_event *event, - uint16 flags, - void *private_data); - void *private_data; -}; - -#define EVENT_FD_WRITEABLE(fde) \ - event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE) -#define EVENT_FD_READABLE(fde) \ - event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ) - -#define EVENT_FD_NOT_WRITEABLE(fde) \ - event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) -#define EVENT_FD_NOT_READABLE(fde) \ - event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ) - -struct event_context { - struct timed_event *timed_events; - struct fd_event *fd_events; -}; - -static int timed_event_destructor(struct timed_event *te) +static int s3_event_timer_destructor(struct tevent_timer *te) { - DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, - te->event_name)); + DEBUG(10, ("Destroying timer event %p \"%s\"\n", + te, te->handler_name)); if (te->event_ctx != NULL) { - DLIST_REMOVE(te->event_ctx->timed_events, te); + DLIST_REMOVE(te->event_ctx->timer_events, te); } return 0; } @@ -73,23 +40,23 @@ static int timed_event_destructor(struct timed_event *te) Add te by time. ****************************************************************************/ -static void add_event_by_time(struct timed_event *te) +static void add_event_by_time(struct tevent_timer *te) { - struct event_context *ctx = te->event_ctx; - struct timed_event *last_te, *cur_te; + struct tevent_context *ctx = te->event_ctx; + struct tevent_timer *last_te, *cur_te; /* Keep the list ordered by time. We must preserve this. */ last_te = NULL; - for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) { + for (cur_te = ctx->timer_events; cur_te; cur_te = cur_te->next) { /* if the new event comes before the current one break */ - if (!timeval_is_zero(&cur_te->when) && - timeval_compare(&te->when, &cur_te->when) < 0) { + if (!timeval_is_zero(&cur_te->next_event) && + timeval_compare(&te->next_event, &cur_te->next_event) < 0) { break; } last_te = cur_te; } - DLIST_ADD_AFTER(ctx->timed_events, te, last_te); + DLIST_ADD_AFTER(ctx->timer_events, te, last_te); } /**************************************************************************** @@ -98,115 +65,128 @@ static void add_event_by_time(struct timed_event *te) handed to it. ****************************************************************************/ -struct timed_event *event_add_timed(struct event_context *event_ctx, - TALLOC_CTX *mem_ctx, - struct timeval when, - const char *event_name, - void (*handler)(struct event_context *event_ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data), - void *private_data) +static struct tevent_timer *s3_event_add_timer(struct tevent_context *event_ctx, + TALLOC_CTX *mem_ctx, + struct timeval when, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) { - struct timed_event *te; + struct tevent_timer *te; - te = TALLOC_P(mem_ctx, struct timed_event); + te = TALLOC_P(mem_ctx, struct tevent_timer); if (te == NULL) { DEBUG(0, ("talloc failed\n")); return NULL; } te->event_ctx = event_ctx; - te->when = when; - te->event_name = event_name; + te->next_event = when; te->handler = handler; te->private_data = private_data; + te->handler_name = handler_name; + te->location = location; + te->additional_data = NULL; add_event_by_time(te); - talloc_set_destructor(te, timed_event_destructor); + talloc_set_destructor(te, s3_event_timer_destructor); - DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, - (unsigned long)te)); + DEBUG(10, ("Added timed event \"%s\": %p\n", handler_name, te)); return te; } -static int fd_event_destructor(struct fd_event *fde) +static int s3_event_fd_destructor(struct tevent_fd *fde) { if (fde->event_ctx != NULL) { - DLIST_REMOVE(fde->event_ctx->fd_events, fde); + struct s3_event_context *ev3; + ev3 = talloc_get_type(fde->event_ctx->additional_data, + struct s3_event_context); + DLIST_REMOVE(ev3->fd_events, fde); + } + if (fde->close_fn) { + fde->close_fn(fde->event_ctx, fde, fde->fd, fde->private_data); + fde->fd = -1; } return 0; } -struct fd_event *event_add_fd(struct event_context *event_ctx, - TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - void (*handler)(struct event_context *event_ctx, - struct fd_event *event, - uint16 flags, - void *private_data), - void *private_data) +static struct tevent_fd *s3_event_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) { - struct fd_event *fde; + struct s3_event_context *ev3 = talloc_get_type(ev->additional_data, + struct s3_event_context); + struct tevent_fd *fde; - if (!(fde = TALLOC_P(mem_ctx, struct fd_event))) { + if (!(fde = TALLOC_P(mem_ctx, struct tevent_fd))) { return NULL; } - fde->event_ctx = event_ctx; + fde->event_ctx = ev; 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; - DLIST_ADD(event_ctx->fd_events, fde); + DLIST_ADD(ev3->fd_events, fde); - talloc_set_destructor(fde, fd_event_destructor); + talloc_set_destructor(fde, s3_event_fd_destructor); return fde; } -void event_fd_set_writeable(struct fd_event *fde) +void event_fd_set_writeable(struct tevent_fd *fde) { - fde->flags |= EVENT_FD_WRITE; + TEVENT_FD_WRITEABLE(fde); } -void event_fd_set_not_writeable(struct fd_event *fde) +void event_fd_set_not_writeable(struct tevent_fd *fde) { - fde->flags &= ~EVENT_FD_WRITE; + TEVENT_FD_NOT_WRITEABLE(fde); } -void event_fd_set_readable(struct fd_event *fde) +void event_fd_set_readable(struct tevent_fd *fde) { - fde->flags |= EVENT_FD_READ; + TEVENT_FD_READABLE(fde); } -void event_fd_set_not_readable(struct fd_event *fde) +void event_fd_set_not_readable(struct tevent_fd *fde) { - fde->flags &= ~EVENT_FD_READ; + TEVENT_FD_NOT_READABLE(fde); } /* * Return if there's something in the queue */ -bool event_add_to_select_args(struct event_context *event_ctx, +bool event_add_to_select_args(struct tevent_context *ev, const struct timeval *now, fd_set *read_fds, fd_set *write_fds, struct timeval *timeout, int *maxfd) { - struct fd_event *fde; + struct s3_event_context *ev3 = talloc_get_type(ev->additional_data, + struct s3_event_context); + struct tevent_fd *fde; struct timeval diff; - bool ret = False; + bool ret = false; - for (fde = event_ctx->fd_events; fde; fde = fde->next) { + for (fde = ev3->fd_events; fde; fde = fde->next) { if (fde->flags & EVENT_FD_READ) { FD_SET(fde->fd, read_fds); - ret = True; + ret = true; } if (fde->flags & EVENT_FD_WRITE) { FD_SET(fde->fd, write_fds); - ret = True; + ret = true; } if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) @@ -215,61 +195,48 @@ bool event_add_to_select_args(struct event_context *event_ctx, } } - if (event_ctx->timed_events == NULL) { + if (ev->timer_events == NULL) { return ret; } - diff = timeval_until(now, &event_ctx->timed_events->when); + diff = timeval_until(now, &ev->timer_events->next_event); *timeout = timeval_min(timeout, &diff); - return True; + return true; } -bool events_pending(struct event_context *event_ctx) -{ - struct fd_event *fde; - - if (event_ctx->timed_events != NULL) { - return True; - } - for (fde = event_ctx->fd_events; fde; fde = fde->next) { - if (fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) { - return True; - } - } - return False; -} - -bool run_events(struct event_context *event_ctx, +bool run_events(struct tevent_context *ev, int selrtn, fd_set *read_fds, fd_set *write_fds) { - bool fired = False; - struct fd_event *fde, *next; + struct s3_event_context *ev3 = talloc_get_type(ev->additional_data, + struct s3_event_context); + bool fired = false; + struct tevent_fd *fde, *next; /* Run all events that are pending, not just one (as we did previously. */ - while (event_ctx->timed_events) { + while (ev->timer_events) { struct timeval now; GetTimeOfDay(&now); if (timeval_compare( - &now, &event_ctx->timed_events->when) < 0) { + &now, &ev->timer_events->next_event) < 0) { /* Nothing to do yet */ DEBUG(11, ("run_events: Nothing to do\n")); break; } - DEBUG(10, ("Running event \"%s\" %lx\n", - event_ctx->timed_events->event_name, - (unsigned long)event_ctx->timed_events)); + DEBUG(10, ("Running event \"%s\" %p\n", + ev->timer_events->handler_name, + ev->timer_events)); - event_ctx->timed_events->handler( - event_ctx, - event_ctx->timed_events, &now, - event_ctx->timed_events->private_data); + ev->timer_events->handler( + ev, + ev->timer_events, now, + ev->timer_events->private_data); - fired = True; + fired = true; } if (fired) { @@ -277,7 +244,7 @@ bool run_events(struct event_context *event_ctx, * We might have changed the socket status during the timed * events, return to run select again. */ - return True; + return true; } if (selrtn == 0) { @@ -287,7 +254,7 @@ bool run_events(struct event_context *event_ctx, return fired; } - for (fde = event_ctx->fd_events; fde; fde = next) { + for (fde = ev3->fd_events; fde; fde = next) { uint16 flags = 0; next = fde->next; @@ -295,8 +262,8 @@ bool run_events(struct event_context *event_ctx, if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE; if (flags & fde->flags) { - fde->handler(event_ctx, fde, flags, fde->private_data); - fired = True; + fde->handler(ev, fde, flags, fde->private_data); + fired = true; } } @@ -304,17 +271,17 @@ bool run_events(struct event_context *event_ctx, } -struct timeval *get_timed_events_timeout(struct event_context *event_ctx, +struct timeval *get_timed_events_timeout(struct tevent_context *ev, struct timeval *to_ret) { struct timeval now; - if (event_ctx->timed_events == NULL) { + if (ev->timer_events == NULL) { return NULL; } now = timeval_current(); - *to_ret = timeval_until(&now, &event_ctx->timed_events->when); + *to_ret = timeval_until(&now, &ev->timer_events->next_event); DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec, (int)to_ret->tv_usec)); @@ -322,7 +289,7 @@ struct timeval *get_timed_events_timeout(struct event_context *event_ctx, return to_ret; } -int event_loop_once(struct event_context *ev) +static int s3_event_loop_once(struct tevent_context *ev) { struct timeval now, to; fd_set r_fds, w_fds; @@ -356,71 +323,60 @@ int event_loop_once(struct event_context *ev) return 0; } -static int event_context_destructor(struct event_context *ev) +static int s3_event_loop_wait(struct tevent_context *ev) { - while (ev->fd_events != NULL) { - ev->fd_events->event_ctx = NULL; - DLIST_REMOVE(ev->fd_events, ev->fd_events); - } - while (ev->timed_events != NULL) { - ev->timed_events->event_ctx = NULL; - DLIST_REMOVE(ev->timed_events, ev->timed_events); - } - return 0; -} + int ret = 0; -struct event_context *event_context_init(TALLOC_CTX *mem_ctx) -{ - struct event_context *result; - - result = TALLOC_ZERO_P(mem_ctx, struct event_context); - if (result == NULL) { - return NULL; + while (ret == 0) { + ret = s3_event_loop_once(ev); } - talloc_set_destructor(result, event_context_destructor); - return result; + return ret; } -int set_event_dispatch_time(struct event_context *event_ctx, - const char *event_name, struct timeval when) +static int s3_event_context_destructor(struct tevent_context *ev) { - struct timed_event *te; - - for (te = event_ctx->timed_events; te; te = te->next) { - if (strcmp(event_name, te->event_name) == 0) { - DLIST_REMOVE(event_ctx->timed_events, te); - te->when = when; - add_event_by_time(te); - return 1; - } + struct s3_event_context *ev3 = talloc_get_type(ev->additional_data, + struct s3_event_context); + while (ev3->fd_events != NULL) { + ev3->fd_events->event_ctx = NULL; + DLIST_REMOVE(ev3->fd_events, ev3->fd_events); + } + while (ev->timer_events != NULL) { + ev->timer_events->event_ctx = NULL; + DLIST_REMOVE(ev->timer_events, ev3->ev->timer_events); } return 0; } -/* Returns 1 if event was found and cancelled, 0 otherwise. */ +void event_context_reinit(struct tevent_context *ev) +{ + s3_event_context_destructor(ev); + return; +} -int cancel_named_event(struct event_context *event_ctx, - const char *event_name) +static int s3_event_context_init(struct tevent_context *ev) { - struct timed_event *te; + struct s3_event_context *ev3; - for (te = event_ctx->timed_events; te; te = te->next) { - if (strcmp(event_name, te->event_name) == 0) { - TALLOC_FREE(te); - return 1; - } - } + ev3 = talloc_zero(ev, struct s3_event_context); + if (!ev3) return -1; + ev3->ev = ev; + + ev->additional_data = ev3; + talloc_set_destructor(ev, s3_event_context_destructor); return 0; } -void dump_event_list(struct event_context *event_ctx) +void dump_event_list(struct tevent_context *ev) { - struct timed_event *te; - struct fd_event *fe; + struct s3_event_context *ev3 = talloc_get_type(ev->additional_data, + struct s3_event_context); + struct tevent_timer *te; + struct tevent_fd *fe; struct timeval evt, now; - if (!event_ctx) { + if (!ev) { return; } @@ -428,22 +384,50 @@ void dump_event_list(struct event_context *event_ctx) DEBUG(10,("dump_event_list:\n")); - for (te = event_ctx->timed_events; te; te = te->next) { + for (te = ev->timer_events; te; te = te->next) { - evt = timeval_until(&now, &te->when); + evt = timeval_until(&now, &te->next_event); - DEBUGADD(10,("Timed Event \"%s\" %lx handled in %d seconds (at %s)\n", - te->event_name, - (unsigned long)te, + DEBUGADD(10,("Timed Event \"%s\" %p handled in %d seconds (at %s)\n", + te->handler_name, + te, (int)evt.tv_sec, - http_timestring(talloc_tos(), te->when.tv_sec))); + http_timestring(talloc_tos(), te->next_event.tv_sec))); } - for (fe = event_ctx->fd_events; fe; fe = fe->next) { + for (fe = ev3->fd_events; fe; fe = fe->next) { - DEBUGADD(10,("FD Event %d %lx, flags: 0x%04x\n", + DEBUGADD(10,("FD Event %d %p, flags: 0x%04x\n", fe->fd, - (unsigned long)fe, + fe, fe->flags)); } } + +static const struct tevent_ops s3_event_ops = { + .context_init = s3_event_context_init, + .add_fd = s3_event_add_fd, + .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 = s3_event_add_timer, + .loop_once = s3_event_loop_once, + .loop_wait = s3_event_loop_wait, +}; + +static bool s3_tevent_init(void) +{ + static bool initialized; + if (initialized) { + return true; + } + initialized = tevent_register_backend("s3", &s3_event_ops); + tevent_set_default_backend("s3"); + return initialized; +} + +struct tevent_context *s3_tevent_context_init(TALLOC_CTX *mem_ctx) +{ + s3_tevent_init(); + return tevent_context_init_byname(mem_ctx, "s3"); +} diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index f2161dc946..f0561a5081 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1014,7 +1014,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ static void smbldap_idle_fn(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data); /********************************************************************** @@ -1079,7 +1079,7 @@ static int smbldap_open(struct smbldap_state *ldap_state) ldap_state->idle_event = event_add_timed( ldap_state->event_context, NULL, timeval_current_ofs(SMBLDAP_IDLE_TIME, 0), - "smbldap_idle_fn", smbldap_idle_fn, ldap_state); + smbldap_idle_fn, ldap_state); } DEBUG(4,("The LDAP server is successfully connected\n")); @@ -1572,7 +1572,7 @@ int smbldap_search_suffix (struct smbldap_state *ldap_state, static void smbldap_idle_fn(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct smbldap_state *state = (struct smbldap_state *)private_data; @@ -1584,13 +1584,13 @@ static void smbldap_idle_fn(struct event_context *event_ctx, return; } - if ((state->last_use+SMBLDAP_IDLE_TIME) > now->tv_sec) { + if ((state->last_use+SMBLDAP_IDLE_TIME) > now.tv_sec) { DEBUG(10,("ldap connection not idle...\n")); state->idle_event = event_add_timed( event_ctx, NULL, - timeval_add(now, SMBLDAP_IDLE_TIME, 0), - "smbldap_idle_fn", smbldap_idle_fn, + timeval_add(&now, SMBLDAP_IDLE_TIME, 0), + smbldap_idle_fn, private_data); return; } diff --git a/source3/lib/util.c b/source3/lib/util.c index d00a764c1d..08ea5add7a 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -949,6 +949,7 @@ void become_daemon(bool Fork, bool no_process_group) } bool reinit_after_fork(struct messaging_context *msg_ctx, + struct event_context *ev_ctx, bool parent_longlived) { NTSTATUS status; @@ -976,6 +977,8 @@ bool reinit_after_fork(struct messaging_context *msg_ctx, return false; } + event_context_reinit(ev_ctx); + return true; } diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c index 7914e8f401..30b14f280f 100644 --- a/source3/modules/vfs_aio_fork.c +++ b/source3/modules/vfs_aio_fork.c @@ -216,7 +216,7 @@ static ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) static void aio_child_cleanup(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct aio_child_list *list = talloc_get_type_abort( @@ -252,8 +252,7 @@ static void aio_child_cleanup(struct event_context *event_ctx, * Re-schedule the next cleanup round */ list->cleanup_event = event_add_timed(smbd_event_context(), list, - timeval_add(now, 30, 0), - "aio_child_cleanup", + timeval_add(&now, 30, 0), aio_child_cleanup, list); } @@ -284,7 +283,6 @@ static struct aio_child_list *init_aio_children(struct vfs_handle_struct *handle if (data->cleanup_event == NULL) { data->cleanup_event = event_add_timed(smbd_event_context(), data, timeval_current_ofs(30, 0), - "aio_child_cleanup", aio_child_cleanup, data); if (data->cleanup_event == NULL) { TALLOC_FREE(data); diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index ab9b1ed740..baa88bc44b 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -164,7 +164,8 @@ void start_async_dns(void) CatchSignal(SIGHUP, SIG_IGN); CatchSignal(SIGTERM, SIGNAL_CAST sig_term ); - if (!reinit_after_fork(nmbd_messaging_context(), true)) { + if (!reinit_after_fork(nmbd_messaging_context(), + nmbd_event_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index d1ab3aaacb..659db85e69 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -911,7 +911,8 @@ static bool open_sockets(bool isdaemon, int port) pidfile_create("nmbd"); - if (!reinit_after_fork(nmbd_messaging_context(), false)) { + if (!reinit_after_fork(nmbd_messaging_context(), + nmbd_event_context(), false)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index 565d81f82d..a4ef528133 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -52,7 +52,7 @@ static bool delay_logon(const char *peer_name, const char *peer_addr) static void delayed_init_logon_handler(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct packet_struct *p = (struct packet_struct *)private_data; @@ -657,7 +657,6 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", event_add_timed(nmbd_event_context(), NULL, when, - "delayed_init_logon", delayed_init_logon_handler, p); } else { diff --git a/source3/printing/notify.c b/source3/printing/notify.c index b24a8a52f5..860a400d64 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -221,7 +221,7 @@ void print_notify_send_messages(struct messaging_context *msg_ctx, static void print_notify_event_send_messages(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { /* Remove this timed event handler. */ @@ -326,7 +326,6 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer)); /* Add an event for 1 second's time to send this queue. */ notify_event = event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(1,0), - "print_notify", print_notify_event_send_messages, NULL); } diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index 5fb1d379a6..d75d635779 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -425,7 +425,8 @@ static bool cups_pcap_load_async(int *pfd) } /* Child. */ - if (!reinit_after_fork(smbd_messaging_context(), true)) { + if (!reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), true)) { DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n")); smb_panic("cups_pcap_load_async: reinit_after_fork() failed"); } diff --git a/source3/printing/printing.c b/source3/printing/printing.c index ba88f8ee56..0f38aeab80 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1421,7 +1421,8 @@ void start_background_queue(void) close(pause_pipe[0]); pause_pipe[0] = -1; - if (!reinit_after_fork(smbd_messaging_context(), true)) { + if (!reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 342f432c4e..24d14d720f 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -457,7 +457,7 @@ static void free_samr_info(void *ptr) static void disp_info_cache_idle_timeout_handler(struct event_context *ev_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { DISP_INFO *disp_info = (DISP_INFO *)private_data; @@ -486,7 +486,6 @@ static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromno disp_info->cache_timeout_event = event_add_timed( smbd_event_context(), NULL, timeval_current_ofs(secs_fromnow, 0), - "disp_info_cache_idle_timeout_handler", disp_info_cache_idle_timeout_handler, (void *)disp_info); } diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2237a89ace..2b90d24c87 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -68,7 +68,7 @@ static void process_blocking_lock_queue(void); static void brl_timeout_fn(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { SMB_ASSERT(brl_timeout == te); @@ -123,7 +123,7 @@ static bool recalc_brl_timeout(void) } if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL, - next_timeout, "brl_timeout", + next_timeout, brl_timeout_fn, NULL))) { return False; } diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c index 2319097ca5..c092251fee 100644 --- a/source3/smbd/dnsregister.c +++ b/source3/smbd/dnsregister.c @@ -85,7 +85,6 @@ static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state, event= event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0), - "DNS registration handler", dns_register_smbd_retry, dns_state); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index e67f926a04..30253d4466 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -173,7 +173,7 @@ static int wcp_file_size_change(files_struct *fsp) static void update_write_time_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { files_struct *fsp = (files_struct *)private_data; @@ -221,7 +221,6 @@ void trigger_write_time_update(struct files_struct *fsp) fsp->update_write_time_event = event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(0, delay), - "update_write_time_handler", update_write_time_handler, fsp); } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 261d8fd670..6efa3dcfc6 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -346,7 +346,7 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f static void oplock_timeout_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { files_struct *fsp = (files_struct *)private_data; @@ -373,7 +373,6 @@ static void add_oplock_timeout_handler(files_struct *fsp) fsp->oplock_timeout = event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), - "oplock_timeout_handler", oplock_timeout_handler, fsp); if (fsp->oplock_timeout == NULL) { diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 67e6067b26..cd9eaa6b1e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -583,26 +583,33 @@ struct idle_event { void *private_data; }; -static void idle_event_handler(struct event_context *ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) +static void smbd_idle_event_handler(struct event_context *ctx, + struct timed_event *te, + struct timeval now, + void *private_data) { struct idle_event *event = talloc_get_type_abort(private_data, struct idle_event); TALLOC_FREE(event->te); - if (!event->handler(now, event->private_data)) { + DEBUG(10,("smbd_idle_event_handler: %s %p called\n", + event->name, event->te)); + + if (!event->handler(&now, event->private_data)) { + DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n", + event->name, event->te)); /* Don't repeat, delete ourselves */ TALLOC_FREE(event); return; } + DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n", + event->name, event->te)); + event->te = event_add_timed(ctx, event, - timeval_sum(now, &event->interval), - event->name, - idle_event_handler, event); + timeval_sum(&now, &event->interval), + smbd_idle_event_handler, event); /* We can't do much but fail here. */ SMB_ASSERT(event->te != NULL); @@ -637,14 +644,14 @@ struct idle_event *event_add_idle(struct event_context *event_ctx, result->te = event_add_timed(event_ctx, result, timeval_sum(&now, &interval), - result->name, - idle_event_handler, result); + smbd_idle_event_handler, result); if (result->te == NULL) { DEBUG(0, ("event_add_timed failed\n")); TALLOC_FREE(result); return NULL; } + DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te)); return result; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 254180ae1c..a84b58a052 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -753,7 +753,9 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ false); if (!reinit_after_fork( - smbd_messaging_context(), true)) { + smbd_messaging_context(), + smbd_event_context(), + true)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } @@ -1327,7 +1329,8 @@ extern void build_options(bool screen); if (is_daemon) pidfile_create("smbd"); - if (!reinit_after_fork(smbd_messaging_context(), false)) { + if (!reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), false)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/utils/net_lua.c b/source3/utils/net_lua.c index 3a5d1bdeb6..e4af9b5577 100644 --- a/source3/utils/net_lua.c +++ b/source3/utils/net_lua.c @@ -248,7 +248,7 @@ static int evt_userdata_tostring(lua_State *L) { static void evt_userdata_sleep_done(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *priv) { struct thread_reference *ref = talloc_get_type_abort( @@ -279,7 +279,7 @@ static int evt_userdata_sleep(lua_State *L) } te = event_add_timed(p->ev, ref, timeval_current_ofs(0, usecs), - "evt_userdata_sleep", evt_userdata_sleep_done, + evt_userdata_sleep_done, ref); if (te == NULL) { diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 9d571f7ee3..330e7643cd 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -65,9 +65,9 @@ static bool send_message(struct messaging_context *msg_ctx, return ret; } -static void timeout_handler(struct event_context *event_ctx, +static void smbcontrol_timeout(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { bool *timed_out = (bool *)private_data; @@ -85,8 +85,7 @@ static void wait_replies(struct messaging_context *msg_ctx, if (!(te = event_add_timed(messaging_event_context(msg_ctx), NULL, timeval_current_ofs(timeout, 0), - "smbcontrol_timeout", - timeout_handler, (void *)&timed_out))) { + smbcontrol_timeout, (void *)&timed_out))) { DEBUG(0, ("event_add_timed failed\n")); return; } diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index e881ab412e..cf1dbf6f72 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -415,16 +415,16 @@ static void process_request(struct winbindd_cli_state *state) /* * A list of file descriptors being monitored by select in the main processing - * loop. fd_event->handler is called whenever the socket is readable/writable. + * loop. winbindd_fd_event->handler is called whenever the socket is readable/writable. */ -static struct fd_event *fd_events = NULL; +static struct winbindd_fd_event *fd_events = NULL; -void add_fd_event(struct fd_event *ev) +void add_fd_event(struct winbindd_fd_event *ev) { - struct fd_event *match; + struct winbindd_fd_event *match; - /* only add unique fd_event structs */ + /* only add unique winbindd_fd_event structs */ for (match=fd_events; match; match=match->next ) { #ifdef DEVELOPER @@ -438,17 +438,17 @@ void add_fd_event(struct fd_event *ev) DLIST_ADD(fd_events, ev); } -void remove_fd_event(struct fd_event *ev) +void remove_fd_event(struct winbindd_fd_event *ev) { DLIST_REMOVE(fd_events, ev); } /* - * Handler for fd_events to complete a read/write request, set up by + * Handler for winbindd_fd_events to complete a read/write request, set up by * setup_async_read/setup_async_write. */ -static void rw_callback(struct fd_event *event, int flags) +static void rw_callback(struct winbindd_fd_event *event, int flags) { size_t todo; ssize_t done = 0; @@ -489,11 +489,11 @@ static void rw_callback(struct fd_event *event, int flags) } /* - * Request an async read/write on a fd_event structure. (*finished) is called + * Request an async read/write on a winbindd_fd_event structure. (*finished) is called * when the request is completed or an error had occurred. */ -void setup_async_read(struct fd_event *event, void *data, size_t length, +void setup_async_read(struct winbindd_fd_event *event, void *data, size_t length, void (*finished)(void *private_data, bool success), void *private_data) { @@ -507,7 +507,7 @@ void setup_async_read(struct fd_event *event, void *data, size_t length, event->flags = EVENT_FD_READ; } -void setup_async_write(struct fd_event *event, void *data, size_t length, +void setup_async_write(struct winbindd_fd_event *event, void *data, size_t length, void (*finished)(void *private_data, bool success), void *private_data) { @@ -826,7 +826,7 @@ void winbind_check_sigterm(bool is_parent) static void process_loop(void) { struct winbindd_cli_state *state; - struct fd_event *ev; + struct winbindd_fd_event *ev; fd_set r_fds, w_fds; int maxfd, listen_sock, listen_priv_sock, selret; struct timeval timeout, ev_timeout; @@ -865,6 +865,13 @@ static void process_loop(void) timeout.tv_usec = 0; /* Check for any event timeouts. */ + { + struct timeval now; + GetTimeOfDay(&now); + + event_add_to_select_args(winbind_event_context(), &now, + &r_fds, &w_fds, &ev_timeout, &maxfd); + } if (get_timed_events_timeout(winbind_event_context(), &ev_timeout)) { timeout = timeval_min(&timeout, &ev_timeout); } @@ -918,9 +925,11 @@ static void process_loop(void) /* selret > 0 */ + run_events(winbind_event_context(), selret, &r_fds, &w_fds); + ev = fd_events; while (ev != NULL) { - struct fd_event *next = ev->next; + struct winbindd_fd_event *next = ev->next; int flags = 0; if (FD_ISSET(ev->fd, &r_fds)) flags |= EVENT_FD_READ; @@ -1191,7 +1200,8 @@ int main(int argc, char **argv, char **envp) TimeInit(); - if (!reinit_after_fork(winbind_messaging_context(), false)) { + if (!reinit_after_fork(winbind_messaging_context(), + winbind_event_context(), false)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 04b0b39f81..d8e6ec4c7f 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -39,15 +39,11 @@ #define WB_REPLACE_CHAR '_' -/* bits for fd_event.flags */ -#define EVENT_FD_READ 1 -#define EVENT_FD_WRITE 2 - -struct fd_event { - struct fd_event *next, *prev; +struct winbindd_fd_event { + struct winbindd_fd_event *next, *prev; int fd; int flags; /* see EVENT_FD_* flags */ - void (*handler)(struct fd_event *fde, int flags); + void (*handler)(struct winbindd_fd_event *fde, int flags); void *data; size_t length, done; void (*finished)(void *private_data, bool success); @@ -65,7 +61,7 @@ struct sid_ctr { struct winbindd_cli_state { struct winbindd_cli_state *prev, *next; /* Linked list pointers */ int sock; /* Open socket from client */ - struct fd_event fd_event; + struct winbindd_fd_event fd_event; pid_t pid; /* pid of client */ bool finished; /* Can delete from list */ bool write_extra_data; /* Write extra_data field */ @@ -151,7 +147,7 @@ struct winbindd_child { struct winbindd_domain *domain; char *logfilename; - struct fd_event event; + struct winbindd_fd_event event; struct timed_event *lockout_policy_event; struct timed_event *machine_password_change_event; struct winbindd_async_request *requests; @@ -377,7 +373,34 @@ enum ent_type { LIST_USERS = 0, LIST_GROUPS, }; - + +struct WINBINDD_MEMORY_CREDS { + struct WINBINDD_MEMORY_CREDS *next, *prev; + const char *username; /* lookup key. */ + uid_t uid; + int ref_count; + size_t len; + uint8_t *nt_hash; /* Base pointer for the following 2 */ + uint8_t *lm_hash; + char *pass; +}; + +struct WINBINDD_CCACHE_ENTRY { + struct WINBINDD_CCACHE_ENTRY *next, *prev; + const char *principal_name; + const char *ccname; + const char *service; + const char *username; + const char *realm; + struct WINBINDD_MEMORY_CREDS *cred_ptr; + int ref_count; + uid_t uid; + time_t create_time; + time_t renew_until; + time_t refresh_time; + struct timed_event *event; +}; + #include "winbindd/winbindd_proto.h" #define WINBINDD_ESTABLISH_LOOP 30 diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 3135b6a2a3..e5e3565604 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -212,7 +212,8 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) /* Leave messages blocked - we will never process one. */ - if (!reinit_after_fork(winbind_messaging_context(), true)) { + if (!reinit_after_fork(winbind_messaging_context(), + winbind_event_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); messaging_send_buf(winbind_messaging_context(), pid_to_procid(parent_pid), @@ -271,7 +272,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain) static void check_domain_online_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct winbindd_domain *domain = @@ -285,7 +286,7 @@ static void check_domain_online_handler(struct event_context *ctx, /* Are we still in "startup" mode ? */ - if (domain->startup && (now->tv_sec > domain->startup_time + 30)) { + if (domain->startup && (now.tv_sec > domain->startup_time + 30)) { /* No longer in "startup" mode. */ DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n", domain->name )); @@ -366,7 +367,6 @@ void set_domain_offline(struct winbindd_domain *domain) domain->check_online_event = event_add_timed(winbind_event_context(), NULL, timeval_current_ofs(domain->check_online_timeout,0), - "check_domain_online_handler", check_domain_online_handler, domain); @@ -402,8 +402,6 @@ void set_domain_offline(struct winbindd_domain *domain) static void set_domain_online(struct winbindd_domain *domain) { - struct timeval now; - DEBUG(10,("set_domain_online: called for domain %s\n", domain->name )); @@ -422,9 +420,7 @@ static void set_domain_online(struct winbindd_domain *domain) winbindd_set_locator_kdc_envs(domain); /* If we are waiting to get a krb5 ticket, trigger immediately. */ - GetTimeOfDay(&now); - set_event_dispatch_time(winbind_event_context(), - "krb5_ticket_gain_handler", now); + ccache_regain_all_now(); /* Ok, we're out of any startup mode now... */ domain->startup = False; @@ -497,6 +493,15 @@ void set_domain_online_request(struct winbindd_domain *domain) because network manager seems to lie. Wait at least 5 seconds. Heuristics suck... */ + + GetTimeOfDay(&tev); + + /* Go into "startup" mode again. */ + domain->startup_time = tev.tv_sec; + domain->startup = True; + + tev.tv_sec += 5; + if (!domain->check_online_event) { /* If we've come from being globally offline we don't have a check online event handler set. @@ -505,29 +510,20 @@ void set_domain_online_request(struct winbindd_domain *domain) DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n", domain->name )); - - domain->check_online_event = event_add_timed(winbind_event_context(), - NULL, - timeval_current_ofs(5, 0), - "check_domain_online_handler", - check_domain_online_handler, - domain); - - /* The above *has* to succeed for winbindd to work. */ - if (!domain->check_online_event) { - smb_panic("set_domain_online_request: failed to add online handler"); - } } - GetTimeOfDay(&tev); - - /* Go into "startup" mode again. */ - domain->startup_time = tev.tv_sec; - domain->startup = True; + TALLOC_FREE(domain->check_online_event); - tev.tv_sec += 5; + domain->check_online_event = event_add_timed(winbind_event_context(), + NULL, + tev, + check_domain_online_handler, + domain); - set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev); + /* The above *has* to succeed for winbindd to work. */ + if (!domain->check_online_event) { + smb_panic("set_domain_online_request: failed to add online handler"); + } } /**************************************************************** diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index 311b1d1822..900f9acdfa 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -34,6 +34,10 @@ #define MAX_CCACHES 100 static struct WINBINDD_CCACHE_ENTRY *ccache_list; +static void krb5_ticket_gain_handler(struct event_context *, + struct timed_event *, + struct timeval, + void *); /* The Krb5 ticket refresh handler should be scheduled at one-half of the period from now till the tkt @@ -71,13 +75,27 @@ static int ccache_entry_count(void) return i; } +void ccache_remove_all_after_fork(void) +{ + struct WINBINDD_CCACHE_ENTRY *cur, *next; + + for (cur = ccache_list; cur; cur = next) { + next = cur->next; + DLIST_REMOVE(ccache_list, cur); + TALLOC_FREE(cur->event); + TALLOC_FREE(cur); + } + + return; +} + /**************************************************************** Do the work of refreshing the ticket. ****************************************************************/ static void krb5_ticket_refresh_handler(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct WINBINDD_CCACHE_ENTRY *entry = @@ -85,6 +103,7 @@ static void krb5_ticket_refresh_handler(struct event_context *event_ctx, #ifdef HAVE_KRB5 int ret; time_t new_start; + time_t expire_time = 0; struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr; #endif @@ -97,44 +116,83 @@ static void krb5_ticket_refresh_handler(struct event_context *event_ctx, #ifdef HAVE_KRB5 /* Kinit again if we have the user password and we can't renew the old - * tgt anymore */ - - if ((entry->renew_until < time(NULL)) && cred_ptr && cred_ptr->pass) { - - set_effective_uid(entry->uid); - - ret = kerberos_kinit_password_ext(entry->principal_name, - cred_ptr->pass, - 0, /* hm, can we do time correction here ? */ - &entry->refresh_time, - &entry->renew_until, - entry->ccname, - False, /* no PAC required anymore */ - True, - WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, - NULL); - gain_root_privilege(); - - if (ret) { - DEBUG(3,("krb5_ticket_refresh_handler: " - "could not re-kinit: %s\n", - error_message(ret))); - TALLOC_FREE(entry->event); - return; - } - - DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit " - "for: %s in ccache: %s\n", - entry->principal_name, entry->ccname)); + * tgt anymore + * NB + * This happens when machine are put to sleep for a very long time. */ + + if (entry->renew_until < time(NULL)) { +rekinit: + if (cred_ptr && cred_ptr->pass) { + + set_effective_uid(entry->uid); + + ret = kerberos_kinit_password_ext(entry->principal_name, + cred_ptr->pass, + 0, /* hm, can we do time correction here ? */ + &entry->refresh_time, + &entry->renew_until, + entry->ccname, + False, /* no PAC required anymore */ + True, + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, + NULL); + gain_root_privilege(); + + if (ret) { + DEBUG(3,("krb5_ticket_refresh_handler: " + "could not re-kinit: %s\n", + error_message(ret))); + /* destroy the ticket because we cannot rekinit + * it, ignore error here */ + ads_kdestroy(entry->ccname); + + /* Don't break the ticket refresh chain: retry + * refreshing ticket sometime later when KDC is + * unreachable -- BoYang + * */ + + if ((ret == KRB5_KDC_UNREACH) + || (ret == KRB5_REALM_CANT_RESOLVE)) { +#if defined(DEBUG_KRB5_TKT_RENEWAL) + new_start = time(NULL) + 30; +#else + new_start = time(NULL) + + MAX(30, lp_winbind_cache_time()); +#endif + /* try to regain ticket here */ + entry->event = event_add_timed(winbind_event_context(), + entry, + timeval_set(new_start, 0), + krb5_ticket_gain_handler, + entry); + return; + } + TALLOC_FREE(entry->event); + return; + } + + DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit " + "for: %s in ccache: %s\n", + entry->principal_name, entry->ccname)); #if defined(DEBUG_KRB5_TKT_RENEWAL) - new_start = time(NULL) + 30; + new_start = time(NULL) + 30; #else - /* The tkt should be refreshed at one-half the period - from now to the expiration time */ - new_start = KRB5_EVENT_REFRESH_TIME(entry->refresh_time); + /* The tkt should be refreshed at one-half the period + from now to the expiration time */ + expire_time = entry->refresh_time; + new_start = KRB5_EVENT_REFRESH_TIME(entry->refresh_time); #endif - goto done; + goto done; + } else { + /* can this happen? + * No cached credentials + * destroy ticket and refresh chain + * */ + ads_kdestroy(entry->ccname); + TALLOC_FREE(entry->event); + return; + } } set_effective_uid(entry->uid); @@ -146,6 +204,7 @@ static void krb5_ticket_refresh_handler(struct event_context *event_ctx, #if defined(DEBUG_KRB5_TKT_RENEWAL) new_start = time(NULL) + 30; #else + expire_time = new_start; new_start = KRB5_EVENT_REFRESH_TIME(new_start); #endif @@ -157,24 +216,73 @@ static void krb5_ticket_refresh_handler(struct event_context *event_ctx, error_message(ret))); /* maybe we are beyond the renewing window */ + /* evil rises here, we refresh ticket failed, + * but the ticket might be expired. Therefore, + * When we refresh ticket failed, destory the + * ticket */ + + ads_kdestroy(entry->ccname); + /* avoid breaking the renewal chain: retry in * lp_winbind_cache_time() seconds when the KDC was not - * available right now. */ + * available right now. + * the return code can be KRB5_REALM_CANT_RESOLVE*/ - if (ret == KRB5_KDC_UNREACH) { + if ((ret == KRB5_KDC_UNREACH) + || (ret == KRB5_REALM_CANT_RESOLVE)) { +#if defined(DEBUG_KRB5_TKT_RENEWAL) + new_start = time(NULL) + 30; +#else new_start = time(NULL) + MAX(30, lp_winbind_cache_time()); - goto done; +#endif + /* ticket is destroyed here, we have to regain it + * if it is possible */ + entry->event = event_add_timed(winbind_event_context(), + entry, + timeval_set(new_start, 0), + krb5_ticket_gain_handler, + entry); + return; } + /* This is evil, if the ticket was already expired. + * renew ticket function returns KRB5KRB_AP_ERR_TKT_EXPIRED. + * But there is still a chance that we can rekinit it. + * + * This happens when user login in online mode, and then network + * down or something cause winbind goes offline for a very long time, + * and then goes online again. ticket expired, renew failed. + * This happens when machine are put to sleep for a long time, + * but shorter than entry->renew_util. + * NB + * Looks like the KDC is reachable, we want to rekinit as soon as + * possible instead of waiting some time later. */ + if ((ret == KRB5KRB_AP_ERR_TKT_EXPIRED) + || (ret == KRB5_FCC_NOFILE)) goto rekinit; + return; } done: + /* in cases that ticket will be unrenewable soon, we don't try to renew ticket + * but try to regain ticket if it is possible */ + if (entry->renew_until && expire_time + && (entry->renew_until <= expire_time)) { + /* try to regain ticket 10 seconds beforre expiration */ + expire_time -= 10; + entry->event = event_add_timed(winbind_event_context(), entry, + timeval_set(expire_time, 0), + krb5_ticket_gain_handler, + entry); + return; + } + if (entry->refresh_time == 0) { + entry->refresh_time = new_start; + } entry->event = event_add_timed(winbind_event_context(), entry, timeval_set(new_start, 0), - "krb5_ticket_refresh_handler", krb5_ticket_refresh_handler, entry); @@ -187,7 +295,7 @@ done: static void krb5_ticket_gain_handler(struct event_context *event_ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct WINBINDD_CCACHE_ENTRY *entry = @@ -239,6 +347,9 @@ static void krb5_ticket_gain_handler(struct event_context *event_ctx, DEBUG(3,("krb5_ticket_gain_handler: " "could not kinit: %s\n", error_message(ret))); + /* evil. If we cannot do it, destroy any the __maybe__ + * __existing__ ticket */ + ads_kdestroy(entry->ccname); goto retry_later; } @@ -249,13 +360,17 @@ static void krb5_ticket_gain_handler(struct event_context *event_ctx, goto got_ticket; retry_later: - + +#if defined(DEBUG_KRB5_TKT_REGAIN) + t = timeval_set(time(NULL) + 30, 0); +#else t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); +#endif + entry->refresh_time = 0; entry->event = event_add_timed(winbind_event_context(), entry, t, - "krb5_ticket_gain_handler", krb5_ticket_gain_handler, entry); @@ -269,10 +384,12 @@ static void krb5_ticket_gain_handler(struct event_context *event_ctx, t = timeval_set(KRB5_EVENT_REFRESH_TIME(entry->refresh_time), 0); #endif + if (entry->refresh_time == 0) { + entry->refresh_time = t.tv_sec; + } entry->event = event_add_timed(winbind_event_context(), entry, t, - "krb5_ticket_refresh_handler", krb5_ticket_refresh_handler, entry); @@ -280,6 +397,43 @@ static void krb5_ticket_gain_handler(struct event_context *event_ctx, #endif } +void ccache_regain_all_now(void) +{ + struct WINBINDD_CCACHE_ENTRY *cur; + struct timeval t = timeval_current(); + + for (cur = ccache_list; cur; cur = cur->next) { + struct timed_event *new_event; + + /* + * if refresh_time is 0, we know that the + * the event has the krb5_ticket_gain_handler + */ + if (cur->refresh_time == 0) { + new_event = event_add_timed(winbind_event_context(), + cur, + t, + krb5_ticket_gain_handler, + cur); + } else { + new_event = event_add_timed(winbind_event_context(), + cur, + t, + krb5_ticket_refresh_handler, + cur); + } + + if (!new_event) { + continue; + } + + TALLOC_FREE(cur->event); + cur->event = new_event; + } + + return; +} + /**************************************************************** Check if an ccache entry exists. ****************************************************************/ @@ -331,6 +485,10 @@ NTSTATUS add_ccache_to_list(const char *princ_name, { struct WINBINDD_CCACHE_ENTRY *entry = NULL; struct timeval t; + NTSTATUS ntret; +#ifdef HAVE_KRB5 + int ret; +#endif if ((username == NULL && princ_name == NULL) || ccname == NULL || uid < 0) { @@ -343,6 +501,28 @@ NTSTATUS add_ccache_to_list(const char *princ_name, return NT_STATUS_NO_MORE_ENTRIES; } + /* If it is cached login, destroy krb5 ticket + * to avoid surprise. */ +#ifdef HAVE_KRB5 + if (postponed_request) { + /* ignore KRB5_FCC_NOFILE error here */ + ret = ads_kdestroy(ccname); + if (ret == KRB5_FCC_NOFILE) { + ret = 0; + } + if (ret) { + DEBUG(0, ("add_ccache_to_list: failed to destroy " + "user krb5 ccache %s with %s\n", ccname, + error_message(ret))); + return krb5_to_nt_status(ret); + } else { + DEBUG(10, ("add_ccache_to_list: successfully destroyed " + "krb5 ccache %s for user %s\n", ccname, + username)); + } + } +#endif + /* Reference count old entries */ entry = get_ccache_by_username(username); if (entry) { @@ -355,7 +535,51 @@ NTSTATUS add_ccache_to_list(const char *princ_name, "ref count on entry %s is now %d\n", username, entry->ref_count)); /* FIXME: in this case we still might want to have a krb5 cred - * event handler created - gd*/ + * event handler created - gd + * Add ticket refresh handler here */ + + if (!lp_winbind_refresh_tickets() || renew_until <= 0) { + return NT_STATUS_OK; + } + + if (!entry->event) { + if (postponed_request) { + t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + krb5_ticket_gain_handler, + entry); + } else { + /* Renew at 1/2 the ticket expiration time */ +#if defined(DEBUG_KRB5_TKT_RENEWAL) + t = timeval_set(time(NULL)+30, 0); +#else + t = timeval_set(KRB5_EVENT_REFRESH_TIME(ticket_end), 0); +#endif + entry->event = event_add_timed(winbind_event_context(), + entry, + t, + krb5_ticket_refresh_handler, + entry); + } + + if (!entry->event) { + ntret = remove_ccache(username); + if (!NT_STATUS_IS_OK(ntret)) { + DEBUG(0, ("add_ccache_to_list: Failed to remove krb5 " + "ccache %s for user %s\n", entry->ccname, + entry->username)); + DEBUG(0, ("add_ccache_to_list: error is %s\n", + nt_errstr(ntret))); + return ntret; + } + return NT_STATUS_NO_MEMORY; + } + + DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n")); + } + return NT_STATUS_OK; } @@ -406,10 +630,10 @@ NTSTATUS add_ccache_to_list(const char *princ_name, if (postponed_request) { t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); + entry->refresh_time = 0; entry->event = event_add_timed(winbind_event_context(), entry, t, - "krb5_ticket_gain_handler", krb5_ticket_gain_handler, entry); } else { @@ -419,10 +643,12 @@ NTSTATUS add_ccache_to_list(const char *princ_name, #else t = timeval_set(KRB5_EVENT_REFRESH_TIME(ticket_end), 0); #endif + if (entry->refresh_time == 0) { + entry->refresh_time = t.tv_sec; + } entry->event = event_add_timed(winbind_event_context(), entry, t, - "krb5_ticket_refresh_handler", krb5_ticket_refresh_handler, entry); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 4f1e92ed7c..1499141c34 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -175,7 +175,7 @@ static void async_main_request_sent(void *private_data, bool success) static void async_request_timeout_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct winbindd_async_request *state = @@ -247,7 +247,6 @@ static void async_request_sent(void *private_data_data, bool success) state->reply_timeout_event = event_add_timed(winbind_event_context(), NULL, timeval_current_ofs(300,0), - "async_request_timeout", async_request_timeout_handler, state); if (!state->reply_timeout_event) { @@ -827,7 +826,7 @@ void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx, static void account_lockout_policy_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct winbindd_child *child = @@ -866,7 +865,6 @@ static void account_lockout_policy_handler(struct event_context *ctx, child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL, timeval_current_ofs(3600, 0), - "account_lockout_policy_handler", account_lockout_policy_handler, child); } @@ -919,7 +917,7 @@ static bool calculate_next_machine_pwd_change(const char *domain, static void machine_password_change_handler(struct event_context *ctx, struct timed_event *te, - const struct timeval *now, + struct timeval now, void *private_data) { struct winbindd_child *child = @@ -971,7 +969,6 @@ static void machine_password_change_handler(struct event_context *ctx, child->machine_password_change_event = event_add_timed(winbind_event_context(), NULL, next_change, - "machine_password_change_handler", machine_password_change_handler, child); } @@ -985,6 +982,7 @@ static void child_msg_offline(struct messaging_context *msg, DATA_BLOB *data) { struct winbindd_domain *domain; + struct winbindd_domain *primary_domain = NULL; const char *domainname = (const char *)data->data; if (data->data == NULL || data->length == 0) { @@ -998,6 +996,8 @@ static void child_msg_offline(struct messaging_context *msg, return; } + primary_domain = find_our_domain(); + /* Mark the requested domain offline. */ for (domain = domain_list(); domain; domain = domain->next) { @@ -1007,6 +1007,11 @@ static void child_msg_offline(struct messaging_context *msg, if (strequal(domain->name, domainname)) { DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name)); set_domain_offline(domain); + /* we are in the trusted domain, set the primary domain + * offline too */ + if (domain != primary_domain) { + set_domain_offline(primary_domain); + } } } } @@ -1020,6 +1025,7 @@ static void child_msg_online(struct messaging_context *msg, DATA_BLOB *data) { struct winbindd_domain *domain; + struct winbindd_domain *primary_domain = NULL; const char *domainname = (const char *)data->data; if (data->data == NULL || data->length == 0) { @@ -1033,6 +1039,8 @@ static void child_msg_online(struct messaging_context *msg, return; } + primary_domain = find_our_domain(); + /* Set our global state as online. */ set_global_winbindd_state_online(); @@ -1047,6 +1055,16 @@ static void child_msg_online(struct messaging_context *msg, DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name)); winbindd_flush_negative_conn_cache(domain); set_domain_online_request(domain); + + /* we can be in trusted domain, which will contact primary domain + * we have to bring primary domain online in trusted domain process + * see, winbindd_dual_pam_auth() --> winbindd_dual_pam_auth_samlogon() + * --> contact_domain = find_our_domain() + * */ + if (domain != primary_domain) { + winbindd_flush_negative_conn_cache(primary_domain); + set_domain_online_request(primary_domain); + } } } } @@ -1177,13 +1195,18 @@ static bool fork_domain_child(struct winbindd_child *child) state.sock = fdpair[0]; close(fdpair[1]); - if (!reinit_after_fork(winbind_messaging_context(), true)) { + if (!reinit_after_fork(winbind_messaging_context(), + winbind_event_context(), true)) { DEBUG(0,("reinit_after_fork() failed\n")); _exit(0); } close_conns_after_fork(); + /* Ensure we're not handling an event inherited from + our parent. */ + ccache_remove_all_after_fork(); + if (!override_logfile) { lp_set_logfile(child->logfilename); reopen_logs(); @@ -1219,33 +1242,34 @@ static bool fork_domain_child(struct winbindd_child *child) messaging_register(winbind_messaging_context(), NULL, MSG_DEBUG, debug_message); + primary_domain = find_our_domain(); + + if (primary_domain == NULL) { + smb_panic("no primary domain found"); + } + /* we have destroy all time event in reinit_after_fork() + * set check_online_event to NULL */ + for (domain = domain_list(); domain; domain = domain->next) { + domain->check_online_event = NULL; + } + /* It doesn't matter if we allow cache login, + * try to bring domain online after fork. */ if ( child->domain ) { child->domain->startup = True; child->domain->startup_time = time(NULL); - } - - /* Ensure we have no pending check_online events other - than one for this domain or the primary domain. */ - - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->primary) { - primary_domain = domain; - } - if ((domain != child->domain) && !domain->primary) { - TALLOC_FREE(domain->check_online_event); + /* we can be in primary domain or in trusted domain + * If we are in trusted domain, set the primary domain + * in start-up mode */ + if (!(child->domain->internal)) { + set_domain_online_request(child->domain); + if (!(child->domain->primary)) { + primary_domain->startup = True; + primary_domain->startup_time = time(NULL); + set_domain_online_request(primary_domain); + } } } - if (primary_domain == NULL) { - smb_panic("no primary domain found"); - } - - /* Ensure we're not handling an event inherited from - our parent. */ - - cancel_named_event(winbind_event_context(), - "krb5_ticket_refresh_handler"); - /* We might be in the idmap child...*/ if (child->domain && !(child->domain->internal) && lp_winbind_offline_logon()) { @@ -1266,7 +1290,6 @@ static bool fork_domain_child(struct winbindd_child *child) child->lockout_policy_event = event_add_timed( winbind_event_context(), NULL, timeval_zero(), - "account_lockout_policy_handler", account_lockout_policy_handler, child); } @@ -1281,7 +1304,6 @@ static bool fork_domain_child(struct winbindd_child *child) &next_change)) { child->machine_password_change_event = event_add_timed( winbind_event_context(), NULL, next_change, - "machine_password_change_handler", machine_password_change_handler, child); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 3869ac5771..32f057ad61 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -53,12 +53,12 @@ bool register_message_flags(bool doreg, uint32 msg_flags); struct event_context *winbind_event_context(void); struct messaging_context *winbind_messaging_context(void); -void add_fd_event(struct fd_event *ev); -void remove_fd_event(struct fd_event *ev); -void setup_async_read(struct fd_event *event, void *data, size_t length, +void add_fd_event(struct winbindd_fd_event *ev); +void remove_fd_event(struct winbindd_fd_event *ev); +void setup_async_read(struct winbindd_fd_event *event, void *data, size_t length, void (*finished)(void *private_data, bool success), void *private_data); -void setup_async_write(struct fd_event *event, void *data, size_t length, +void setup_async_write(struct winbindd_fd_event *event, void *data, size_t length, void (*finished)(void *private_data, bool success), void *private_data); void request_error(struct winbindd_cli_state *state); @@ -243,6 +243,8 @@ bool ccache_entry_exists(const char *username); bool ccache_entry_identical(const char *username, uid_t uid, const char *ccname); +void ccache_remove_all_after_fork(void); +void ccache_regain_all_now(void); NTSTATUS add_ccache_to_list(const char *princ_name, const char *ccname, const char *service, |