The branch, master has been updated via c118bcf s3: Use resolve_wins_send/recv in resolve_wins via 0dfcf3e s3: Add resolve_wins_send/recv via 396b646 s3: Add wins_server_tag_ips() via 12c3c35 s3: Add query_wins_list_send/recv via f0994c7 s3: Fix IO_TIMEOUT handling for wins queries via ebf04d7 s3: Remove "struct ip_service" from resolve_wins via eb16915 nsswitch: Remove some refs to the global winbindd_fd from d566146 s3-passdb: Implement new pdb trust calls for the default backend
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c118bcf7556929aadf853a3e0bb7748210126dd2 Author: Volker Lendecke <v...@samba.org> Date: Fri Jun 3 16:11:17 2011 +0200 s3: Use resolve_wins_send/recv in resolve_wins Autobuild-User: Volker Lendecke <vlen...@samba.org> Autobuild-Date: Sun Jun 12 18:19:41 CEST 2011 on sn-devel-104 commit 0dfcf3ef78bb16d79644ee08f58d519e74ff0f0a Author: Volker Lendecke <v...@samba.org> Date: Thu Jun 2 14:12:06 2011 +0200 s3: Add resolve_wins_send/recv commit 396b646123c1aef81c644ae744e65c71b30067d0 Author: Volker Lendecke <v...@samba.org> Date: Sun Jun 12 14:07:22 2011 +0200 s3: Add wins_server_tag_ips() For a given tag, return the list of all wins servers commit 12c3c355966ba7c2da101219ae993fd0ef633026 Author: Volker Lendecke <v...@samba.org> Date: Sat May 14 18:24:03 2011 +0200 s3: Add query_wins_list_send/recv commit f0994c749505f11ea115f9e1ae7de52cf25412d0 Author: Volker Lendecke <v...@samba.org> Date: Sun Jun 12 15:44:19 2011 +0200 s3: Fix IO_TIMEOUT handling for wins queries commit ebf04d79abdf0a15248a266162c8ec8906ce3c5f Author: Volker Lendecke <v...@samba.org> Date: Fri Jun 3 15:49:55 2011 +0200 s3: Remove "struct ip_service" from resolve_wins commit eb16915e283879aaf0797896fc9bd96b095ff550 Author: Volker Lendecke <v...@samba.org> Date: Sun Jun 5 16:39:36 2011 +0200 nsswitch: Remove some refs to the global winbindd_fd ----------------------------------------------------------------------- Summary of changes: nsswitch/wb_common.c | 18 +- nsswitch/wins.c | 15 +- source3/include/proto.h | 12 +- source3/lib/wins_srv.c | 42 ++++ source3/libsmb/namequery.c | 403 ++++++++++++++++++++++++++++++-------- source3/winbindd/winbindd_wins.c | 18 +-- 6 files changed, 394 insertions(+), 114 deletions(-) Changeset truncated at 500 lines: diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c index dcfc8a5..80c729a 100644 --- a/nsswitch/wb_common.c +++ b/nsswitch/wb_common.c @@ -369,13 +369,14 @@ static int winbind_open_pipe_sock(int recursing, int need_priv) static int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) { - int result, nwritten; + int fd, result, nwritten; /* Open connection to winbind daemon */ restart: - if (winbind_open_pipe_sock(recursing, need_priv) == -1) { + fd = winbind_open_pipe_sock(recursing, need_priv); + if (fd == -1) { errno = ENOENT; return -1; } @@ -391,7 +392,7 @@ static int winbind_write_sock(void *buffer, int count, int recursing, /* Catch pipe close on other end by checking if a read() call would not block by calling poll(). */ - pfd.fd = winbindd_fd; + pfd.fd = fd; pfd.events = POLLIN|POLLHUP; ret = poll(&pfd, 1, 0); @@ -412,8 +413,7 @@ static int winbind_write_sock(void *buffer, int count, int recursing, /* Do the write */ - result = write(winbindd_fd, - (char *)buffer + nwritten, + result = write(fd, (char *)buffer + nwritten, count - nwritten); if ((result == -1) || (result == 0)) { @@ -434,10 +434,12 @@ static int winbind_write_sock(void *buffer, int count, int recursing, static int winbind_read_sock(void *buffer, int count) { + int fd; int nread = 0; int total_time = 0; - if (winbindd_fd == -1) { + fd = winbind_open_pipe_sock(false, false); + if (fd == -1) { return -1; } @@ -449,7 +451,7 @@ static int winbind_read_sock(void *buffer, int count) /* Catch pipe close on other end by checking if a read() call would not block by calling poll(). */ - pfd.fd = winbindd_fd; + pfd.fd = fd; pfd.events = POLLIN|POLLHUP; /* Wait for 5 seconds for a reply. May need to parameterise this... */ @@ -475,7 +477,7 @@ static int winbind_read_sock(void *buffer, int count) /* Do the Read */ - int result = read(winbindd_fd, (char *)buffer + nread, + int result = read(fd, (char *)buffer + nread, count - nread); if ((result == -1) || (result == 0)) { diff --git a/nsswitch/wins.c b/nsswitch/wins.c index 5c9ad2f..d63968b 100644 --- a/nsswitch/wins.c +++ b/nsswitch/wins.c @@ -60,8 +60,9 @@ static void nss_wins_init(void) static struct in_addr *lookup_byname_backend(const char *name, int *count) { TALLOC_CTX *frame = talloc_stackframe(); - struct ip_service *address = NULL; + struct sockaddr_storage *address = NULL; struct in_addr *ret = NULL; + NTSTATUS status; int j; if (!initialised) { @@ -71,21 +72,20 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) *count = 0; /* always try with wins first */ - if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) { + status = resolve_wins(name, 0x00, talloc_tos(), + &address, count); + if (NT_STATUS_IS_OK(status)) { if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) { - free( address ); TALLOC_FREE(frame); return NULL; } - if (address[0].ss.ss_family != AF_INET) { - free(address); + if (address[0].ss_family != AF_INET) { free(ret); TALLOC_FREE(frame); return NULL; } - *ret = ((struct sockaddr_in *)(void *)&address[0].ss) + *ret = ((struct sockaddr_in *)(void *)address) ->sin_addr; - free( address ); TALLOC_FREE(frame); return ret; } @@ -95,7 +95,6 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) const struct in_addr *bcast = iface_n_bcast_v4(j); struct sockaddr_storage ss; struct sockaddr_storage *pss; - NTSTATUS status; if (!bcast) { continue; diff --git a/source3/include/proto.h b/source3/include/proto.h index 1cde4be..ad8ae99 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -913,6 +913,8 @@ unsigned wins_srv_count(void); char **wins_srv_tags(void); void wins_srv_tags_free(char **list); struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip); +bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx, + struct in_addr **pservers, int *pnum_servers); unsigned wins_srv_count_tag(const char *tag); /* The following definitions come from libsmb/clispnego.c */ @@ -1050,9 +1052,17 @@ NTSTATUS name_resolve_bcast(const char *name, TALLOC_CTX *mem_ctx, struct sockaddr_storage **return_iplist, int *return_count); +struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + int name_type); +NTSTATUS resolve_wins_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct sockaddr_storage **addrs, + int *num_addrs, uint8_t *flags); NTSTATUS resolve_wins(const char *name, int name_type, - struct ip_service **return_iplist, + TALLOC_CTX *mem_ctx, + struct sockaddr_storage **return_iplist, int *return_count); NTSTATUS internal_resolve_name(const char *name, int name_type, diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c index 6676f02..f9e8f3b 100644 --- a/source3/lib/wins_srv.c +++ b/source3/lib/wins_srv.c @@ -328,6 +328,48 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) return t_ip.ip; } +bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx, + struct in_addr **pservers, int *pnum_servers) +{ + const char **list; + int i, num_servers; + struct in_addr *servers; + + list = lp_wins_server_list(); + if ((list == NULL) || (list[0] == NULL)) { + return false; + } + + num_servers = 0; + + for (i=0; list[i] != NULL; i++) { + struct tagged_ip t_ip; + parse_ip(&t_ip, list[i]); + if (strcmp(tag, t_ip.tag) == 0) { + num_servers += 1; + } + } + + servers = talloc_array(mem_ctx, struct in_addr, num_servers); + if (servers == NULL) { + return false; + } + + num_servers = 0; + + for (i=0; list[i] != NULL; i++) { + struct tagged_ip t_ip; + parse_ip(&t_ip, list[i]); + if (strcmp(tag, t_ip.tag) == 0) { + servers[num_servers] = t_ip.ip; + num_servers += 1; + } + } + *pnum_servers = num_servers; + *pservers = servers; + return true; +} + /* return a count of the number of IPs for a particular tag, including diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 511eba4..dc062fb 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -208,6 +208,15 @@ static void set_socket_addr_v4(struct sockaddr_storage *addr) } } +static struct in_addr my_socket_addr_v4(void) +{ + struct sockaddr_storage my_addr; + struct sockaddr_in *in_addr = (struct sockaddr_in *)((char *)&my_addr); + + set_socket_addr_v4(&my_addr); + return in_addr->sin_addr; +} + /**************************************************************************** Generate a random trn_id. ****************************************************************************/ @@ -1423,9 +1432,18 @@ NTSTATUS name_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, req, struct name_query_state); NTSTATUS status; - if (tevent_req_is_nterror(req, &status) - && !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - return status; + if (tevent_req_is_nterror(req, &status)) { + if (state->bcast && + NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + /* + * In the broadcast case we collect replies until the + * timeout. + */ + status = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(status)) { + return status; + } } if (state->num_addrs == 0) { return NT_STATUS_NOT_FOUND; @@ -1793,45 +1811,175 @@ NTSTATUS name_resolve_bcast(const char *name, NULL, NULL); } -/******************************************************** - Resolve via "wins" method. -*********************************************************/ +struct query_wins_list_state { + struct tevent_context *ev; + const char *name; + uint8_t name_type; + struct in_addr *servers; + uint32_t num_servers; + struct sockaddr_storage server; + uint32_t num_sent; -NTSTATUS resolve_wins(const char *name, - int name_type, - struct ip_service **return_iplist, - int *return_count) + struct sockaddr_storage *addrs; + int num_addrs; + uint8_t flags; +}; + +static void query_wins_list_done(struct tevent_req *subreq); + +/* + * Query a list of (replicating) wins servers in sequence, call them + * dead if they don't reply + */ + +static struct tevent_req *query_wins_list_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct in_addr src_ip, const char *name, uint8_t name_type, + struct in_addr *servers, int num_servers) { - int t, i; - char **wins_tags; - struct sockaddr_storage src_ss, *ss_list = NULL; - struct in_addr src_ip; + struct tevent_req *req, *subreq; + struct query_wins_list_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct query_wins_list_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->name = name; + state->name_type = name_type; + state->servers = servers; + state->num_servers = num_servers; + + if (state->num_servers == 0) { + tevent_req_nterror(req, NT_STATUS_NOT_FOUND); + return tevent_req_post(req, ev); + } + + in_addr_to_sockaddr_storage( + &state->server, state->servers[state->num_sent]); + + subreq = name_query_send(state, state->ev, + state->name, state->name_type, + false, true, &state->server); + state->num_sent += 1; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + if (!tevent_req_set_endtime(subreq, state->ev, + timeval_current_ofs(2, 0))) { + tevent_req_nomem(NULL, req); + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, query_wins_list_done, req); + return req; +} + +static void query_wins_list_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct query_wins_list_state *state = tevent_req_data( + req, struct query_wins_list_state); NTSTATUS status; - if (lp_disable_netbios()) { - DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", - name, name_type)); - return NT_STATUS_INVALID_PARAMETER; + status = name_query_recv(subreq, state, + &state->addrs, &state->num_addrs, + &state->flags); + TALLOC_FREE(subreq); + if (NT_STATUS_IS_OK(status)) { + tevent_req_done(req); + return; } + if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + tevent_req_nterror(req, status); + return; + } + wins_srv_died(state->servers[state->num_sent-1], + my_socket_addr_v4()); - *return_iplist = NULL; - *return_count = 0; + if (state->num_sent == state->num_servers) { + tevent_req_nterror(req, NT_STATUS_NOT_FOUND); + return; + } - DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", - name, name_type)); + in_addr_to_sockaddr_storage( + &state->server, state->servers[state->num_sent]); - if (wins_srv_count() < 1) { - DEBUG(3,("resolve_wins: WINS server resolution selected " - "and no WINS servers listed.\n")); - return NT_STATUS_INVALID_PARAMETER; + subreq = name_query_send(state, state->ev, + state->name, state->name_type, + false, true, &state->server); + state->num_sent += 1; + if (tevent_req_nomem(subreq, req)) { + return; } + if (!tevent_req_set_endtime(subreq, state->ev, + timeval_current_ofs(2, 0))) { + tevent_req_nomem(NULL, req); + return; + } + tevent_req_set_callback(subreq, query_wins_list_done, req); +} - /* we try a lookup on each of the WINS tags in turn */ - wins_tags = wins_srv_tags(); +static NTSTATUS query_wins_list_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct sockaddr_storage **addrs, + int *num_addrs, + uint8_t *flags) +{ + struct query_wins_list_state *state = tevent_req_data( + req, struct query_wins_list_state); + NTSTATUS status; - if (!wins_tags) { - /* huh? no tags?? give up in disgust */ - return NT_STATUS_INVALID_PARAMETER; + if (tevent_req_is_nterror(req, &status)) { + return status; + } + if (addrs != NULL) { + *addrs = talloc_move(mem_ctx, &state->addrs); + } + if (num_addrs != NULL) { + *num_addrs = state->num_addrs; + } + if (flags != NULL) { + *flags = state->flags; + } + return NT_STATUS_OK; +} + +struct resolve_wins_state { + int num_sent; + int num_received; + + struct sockaddr_storage *addrs; + int num_addrs; + uint8_t flags; +}; + +static void resolve_wins_done(struct tevent_req *subreq); + +struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + int name_type) +{ + struct tevent_req *req, *subreq; + struct resolve_wins_state *state; + char **wins_tags = NULL; + struct sockaddr_storage src_ss; + struct in_addr src_ip; + int i, num_wins_tags; + + req = tevent_req_create(mem_ctx, &state, + struct resolve_wins_state); + if (req == NULL) { + return NULL; + } + + if (wins_srv_count() < 1) { + DEBUG(3,("resolve_wins: WINS server resolution selected " + "and no WINS servers listed.\n")); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; } /* the address we will be sending from */ @@ -1846,80 +1994,164 @@ NTSTATUS resolve_wins(const char *name, DEBUG(3,("resolve_wins: cannot receive WINS replies " "on IPv6 address %s\n", addr)); - wins_srv_tags_free(wins_tags); - return NT_STATUS_INVALID_PARAMETER; + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; } - src_ip = ((struct sockaddr_in *)&src_ss)->sin_addr; + src_ip = ((const struct sockaddr_in *)(void *)&src_ss)->sin_addr; - /* in the worst case we will try every wins server with every - tag! */ - for (t=0; wins_tags && wins_tags[t]; t++) { - int srv_count = wins_srv_count_tag(wins_tags[t]); - for (i=0; i<srv_count; i++) { - struct sockaddr_storage wins_ss; - struct in_addr wins_ip; + wins_tags = wins_srv_tags(); + if (wins_tags == NULL) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; + } - wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip); + num_wins_tags = 0; + while (wins_tags[num_wins_tags] != NULL) { + num_wins_tags += 1; + } + + for (i=0; i<num_wins_tags; i++) { + int num_servers, num_alive; + struct in_addr *servers, *alive; + int j; + + if (!wins_server_tag_ips(wins_tags[i], talloc_tos(), + &servers, &num_servers)) { + DEBUG(10, ("wins_server_tag_ips failed for tag %s\n", + wins_tags[i])); + continue; + } + + alive = talloc_array(state, struct in_addr, num_servers); + if (tevent_req_nomem(alive, req)) { + goto fail; -- Samba Shared Repository