r5346: - a bit more preparation for the WINS server going in
authorAndrew Tridgell <tridge@samba.org>
Fri, 11 Feb 2005 23:54:37 +0000 (23:54 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:44 +0000 (13:09 -0500)
- more NBT packet asserts, to ensure that incoming requests have all
  the elements we depend on

- open the WINS database at startup if we are configured as a WINS server

- split out the nbtd server reply packet generation code so it can be
  shared by the WINS server

- re-did the logic of what is answered by the WINS server and what by
  the B node server. It now always tries to answer by the B node, and
  only "recurses" to the WINS server for names that are not found.

source/nbt_server/defense.c
source/nbt_server/interfaces.c
source/nbt_server/nbt_server.c
source/nbt_server/nbt_server.h
source/nbt_server/nodestatus.c
source/nbt_server/packet.c
source/nbt_server/query.c
source/nbt_server/winsserver.c
source/param/loadparm.c

index 86cf587235702e4d53dea6e8c66516b197cd30ea..bce72d805f6fdea5f5accec90cd8f87df5e1beb0 100644 (file)
 #include "system/network.h"
 #include "nbt_server/nbt_server.h"
 
-/*
-  send a name defense reply
-*/
-static void nbtd_name_defense_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)
-{
-       struct nbt_name_packet *packet;
-
-       packet = talloc_zero(nbtsock, struct nbt_name_packet);
-       if (packet == NULL) return;
-
-       packet->name_trn_id = request_packet->name_trn_id;
-       packet->ancount = 1;
-       packet->operation = 
-               NBT_FLAG_REPLY | 
-               NBT_OPCODE_REGISTER |
-               NBT_FLAG_AUTHORITIVE |
-               NBT_FLAG_RECURSION_DESIRED |
-               NBT_FLAG_RECURSION_AVAIL |
-               NBT_RCODE_ACT;
-       
-       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
-       if (packet->answers == NULL) goto failed;
-
-       packet->answers[0].name     = *name;
-       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);
-       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;
-
-       DEBUG(7,("Sending name defense reply for %s<%02x> at %s to %s:%d\n", 
-                name->name, name->type, src_address, address, src_port));
-       
-       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
-
-failed:
-       talloc_free(packet);
-}
-
 
 /*
   defend our registered names against registration or name refresh
@@ -89,12 +39,18 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
        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);
-       NBT_ASSERT_PACKET(packet, src_address, 
-                         packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
-       NBT_ASSERT_PACKET(packet, src_address, 
-                         packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->arcount == 1);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                          packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                          packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                         packet->additional[0].rr_type == NBT_QTYPE_NETBIOS);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                         packet->additional[0].rr_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                         packet->additional[0].rdata.netbios.length == 6);
 
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
@@ -103,8 +59,9 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
        if (iname != NULL && !(iname->nb_flags & NBT_NM_GROUP)) {
                DEBUG(2,("Defending name %s<%02x> on %s against %s\n",
                         name->name, name->type, iface->bcast_address, src_address));
-               nbtd_name_defense_reply(nbtsock, packet, src_address, src_port,
-                                       &iname->name, iname->ttl, iname->nb_flags, 
-                                       iface->ip_address);
+               nbtd_negative_name_registration_reply(nbtsock, packet, 
+                                                     src_address, src_port);
+       } else {
+               nbtd_winsserver_request(nbtsock, packet, src_address, src_port);
        }
 }
index 42572614f20cc3241191300af58b3bb8ad203b66..bc01ac6d99909afdfd30725da63e1ec88c866600 100644 (file)
@@ -34,23 +34,13 @@ 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 we
-          are running one */
-       if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
-           !(packet->operation & NBT_FLAG_BROADCAST) &&
-           lp_wins_support()) {
-               nbtd_query_wins(nbtsock, packet, src_address, src_port);
-               return;
-       }
-
        /* see if its from one of our own interfaces - if so, then ignore it */
        if (nbtd_self_packet(nbtsock, packet, src_address, src_port)) {
                DEBUG(10,("Ignoring self packet from %s:%d\n", src_address, src_port));
                return;
        }
 
