summaryrefslogtreecommitdiff
path: root/source4/nbt_server/wins
diff options
context:
space:
mode:
Diffstat (limited to 'source4/nbt_server/wins')
-rw-r--r--source4/nbt_server/wins/winsdb.c114
-rw-r--r--source4/nbt_server/wins/winsdb.h6
-rw-r--r--source4/nbt_server/wins/winsserver.c23
-rw-r--r--source4/nbt_server/wins/winswack.c15
4 files changed, 135 insertions, 23 deletions
diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c
index 2b17104b9d..a1af256eb5 100644
--- a/source4/nbt_server/wins/winsdb.c
+++ b/source4/nbt_server/wins/winsdb.c
@@ -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++) {
diff --git a/source4/nbt_server/wins/winsdb.h b/source4/nbt_server/wins/winsdb.h
index c6e3ac4c5c..44d4003acc 100644
--- a/source4/nbt_server/wins/winsdb.h
+++ b/source4/nbt_server/wins/winsdb.h
@@ -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;
};
diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c
index a2f7fccad5..eba85ecb84 100644
--- a/source4/nbt_server/wins/winsserver.c
+++ b/source4/nbt_server/wins/winsserver.c
@@ -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;
}
diff --git a/source4/nbt_server/wins/winswack.c b/source4/nbt_server/wins/winswack.c
index c9f102fdc8..461acad981 100644
--- a/source4/nbt_server/wins/winswack.c
+++ b/source4/nbt_server/wins/winswack.c
@@ -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);