summaryrefslogtreecommitdiff
path: root/source4/nbt_server/wins/winswack.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2005-12-30 12:13:46 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:49:03 -0500
commit805f5d861fe84ff9bc53f974d667434b7d4c60d8 (patch)
tree7f5b91a5bd5e6a36dba28e864a25921d6bbb31ad /source4/nbt_server/wins/winswack.c
parenta6d0d564597ea793e0a145ff39fafd6a0dfd6c0f (diff)
downloadsamba-805f5d861fe84ff9bc53f974d667434b7d4c60d8.tar.gz
samba-805f5d861fe84ff9bc53f974d667434b7d4c60d8.tar.bz2
samba-805f5d861fe84ff9bc53f974d667434b7d4c60d8.zip
r12606: - fix multihomed registrations
always remove the addresses which are no longer valid - use the wins_challenge_send/recv calls which are also used by the replication challenge metze (This used to be commit 037b5d9f3661fd7a121d1db0a50dc7743d62a5e1)
Diffstat (limited to 'source4/nbt_server/wins/winswack.c')
-rw-r--r--source4/nbt_server/wins/winswack.c212
1 files changed, 3 insertions, 209 deletions
diff --git a/source4/nbt_server/wins/winswack.c b/source4/nbt_server/wins/winswack.c
index cedd66603f..9e41d14e45 100644
--- a/source4/nbt_server/wins/winswack.c
+++ b/source4/nbt_server/wins/winswack.c
@@ -24,23 +24,10 @@
#include "includes.h"
#include "nbt_server/nbt_server.h"
#include "nbt_server/wins/winsdb.h"
+#include "nbt_server/wins/winswack.h"
#include "system/time.h"
#include "libcli/composite/composite.h"
-struct wins_challenge_io {
- struct {
- struct nbtd_server *nbtd_server;
- struct event_context *event_ctx;
- struct nbt_name *name;
- uint32_t num_addresses;
- const char **addresses;
- } in;
- struct {
- uint32_t num_addresses;
- const char **addresses;
- } out;
-};
-
struct wins_challenge_state {
struct wins_challenge_io *io;
uint32_t current_address;
@@ -78,7 +65,7 @@ static void wins_challenge_handler(struct nbt_name_request *req)
composite_done(ctx);
}
-static NTSTATUS wins_challenge_recv(struct composite_context *ctx, TALLOC_CTX *mem_ctx, struct wins_challenge_io *io)
+NTSTATUS wins_challenge_recv(struct composite_context *ctx, TALLOC_CTX *mem_ctx, struct wins_challenge_io *io)
{
NTSTATUS status = ctx->status;
struct wins_challenge_state *state = talloc_get_type(ctx->private_data, struct wins_challenge_state);
@@ -95,7 +82,7 @@ static NTSTATUS wins_challenge_recv(struct composite_context *ctx, TALLOC_CTX *m
return status;
}
-static struct composite_context *wins_challenge_send(TALLOC_CTX *mem_ctx, struct wins_challenge_io *io)
+struct composite_context *wins_challenge_send(TALLOC_CTX *mem_ctx, struct wins_challenge_io *io)
{
struct composite_context *result;
struct wins_challenge_state *state;
@@ -256,199 +243,6 @@ failed:
return NULL;
}
-struct wack_state {
- struct wins_server *winssrv;
- struct nbt_name_socket *nbtsock;
- struct nbt_name_packet *request_packet;
- struct winsdb_record *rec;
- struct nbt_peer_socket src;
- const char **owner_addresses;
- const char *reg_address;
- struct nbt_name_query query;
-};
-
-
-/*
- deny a registration request
-*/
-static void wins_wack_deny(struct wack_state *state)
-{
- nbtd_name_registration_reply(state->nbtsock, state->request_packet,
- &state->src, NBT_RCODE_ACT);
- DEBUG(4,("WINS: denied name registration request for %s from %s:%d\n",
- nbt_name_string(state, state->rec->name), state->src.addr, state->src.port));
- talloc_free(state);
-}
-
-/*
- allow a registration request
-*/
-static void wins_wack_allow(struct wack_state *state)
-{
- NTSTATUS status;
- uint32_t ttl = wins_server_ttl(state->winssrv, state->request_packet->additional[0].ttl);
- struct winsdb_record *rec = state->rec, *rec2;
-
- status = winsdb_lookup(state->winssrv->wins_db, rec->name, state, &rec2);
- if (!NT_STATUS_IS_OK(status)
- || rec2->version != rec->version
- || strcmp(rec2->wins_owner, rec->wins_owner) != 0) {
- DEBUG(1,("WINS: record %s changed during WACK - failing registration\n",
- nbt_name_string(state, rec->name)));
- wins_wack_deny(state);
- return;
- }
-
- nbtd_name_registration_reply(state->nbtsock, state->request_packet,
- &state->src, NBT_RCODE_OK);
-
- rec->expire_time = time(NULL) + ttl;
- rec->registered_by = state->src.addr;
-
- /* TODO: is it correct to only add this address? */
- rec->addresses = winsdb_addr_list_add(rec->addresses,
- state->reg_address,
- WINSDB_OWNER_LOCAL,
- rec->expire_time);
- if (rec->addresses == NULL) goto failed;
-
- /* if we have more than one address, this becomes implicit a MHOMED record */
- if (winsdb_addr_list_length(rec->addresses) > 1) {
- rec->type = WREPL_TYPE_MHOMED;
- }
-
- winsdb_modify(state->winssrv->wins_db, rec, WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP);
-
- DEBUG(4,("WINS: accepted registration of %s with address %s\n",
- nbt_name_string(state, rec->name), state->reg_address));
-
-failed:
- talloc_free(state);
-}
-
-/*
- called when a name query to a current owner completes
-*/
-static void wins_wack_handler(struct nbt_name_request *req)
-{
- struct wack_state *state = talloc_get_type(req->async.private, struct wack_state);
- NTSTATUS status;
- int i;
- struct winsdb_record *rec = state->rec;
-
- status = nbt_name_query_recv(req, state, &state->query);
-
- /* if we timed out then try the next owner address, if any */
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
- state->owner_addresses++;
- if (state->owner_addresses[0] == NULL) {
- wins_wack_allow(state);
- return;
- }
- state->query.in.dest_addr = state->owner_addresses[0];
-
- req = nbt_name_query_send(state->nbtsock, &state->query);
- if (req == NULL) goto failed;
-
- req->async.fn = wins_wack_handler;
- req->async.private = state;
- return;
- }
-
- /* if the owner denies it holds the name, then allow
- the registration */
- if (!NT_STATUS_IS_OK(status)) {
- wins_wack_allow(state);
- return;
- }
-
- /* if the owner still wants the name and doesn't reply
- with the address trying to be registered, then deny
- the registration */
- if (!str_list_check(state->query.out.reply_addrs, state->reg_address)) {
- wins_wack_deny(state);
- return;
- }
-
- /* we are going to allow the registration, but first remove any addresses
- from the record that aren't in the reply from the client */
- for (i=0; state->query.out.reply_addrs[i]; i++) {
- if (!winsdb_addr_list_check(rec->addresses, state->query.out.reply_addrs[i])) {
- winsdb_addr_list_remove(rec->addresses, state->query.out.reply_addrs[i]);
- }
- }
-
- wins_wack_allow(state);
- return;
-
-failed:
- talloc_free(state);
-}
-
-
-/*
- a client has asked to register a unique name that someone else owns. We
- need to ask each of the current owners if they still want it. If they do
- then reject the registration, otherwise allow it
-*/
-void wins_register_wack(struct nbt_name_socket *nbtsock,
- struct nbt_name_packet *packet,
- struct winsdb_record *rec,
- const struct nbt_peer_socket *src)
-{
- struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
- struct nbtd_interface);
- struct wins_server *winssrv = iface->nbtsrv->winssrv;
- struct wack_state *state;
- struct nbt_name_request *req;
- uint32_t ttl;
-
- state = talloc(nbtsock, struct wack_state);
- if (state == NULL) goto failed;
-
- /* package up the state variables for this wack request */
- state->winssrv = winssrv;
- state->nbtsock = nbtsock;
- state->request_packet = talloc_steal(state, packet);
- state->rec = talloc_steal(state, rec);
- state->owner_addresses = winsdb_addr_string_list(state, rec->addresses);
- if (state->owner_addresses == NULL) goto failed;
- state->reg_address = packet->additional[0].rdata.netbios.addresses[0].ipaddr;
- state->src.port = src->port;
- state->src.addr = talloc_strdup(state, src->addr);
- if (state->src.addr == NULL) goto failed;
-
- /* setup a name query to the first address */
- state->query.in.name = *rec->name;
- state->query.in.dest_addr = state->owner_addresses[0];
- state->query.in.broadcast = False;
- state->query.in.wins_lookup = True;
- state->query.in.timeout = 1;
- state->query.in.retries = 2;
-
- /* the LOGON type is a nasty hack */
- if (rec->name->type == NBT_NAME_LOGON) {
- wins_wack_allow(state);
- return;
- }
-
- /* send a WACK to the client, specifying the maximum time it could
- take to check with the owner, plus some slack */
- ttl = 5 + 4 * winsdb_addr_list_length(rec->addresses);
- nbtd_wack_reply(nbtsock, packet, src, ttl);
-
- req = nbt_name_query_send(nbtsock, &state->query);
- if (req == NULL) goto failed;
-
- req->async.fn = wins_wack_handler;
- req->async.private = state;
- return;
-
-failed:
- talloc_free(state);
- nbtd_name_registration_reply(nbtsock, packet, src, NBT_RCODE_SVR);
-}
-
/*
wrepl_server needs to be able to do a name query request, but some windows
servers always send the reply to port 137, regardless of the request