diff options
Diffstat (limited to 'source4/nbt_server/wins/winsserver.c')
-rw-r--r-- | source4/nbt_server/wins/winsserver.c | 90 |
1 files changed, 70 insertions, 20 deletions
diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c index 19b9c6c47f..12201b1620 100644 --- a/source4/nbt_server/wins/winsserver.c +++ b/source4/nbt_server/wins/winsserver.c @@ -236,11 +236,15 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock, uint16_t nb_flags = 0; /* TODO: ... */ status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); - if (!NT_STATUS_IS_OK(status) || rec->state != WREPL_STATE_ACTIVE) { - nbtd_negative_name_query_reply(nbtsock, packet, src); - return; + if (!NT_STATUS_IS_OK(status)) { + goto notfound; } + /* + * for group's we always reply with + * 255.255.255.255 as address, even if + * the record is released or tombstoned + */ if (rec->type == WREPL_TYPE_GROUP) { addresses = talloc_array(packet, const char *, 2); if (addresses == NULL) { @@ -249,16 +253,24 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock, } addresses[0] = WINSDB_GROUP_ADDRESS; addresses[1] = NULL; - } else { - addresses = winsdb_addr_string_list(packet, rec->addresses); - if (addresses == NULL) { - nbtd_negative_name_query_reply(nbtsock, packet, src); - return; - } + goto found; + } + + if (rec->state != WREPL_STATE_ACTIVE) { + goto notfound; } + addresses = winsdb_addr_string_list(packet, rec->addresses); + if (!addresses) { + goto notfound; + } +found: nbtd_name_query_reply(nbtsock, packet, src, name, 0, nb_flags, addresses); + return; + +notfound: + nbtd_negative_name_query_reply(nbtsock, packet, src); } /* @@ -274,27 +286,65 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; struct winsdb_record *rec; + uint32_t modify_flags = 0; + uint8_t ret; status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); - if (!NT_STATUS_IS_OK(status) || - rec->state != WREPL_STATE_ACTIVE || - rec->type == WREPL_TYPE_GROUP) { + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (rec->state != WREPL_STATE_ACTIVE) { + goto done; + } + + /* + * TODO: do we need to check if + * src->addr matches packet->additional[0].rdata.netbios.addresses[0].ipaddr + * here? + */ + + /* + * we only allow releases from an owner - other releases are + * silently ignored + */ + if (!winsdb_addr_list_check(rec->addresses, src->addr)) { goto done; } - /* we only allow releases from an owner - other releases are - silently ignored */ - 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 from %s\n", nbt_name_string(rec, rec->name), src->addr)); + + switch (rec->type) { + case WREPL_TYPE_UNIQUE: + rec->state = WREPL_STATE_RELEASED; + break; - DEBUG(4,("WINS: released name %s at %s\n", nbt_name_string(rec, rec->name), address)); - winsdb_addr_list_remove(rec->addresses, address); - if (rec->addresses[0] == NULL) { + case WREPL_TYPE_GROUP: + rec->state = WREPL_STATE_RELEASED; + break; + + case WREPL_TYPE_SGROUP: + winsdb_addr_list_remove(rec->addresses, src->addr); + /* TODO: do we need to take the ownership here? */ + if (winsdb_addr_list_length(rec->addresses) == 0) { rec->state = WREPL_STATE_RELEASED; } - winsdb_modify(winssrv->wins_db, rec, 0); + break; + + case WREPL_TYPE_MHOMED: + winsdb_addr_list_remove(rec->addresses, src->addr); + /* TODO: do we need to take the ownership here? */ + if (winsdb_addr_list_length(rec->addresses) == 0) { + rec->state = WREPL_STATE_RELEASED; + } + break; } + ret = winsdb_modify(winssrv->wins_db, rec, modify_flags); + if (ret != NBT_RCODE_OK) { + DEBUG(1,("WINS: FAILED: released name %s at %s: error:%u\n", + nbt_name_string(rec, rec->name), src->addr, ret)); + } done: /* we match w2k3 by always giving a positive reply to name releases. */ nbtd_name_release_reply(nbtsock, packet, src, NBT_RCODE_OK); |