s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[bbaumbach/samba-autobuild/.git] / source4 / nbt_server / wins / winsserver.c
index f116c458981723e391d6d4d78068e75d1d06afa9..516258e8925e810f015428efa0b55957f8d80e42 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "lib/util/dlinklist.h"
 #include "nbt_server/nbt_server.h"
 #include "nbt_server/wins/winsdb.h"
 #include "nbt_server/wins/winsserver.h"
@@ -34,6 +35,7 @@
 #include "lib/ldb/include/ldb.h"
 #include "param/param.h"
 #include "libcli/resolve/resolve.h"
+#include "lib/util/util_net.h"
 
 /*
   work out the ttl we will use given a client requested ttl
@@ -68,7 +70,7 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock,
                                 const struct socket_address *src,
                                 enum wrepl_name_type type)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
@@ -119,7 +121,7 @@ static uint8_t wins_update_ttl(struct nbt_name_socket *nbtsock,
                               struct winsdb_addr *winsdb_addr,
                               const struct socket_address *src)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        uint32_t ttl = wins_server_ttl(winssrv, packet->additional[0].ttl);
@@ -158,7 +160,7 @@ static uint8_t wins_sgroup_merge(struct nbt_name_socket *nbtsock,
                                 const char *address,
                                 const struct socket_address *src)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        uint32_t ttl = wins_server_ttl(winssrv, packet->additional[0].ttl);
@@ -180,9 +182,11 @@ static uint8_t wins_sgroup_merge(struct nbt_name_socket *nbtsock,
        return winsdb_modify(winssrv->wins_db, rec, WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP);
 }
 
-struct wack_state {
+struct nbtd_wins_wack_state {
+       struct nbtd_wins_wack_state *prev, *next;
        struct wins_server *winssrv;
        struct nbt_name_socket *nbtsock;
+       struct nbtd_interface *iface;
        struct nbt_name_packet *request_packet;
        struct winsdb_record *rec;
        struct socket_address *src;
@@ -192,10 +196,42 @@ struct wack_state {
        NTSTATUS status;
 };
 
+static int nbtd_wins_wack_state_destructor(struct nbtd_wins_wack_state *s)
+{
+       DLIST_REMOVE(s->iface->wack_queue, s);
+       return 0;
+}
+
+static bool wins_check_wack_queue(struct nbtd_interface *iface,
+                                 struct nbt_name_packet *packet,
+                                 struct socket_address *src)
+{
+       struct nbtd_wins_wack_state *s;
+
+       for (s= iface->wack_queue; s; s = s->next) {
+               if (packet->name_trn_id != s->request_packet->name_trn_id) {
+                       continue;
+               }
+               if (packet->operation != s->request_packet->operation) {
+                       continue;
+               }
+               if (src->port != s->src->port) {
+                       continue;
+               }
+               if (strcmp(src->addr, s->src->addr) != 0) {
+                       continue;
+               }
+
+               return true;
+       }
+
+       return false;
+}
+
 /*
   deny a registration request
 */
