r5251: - renamed the nbtd server side structures to have a nbtd_ prefix, to
authorAndrew Tridgell <tridge@samba.org>
Sun, 6 Feb 2005 08:25:53 +0000 (08:25 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:34 +0000 (13:09 -0500)
  be consistent with the function names

- added WINS client support to the NBT server. It will do initial WINS
  registration, and WINS refresh, automatically failing over to
  secondary WINS servers and handling multi-homed servers where we need
  to register multiple IPs.

- added support for multi-homed name query replies, which are
  essential for multi-homed registration as the WINS server will query
  us to ensure we have the names when doing the secondary IPs in
  multi-homed registration
(This used to be commit a1553fa8054dc7d33f5d77f8f95d3ffd90392b2a)

source4/nbt_server/config.mk
source4/nbt_server/defense.c
source4/nbt_server/interfaces.c
source4/nbt_server/nbt_server.c
source4/nbt_server/nbt_server.h
source4/nbt_server/nodestatus.c
source4/nbt_server/packet.c
source4/nbt_server/query.c
source4/nbt_server/register.c
source4/nbt_server/winsclient.c [new file with mode: 0644]
source4/nbt_server/winsserver.c

index 34ed8878e8ca865a7971bc460a914d920798790d..8054ebc4de2f4a9a43cafc2148a9d91de57afd2c 100644 (file)
@@ -11,6 +11,7 @@ ADD_OBJ_FILES = \
                nbt_server/query.o \
                nbt_server/nodestatus.o \
                nbt_server/winsserver.o \
+               nbt_server/winsclient.o \
                nbt_server/defense.o \
                nbt_server/packet.o
 REQUIRED_SUBSYSTEMS = \
index e2095f22bd6b5a450a1a822dff5670626033bc2b..86cf587235702e4d53dea6e8c66516b197cd30ea 100644 (file)
@@ -43,7 +43,7 @@ static void nbtd_name_defense_reply(struct nbt_name_socket *nbtsock,
        packet->ancount = 1;
        packet->operation = 
                NBT_FLAG_REPLY | 
-               (request_packet->operation & NBT_OPCODE) |
+               NBT_OPCODE_REGISTER |
                NBT_FLAG_AUTHORITIVE |
                NBT_FLAG_RECURSION_DESIRED |
                NBT_FLAG_RECURSION_AVAIL |
@@ -84,10 +84,10 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
                          struct nbt_name_packet *packet, 
                          const char *src_address, int src_port)
 {
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        struct nbt_name *name;
-       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
-                                                     struct nbt_interface);
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                      struct nbtd_interface);
 
        NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
        NBT_ASSERT_PACKET(packet, src_address, packet->arcount == 1);
index bb599b4fcdf59ec35da22deb5552fe76e703f371..b99c17089cb878b71a497a18c0e9d2eff7921ffb 100644 (file)
@@ -33,9 +33,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
                                 struct nbt_name_packet *packet, 
                                 const char *src_address, int src_port)
 {
-       /* if its a WINS query then direct to our WINS server */
+       /* if its a WINS query then direct to our WINS server if we
+          are running one */
        if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
-           !(packet->operation & NBT_FLAG_BROADCAST)) {
+           !(packet->operation & NBT_FLAG_BROADCAST) &&
+           lp_wins_support()) {
                nbtd_query_wins(nbtsock, packet, src_address, src_port);
                return;
        }
@@ -56,6 +58,10 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
        case NBT_OPCODE_REFRESH:
                nbtd_request_defense(nbtsock, packet, src_address, src_port);
                break;
+
+       default:
+               nbtd_bad_packet(packet, src_address, "Unexpected opcode");
+               break;
        }
 }
 
@@ -64,11 +70,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
 /*
   find a registered name on an interface
 */
-struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface, 
-                                      struct nbt_name *name, 
-                                      uint16_t nb_flags)
+struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface, 
+                                       struct nbt_name *name, 
+                                       uint16_t nb_flags)
 {
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        for (iname=iface->names;iname;iname=iname->next) {
                if (iname->name.type == name->type &&
                    StrCaseCmp(name->name, iname->name.name) == 0 &&
@@ -82,13 +88,13 @@ struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface,
 /*
   start listening on the given address
 */
-static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv, 
+static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv, 
                                const char *bind_address, 
                                const char *address, 
                                const char *bcast, 
                                const char *netmask)
 {
-       struct nbt_interface *iface;
+       struct nbtd_interface *iface;
        NTSTATUS status;
        struct nbt_name_socket *bcast_nbtsock;
 
@@ -100,7 +106,7 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
          to interfaces
        */
 
-       iface = talloc(nbtsrv, struct nbt_interface);
+       iface = talloc(nbtsrv, struct nbtd_interface);
        NT_STATUS_HAVE_NO_MEMORY(iface);
 
        iface->nbtsrv        = nbtsrv;
@@ -150,10 +156,31 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
 }
 
 
+/*
+  setup a socket for talking to our WINS servers
+*/
+static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
+{
+       struct nbtd_interface *iface;
+
+       iface = talloc_zero(nbtsrv, struct nbtd_interface);
+       NT_STATUS_HAVE_NO_MEMORY(iface);
+
+       iface->nbtsrv        = nbtsrv;
+
+       iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
+       NT_STATUS_HAVE_NO_MEMORY(iface->nbtsock);
+
+       DLIST_ADD(nbtsrv->wins_interface, iface);
+
+       return NT_STATUS_OK;
+}
+
+
 /*
   setup our listening sockets on the configured network interfaces
 */
-NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
+NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
 {
        int num_interfaces = iface_count();
        int i;
@@ -194,7 +221,38 @@ NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
                NT_STATUS_NOT_OK_RETURN(status);
        }
 
+       if (lp_wins_server_list()) {
+               status = nbtd_add_wins_socket(nbtsrv);
+               NT_STATUS_NOT_OK_RETURN(status);
+       }
+
        talloc_free(tmp_ctx);
 
        return NT_STATUS_OK;
 }
+
+
+/*
+  form a list of addresses that we should use in name query replies
+*/
+const char **nbtd_address_list(struct nbtd_server *nbtsrv, TALLOC_CTX *mem_ctx)
+{
+       const char **ret = NULL;
+       struct nbtd_interface *iface;
+       int count = 0;
+
+       for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
+               const char **ret2 = talloc_realloc(mem_ctx, ret, const char *, count+2);
+               if (ret2 == NULL) goto failed;
+               ret = ret2;
+               ret[count] = talloc_strdup(ret, iface->ip_address);
+               if (ret[count] == NULL) goto failed;
+               count++;
+       }
+       ret[count] = NULL;
+       return ret;
+
+failed:
+       talloc_free(ret);
+       return NULL;
+}
index d312269a1952f8e495a42ff4b67f84c654a4676e..73724720e5edc6e57c9bf7d921789fb4c727d92d 100644 (file)
 */
 static void nbtd_task_init(struct task_server *task)
 {
-       struct nbt_server *nbtsrv;
+       struct nbtd_server *nbtsrv;
        NTSTATUS status;
 
-       nbtsrv = talloc(task, struct nbt_server);
+       nbtsrv = talloc(task, struct nbtd_server);
        if (nbtsrv == NULL) {
                task_terminate(task, "nbtd: out of memory");
                return;
@@ -43,6 +43,7 @@ static void nbtd_task_init(struct task_server *task)
        nbtsrv->task            = task;
        nbtsrv->interfaces      = NULL;
        nbtsrv->bcast_interface = NULL;
+       nbtsrv->wins_interface  = NULL;
 
        /* start listening on the configured network interfaces */
        status = nbtd_startup_interfaces(nbtsrv);
index d7c85d77f2f0234bd3cf1fc5fe56a1c1a1a82cb9..3def958cc4587c78b64dc81b39e06805ed64f7c1 100644 (file)
 /* 
    a list of our registered names on each interface
 */
-struct nbt_iface_name {
-       struct nbt_iface_name *next, *prev;
-       struct nbt_interface *iface;
+struct nbtd_iface_name {
+       struct nbtd_iface_name *next, *prev;
+       struct nbtd_interface *iface;
        struct nbt_name name;
        uint16_t nb_flags;
        struct timeval registration_time;
        uint32_t ttl;
+
+       /* if registered with a wins server, then this lists the server being
+          used */
+       char *wins_server;
 };
 
 
 /* a list of network interfaces we are listening on */
-struct nbt_interface {
-       struct nbt_interface *next, *prev;
-       struct nbt_server *nbtsrv;
+struct nbtd_interface {
+       struct nbtd_interface *next, *prev;
+       struct nbtd_server *nbtsrv;
        const char *ip_address;
        const char *bcast_address;
        const char *netmask;
        struct nbt_name_socket *nbtsock;
-       struct nbt_iface_name *names;
+       struct nbtd_iface_name *names;
 };
 
 
 /*
   top level context structure for the nbt server
 */
-struct nbt_server {
+struct nbtd_server {
        struct task_server *task;
 
        /* the list of local network interfaces */
-       struct nbt_interface *interfaces;
+       struct nbtd_interface *interfaces;
 
        /* broadcast interface used for receiving packets only */
-       struct nbt_interface *bcast_interface;
+       struct nbtd_interface *bcast_interface;
+
+       /* wins client interface - used for registering and refreshing
+          our names with a WINS server */
+       struct nbtd_interface *wins_interface;
 };
 
 
index 0d0fbb8086c5a8ebf16f89dedd04da4959aea6cf..ba6c3ea77b64abe573638967da479a5629ac8ba9 100644 (file)
@@ -32,11 +32,11 @@ static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
                                   struct nbt_name_packet *request_packet, 
                                   const char *src_address, int src_port,
                                   struct nbt_name *name, 
-                                  struct nbt_interface *iface)
+                                  struct nbtd_interface *iface)
 {
        struct nbt_name_packet *packet;
        uint32_t name_count;
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        
        /* work out how many names to send */
        name_count = 0;
@@ -100,9 +100,9 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock,
                       const char *src_address, int src_port)
 {
        struct nbt_name *name;
-       struct nbt_iface_name *iname;
-       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
-                                                     struct nbt_interface);
+       struct nbtd_iface_name *iname;
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                      struct nbtd_interface);
 
        NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
        NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_STATUS);
index bb9e2459b1ca081a4700577d9eed30eb32e92e23..ac803f3d5ee4fcb83bcb16dc524c0c2b5b8f2d41 100644 (file)
@@ -45,9 +45,9 @@ BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock,
                      struct nbt_name_packet *packet, 
                      const char *src_address, int src_port)
 {
-       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
-                                                     struct nbt_interface);
-       struct nbt_server *nbtsrv = iface->nbtsrv;
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                      struct nbtd_interface);
+       struct nbtd_server *nbtsrv = iface->nbtsrv;
        
        /* if its not a broadcast then its not considered a self packet */
        if (!(packet->operation & NBT_FLAG_BROADCAST)) {
index bf2c75f2d1b69e201bc8868182e7d078f2d257be..80ea3d6ab818dd82270a425e092820850865d386 100644 (file)
@@ -32,9 +32,16 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
                                  struct nbt_name_packet *request_packet, 
                                  const char *src_address, int src_port,
                                  struct nbt_name *name, uint32_t ttl,
-                                 uint16_t nb_flags, const char *address)
+                                 uint16_t nb_flags, const char **addresses)
 {
        struct nbt_name_packet *packet;
+       size_t num_addresses = str_list_length(addresses);
+       int i;
+
+       if (num_addresses == 0) {
+               DEBUG(3,("No addresses in name query reply - failing\n"));
+               return;
+       }
 
        packet = talloc_zero(nbtsock, struct nbt_name_packet);
        if (packet == NULL) return;
@@ -55,17 +62,21 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
        packet->answers[0].rr_type  = NBT_QTYPE_NETBIOS;
        packet->answers[0].rr_class = NBT_QCLASS_IP;
        packet->answers[0].ttl      = ttl;
-       packet->answers[0].rdata.netbios.length = 6;
-       packet->answers[0].rdata.netbios.addresses = talloc_array(packet->answers,
-                                                           struct nbt_rdata_address, 1);
+       packet->answers[0].rdata.netbios.length = num_addresses*6;
+       packet->answers[0].rdata.netbios.addresses = 
+               talloc_array(packet->answers, struct nbt_rdata_address, num_addresses);
        if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
-       packet->answers[0].rdata.netbios.addresses[0].nb_flags = nb_flags;
-       packet->answers[0].rdata.netbios.addresses[0].ipaddr = 
-               talloc_strdup(packet->answers, address);
-       if (packet->answers[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
+
+       for (i=0;i<num_addresses;i++) {
+               struct nbt_rdata_address *addr = 
+                       &packet->answers[0].rdata.netbios.addresses[i];
+               addr->nb_flags = nb_flags;
+               addr->ipaddr = talloc_strdup(packet->answers, addresses[i]);
+               if (addr->ipaddr == NULL) goto failed;
+       }
 
        DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n", 
-                name->name, name->type, src_address, address, src_port));
+                name->name, name->type, src_address, addresses[0], src_port));
        
        nbt_name_reply_send(nbtsock, src_address, src_port, packet);
 
