diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-08 01:09:21 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:36 -0500 |
commit | 998c856d9005cd8e1111a939db6fa7b25196b766 (patch) | |
tree | cc562247c591a12fbad4d9fce76c7e816636d511 /source4/nbt_server/winsclient.c | |
parent | 2513ac33de03e4c92f6d4a10595db44700971bb8 (diff) | |
download | samba-998c856d9005cd8e1111a939db6fa7b25196b766.tar.gz samba-998c856d9005cd8e1111a939db6fa7b25196b766.tar.bz2 samba-998c856d9005cd8e1111a939db6fa7b25196b766.zip |
r5276: - added support for NBT_OPCODE_REFRESH2 (type 0x9)
- when registering with a WINS server, initially use multi-homed
registration, then switch to name refresh requests. Send refresh
requests only to the WINS server that responded to our
registration. If that server goes away, then start the registration
from scratch. This makes registration more robust to WINS server
failure.
- send WINS registration requests out on our first interface rather
than an unbound interface, to avoid the problem of WACK replies
being sent to the wrong port (w2k3 WINS server does this)
(This used to be commit f7712ac7468184c07b3e3c10cb7b847ad1791dd2)
Diffstat (limited to 'source4/nbt_server/winsclient.c')
-rw-r--r-- | source4/nbt_server/winsclient.c | 141 |
1 files changed, 124 insertions, 17 deletions
diff --git a/source4/nbt_server/winsclient.c b/source4/nbt_server/winsclient.c index 80168c9181..e941d77e28 100644 --- a/source4/nbt_server/winsclient.c +++ b/source4/nbt_server/winsclient.c @@ -28,20 +28,33 @@ #include "smbd/service_task.h" +/* we send WINS client requests using our primary network interface +*/ +static struct nbt_name_socket *wins_socket(struct nbtd_interface *iface) +{ + struct nbtd_server *nbtsrv = iface->nbtsrv; + return nbtsrv->interfaces->nbtsock; +} + + +static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private); + /* - refresh a WINS name registration + retry a WINS name registration */ -static void nbtd_refresh_wins_refresh(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) +static void nbtd_wins_register_retry(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private) { struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name); - nbtd_winsclient_refresh(iname); + nbtd_winsclient_register(iname); } + /* called when a wins name refresh has completed */ -static void nbtd_refresh_wins_handler(struct composite_context *c) +static void nbtd_wins_refresh_handler(struct composite_context *c) { NTSTATUS status; struct nbt_name_refresh_wins io; @@ -51,28 +64,119 @@ static void nbtd_refresh_wins_handler(struct composite_context *c) status = nbt_name_refresh_wins_recv(c, tmp_ctx, &io); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + /* our WINS server is dead - start registration over + from scratch */ + DEBUG(2,("Failed to refresh %s<%02x> with WINS server %s\n", + iname->name.name, iname->name.type, iname->wins_server)); + nbtd_winsclient_register(iname); + return; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("Name refresh failure with WINS for %s<%02x> - %s\n", + iname->name.name, iname->name.type, nt_errstr(status))); + talloc_free(tmp_ctx); + return; + } + + if (io.out.rcode != 0) { + DEBUG(1,("WINS server %s rejected name refresh of %s<%02x> - %s\n", + io.out.wins_server, iname->name.name, iname->name.type, + nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode)))); + iname->nb_flags |= NBT_NM_CONFLICT; + talloc_free(tmp_ctx); + return; + } + + DEBUG(4,("Refreshed name %s<%02x> with WINS server %s\n", + iname->name.name, iname->name.type, iname->wins_server)); + /* success - start a periodic name refresh */ + iname->nb_flags |= NBT_NM_ACTIVE; + if (iname->wins_server) { + talloc_free(iname->wins_server); + } + iname->wins_server = talloc_steal(iname, io.out.wins_server); + + iname->registration_time = timeval_current(); + event_add_timed(iname->iface->nbtsrv->task->event_ctx, + iname, + timeval_add(&iname->registration_time, iname->ttl/2, 0), + nbtd_wins_refresh, + iname); + + talloc_free(tmp_ctx); +} + + +/* + refresh a WINS name registration +*/ +static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private) +{ + struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name); + struct nbtd_interface *iface = iname->iface; + struct nbt_name_refresh_wins io; + struct composite_context *c; + TALLOC_CTX *tmp_ctx = talloc_new(iname); + + /* setup a wins name refresh request */ + io.in.name = iname->name; + io.in.wins_servers = str_list_make(tmp_ctx, iname->wins_server, NULL); + io.in.addresses = nbtd_address_list(iface, tmp_ctx); + io.in.nb_flags = iname->nb_flags; + io.in.ttl = iname->ttl; + + c = nbt_name_refresh_wins_send(wins_socket(iface), &io); + if (c == NULL) { + talloc_free(tmp_ctx); + return; + } + talloc_steal(c, io.in.addresses); + + c->async.fn = nbtd_wins_refresh_handler; + c->async.private = iname; + + talloc_free(tmp_ctx); +} + + +/* + called when a wins name register has completed +*/ +static void nbtd_wins_register_handler(struct composite_context *c) +{ + NTSTATUS status; + struct nbt_name_register_wins io; + struct nbtd_iface_name *iname = talloc_get_type(c->async.private, + struct nbtd_iface_name); + TALLOC_CTX *tmp_ctx = talloc_new(iname); + + status = nbt_name_register_wins_recv(c, tmp_ctx, &io); + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { /* none of the WINS servers responded - try again periodically */ - int wins_retry_time = lp_parm_int(-1, "nbt", "wins_retry", 300); + int wins_retry_time = lp_parm_int(-1, "nbtd", "wins_retry", 300); event_add_timed(iname->iface->nbtsrv->task->event_ctx, iname, timeval_current_ofs(wins_retry_time, 0), - nbtd_refresh_wins_refresh, + nbtd_wins_register_retry, iname); talloc_free(tmp_ctx); return; } if (!NT_STATUS_IS_OK(status)) { - DEBUG(1,("Name refresh failure with WINS for %s<%02x> - %s\n", + DEBUG(1,("Name register failure with WINS for %s<%02x> - %s\n", iname->name.name, iname->name.type, nt_errstr(status))); talloc_free(tmp_ctx); return; } if (io.out.rcode != 0) { - DEBUG(1,("WINS server %s rejected name refresh of %s<%02x> - rcode %d\n", - io.out.wins_server, iname->name.name, iname->name.type, io.out.rcode)); + DEBUG(1,("WINS server %s rejected name register of %s<%02x> - %s\n", + io.out.wins_server, iname->name.name, iname->name.type, + nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode)))); iname->nb_flags |= NBT_NM_CONFLICT; talloc_free(tmp_ctx); return; @@ -89,35 +193,38 @@ static void nbtd_refresh_wins_handler(struct composite_context *c) event_add_timed(iname->iface->nbtsrv->task->event_ctx, iname, timeval_add(&iname->registration_time, iname->ttl/2, 0), - nbtd_refresh_wins_refresh, + nbtd_wins_refresh, iname); + DEBUG(3,("Registered %s<%02x> with WINS server %s\n", + iname->name.name, iname->name.type, iname->wins_server)); + talloc_free(tmp_ctx); } /* - refresh a name with our WINS servers + register a name with our WINS servers */ -void nbtd_winsclient_refresh(struct nbtd_iface_name *iname) +void nbtd_winsclient_register(struct nbtd_iface_name *iname) { struct nbtd_interface *iface = iname->iface; - struct nbt_name_refresh_wins io; + struct nbt_name_register_wins io; struct composite_context *c; - /* setup a wins name refresh request */ + /* setup a wins name register request */ io.in.name = iname->name; io.in.wins_servers = lp_wins_server_list(); io.in.addresses = nbtd_address_list(iface, iname); io.in.nb_flags = iname->nb_flags; io.in.ttl = iname->ttl; - c = nbt_name_refresh_wins_send(iface->nbtsock, &io); + c = nbt_name_register_wins_send(wins_socket(iface), &io); if (c == NULL) { talloc_free(io.in.addresses); return; } talloc_steal(c, io.in.addresses); - c->async.fn = nbtd_refresh_wins_handler; + c->async.fn = nbtd_wins_register_handler; c->async.private = iname; } |