-static void wins_wack_deny(struct wack_state *s)
+static void wins_wack_deny(struct nbtd_wins_wack_state *s)
 {
        nbtd_name_registration_reply(s->nbtsock, s->request_packet, 
                                     s->src, NBT_RCODE_ACT);
@@ -207,7 +243,7 @@ static void wins_wack_deny(struct wack_state *s)
 /*
   allow a registration request
 */
-static void wins_wack_allow(struct wack_state *s)
+static void wins_wack_allow(struct nbtd_wins_wack_state *s)
 {
        NTSTATUS status;
        uint32_t ttl = wins_server_ttl(s->winssrv, s->request_packet->additional[0].ttl);
@@ -246,8 +282,8 @@ static void wins_wack_allow(struct wack_state *s)
        rec->registered_by = s->src->addr;
 
        /*
-        * now remove all addresses that're the client doesn't hold anymore
-        * and update the time stamp and owner for the ownes that are still there
+        * now remove all addresses that the client doesn't hold anymore
+        * and update the time stamp and owner for the ones that are still there
         */
        for (i=0; rec->addresses[i]; i++) {
                bool found = false;
@@ -301,8 +337,8 @@ failed:
 */
 static void wack_wins_challenge_handler(struct composite_context *c_req)
 {
-       struct wack_state *s = talloc_get_type(c_req->async.private_data,
-                                              struct wack_state);
+       struct nbtd_wins_wack_state *s = talloc_get_type(c_req->async.private_data,
+                                        struct nbtd_wins_wack_state);
        bool found;
        uint32_t i;
 
@@ -357,19 +393,20 @@ static void wins_register_wack(struct nbt_name_socket *nbtsock,
                               struct socket_address *src,
                               enum wrepl_name_type new_type)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
-       struct wack_state *s;
+       struct nbtd_wins_wack_state *s;
        struct composite_context *c_req;
        uint32_t ttl;
 
-       s = talloc_zero(nbtsock, struct wack_state);
+       s = talloc_zero(nbtsock, struct nbtd_wins_wack_state);
        if (s == NULL) goto failed;
 
        /* package up the state variables for this wack request */
        s->winssrv              = winssrv;
        s->nbtsock              = nbtsock;
+       s->iface                = iface;
        s->request_packet       = talloc_steal(s, packet);
        s->rec                  = talloc_steal(s, rec);
        s->reg_address          = packet->additional[0].rdata.netbios.addresses[0].ipaddr;
@@ -378,13 +415,17 @@ static void wins_register_wack(struct nbt_name_socket *nbtsock,
        if (talloc_reference(s, src) == NULL) goto failed;
 
        s->io.in.nbtd_server    = iface->nbtsrv;
-       s->io.in.nbt_port       = lp_nbt_port(iface->nbtsrv->task->lp_ctx);
+       s->io.in.nbt_port       = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
        s->io.in.event_ctx      = iface->nbtsrv->task->event_ctx;
        s->io.in.name           = rec->name;
        s->io.in.num_addresses  = winsdb_addr_list_length(rec->addresses);
        s->io.in.addresses      = winsdb_addr_string_list(s, rec->addresses);
        if (s->io.in.addresses == NULL) goto failed;
 
+       DLIST_ADD_END(iface->wack_queue, s, struct nbtd_wins_wack_state *);
+
+       talloc_set_destructor(s, nbtd_wins_wack_state_destructor);
+
        /*
         * send a WACK to the client, specifying the maximum time it could
          * take to check with the owner, plus some slack
@@ -415,7 +456,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
                                     struct socket_address *src)
 {
        NTSTATUS status;
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
@@ -426,6 +467,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
        bool mhomed = ((packet->operation & NBT_OPCODE) == NBT_OPCODE_MULTI_HOME_REG);
        enum wrepl_name_type new_type = wrepl_type(nb_flags, name, mhomed);
        struct winsdb_addr *winsdb_addr = NULL;
+       bool duplicate_packet;
 
        /*
         * as a special case, the local master browser name is always accepted
@@ -455,6 +497,19 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
                goto done;
        }
 
+       if (name->scope && strlen(name->scope) > 237) {
+               rcode = NBT_RCODE_SVR;
+               goto done;
+       }
+
+       duplicate_packet = wins_check_wack_queue(iface, packet, src);
+       if (duplicate_packet) {
+               /* just ignore the packet */
+               DEBUG(5,("Ignoring duplicate packet while WACK is pending from %s:%d\n",
+                        src->addr, src->port));
+               return;
+       }
+
        status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
        if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
                rcode = wins_register_new(nbtsock, packet, src, new_type);
@@ -615,10 +670,9 @@ static void nbtd_wins_randomize1Clist(struct loadparm_context *lp_ctx,
        if (num_addrs <= 1) return; /* nothing to do */
 
        /* first sort the addresses depending on the matching to the client */
-       ldb_qsort(addresses, num_addrs , sizeof(addresses[0]),
-                 src, (ldb_qsort_cmp_fn_t)nbtd_wins_randomize1Clist_sort);
+       LDB_TYPESAFE_QSORT(addresses, num_addrs, src, nbtd_wins_randomize1Clist_sort);
 
-       mask = lp_parm_string(lp_ctx, NULL, "nbtd", "wins_randomize1Clist_mask");
+       mask = lpcfg_parm_string(lp_ctx, NULL, "nbtd", "wins_randomize1Clist_mask");
        if (!mask) {
                mask = "255.255.255.0";
        }
@@ -671,7 +725,7 @@ static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,
                                  struct socket_address *src)
 {
        NTSTATUS status;
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
@@ -696,7 +750,7 @@ static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,
         * Value: 0 = deactivated, 1 = activated
         */
        if (name->type == NBT_NAME_LOGON && 
-           lp_parm_bool(lp_ctx, NULL, "nbtd", "wins_prepend1Bto1Cqueries", true)) {
+           lpcfg_parm_bool(lp_ctx, NULL, "nbtd", "wins_prepend1Bto1Cqueries", true)) {
                struct nbt_name name_1b;
 
                name_1b = *name;
@@ -710,7 +764,7 @@ static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,
 
        status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
        if (!NT_STATUS_IS_OK(status)) {
-               if (!lp_wins_dns_proxy(lp_ctx)) {
+               if (!lpcfg_wins_dns_proxy(lp_ctx)) {
                        goto notfound;
                }
 
@@ -792,7 +846,7 @@ static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,
         * Value: 0 = deactivated, 1 = activated
         */
        if (name->type == NBT_NAME_LOGON && 
-           lp_parm_bool(lp_ctx, NULL, "nbtd", "wins_randomize1Clist", false)) {
+           lpcfg_parm_bool(lp_ctx, NULL, "nbtd", "wins_randomize1Clist", false)) {
                nbtd_wins_randomize1Clist(lp_ctx, addresses, src);
        }
 
@@ -813,7 +867,7 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
                                    struct socket_address *src)
 {
        NTSTATUS status;
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
@@ -825,6 +879,10 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
                goto done;
        }
 
+       if (name->scope && strlen(name->scope) > 237) {
+               goto done;
+       }
+
        status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
@@ -890,7 +948,25 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
                break;
        }
 
-       if (rec->state == WREPL_STATE_RELEASED) {
+       if (rec->state == WREPL_STATE_ACTIVE) {
+               /*
+                * If the record is still active, we need to update the
+                * expire_time.
+                *
+                * if we're not the owner, we need to take the ownership.
+                */
+               rec->expire_time= time(NULL) + winssrv->config.max_renew_interval;
+               if (strcmp(rec->wins_owner, winssrv->wins_db->local_owner) != 0) {
+                       modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
+               }
+               if (lpcfg_parm_bool(iface->nbtsrv->task->lp_ctx, NULL, "wreplsrv", "propagate name releases", false)) {
+                       /*
+                        * We have an option to propagate every name release,
+                        * this is off by default to match windows servers
+                        */
+                       modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
+               }
+       } else if (rec->state == WREPL_STATE_RELEASED) {
                /*
                 * if we're not the owner, we need to take the owner ship
                 * and make the record tombstone, but expire after
@@ -928,7 +1004,7 @@ void nbtd_winsserver_request(struct nbt_name_socket *nbtsock,
                             struct nbt_name_packet *packet, 
                             struct socket_address *src)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        if ((packet->operation & NBT_FLAG_BROADCAST) || winssrv == NULL) {
@@ -962,7 +1038,7 @@ NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv)
        uint32_t tmp;
        const char *owner;
 
-       if (!lp_wins_support(nbtsrv->task->lp_ctx)) {
+       if (!lpcfg_wins_support(nbtsrv->task->lp_ctx)) {
                nbtsrv->winssrv = NULL;
                return NT_STATUS_OK;
        }
@@ -970,22 +1046,23 @@ NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv)
        nbtsrv->winssrv = talloc_zero(nbtsrv, struct wins_server);
        NT_STATUS_HAVE_NO_MEMORY(nbtsrv->winssrv);
 
-       nbtsrv->winssrv->config.max_renew_interval = lp_max_wins_ttl(nbtsrv->task->lp_ctx);
-       nbtsrv->winssrv->config.min_renew_interval = lp_min_wins_ttl(nbtsrv->task->lp_ctx);
-       tmp = lp_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv", "tombstone_interval", 6*24*60*60);
+       nbtsrv->winssrv->config.max_renew_interval = lpcfg_max_wins_ttl(nbtsrv->task->lp_ctx);
+       nbtsrv->winssrv->config.min_renew_interval = lpcfg_min_wins_ttl(nbtsrv->task->lp_ctx);
+       tmp = lpcfg_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv", "tombstone_interval", 6*24*60*60);
        nbtsrv->winssrv->config.tombstone_interval = tmp;
-       tmp = lp_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv"," tombstone_timeout", 1*24*60*60);
+       tmp = lpcfg_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv"," tombstone_timeout", 1*24*60*60);
        nbtsrv->winssrv->config.tombstone_timeout = tmp;
 
-       owner = lp_parm_string(nbtsrv->task->lp_ctx, NULL, "winsdb", "local_owner");
+       owner = lpcfg_parm_string(nbtsrv->task->lp_ctx, NULL, "winsdb", "local_owner");
 
        if (owner == NULL) {
                struct interface *ifaces;
-               load_interfaces(nbtsrv->task, lp_interfaces(nbtsrv->task->lp_ctx), &ifaces);
+               load_interfaces(nbtsrv->task, lpcfg_interfaces(nbtsrv->task->lp_ctx), &ifaces);
                owner = iface_n_ip(ifaces, 0);
        }
 
-       nbtsrv->winssrv->wins_db     = winsdb_connect(nbtsrv->winssrv, nbtsrv->task->lp_ctx,
+       nbtsrv->winssrv->wins_db     = winsdb_connect(nbtsrv->winssrv, nbtsrv->task->event_ctx, 
+                                                     nbtsrv->task->lp_ctx,
                                                      owner, WINSDB_HANDLE_CALLER_NBTD);
        if (!nbtsrv->winssrv->wins_db) {
                return NT_STATUS_INTERNAL_DB_ERROR;