r11026: r10318@SERNOX: metze | 2005-09-19 16:38:15 +0200
authorStefan Metzmacher <metze@samba.org>
Fri, 14 Oct 2005 12:49:55 +0000 (12:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:42:16 +0000 (13:42 -0500)
 move to struct winsdb_addr, (I'll add expiry_time and the wins_owner later

 tridge: can you please review the new winsdb_addr_* functions carefull, look for off-by-one bugs, etc.

 metze

source/nbt_server/wins/winsdb.c
source/nbt_server/wins/winsdb.h
source/nbt_server/wins/winsserver.c
source/nbt_server/wins/winswack.c

index 2b17104b9dc9a4d305aa5a96923ef728aea41af3..a1af256eb5b07eb74f7d9b4b1e0f4ad5e6fc85d1 100644 (file)
@@ -119,24 +119,124 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name)
        return dn;
 }
 
-static const char *winsdb_addr_decode(TALLOC_CTX *mem_ctx, struct ldb_val *val)
+static struct winsdb_addr *winsdb_addr_decode(TALLOC_CTX *mem_ctx, struct ldb_val *val)
 {
-       const char *addr;
-       addr = talloc_steal(mem_ctx, val->data);
+       struct winsdb_addr *addr;
+
+       addr = talloc(mem_ctx, struct winsdb_addr);
+       if (!addr) return NULL;
+
+       addr->address = talloc_steal(addr, val->data);
+
        return addr;
 }
 
 static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg, 
-                                  const char *attr_name, const char *addr)
+                                  const char *attr_name, struct winsdb_addr *addr)
 {
        struct ldb_val val;
 
-       val.data = discard_const_p(uint8_t, addr);
-       val.length = strlen(addr);
+       val.data = discard_const_p(uint8_t, addr->address);
+       val.length = strlen(addr->address);
 
        return ldb_msg_add_value(ldb, msg, attr_name, &val);
 }
 
+struct winsdb_addr **winsdb_addr_list_make(TALLOC_CTX *mem_ctx)
+{
+       struct winsdb_addr **addresses;
+
+       addresses = talloc_array(mem_ctx, struct winsdb_addr *, 1);
+       if (!addresses) return NULL;
+
+       addresses[0] = NULL;
+
+       return addresses;
+}
+
+struct winsdb_addr **winsdb_addr_list_add(struct winsdb_addr **addresses, const char *address)
+{
+       size_t len = winsdb_addr_list_length(addresses);
+
+       addresses = talloc_realloc(addresses, addresses, struct winsdb_addr *, len + 2);
+       if (!addresses) return NULL;
+
+       addresses[len] = talloc(addresses, struct winsdb_addr);
+       if (!addresses[len]) {
+               talloc_free(addresses);
+               return NULL;
+       }
+
+       addresses[len]->address = talloc_strdup(addresses[len], address);
+       if (!addresses[len]->address) {
+               talloc_free(addresses);
+               return NULL;    
+       }
+
+       addresses[len+1] = NULL;
+
+       return addresses;
+}
+
+void winsdb_addr_list_remove(struct winsdb_addr **addresses, const char *address)
+{
+       size_t i;
+
+       for (i=0; addresses[i]; i++) {
+               if (strcmp(addresses[i]->address, address) == 0) {
+                       break;
+               }
+       }
+       if (!addresses[i]) return;
+
+       for (; addresses[i]; i++) {
+               addresses[i] = addresses[i+1];
+       }
+
+       return;
+}
+
+struct winsdb_addr *winsdb_addr_list_check(struct winsdb_addr **addresses, const char *address)
+{
+       size_t i;
+
+       for (i=0; addresses[i]; i++) {
+               if (strcmp(addresses[i]->address, address) == 0) {
+                       return addresses[i];
+               }
+       }
+
+       return NULL;
+}
+
+size_t winsdb_addr_list_length(struct winsdb_addr **addresses)
+{
+       size_t i;
+       for (i=0; addresses[i]; i++);
+       return i;
+}
+
+const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **addresses)
+{
+       size_t len = winsdb_addr_list_length(addresses);
+       const char **str_list;
+       size_t i;
+
+       str_list = talloc_array(mem_ctx, const char *, len + 1);
+       if (!str_list) return NULL;
+
+       for (i=0; i < len; i++) {
+               str_list[i] = talloc_strdup(str_list, addresses[i]->address);
+               if (!str_list[i]) {
+                       talloc_free(str_list);
+                       return NULL;
+               }
+       }
+
+       str_list[len] = NULL;
+       return str_list;
+}
+
 /*
   load a WINS entry from the database
 */
