diff options
Diffstat (limited to 'source4/nbt_server/wins')
-rw-r--r-- | source4/nbt_server/wins/winsdb.c | 114 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsdb.h | 6 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsserver.c | 23 | ||||
-rw-r--r-- | source4/nbt_server/wins/winswack.c | 15 |
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); |