-       /* the request is to us in our role as a B node */
-       switch ((enum nbt_opcode)(packet->operation & NBT_OPCODE)) {
+       switch (packet->operation & NBT_OPCODE) {
        case NBT_OPCODE_QUERY:
                nbtd_request_query(nbtsock, packet, src_address, src_port);
                break;
@@ -61,6 +51,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
                nbtd_request_defense(nbtsock, packet, src_address, src_port);
                break;
 
+       case NBT_OPCODE_RELEASE:
+       case NBT_OPCODE_MULTI_HOME_REG:
+               nbtd_winsserver_request(nbtsock, packet, src_address, src_port);
+               break;
+
        default:
                nbtd_bad_packet(packet, src_address, "Unexpected opcode");
                break;
index 73724720e5edc6e57c9bf7d921789fb4c727d92d..d939482d2f5cadc37a6eebcb136faade24785448 100644 (file)
@@ -52,6 +52,13 @@ static void nbtd_task_init(struct task_server *task)
                return;
        }
 
+       /* start the WINS server, if appropriate */
+       status = nbtd_winsserver_init(nbtsrv);
+       if (!NT_STATUS_IS_OK(status)) {
+               task_terminate(task, "nbtd failed to start WINS server");
+               return;
+       }
+
        /* start the process of registering our names on all interfaces */
        nbtd_register_names(nbtsrv);
 }
index 3def958cc4587c78b64dc81b39e06805ed64f7c1..309c01a639e0def914f48e4e8e23d14cd5ec457b 100644 (file)
@@ -66,12 +66,15 @@ struct nbtd_server {
        /* wins client interface - used for registering and refreshing
           our names with a WINS server */
        struct nbtd_interface *wins_interface;
+
+       /* wins server database handle, if configured */
+       struct ldb_wrap *wins_db;
 };
 
 
 
 /* check a condition on an incoming packet */
-#define NBT_ASSERT_PACKET(packet, src_address, test) do { \
+#define NBTD_ASSERT_PACKET(packet, src_address, test) do { \
        if (!(test)) { \
                nbtd_bad_packet(packet, src_address, #test); \
                return; \
index ba6c3ea77b64abe573638967da479a5629ac8ba9..5b79bf315f42ba7d7b886545ac0167842ed57d78 100644 (file)
@@ -104,9 +104,9 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock,
        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);
-       NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_STATUS);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
 
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
index a6df618a3f53b0caf09212959f1ad10520eb6b11..edca4ecb0077c501d1de5dc759b18319e4be1ebe 100644 (file)
@@ -76,3 +76,145 @@ BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock,
 
        return False;
 }
