*/
#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"
#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
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;
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);
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);
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;
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);
/*
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);
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;
*/
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;
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;
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
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;
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
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);
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";
}
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;
* 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;
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;
}
* 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);
}
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;
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;
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
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) {
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;
}
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;