@@ -173,7 +273,7 @@ struct winsdb_record *winsdb_load(struct wins_server *winssrv,
        el = ldb_msg_find_element(res[0], "address");
        if (el == NULL) goto failed;
 
-       rec->addresses     = talloc_array(rec, const char *, el->num_values+1);
+       rec->addresses     = talloc_array(rec, struct winsdb_addr *, el->num_values+1);
        if (rec->addresses == NULL) goto failed;
 
        for (i=0;i<el->num_values;i++) {
index c6e3ac4c5ce9ef6d020b995fa81b516b672bf54f..44d4003acca4847a88e9f1744465afa965b831ea 100644 (file)
@@ -25,6 +25,10 @@ enum wins_record_state {
        WINS_REC_ACTIVE   =1
 };
 
+struct winsdb_addr {
+       const char *address;
+};
+
 /*
   each record in the database contains the following information
 */
@@ -34,7 +38,7 @@ struct winsdb_record {
        enum wins_record_state state;
        time_t expire_time;
        const char *registered_by;
-       const char **addresses;
+       struct winsdb_addr **addresses;
        uint64_t version;
 };
 
index a2f7fccad52997b6366f160a705f5cebce5ea6b0..eba85ecb842b7400f80196d47ac27b6dc2b30284 100644 (file)
@@ -57,15 +57,17 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock,
        rec.state         = WINS_REC_ACTIVE;
        rec.expire_time   = time(NULL) + ttl;
        rec.registered_by = src->addr;
+       rec.addresses     = winsdb_addr_list_make(packet);
+       if (rec.addresses == NULL) return NBT_RCODE_SVR;
        if (IS_GROUP_NAME(name, nb_flags)) {
-               rec.addresses     = str_list_make(packet, "255.255.255.255", NULL);
+               rec.addresses     = winsdb_addr_list_add(rec.addresses, "255.255.255.255");
        } else {
-               rec.addresses     = str_list_make(packet, address, NULL);
+               rec.addresses     = winsdb_addr_list_add(rec.addresses, address);
        }
        if (rec.addresses == NULL) return NBT_RCODE_SVR;
 
        DEBUG(4,("WINS: accepted registration of %s with address %s\n",
-                nbt_name_string(packet, name), rec.addresses[0]));
+                nbt_name_string(packet, name), rec.addresses[0]->address));
        
        return winsdb_add(winssrv, &rec);
 }
@@ -153,7 +155,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
 
        /* if the registration is for an address that is currently active, then 
           just update the expiry time */
-       if (str_list_check(rec->addresses, address)) {
+       if (winsdb_addr_list_check(rec->addresses, address)) {
                wins_update_ttl(nbtsock, packet, rec, src);
                goto done;
        }
@@ -181,6 +183,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
        struct winsdb_record *rec;
+       const char **addresses;
 
        rec = winsdb_load(winssrv, name, packet);
        if (rec == NULL || rec->state != WINS_REC_ACTIVE) {
@@ -188,8 +191,14 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
                return;
        }
 
+       addresses = winsdb_addr_string_list(packet, rec->addresses);
+       if (addresses == NULL) {
+               nbtd_negative_name_query_reply(nbtsock, packet, src);
+               return; 
+       }
+
        nbtd_name_query_reply(nbtsock, packet, src, name, 
-                             0, rec->nb_flags, rec->addresses);
+                             0, rec->nb_flags, addresses);
 }
 
 /*
@@ -214,11 +223,11 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
 
        /* we only allow releases from an owner - other releases are
           silently ignored */
-       if (str_list_check(rec->addresses, src->addr)) {
+       if (winsdb_addr_list_check(rec->addresses, src->addr)) {
                const char *address = packet->additional[0].rdata.netbios.addresses[0].ipaddr;
 
                DEBUG(4,("WINS: released name %s at %s\n", nbt_name_string(rec, rec->name), address));
-               str_list_remove(rec->addresses, address);
+               winsdb_addr_list_remove(rec->addresses, address);
                if (rec->addresses[0] == NULL) {
                        rec->state = WINS_REC_RELEASED;
                }
index c9f102fdc8663cf990d26633d066ecd374b1244f..461acad981ad7ea93d2974bd903c08cdbde8d0f0 100644 (file)
@@ -69,7 +69,7 @@ static void wins_wack_allow(struct wack_state *state)
        nbtd_name_registration_reply(state->nbtsock, state->request_packet, 
                                     &state->src, NBT_RCODE_OK);
 
-       rec->addresses = str_list_add(rec->addresses, state->reg_address);
+       rec->addresses = winsdb_addr_list_add(rec->addresses, state->reg_address);
        if (rec->addresses == NULL) goto failed;
        
        ttl = wins_server_ttl(state->winssrv, state->request_packet->additional[0].ttl);
@@ -133,11 +133,9 @@ static void wins_wack_handler(struct nbt_name_request *req)
 
        /* 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;rec->addresses[i];) {
-               if (!str_list_check(state->query.out.reply_addrs, rec->addresses[i])) {
-                       str_list_remove(rec->addresses, rec->addresses[i]);
-               } else {
-                       i++;
+       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]);
                }
        }
 
@@ -174,7 +172,8 @@ void wins_register_wack(struct nbt_name_socket *nbtsock,
        state->nbtsock         = nbtsock;
        state->request_packet  = talloc_steal(state, packet);
        state->rec             = talloc_steal(state, rec);
-       state->owner_addresses = rec->addresses;
+       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);
@@ -196,7 +195,7 @@ void wins_register_wack(struct nbt_name_socket *nbtsock,
 
        /* send a WACK to the client, specifying the maximum time it could
           take to check with the owner, plus some slack */
-       ttl = 5 + 4 * str_list_length(rec->addresses);
+       ttl = 5 + 4 * winsdb_addr_list_length(rec->addresses);
        nbtd_wack_reply(nbtsock, packet, src, ttl);
 
        req = nbt_name_query_send(nbtsock, &state->query);