+
+
+/*
+  send a name query reply
+*/
+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 **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;
+
+       packet->name_trn_id = request_packet->name_trn_id;
+       packet->ancount = 1;
+       packet->operation = 
+               NBT_FLAG_REPLY | 
+               NBT_OPCODE_QUERY | 
+               NBT_FLAG_AUTHORITIVE |
+               NBT_FLAG_RECURSION_DESIRED |
+               NBT_FLAG_RECURSION_AVAIL;
+
+       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
+       if (packet->answers == NULL) goto failed;
+
+       packet->answers[0].name     = *name;
+       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 = 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;
+
+       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, addresses[0], src_address, src_port));
+       
+       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
+
+failed:
+       talloc_free(packet);
+}
+
+
+/*
+  send a negative name query reply
+*/
+void nbtd_negative_name_query_reply(struct nbt_name_socket *nbtsock, 
+                                   struct nbt_name_packet *request_packet, 
+                                   const char *src_address, int src_port)
+{
+       struct nbt_name_packet *packet;
+       struct nbt_name *name = &request_packet->questions[0].name;
+
+       packet = talloc_zero(nbtsock, struct nbt_name_packet);
+       if (packet == NULL) return;
+
+       packet->name_trn_id = request_packet->name_trn_id;
+       packet->ancount = 1;
+       packet->operation = 
+               NBT_FLAG_REPLY | 
+               NBT_OPCODE_QUERY | 
+               NBT_FLAG_AUTHORITIVE |
+               NBT_RCODE_NAM;
+
+       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
+       if (packet->answers == NULL) goto failed;
+
+       packet->answers[0].name      = *name;
+       packet->answers[0].rr_type   = NBT_QTYPE_NULL;
+       packet->answers[0].rr_class  = NBT_QCLASS_IP;
+       packet->answers[0].ttl       = 0;
+       ZERO_STRUCT(packet->answers[0].rdata);
+
+       DEBUG(7,("Sending negative name query reply for %s<%02x> to %s:%d\n", 
+                name->name, name->type, src_address, src_port));
+       
+       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
+
+failed:
+       talloc_free(packet);
+}
+
+/*
+  send a name defense reply
+*/
+void nbtd_negative_name_registration_reply(struct nbt_name_socket *nbtsock, 
+                                          struct nbt_name_packet *request_packet, 
+                                          const char *src_address, int src_port)
+{
+       struct nbt_name_packet *packet;
+       struct nbt_name *name = &request_packet->questions[0].name;
+
+       packet = talloc_zero(nbtsock, struct nbt_name_packet);
+       if (packet == NULL) return;
+
+       packet->name_trn_id = request_packet->name_trn_id;
+       packet->ancount = 1;
+       packet->operation = 
+               NBT_FLAG_REPLY | 
+               NBT_OPCODE_REGISTER |
+               NBT_FLAG_AUTHORITIVE |
+               NBT_FLAG_RECURSION_DESIRED |
+               NBT_FLAG_RECURSION_AVAIL |
+               NBT_RCODE_ACT;
+       
+       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
+       if (packet->answers == NULL) goto failed;
+
+       packet->answers[0].name     = *name;
+       packet->answers[0].rr_type  = NBT_QTYPE_NETBIOS;
+       packet->answers[0].rr_class = NBT_QCLASS_IP;
+       packet->answers[0].ttl      = 0;
+       packet->answers[0].rdata    = request_packet->additional[0].rdata;
+
+       DEBUG(7,("Sending negative name registration reply for %s<%02x> to %s:%d\n", 
+                name->name, name->type, src_address, src_port));
+       
+       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
+
+failed:
+       talloc_free(packet);
+}
+
index 2bcc2b1892afc68f1fdf2cc581a2792889a4032f..cc14a762daf14e1ef2cfde6f9e93ddf01fb5ecb1 100644 (file)
 #include "system/network.h"
 #include "nbt_server/nbt_server.h"
 
-/*
-  send a name query reply
-*/
-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 **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;
-
-       packet->name_trn_id = request_packet->name_trn_id;
-       packet->ancount = 1;
-       packet->operation = 
-               NBT_FLAG_REPLY | 
-               NBT_OPCODE_QUERY | 
-               NBT_FLAG_AUTHORITIVE |
-               NBT_FLAG_RECURSION_DESIRED |
-               NBT_FLAG_RECURSION_AVAIL;
-
-       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
-       if (packet->answers == NULL) goto failed;
-
-       packet->answers[0].name     = *name;
-       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 = 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;
-
-       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, addresses[0], src_address, src_port));
-       
-       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
-
-failed:
-       talloc_free(packet);
-}
-
 
 /*
   answer a name query
@@ -104,17 +45,33 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
                return;
        }
 
-       NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
-       NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
-       NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                          packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
+       NBTD_ASSERT_PACKET(packet, src_address, 
+                          packet->questions[0].question_class == NBT_QCLASS_IP);
 
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
 
        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));
+               /* don't send negative replies to broadcast queries */
+               if (packet->operation & NBT_FLAG_BROADCAST) {
+                       return;
+               }
+
+               /* if the name does not exist, then redirect to WINS
+                  server if recursion has been asked for */
+               if (packet->operation & NBT_FLAG_RECURSION_DESIRED) {
+                       nbtd_winsserver_request(nbtsock, packet, src_address, src_port);
+                       return;
+               }
+
+               /* otherwise send a negative reply */
+               nbtd_negative_name_query_reply(nbtsock, packet, 
+                                              src_address, src_port);
                return;
        }
 
