The Samba-Bugzilla – Attachment 6159 Details for
Bug 7881
winbind flaky against w2k8
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 3.4
7881-3.4.patch (text/plain), 34.12 KB, created by
Volker Lendecke
on 2010-12-22 08:56:00 UTC
(
hide
)
Description:
Patch for 3.4
Filename:
MIME Type:
Creator:
Volker Lendecke
Created:
2010-12-22 08:56:00 UTC
Size:
34.12 KB
patch
obsolete
>From 2060a0c66fec0946d5fa1fe1071a22ea844c7c59 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Sun, 12 Dec 2010 18:53:49 +0100 >Subject: [PATCH 1/8] s3: Add some const to name_mangle() > >--- > source3/include/proto.h | 2 +- > source3/libsmb/nmblib.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index bd9665c..a6ac512 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -3074,7 +3074,7 @@ struct packet_struct *receive_dgram_packet(int fd, int t, > bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name); > int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len); > void sort_query_replies(char *data, int n, struct in_addr ip); >-char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type); >+char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type); > int name_extract(char *buf,int ofs, fstring name); > int name_len(char *s1); > >diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c >index 5f3eda4..1206d9d 100644 >--- a/source3/libsmb/nmblib.c >+++ b/source3/libsmb/nmblib.c >@@ -1279,7 +1279,7 @@ static int name_interpret(char *in, fstring name) > Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum. > ****************************************************************************/ > >-char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type) >+char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type) > { > int i; > int len; >-- >1.7.3.2 > > >From 621c0182c98f95fe6281f8a1c8855b864c479b79 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Wed, 22 Dec 2010 15:15:47 +0100 >Subject: [PATCH 2/8] v3-4-test: Pull in read_smb_send from master > >--- > source3/libsmb/async_smb.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 87 insertions(+), 0 deletions(-) > >diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c >index 0336ff2..17a8ca4 100644 >--- a/source3/libsmb/async_smb.c >+++ b/source3/libsmb/async_smb.c >@@ -22,6 +22,93 @@ > static void cli_state_handler(struct event_context *event_ctx, > struct fd_event *event, uint16 flags, void *p); > >+/* >+ * Read an smb packet asynchronously, discard keepalives >+ */ >+ >+struct read_smb_state { >+ struct tevent_context *ev; >+ int fd; >+ uint8_t *buf; >+}; >+ >+static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data); >+static void read_smb_done(struct tevent_req *subreq); >+ >+static struct tevent_req *read_smb_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ int fd) >+{ >+ struct tevent_req *result, *subreq; >+ struct read_smb_state *state; >+ >+ result = tevent_req_create(mem_ctx, &state, struct read_smb_state); >+ if (result == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->fd = fd; >+ >+ subreq = read_packet_send(state, ev, fd, 4, read_smb_more, NULL); >+ if (subreq == NULL) { >+ goto fail; >+ } >+ tevent_req_set_callback(subreq, read_smb_done, result); >+ return result; >+ fail: >+ TALLOC_FREE(result); >+ return NULL; >+} >+ >+static ssize_t read_smb_more(uint8_t *buf, size_t buflen, void *private_data) >+{ >+ if (buflen > 4) { >+ return 0; /* We've been here, we're done */ >+ } >+ return smb_len_large(buf); >+} >+ >+static void read_smb_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct read_smb_state *state = tevent_req_data( >+ req, struct read_smb_state); >+ ssize_t len; >+ int err; >+ >+ len = read_packet_recv(subreq, state, &state->buf, &err); >+ TALLOC_FREE(subreq); >+ if (len == -1) { >+ tevent_req_error(req, err); >+ return; >+ } >+ >+ if (CVAL(state->buf, 0) == SMBkeepalive) { >+ subreq = read_packet_send(state, state->ev, state->fd, 4, >+ read_smb_more, NULL); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, read_smb_done, req); >+ return; >+ } >+ tevent_req_done(req); >+} >+ >+static ssize_t read_smb_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, >+ uint8_t **pbuf, int *perrno) >+{ >+ struct read_smb_state *state = tevent_req_data( >+ req, struct read_smb_state); >+ >+ if (tevent_req_is_unix_error(req, perrno)) { >+ return -1; >+ } >+ *pbuf = talloc_move(mem_ctx, &state->buf); >+ return talloc_get_size(*pbuf); >+} >+ > /** > * Fetch an error out of a NBT packet > * @param[in] buf The SMB packet >-- >1.7.3.2 > > >From 7aacdc84f55c177afbcde8ee6e0853cfd5304a8d Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Sun, 12 Dec 2010 18:54:31 +0100 >Subject: [PATCH 3/8] s3: Add async cli_session_request > >This does not do the redirects, but I think that might be obsolete anyway >--- > source3/include/async_smb.h | 7 +++ > source3/libsmb/async_smb.c | 125 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 132 insertions(+), 0 deletions(-) > >diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h >index 7fc4ff7..06e6959 100644 >--- a/source3/include/async_smb.h >+++ b/source3/include/async_smb.h >@@ -149,4 +149,11 @@ NTSTATUS cli_pull_error(char *buf); > > void cli_set_error(struct cli_state *cli, NTSTATUS status); > >+struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ int sock, >+ const struct nmb_name *called, >+ const struct nmb_name *calling); >+bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp); >+ > #endif >diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c >index 17a8ca4..62a8c81 100644 >--- a/source3/libsmb/async_smb.c >+++ b/source3/libsmb/async_smb.c >@@ -1222,3 +1222,128 @@ static void cli_state_handler(struct event_context *event_ctx, > cli->fd = -1; > } > } >+ >+ >+struct cli_session_request_state { >+ struct tevent_context *ev; >+ int sock; >+ uint32 len_hdr; >+ struct iovec iov[3]; >+ uint8_t nb_session_response; >+}; >+ >+static void cli_session_request_sent(struct tevent_req *subreq); >+static void cli_session_request_recvd(struct tevent_req *subreq); >+ >+struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ int sock, >+ const struct nmb_name *called, >+ const struct nmb_name *calling) >+{ >+ struct tevent_req *req, *subreq; >+ struct cli_session_request_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, >+ struct cli_session_request_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->sock = sock; >+ >+ state->iov[1].iov_base = name_mangle( >+ state, called->name, called->name_type); >+ if (tevent_req_nomem(state->iov[1].iov_base, req)) { >+ return tevent_req_post(req, ev); >+ } >+ state->iov[1].iov_len = name_len( >+ (char *)state->iov[1].iov_base); >+ >+ state->iov[2].iov_base = name_mangle( >+ state, calling->name, calling->name_type); >+ if (tevent_req_nomem(state->iov[2].iov_base, req)) { >+ return tevent_req_post(req, ev); >+ } >+ state->iov[2].iov_len = name_len( >+ (char *)state->iov[2].iov_base); >+ >+ _smb_setlen(((char *)&state->len_hdr), >+ state->iov[1].iov_len + state->iov[2].iov_len); >+ SCVAL((char *)&state->len_hdr, 0, 0x81); >+ >+ state->iov[0].iov_base = &state->len_hdr; >+ state->iov[0].iov_len = sizeof(state->len_hdr); >+ >+ subreq = writev_send(state, ev, NULL, sock, state->iov, 3); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, cli_session_request_sent, req); >+ return req; >+} >+ >+static void cli_session_request_sent(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct cli_session_request_state *state = tevent_req_data( >+ req, struct cli_session_request_state); >+ ssize_t ret; >+ int err; >+ >+ ret = writev_recv(subreq, &err); >+ TALLOC_FREE(subreq); >+ if (ret == -1) { >+ tevent_req_error(req, err); >+ return; >+ } >+ subreq = read_smb_send(state, state->ev, state->sock); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, cli_session_request_recvd, req); >+} >+ >+static void cli_session_request_recvd(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct cli_session_request_state *state = tevent_req_data( >+ req, struct cli_session_request_state); >+ uint8_t *buf; >+ ssize_t ret; >+ int err; >+ >+ ret = read_smb_recv(subreq, talloc_tos(), &buf, &err); >+ TALLOC_FREE(subreq); >+ >+ if (ret < 4) { >+ ret = -1; >+ err = EIO; >+ } >+ if (ret == -1) { >+ tevent_req_error(req, err); >+ return; >+ } >+ /* >+ * In case of an error there is more information in the data >+ * portion according to RFC1002. We're not subtle enough to >+ * respond to the different error conditions, so drop the >+ * error info here. >+ */ >+ state->nb_session_response = CVAL(buf, 0); >+ tevent_req_done(req); >+} >+ >+bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp) >+{ >+ struct cli_session_request_state *state = tevent_req_data( >+ req, struct cli_session_request_state); >+ >+ if (tevent_req_is_unix_error(req, err)) { >+ return false; >+ } >+ *resp = state->nb_session_response; >+ return true; >+} >-- >1.7.3.2 > > >From 6e5a5669678dd6f54f8bc115f89e2c0e15b418d7 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Wed, 22 Dec 2010 15:21:27 +0100 >Subject: [PATCH 4/8] v3-4-test: Pull in tevent_req_poll_ntstatus from master > >--- > source3/include/proto.h | 3 +++ > source3/lib/util.c | 11 +++++++++++ > 2 files changed, 14 insertions(+), 0 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index a6ac512..35ac19b 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -1221,6 +1221,9 @@ bool is_valid_policy_hnd(const struct policy_handle *hnd); > bool policy_hnd_equal(const struct policy_handle *hnd1, > const struct policy_handle *hnd2); > const char *strip_hostname(const char *s); >+bool tevent_req_poll_ntstatus(struct tevent_req *req, >+ struct tevent_context *ev, >+ NTSTATUS *status); > > /* The following definitions come from lib/util_file.c */ > >diff --git a/source3/lib/util.c b/source3/lib/util.c >index 3d7336f9..c9afe7b 100644 >--- a/source3/lib/util.c >+++ b/source3/lib/util.c >@@ -3188,3 +3188,14 @@ const char *strip_hostname(const char *s) > > return s; > } >+ >+bool tevent_req_poll_ntstatus(struct tevent_req *req, >+ struct tevent_context *ev, >+ NTSTATUS *status) >+{ >+ bool ret = tevent_req_poll(req, ev); >+ if (!ret) { >+ *status = map_nt_error_from_unix(errno); >+ } >+ return ret; >+} >-- >1.7.3.2 > > >From b2a0f445c828caa67e6844970b7955fd29bc1c48 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Sun, 12 Dec 2010 18:55:06 +0100 >Subject: [PATCH 5/8] s3: Add an async smbsock_connect > >This connects to 445 and after 5 milliseconds also to 139. It treats a netbios >session setup failure as equivalent as a TCP connect failure. So if 139 is >faster but fails the nb session setup, the 445 still has the chance to succeed. >--- > source3/Makefile.in | 1 + > source3/include/proto.h | 11 ++ > source3/libsmb/smbsock_connect.c | 308 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 320 insertions(+), 0 deletions(-) > create mode 100644 source3/libsmb/smbsock_connect.c > >diff --git a/source3/Makefile.in b/source3/Makefile.in >index b863e36..82e108a 100644 >--- a/source3/Makefile.in >+++ b/source3/Makefile.in >@@ -473,6 +473,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ > libsmb/credentials.o \ > libsmb/clioplock.o libsmb/clirap2.o \ > libsmb/smb_seal.o libsmb/async_smb.o \ >+ libsmb/smbsock_connect.o \ > $(LIBSAMBA_OBJ) \ > $(LIBNMB_OBJ) \ > $(LIBNBT_OBJ) \ >diff --git a/source3/include/proto.h b/source3/include/proto.h >index 35ac19b..fbb55ae 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -7282,6 +7282,17 @@ void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev, > > /* Misc protos */ > >+struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ const struct sockaddr_storage *addr, >+ const char *called_name, >+ const char *calling_name); >+NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock, >+ uint16_t *port); >+NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, >+ const char *called_name, const char *calling_name, >+ int *pfd, uint16_t *port); >+ > /* The following definitions come from rpc_server/srv_samr_nt.c */ > NTSTATUS access_check_object( SEC_DESC *psd, NT_USER_TOKEN *token, > SE_PRIV *rights, uint32 rights_mask, >diff --git a/source3/libsmb/smbsock_connect.c b/source3/libsmb/smbsock_connect.c >new file mode 100644 >index 0000000..3355795 >--- /dev/null >+++ b/source3/libsmb/smbsock_connect.c >@@ -0,0 +1,308 @@ >+/* >+ Unix SMB/CIFS implementation. >+ Connect to 445 and 139/nbsesssetup >+ Copyright (C) Volker Lendecke 2010 >+ >+ 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 "../lib/async_req/async_sock.h" >+#include "async_smb.h" >+ >+struct nb_connect_state { >+ struct tevent_context *ev; >+ int sock; >+ struct nmb_name called; >+ struct nmb_name calling; >+}; >+ >+static int nb_connect_state_destructor(struct nb_connect_state *state); >+static void nb_connect_connected(struct tevent_req *subreq); >+static void nb_connect_done(struct tevent_req *subreq); >+ >+static struct tevent_req *nb_connect_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ const struct sockaddr_storage *addr, >+ const char *called_name, >+ int called_type, >+ const char *calling_name, >+ int calling_type) >+{ >+ struct tevent_req *req, *subreq; >+ struct nb_connect_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, struct nb_connect_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ make_nmb_name(&state->called, called_name, called_type); >+ make_nmb_name(&state->calling, calling_name, calling_type); >+ state->sock = -1; >+ >+ talloc_set_destructor(state, nb_connect_state_destructor); >+ >+ subreq = open_socket_out_send(state, ev, addr, 139, 5000); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, nb_connect_connected, req); >+ return req; >+} >+ >+static int nb_connect_state_destructor(struct nb_connect_state *state) >+{ >+ if (state->sock != -1) { >+ close(state->sock); >+ } >+ return 0; >+} >+ >+static void nb_connect_connected(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct nb_connect_state *state = tevent_req_data( >+ req, struct nb_connect_state); >+ NTSTATUS status; >+ >+ status = open_socket_out_recv(subreq, &state->sock); >+ TALLOC_FREE(subreq); >+ if (!NT_STATUS_IS_OK(status)) { >+ tevent_req_nterror(req, status); >+ return; >+ } >+ subreq = cli_session_request_send(state, state->ev, state->sock, >+ &state->called, &state->calling); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, nb_connect_done, req); >+} >+ >+static void nb_connect_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ bool ret; >+ int err; >+ uint8_t resp; >+ >+ ret = cli_session_request_recv(subreq, &err, &resp); >+ TALLOC_FREE(subreq); >+ if (!ret) { >+ tevent_req_nterror(req, map_nt_error_from_unix(err)); >+ return; >+ } >+ if (resp != 0x82) { >+ tevent_req_nterror(req, NT_STATUS_RESOURCE_NAME_NOT_FOUND); >+ return; >+ } >+ tevent_req_done(req); >+} >+ >+static NTSTATUS nb_connect_recv(struct tevent_req *req, int *sock) >+{ >+ struct nb_connect_state *state = tevent_req_data( >+ req, struct nb_connect_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ *sock = state->sock; >+ state->sock = -1; >+ return NT_STATUS_OK; >+} >+ >+struct smbsock_connect_state { >+ struct tevent_context *ev; >+ const struct sockaddr_storage *addr; >+ const char *called_name; >+ const char *calling_name; >+ struct tevent_req *req_139; >+ struct tevent_req *req_445; >+ int sock; >+ uint16_t port; >+}; >+ >+static int smbsock_connect_state_destructor( >+ struct smbsock_connect_state *state); >+static void smbsock_connect_connected(struct tevent_req *subreq); >+static void smbsock_connect_do_139(struct tevent_req *subreq); >+ >+struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ const struct sockaddr_storage *addr, >+ const char *called_name, >+ const char *calling_name) >+{ >+ struct tevent_req *req, *subreq; >+ struct smbsock_connect_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, struct smbsock_connect_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->addr = addr; >+ state->sock = -1; >+ state->called_name = >+ (called_name != NULL) ? called_name : "*SMBSERVER"; >+ state->calling_name = >+ (calling_name != NULL) ? calling_name : global_myname(); >+ >+ talloc_set_destructor(state, smbsock_connect_state_destructor); >+ >+ state->req_445 = open_socket_out_send(state, ev, addr, 445, 5000); >+ if (tevent_req_nomem(state->req_445, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(state->req_445, smbsock_connect_connected, >+ req); >+ >+ /* >+ * After 5 msecs, fire the 139 request >+ */ >+ subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 5000)); >+ if (tevent_req_nomem(subreq, req)) { >+ TALLOC_FREE(state->req_445); >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, smbsock_connect_do_139, req); >+ return req; >+} >+ >+static int smbsock_connect_state_destructor( >+ struct smbsock_connect_state *state) >+{ >+ if (state->sock != -1) { >+ close(state->sock); >+ } >+ return 0; >+} >+ >+static void smbsock_connect_do_139(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smbsock_connect_state *state = tevent_req_data( >+ req, struct smbsock_connect_state); >+ bool ret; >+ >+ ret = tevent_wakeup_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (!ret) { >+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ return; >+ } >+ state->req_139 = nb_connect_send(state, state->ev, state->addr, >+ state->called_name, 0x20, >+ state->calling_name, 0x0); >+ if (tevent_req_nomem(state->req_139, req)) { >+ return; >+ } >+ tevent_req_set_callback(state->req_139, smbsock_connect_connected, >+ req); >+} >+ >+static void smbsock_connect_connected(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smbsock_connect_state *state = tevent_req_data( >+ req, struct smbsock_connect_state); >+ struct tevent_req *unfinished_req; >+ NTSTATUS status; >+ >+ if (subreq == state->req_445) { >+ >+ status = open_socket_out_recv(subreq, &state->sock); >+ TALLOC_FREE(state->req_445); >+ unfinished_req = state->req_139; >+ state->port = 445; >+ >+ } else if (subreq == state->req_139) { >+ >+ status = nb_connect_recv(subreq, &state->sock); >+ TALLOC_FREE(state->req_139); >+ unfinished_req = state->req_445; >+ state->port = 139; >+ >+ } else { >+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ return; >+ } >+ >+ if (NT_STATUS_IS_OK(status)) { >+ TALLOC_FREE(unfinished_req); >+ state->req_139 = NULL; >+ state->req_445 = NULL; >+ tevent_req_done(req); >+ return; >+ } >+ if (unfinished_req == NULL) { >+ /* >+ * Both requests failed >+ */ >+ tevent_req_nterror(req, status); >+ return; >+ } >+ /* >+ * Do nothing, wait for the second request to come here. >+ */ >+} >+ >+NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock, >+ uint16_t *port) >+{ >+ struct smbsock_connect_state *state = tevent_req_data( >+ req, struct smbsock_connect_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ *sock = state->sock; >+ state->sock = -1; >+ *port = state->port; >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, >+ const char *called_name, const char *calling_name, >+ int *pfd, uint16_t *port) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct event_context *ev; >+ struct tevent_req *req; >+ NTSTATUS status = NT_STATUS_NO_MEMORY; >+ >+ ev = event_context_init(frame); >+ if (ev == NULL) { >+ goto fail; >+ } >+ req = smbsock_connect_send(frame, ev, addr, called_name, calling_name); >+ if (req == NULL) { >+ goto fail; >+ } >+ if (!tevent_req_poll_ntstatus(req, ev, &status)) { >+ goto fail; >+ } >+ status = smbsock_connect_recv(req, pfd, port); >+ fail: >+ TALLOC_FREE(frame); >+ return status; >+} >-- >1.7.3.2 > > >From d3d28c439415e3d0116e61f684d5b1dbc4b3d6cf Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Mon, 13 Dec 2010 17:17:51 +0100 >Subject: [PATCH 6/8] s3: Add smbsock_any_connect > >--- > source3/include/proto.h | 11 ++ > source3/libsmb/smbsock_connect.c | 222 +++++++++++++++++++++++++++++++++++++- > 2 files changed, 232 insertions(+), 1 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index fbb55ae..f87d91a 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -7293,6 +7293,17 @@ NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, > const char *called_name, const char *calling_name, > int *pfd, uint16_t *port); > >+struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ const struct sockaddr_storage *addrs, >+ const char **called_names, >+ size_t num_addrs); >+NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd, >+ size_t *chosen_index, uint16_t *port); >+NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs, >+ const char **called_names, size_t num_addrs, >+ int *pfd, size_t *chosen_index, uint16_t *port); >+ > /* The following definitions come from rpc_server/srv_samr_nt.c */ > NTSTATUS access_check_object( SEC_DESC *psd, NT_USER_TOKEN *token, > SE_PRIV *rights, uint32 rights_mask, >diff --git a/source3/libsmb/smbsock_connect.c b/source3/libsmb/smbsock_connect.c >index 3355795..c56045c 100644 >--- a/source3/libsmb/smbsock_connect.c >+++ b/source3/libsmb/smbsock_connect.c >@@ -277,7 +277,9 @@ NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock, > } > *sock = state->sock; > state->sock = -1; >- *port = state->port; >+ if (port != NULL) { >+ *port = state->port; >+ } > return NT_STATUS_OK; > } > >@@ -306,3 +308,221 @@ NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, > TALLOC_FREE(frame); > return status; > } >+ >+struct smbsock_any_connect_state { >+ struct tevent_context *ev; >+ const struct sockaddr_storage *addrs; >+ const char **called_names; >+ size_t num_addrs; >+ >+ struct tevent_req **requests; >+ size_t num_sent; >+ size_t num_received; >+ >+ int fd; >+ uint16_t port; >+ size_t chosen_index; >+}; >+ >+static bool smbsock_any_connect_send_next( >+ struct tevent_req *req, struct smbsock_any_connect_state *state); >+static void smbsock_any_connect_trynext(struct tevent_req *subreq); >+static void smbsock_any_connect_connected(struct tevent_req *subreq); >+ >+struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ const struct sockaddr_storage *addrs, >+ const char **called_names, >+ size_t num_addrs) >+{ >+ struct tevent_req *req, *subreq; >+ struct smbsock_any_connect_state *state; >+ >+ req = tevent_req_create(mem_ctx, &state, >+ struct smbsock_any_connect_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->addrs = addrs; >+ state->num_addrs = num_addrs; >+ state->called_names = called_names; >+ >+ if (num_addrs == 0) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); >+ return tevent_req_post(req, ev); >+ } >+ >+ state->requests = talloc_zero_array(state, struct tevent_req *, >+ num_addrs); >+ if (tevent_req_nomem(state->requests, req)) { >+ return tevent_req_post(req, ev); >+ } >+ if (!smbsock_any_connect_send_next(req, state)) { >+ return tevent_req_post(req, ev); >+ } >+ if (state->num_sent >= state->num_addrs) { >+ return req; >+ } >+ subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000)); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req); >+ return req; >+} >+ >+static void smbsock_any_connect_trynext(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smbsock_any_connect_state *state = tevent_req_data( >+ req, struct smbsock_any_connect_state); >+ bool ret; >+ >+ ret = tevent_wakeup_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (!ret) { >+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ return; >+ } >+ if (!smbsock_any_connect_send_next(req, state)) { >+ return; >+ } >+ if (state->num_sent >= state->num_addrs) { >+ return; >+ } >+ subreq = tevent_wakeup_send(state, state->ev, >+ tevent_timeval_set(0, 10000)); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req); >+} >+ >+static bool smbsock_any_connect_send_next( >+ struct tevent_req *req, struct smbsock_any_connect_state *state) >+{ >+ struct tevent_req *subreq; >+ >+ if (state->num_sent >= state->num_addrs) { >+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ return false; >+ } >+ subreq = smbsock_connect_send( >+ state->requests, state->ev, &state->addrs[state->num_sent], >+ (state->called_names != NULL) >+ ? state->called_names[state->num_sent] : NULL, >+ NULL); >+ if (tevent_req_nomem(subreq, req)) { >+ return false; >+ } >+ tevent_req_set_callback(subreq, smbsock_any_connect_connected, req); >+ >+ state->requests[state->num_sent] = subreq; >+ state->num_sent += 1; >+ >+ return true; >+} >+ >+static void smbsock_any_connect_connected(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct smbsock_any_connect_state *state = tevent_req_data( >+ req, struct smbsock_any_connect_state); >+ NTSTATUS status; >+ int fd; >+ uint16_t port; >+ size_t i; >+ size_t chosen_index = 0; >+ >+ for (i=0; i<state->num_sent; i++) { >+ if (state->requests[i] == subreq) { >+ chosen_index = i; >+ break; >+ } >+ } >+ if (i == state->num_sent) { >+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); >+ return; >+ } >+ >+ status = smbsock_connect_recv(subreq, &fd, &port); >+ >+ TALLOC_FREE(subreq); >+ state->requests[chosen_index] = NULL; >+ >+ if (NT_STATUS_IS_OK(status)) { >+ /* >+ * This will kill all the other requests >+ */ >+ TALLOC_FREE(state->requests); >+ state->fd = fd; >+ state->port = port; >+ state->chosen_index = chosen_index; >+ tevent_req_done(req); >+ return; >+ } >+ >+ state->num_received += 1; >+ if (state->num_received <= state->num_addrs) { >+ /* >+ * More addrs pending, wait for the others >+ */ >+ return; >+ } >+ >+ /* >+ * This is the last response, none succeeded. >+ */ >+ tevent_req_nterror(req, status); >+ return; >+} >+ >+NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd, >+ size_t *chosen_index, uint16_t *port) >+{ >+ struct smbsock_any_connect_state *state = tevent_req_data( >+ req, struct smbsock_any_connect_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ return status; >+ } >+ *pfd = state->fd; >+ if (chosen_index != NULL) { >+ *chosen_index = state->chosen_index; >+ } >+ if (port != NULL) { >+ *port = state->port; >+ } >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs, >+ const char **called_names, size_t num_addrs, >+ int *pfd, size_t *chosen_index, uint16_t *port) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct event_context *ev; >+ struct tevent_req *req; >+ NTSTATUS status = NT_STATUS_NO_MEMORY; >+ >+ ev = event_context_init(frame); >+ if (ev == NULL) { >+ goto fail; >+ } >+ req = smbsock_any_connect_send(frame, ev, addrs, called_names, >+ num_addrs); >+ if (req == NULL) { >+ goto fail; >+ } >+ if (!tevent_req_poll_ntstatus(req, ev, &status)) { >+ goto fail; >+ } >+ status = smbsock_any_connect_recv(req, pfd, chosen_index, port); >+ fail: >+ TALLOC_FREE(frame); >+ return status; >+} >-- >1.7.3.2 > > >From aa2234f1f43de0a18a8cbefe6c7a176156852219 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 21 Dec 2010 18:52:53 +0100 >Subject: [PATCH 7/8] s3: Retry *SMBSERVER in nb_connect > >--- > source3/libsmb/smbsock_connect.c | 49 ++++++++++++++++++++++++++++++++++++- > 1 files changed, 47 insertions(+), 2 deletions(-) > >diff --git a/source3/libsmb/smbsock_connect.c b/source3/libsmb/smbsock_connect.c >index c56045c..8ab12c5 100644 >--- a/source3/libsmb/smbsock_connect.c >+++ b/source3/libsmb/smbsock_connect.c >@@ -23,7 +23,10 @@ > > struct nb_connect_state { > struct tevent_context *ev; >+ const struct sockaddr_storage *addr; >+ const char *called_name; > int sock; >+ > struct nmb_name called; > struct nmb_name calling; > }; >@@ -48,9 +51,12 @@ static struct tevent_req *nb_connect_send(TALLOC_CTX *mem_ctx, > return NULL; > } > state->ev = ev; >+ state->called_name = called_name; >+ state->addr = addr; >+ >+ state->sock = -1; > make_nmb_name(&state->called, called_name, called_type); > make_nmb_name(&state->calling, calling_name, calling_type); >- state->sock = -1; > > talloc_set_destructor(state, nb_connect_state_destructor); > >@@ -96,6 +102,8 @@ static void nb_connect_done(struct tevent_req *subreq) > { > struct tevent_req *req = tevent_req_callback_data( > subreq, struct tevent_req); >+ struct nb_connect_state *state = tevent_req_data( >+ req, struct nb_connect_state); > bool ret; > int err; > uint8_t resp; >@@ -106,11 +114,48 @@ static void nb_connect_done(struct tevent_req *subreq) > tevent_req_nterror(req, map_nt_error_from_unix(err)); > return; > } >+ >+ /* >+ * RFC1002: 0x82 - POSITIVE SESSION RESPONSE >+ */ >+ > if (resp != 0x82) { >- tevent_req_nterror(req, NT_STATUS_RESOURCE_NAME_NOT_FOUND); >+ /* >+ * The server did not like our session request >+ */ >+ close(state->sock); >+ state->sock = -1; >+ >+ if (strequal(state->called_name, "*SMBSERVER")) { >+ /* >+ * Here we could try a name status request and >+ * use the first 0x20 type name. >+ */ >+ tevent_req_nterror( >+ req, NT_STATUS_RESOURCE_NAME_NOT_FOUND); >+ return; >+ } >+ >+ /* >+ * We could be subtle and distinguish between >+ * different failure modes, but what we do here >+ * instead is just retry with *SMBSERVER type 0x20. >+ */ >+ state->called_name = "*SMBSERVER"; >+ make_nmb_name(&state->called, state->called_name, 0x20); >+ >+ subreq = open_socket_out_send(state, state->ev, state->addr, >+ 139, 5000); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, nb_connect_connected, req); > return; > } >+ > tevent_req_done(req); >+ return; >+ > } > > static NTSTATUS nb_connect_recv(struct tevent_req *req, int *sock) >-- >1.7.3.2 > > >From 5f7e695d06c93d175266b1b1ffd0104be9a4e80b Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 21 Dec 2010 21:55:01 +0100 >Subject: [PATCH 8/8] s3: Use smbsock_any_connect in winbind > >--- > source3/winbindd/winbindd_cm.c | 58 +++++++++------------------------------- > 1 files changed, 13 insertions(+), 45 deletions(-) > >diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c >index 0a5c147..6d99f64 100644 >--- a/source3/winbindd/winbindd_cm.c >+++ b/source3/winbindd/winbindd_cm.c >@@ -823,21 +823,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, > goto done; > } > >- if (ntohs(peeraddr_in->sin_port) == 139) { >- struct nmb_name calling; >- struct nmb_name called; >- >- make_nmb_name(&calling, global_myname(), 0x0); >- make_nmb_name(&called, "*SMBSERVER", 0x20); >- >- if (!cli_session_request(*cli, &calling, &called)) { >- DEBUG(8, ("cli_session_request failed for %s\n", >- controller)); >- result = NT_STATUS_UNSUCCESSFUL; >- goto done; >- } >- } >- > result = cli_negprot(*cli); > > if (!NT_STATUS_IS_OK(result)) { >@@ -1340,7 +1325,10 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, > struct sockaddr_storage *addrs = NULL; > int num_addrs = 0; > >- int i, fd_index; >+ int i; >+ size_t fd_index; >+ >+ NTSTATUS status; > > *fd = -1; > >@@ -1358,15 +1346,6 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, > &addrs, &num_addrs)) { > return False; > } >- >- if (!add_string_to_array(mem_ctx, dcs[i].name, >- &dcnames, &num_dcnames)) { >- return False; >- } >- if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139, >- &addrs, &num_addrs)) { >- return False; >- } > } > > if ((num_dcnames == 0) || (num_dcnames != num_addrs)) >@@ -1375,14 +1354,15 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx, > if ((addrs == NULL) || (dcnames == NULL)) > return False; > >- /* 5 second timeout. */ >- if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) { >+ status = smbsock_any_connect(addrs, dcnames, num_addrs, >+ fd, &fd_index, NULL); >+ if (!NT_STATUS_IS_OK(status)) { > for (i=0; i<num_dcs; i++) { > char ab[INET6_ADDRSTRLEN]; > print_sockaddr(ab, sizeof(ab), &dcs[i].ss); >- DEBUG(10, ("find_new_dc: open_any_socket_out failed for " >+ DEBUG(10, ("find_new_dc: smbsock_any_connect failed for " > "domain %s address %s. Error was %s\n", >- domain->name, ab, strerror(errno) )); >+ domain->name, ab, nt_errstr(status) )); > winbind_add_failed_connection_entry(domain, > dcs[i].name, NT_STATUS_UNSUCCESSFUL); > } >@@ -1484,23 +1464,11 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, > && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) > && (resolve_name(domain->dcname, &domain->dcaddr, 0x20))) > { >- struct sockaddr_storage *addrs = NULL; >- int num_addrs = 0; >- int dummy = 0; >- >- if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) { >- set_domain_offline(domain); >- talloc_destroy(mem_ctx); >- return NT_STATUS_NO_MEMORY; >- } >- if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) { >- set_domain_offline(domain); >- talloc_destroy(mem_ctx); >- return NT_STATUS_NO_MEMORY; >- } >+ NTSTATUS status; > >- /* 5 second timeout. */ >- if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) { >+ status = smbsock_connect(&domain->dcaddr, NULL, NULL, >+ &fd, NULL); >+ if (!NT_STATUS_IS_OK(status)) { > fd = -1; > } > } >-- >1.7.3.2 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review+
Actions:
View
Attachments on
bug 7881
: 6159 |
6160
|
6225