@@ -81,10 +92,10 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
                        struct nbt_name_packet *packet, 
                        const char *src_address, int src_port)
 {
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        struct nbt_name *name;
-       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
-                                                     struct nbt_interface);
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                      struct nbtd_interface);
 
        /* see if its a node status query */
        if (packet->qdcount == 1 &&
@@ -100,14 +111,23 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
 
-       iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
+       iname = nbtd_find_iname(iface, name, 0);
        if (iname == NULL) {
                DEBUG(7,("Query for %s<%02x> from %s - not found on %s\n",
                         name->name, name->type, src_address, iface->ip_address));
                return;
        }
 
+       /* if the name is not yet active and its a broadcast query then
+          ignore it for now */
+       if (!(iname->nb_flags & NBT_NM_ACTIVE) && 
+           (packet->operation & NBT_FLAG_BROADCAST)) {
+               DEBUG(7,("Query for %s<%02x> from %s - name not active yet on %s\n",
+                        name->name, name->type, src_address, iface->ip_address));
+               return;
+       }
+
        nbtd_name_query_reply(nbtsock, packet, src_address, src_port,
                              &iname->name, iname->ttl, iname->nb_flags, 
-                             iface->ip_address);
+                             nbtd_address_list(iface->nbtsrv, packet));
 }