index 5940303f66b4b5357703648b2ccd47e17f2517dc..c7720b6ec7ce7085768668a6eb7df0620048f296 100644 (file)
 #include "includes.h"
 #include "nbt_server/nbt_server.h"
 
+
+static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock, 
+                                 struct nbt_name_packet *packet, 
+                                 const char *src_address, int src_port)
+{
+       nbtd_negative_name_query_reply(nbtsock, packet, src_address, src_port);
+}
+
+static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, 
+                                   struct nbt_name_packet *packet, 
+                                   const char *src_address, int src_port)
+{
+       nbtd_negative_name_registration_reply(nbtsock, packet, src_address, src_port);
+}
+
+
+static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, 
+                                   struct nbt_name_packet *packet, 
+                                   const char *src_address, int src_port)
+{
+}
+
+
 /*
   answer a name query
 */
-void nbtd_query_wins(struct nbt_name_socket *nbtsock, 
-                    struct nbt_name_packet *packet, 
-                    const char *src_address, int src_port)
+void nbtd_winsserver_request(struct nbt_name_socket *nbtsock, 
+                            struct nbt_name_packet *packet, 
+                            const char *src_address, int src_port)
+{
+       if (packet->operation & NBT_FLAG_BROADCAST) {
+               return;
+       }
+
+       switch (packet->operation & NBT_OPCODE) {
+       case NBT_OPCODE_QUERY:
+               nbtd_winsserver_query(nbtsock, packet, src_address, src_port);
+               break;
+
+       case NBT_OPCODE_REGISTER:
+       case NBT_OPCODE_REFRESH:
+       case NBT_OPCODE_REFRESH2:
+       case NBT_OPCODE_MULTI_HOME_REG:
+               nbtd_winsserver_register(nbtsock, packet, src_address, src_port);
+               break;
+
+       case NBT_OPCODE_RELEASE:
+               nbtd_winsserver_release(nbtsock, packet, src_address, src_port);
+               break;
+       }
+
+}
+
+/*
+  startup the WINS server, if configured
+*/
+NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv)
 {
-       DEBUG(0,("WINS query from %s\n", src_address));
-       if (DEBUGLVL(10)) {
-               NDR_PRINT_DEBUG(nbt_name_packet, packet);               
+       if (!lp_wins_support()) {
+               nbtsrv->wins_db = NULL;
+               return NT_STATUS_OK;
        }
+
+       nbtsrv->wins_db = ldb_wrap_connect(nbtsrv, lp_wins_url(), 0, NULL);
+       if (nbtsrv->wins_db == NULL) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+
+       return NT_STATUS_OK;
 }
index bd4bb8af043e940ef26afd811c69dfefb8fcfe4f..c6a58386ece40af9387dfff776358df7c8215b8b 100644 (file)
@@ -170,6 +170,7 @@ typedef struct
        char *szSMBPasswdFile;
        char *szSAM_URL;
        char *szSPOOLSS_URL;
+       char *szWINS_URL;
        char *szPrivateDir;
        char **szPreloadModules;
        char **szPasswordServers;
@@ -568,6 +569,7 @@ static struct parm_struct parm_table[] = {
        {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
@@ -938,6 +940,7 @@ static void init_globals(void)
        do_parameter("private dir", dyn_PRIVATE_DIR);
        do_parameter_var("sam database", "tdb://%s/sam.ldb", dyn_PRIVATE_DIR);
        do_parameter_var("spoolss database", "tdb://%s/spoolss.ldb", dyn_PRIVATE_DIR);
+       do_parameter_var("wins database", "tdb://%s/wins.ldb", dyn_PRIVATE_DIR);
        do_parameter_var("registry:HKEY_LOCAL_MACHINE", "ldb:/%s/hklm.ldb", dyn_PRIVATE_DIR);
        do_parameter("guest account", GUEST_ACCOUNT);
 
@@ -1154,6 +1157,7 @@ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
+FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)