summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-01-04 22:48:23 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-01-04 22:48:23 +0100
commitaf744e0954bbe9ddfa2e3da173e79de65e640a4c (patch)
tree78b98c28e6d54c5339c12f2f942883d5088fda84 /source3
parentce47b69d8e318bbb3642d27aa0451e2914c92be7 (diff)
parent2c0faaf5d921fe57a88d3b999067458e8774c6f6 (diff)
downloadsamba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.tar.gz
samba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.tar.bz2
samba-af744e0954bbe9ddfa2e3da173e79de65e640a4c.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in2
-rwxr-xr-xsource3/autogen.sh4
-rw-r--r--source3/client/client.c13
-rw-r--r--source3/include/async_req.h30
-rw-r--r--source3/include/async_sock.h10
-rw-r--r--source3/include/packet.h6
-rw-r--r--source3/include/proto.h29
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/lib/async_req.c129
-rw-r--r--source3/lib/async_sock.c245
-rw-r--r--source3/lib/ctdbd_conn.c49
-rw-r--r--source3/lib/ldb/include/ldb.h2
-rw-r--r--source3/lib/ldb/tools/ldbadd.c13
-rw-r--r--source3/lib/ldb/tools/ldbmodify.c12
-rw-r--r--source3/lib/packet.c44
-rw-r--r--source3/lib/util_sock.c341
-rw-r--r--source3/lib/wb_reqtrans.c (renamed from source3/winbindd/winbindd_reqtrans.c)153
-rw-r--r--source3/lib/wbclient.c774
-rw-r--r--source3/libads/krb5_setpw.c31
-rw-r--r--source3/libsmb/async_smb.c2
-rw-r--r--source3/libsmb/cliconnect.c97
-rw-r--r--source3/libsmb/clidfs.c20
-rw-r--r--source3/libsmb/clireadwrite.c10
-rw-r--r--source3/libsmb/smb_share_modes.c43
-rw-r--r--source3/modules/onefs_open.c6
-rw-r--r--source3/modules/vfs_smb_traffic_analyzer.c5
-rw-r--r--source3/param/loadparm.c2
-rw-r--r--source3/rpc_client/cli_pipe.c5
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c6
-rw-r--r--source3/samba4.m411
-rw-r--r--source3/smbd/process.c2
-rw-r--r--source3/torture/nbio.c19
-rw-r--r--source3/torture/torture.c83
-rw-r--r--source3/torture/utable.c6
-rw-r--r--source3/utils/smbfilter.c5
-rw-r--r--source3/winbindd/idmap.c11
-rw-r--r--source3/winbindd/winbindd_proto.h9
37 files changed, 1721 insertions, 511 deletions
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 */