index e033797164e9c879f644c88375c09e9efa603259..b65bd6d5acd7a802b335e72a2eb35668a3e6efe3 100644 (file)
 #include "libcli/composite/composite.h"
 
 
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname);
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
 
 /*
   a name refresh request has completed
 */
 static void refresh_completion_handler(struct nbt_name_request *req)
 {
-       struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
+       struct nbtd_iface_name *iname = talloc_get_type(req->async.private, 
+                                                       struct nbtd_iface_name);
        NTSTATUS status;
        struct nbt_name_refresh io;
        TALLOC_CTX *tmp_ctx = talloc_new(iname);
@@ -74,8 +75,8 @@ static void refresh_completion_handler(struct nbt_name_request *req)
 static void name_refresh_handler(struct event_context *ev, struct timed_event *te, 
                                 struct timeval t, void *private)
 {
-       struct nbt_iface_name *iname = talloc_get_type(private, struct nbt_iface_name);
-       struct nbt_interface *iface = iname->iface;
+       struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
+       struct nbtd_interface *iface = iname->iface;
        struct nbt_name_register io;
        struct nbt_name_request *req;
 
@@ -92,6 +93,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
        io.in.register_demand = False;
        io.in.broadcast       = True;
        io.in.timeout         = 3;
+       io.in.retries         = 0;
 
        req = nbt_name_register_send(iface->nbtsock, &io);
        if (req == NULL) return;
@@ -104,7 +106,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
 /*
   start a timer to refresh this name
 */
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
 {
        uint32_t refresh_time;
        uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
@@ -123,8 +125,8 @@ static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
 */
 static void nbtd_register_handler(struct composite_context *req)
 {
-       struct nbt_iface_name *iname = talloc_get_type(req->async.private, 
-                                                      struct nbt_iface_name);
+       struct nbtd_iface_name *iname = talloc_get_type(req->async.private, 
+                                                       struct nbtd_iface_name);
        NTSTATUS status;
 
        status = nbt_name_register_bcast_recv(req);
@@ -150,16 +152,16 @@ static void nbtd_register_handler(struct composite_context *req)
 /*
   register a name on a network interface
 */
-static void nbtd_register_name_iface(struct nbt_interface *iface,
+static void nbtd_register_name_iface(struct nbtd_interface *iface,
                                     const char *name, enum nbt_name_type type,
                                     uint16_t nb_flags)
 {
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        const char *scope = lp_netbios_scope();
        struct nbt_name_register_bcast io;
        struct composite_context *req;
 
-       iname = talloc(iface, struct nbt_iface_name);
+       iname = talloc(iface, struct nbtd_iface_name);
        if (!iname) return;
 
        iname->iface     = iface;
@@ -173,8 +175,9 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
        iname->nb_flags          = nb_flags;
        iname->ttl               = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
        iname->registration_time = timeval_zero();
+       iname->wins_server       = NULL;
 
-       DLIST_ADD_END(iface->names, iname, struct nbt_iface_name *);
+       DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
 
        if (nb_flags & NBT_NM_PERMANENT) {
                /* permanent names are not announced and are immediately active */
@@ -183,6 +186,13 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
                return;
        }
 
+       /* if this is the wins interface, then we need to do a special
+          wins name registration */
+       if (iface == iface->nbtsrv->wins_interface) {
+               nbtd_winsclient_refresh(iname);
+               return;
+       }
+
        /* setup a broadcast name registration request */
        io.in.name            = iname->name;
        io.in.dest_addr       = iface->bcast_address;
@@ -201,11 +211,11 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
 /*
   register one name on all our interfaces
 */
-static void nbtd_register_name(struct nbt_server *nbtsrv, 
+static void nbtd_register_name(struct nbtd_server *nbtsrv, 
                               const char *name, enum nbt_name_type type,
                               uint16_t nb_flags)
 {
-       struct nbt_interface *iface;
+       struct nbtd_interface *iface;
        
        /* register with all the local interfaces */
        for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
@@ -218,14 +228,17 @@ static void nbtd_register_name(struct nbt_server *nbtsrv,
                                         nb_flags | NBT_NM_PERMANENT);
        }
 
-       /* TODO: register with our WINS servers */
+       /* register with our WINS servers */
+       if (nbtsrv->wins_interface) {
+               nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
+       }
 }
 
 
 /*
   register our names on all interfaces
 */
-void nbtd_register_names(struct nbt_server *nbtsrv)
+void nbtd_register_names(struct nbtd_server *nbtsrv)
 {
        uint16_t nb_flags = NBT_NODE_M;
        const char **aliases;
diff --git a/source4/nbt_server/winsclient.c b/source4/nbt_server/winsclient.c
new file mode 100644 (file)
index 0000000..572d46b
--- /dev/null
@@ -0,0 +1,123 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   wins client name registration and refresh
+
+   Copyright (C) Andrew Tridgell       2005
+   
+   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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "nbt_server/nbt_server.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
+#include "lib/events/events.h"
+#include "smbd/service_task.h"
+
+
+/*
+  refresh a WINS name registration
+*/
+static void nbtd_refresh_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);
+       nbtd_winsclient_refresh(iname);
+}
+
+/*
+  called when a wins name refresh has completed
+*/
+static void nbtd_refresh_wins_handler(struct composite_context *c)
+{
+       NTSTATUS status;
+       struct nbt_name_refresh_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_refresh_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);
+               event_add_timed(iname->iface->nbtsrv->task->event_ctx, 
+                               iname,
+                               timeval_current_ofs(wins_retry_time, 0),
+                               nbtd_refresh_wins_refresh,
+                               iname);
+               talloc_free(tmp_ctx);
+               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> - rcode %d\n", 
+                        io.out.wins_server, iname->name.name, iname->name.type, io.out.rcode));
+               iname->nb_flags |= NBT_NM_CONFLICT;
+               talloc_free(tmp_ctx);
+               return;
+       }       
+
+       /* 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_refresh_wins_refresh,
+                       iname);
+
+       talloc_free(tmp_ctx);
+}
+
+/*
+  refresh a name with our WINS servers
+*/
+void nbtd_winsclient_refresh(struct nbtd_iface_name *iname)
+{
+       struct nbtd_interface *iface = iname->iface;
+       struct nbt_name_refresh_wins io;
+       struct composite_context *c;
+
+       /* setup a wins name refresh request */
+       io.in.name            = iname->name;
+       io.in.wins_servers    = lp_wins_server_list();
+       io.in.addresses       = nbtd_address_list(iface->nbtsrv, iname);
+       io.in.nb_flags        = iname->nb_flags;
+       io.in.ttl             = iname->ttl;
+
+       c = nbt_name_refresh_wins_send(iface->nbtsock, &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.private = iname;
+}
index 44216a1cb52485d4601af401c8719cf9aa945ef7..5940303f66b4b5357703648b2ccd47e17f2517dc 100644 (file)
@@ -21,7 +21,6 @@
 */
 
 #include "includes.h"
-#include "dlinklist.h"
 #include "nbt_server/nbt_server.h"
 
 /*