mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r5251: - renamed the nbtd server side structures to have a nbtd_ prefix, to
be consistent with the function names - added WINS client support to the NBT server. It will do initial WINS registration, and WINS refresh, automatically failing over to secondary WINS servers and handling multi-homed servers where we need to register multiple IPs. - added support for multi-homed name query replies, which are essential for multi-homed registration as the WINS server will query us to ensure we have the names when doing the secondary IPs in multi-homed registration
This commit is contained in:
parent
76be35cb99
commit
a1553fa805
@ -11,6 +11,7 @@ ADD_OBJ_FILES = \
|
||||
nbt_server/query.o \
|
||||
nbt_server/nodestatus.o \
|
||||
nbt_server/winsserver.o \
|
||||
nbt_server/winsclient.o \
|
||||
nbt_server/defense.o \
|
||||
nbt_server/packet.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
|
@ -43,7 +43,7 @@ static void nbtd_name_defense_reply(struct nbt_name_socket *nbtsock,
|
||||
packet->ancount = 1;
|
||||
packet->operation =
|
||||
NBT_FLAG_REPLY |
|
||||
(request_packet->operation & NBT_OPCODE) |
|
||||
NBT_OPCODE_REGISTER |
|
||||
NBT_FLAG_AUTHORITIVE |
|
||||
NBT_FLAG_RECURSION_DESIRED |
|
||||
NBT_FLAG_RECURSION_AVAIL |
|
||||
@ -84,10 +84,10 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbtd_iface_name *iname;
|
||||
struct nbt_name *name;
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbt_interface);
|
||||
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbtd_interface);
|
||||
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->arcount == 1);
|
||||
|
@ -33,9 +33,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
/* if its a WINS query then direct to our WINS server */
|
||||
/* if its a WINS query then direct to our WINS server if we
|
||||
are running one */
|
||||
if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
|
||||
!(packet->operation & NBT_FLAG_BROADCAST)) {
|
||||
!(packet->operation & NBT_FLAG_BROADCAST) &&
|
||||
lp_wins_support()) {
|
||||
nbtd_query_wins(nbtsock, packet, src_address, src_port);
|
||||
return;
|
||||
}
|
||||
@ -56,6 +58,10 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
|
||||
case NBT_OPCODE_REFRESH:
|
||||
nbtd_request_defense(nbtsock, packet, src_address, src_port);
|
||||
break;
|
||||
|
||||
default:
|
||||
nbtd_bad_packet(packet, src_address, "Unexpected opcode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,11 +70,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
|
||||
/*
|
||||
find a registered name on an interface
|
||||
*/
|
||||
struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface,
|
||||
struct nbt_name *name,
|
||||
uint16_t nb_flags)
|
||||
struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
|
||||
struct nbt_name *name,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbtd_iface_name *iname;
|
||||
for (iname=iface->names;iname;iname=iname->next) {
|
||||
if (iname->name.type == name->type &&
|
||||
StrCaseCmp(name->name, iname->name.name) == 0 &&
|
||||
@ -82,13 +88,13 @@ struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface,
|
||||
/*
|
||||
start listening on the given address
|
||||
*/
|
||||
static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
|
||||
static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
|
||||
const char *bind_address,
|
||||
const char *address,
|
||||
const char *bcast,
|
||||
const char *netmask)
|
||||
{
|
||||
struct nbt_interface *iface;
|
||||
struct nbtd_interface *iface;
|
||||
NTSTATUS status;
|
||||
struct nbt_name_socket *bcast_nbtsock;
|
||||
|
||||
@ -100,7 +106,7 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
|
||||
to interfaces
|
||||
*/
|
||||
|
||||
iface = talloc(nbtsrv, struct nbt_interface);
|
||||
iface = talloc(nbtsrv, struct nbtd_interface);
|
||||
NT_STATUS_HAVE_NO_MEMORY(iface);
|
||||
|
||||
iface->nbtsrv = nbtsrv;
|
||||
@ -150,10 +156,31 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup a socket for talking to our WINS servers
|
||||
*/
|
||||
static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
|
||||
{
|
||||
struct nbtd_interface *iface;
|
||||
|
||||
iface = talloc_zero(nbtsrv, struct nbtd_interface);
|
||||
NT_STATUS_HAVE_NO_MEMORY(iface);
|
||||
|
||||
iface->nbtsrv = nbtsrv;
|
||||
|
||||
iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
|
||||
NT_STATUS_HAVE_NO_MEMORY(iface->nbtsock);
|
||||
|
||||
DLIST_ADD(nbtsrv->wins_interface, iface);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup our listening sockets on the configured network interfaces
|
||||
*/
|
||||
NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
|
||||
NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
|
||||
{
|
||||
int num_interfaces = iface_count();
|
||||
int i;
|
||||
@ -194,7 +221,38 @@ NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
if (lp_wins_server_list()) {
|
||||
status = nbtd_add_wins_socket(nbtsrv);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
form a list of addresses that we should use in name query replies
|
||||
*/
|
||||
const char **nbtd_address_list(struct nbtd_server *nbtsrv, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
const char **ret = NULL;
|
||||
struct nbtd_interface *iface;
|
||||
int count = 0;
|
||||
|
||||
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
|
||||
const char **ret2 = talloc_realloc(mem_ctx, ret, const char *, count+2);
|
||||
if (ret2 == NULL) goto failed;
|
||||
ret = ret2;
|
||||
ret[count] = talloc_strdup(ret, iface->ip_address);
|
||||
if (ret[count] == NULL) goto failed;
|
||||
count++;
|
||||
}
|
||||
ret[count] = NULL;
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
talloc_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -31,10 +31,10 @@
|
||||
*/
|
||||
static void nbtd_task_init(struct task_server *task)
|
||||
{
|
||||
struct nbt_server *nbtsrv;
|
||||
struct nbtd_server *nbtsrv;
|
||||
NTSTATUS status;
|
||||
|
||||
nbtsrv = talloc(task, struct nbt_server);
|
||||
nbtsrv = talloc(task, struct nbtd_server);
|
||||
if (nbtsrv == NULL) {
|
||||
task_terminate(task, "nbtd: out of memory");
|
||||
return;
|
||||
@ -43,6 +43,7 @@ static void nbtd_task_init(struct task_server *task)
|
||||
nbtsrv->task = task;
|
||||
nbtsrv->interfaces = NULL;
|
||||
nbtsrv->bcast_interface = NULL;
|
||||
nbtsrv->wins_interface = NULL;
|
||||
|
||||
/* start listening on the configured network interfaces */
|
||||
status = nbtd_startup_interfaces(nbtsrv);
|
||||
|
@ -25,39 +25,47 @@
|
||||
/*
|
||||
a list of our registered names on each interface
|
||||
*/
|
||||
struct nbt_iface_name {
|
||||
struct nbt_iface_name *next, *prev;
|
||||
struct nbt_interface *iface;
|
||||
struct nbtd_iface_name {
|
||||
struct nbtd_iface_name *next, *prev;
|
||||
struct nbtd_interface *iface;
|
||||
struct nbt_name name;
|
||||
uint16_t nb_flags;
|
||||
struct timeval registration_time;
|
||||
uint32_t ttl;
|
||||
|
||||
/* if registered with a wins server, then this lists the server being
|
||||
used */
|
||||
char *wins_server;
|
||||
};
|
||||
|
||||
|
||||
/* a list of network interfaces we are listening on */
|
||||
struct nbt_interface {
|
||||
struct nbt_interface *next, *prev;
|
||||
struct nbt_server *nbtsrv;
|
||||
struct nbtd_interface {
|
||||
struct nbtd_interface *next, *prev;
|
||||
struct nbtd_server *nbtsrv;
|
||||
const char *ip_address;
|
||||
const char *bcast_address;
|
||||
const char *netmask;
|
||||
struct nbt_name_socket *nbtsock;
|
||||
struct nbt_iface_name *names;
|
||||
struct nbtd_iface_name *names;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
top level context structure for the nbt server
|
||||
*/
|
||||
struct nbt_server {
|
||||
struct nbtd_server {
|
||||
struct task_server *task;
|
||||
|
||||
/* the list of local network interfaces */
|
||||
struct nbt_interface *interfaces;
|
||||
struct nbtd_interface *interfaces;
|
||||
|
||||
/* broadcast interface used for receiving packets only */
|
||||
struct nbt_interface *bcast_interface;
|
||||
struct nbtd_interface *bcast_interface;
|
||||
|
||||
/* wins client interface - used for registering and refreshing
|
||||
our names with a WINS server */
|
||||
struct nbtd_interface *wins_interface;
|
||||
};
|
||||
|
||||
|
||||
|
@ -32,11 +32,11 @@ static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *request_packet,
|
||||
const char *src_address, int src_port,
|
||||
struct nbt_name *name,
|
||||
struct nbt_interface *iface)
|
||||
struct nbtd_interface *iface)
|
||||
{
|
||||
struct nbt_name_packet *packet;
|
||||
uint32_t name_count;
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbtd_iface_name *iname;
|
||||
|
||||
/* work out how many names to send */
|
||||
name_count = 0;
|
||||
@ -100,9 +100,9 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
struct nbt_name *name;
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbt_interface);
|
||||
struct nbtd_iface_name *iname;
|
||||
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbtd_interface);
|
||||
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_STATUS);
|
||||
|
@ -45,9 +45,9 @@ BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbt_interface);
|
||||
struct nbt_server *nbtsrv = iface->nbtsrv;
|
||||
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbtd_interface);
|
||||
struct nbtd_server *nbtsrv = iface->nbtsrv;
|
||||
|
||||
/* if its not a broadcast then its not considered a self packet */
|
||||
if (!(packet->operation & NBT_FLAG_BROADCAST)) {
|
||||
|
@ -32,9 +32,16 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *request_packet,
|
||||
const char *src_address, int src_port,
|
||||
struct nbt_name *name, uint32_t ttl,
|
||||
uint16_t nb_flags, const char *address)
|
||||
uint16_t nb_flags, const char **addresses)
|
||||
{
|
||||
struct nbt_name_packet *packet;
|
||||
size_t num_addresses = str_list_length(addresses);
|
||||
int i;
|
||||
|
||||
if (num_addresses == 0) {
|
||||
DEBUG(3,("No addresses in name query reply - failing\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
packet = talloc_zero(nbtsock, struct nbt_name_packet);
|
||||
if (packet == NULL) return;
|
||||
@ -55,17 +62,21 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
|
||||
packet->answers[0].rr_type = NBT_QTYPE_NETBIOS;
|
||||
packet->answers[0].rr_class = NBT_QCLASS_IP;
|
||||
packet->answers[0].ttl = ttl;
|
||||
packet->answers[0].rdata.netbios.length = 6;
|
||||
packet->answers[0].rdata.netbios.addresses = talloc_array(packet->answers,
|
||||
struct nbt_rdata_address, 1);
|
||||
packet->answers[0].rdata.netbios.length = num_addresses*6;
|
||||
packet->answers[0].rdata.netbios.addresses =
|
||||
talloc_array(packet->answers, struct nbt_rdata_address, num_addresses);
|
||||
if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
|
||||
packet->answers[0].rdata.netbios.addresses[0].nb_flags = nb_flags;
|
||||
packet->answers[0].rdata.netbios.addresses[0].ipaddr =
|
||||
talloc_strdup(packet->answers, address);
|
||||
if (packet->answers[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
|
||||
|
||||
for (i=0;i<num_addresses;i++) {
|
||||
struct nbt_rdata_address *addr =
|
||||
&packet->answers[0].rdata.netbios.addresses[i];
|
||||
addr->nb_flags = nb_flags;
|
||||
addr->ipaddr = talloc_strdup(packet->answers, addresses[i]);
|
||||
if (addr->ipaddr == NULL) goto failed;
|
||||
}
|
||||
|
||||
DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n",
|
||||
name->name, name->type, src_address, address, src_port));
|
||||
name->name, name->type, src_address, addresses[0], src_port));
|
||||
|
||||
nbt_name_reply_send(nbtsock, src_address, src_port, packet);
|
||||
|
||||
@ -81,10 +92,10 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbtd_iface_name *iname;
|
||||
struct nbt_name *name;
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbt_interface);
|
||||
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbtd_interface);
|
||||
|
||||
/* see if its a node status query */
|
||||
if (packet->qdcount == 1 &&
|
||||
@ -100,14 +111,23 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
|
||||
/* see if we have the requested name on this interface */
|
||||
name = &packet->questions[0].name;
|
||||
|
||||
iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
|
||||
iname = nbtd_find_iname(iface, name, 0);
|
||||
if (iname == NULL) {
|
||||
DEBUG(7,("Query for %s<%02x> from %s - not found on %s\n",
|
||||
name->name, name->type, src_address, iface->ip_address));
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the name is not yet active and its a broadcast query then
|
||||
ignore it for now */
|
||||
if (!(iname->nb_flags & NBT_NM_ACTIVE) &&
|
||||
(packet->operation & NBT_FLAG_BROADCAST)) {
|
||||
DEBUG(7,("Query for %s<%02x> from %s - name not active yet on %s\n",
|
||||
name->name, name->type, src_address, iface->ip_address));
|
||||
return;
|
||||
}
|
||||
|
||||
nbtd_name_query_reply(nbtsock, packet, src_address, src_port,
|
||||
&iname->name, iname->ttl, iname->nb_flags,
|
||||
iface->ip_address);
|
||||
nbtd_address_list(iface->nbtsrv, packet));
|
||||
}
|
||||
|
@ -29,14 +29,15 @@
|
||||
#include "libcli/composite/composite.h"
|
||||
|
||||
|
||||
static void nbtd_start_refresh_timer(struct nbt_iface_name *iname);
|
||||
static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
|
||||
|
||||
/*
|
||||
a name refresh request has completed
|
||||
*/
|
||||
static void refresh_completion_handler(struct nbt_name_request *req)
|
||||
{
|
||||
struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
|
||||
struct nbtd_iface_name *iname = talloc_get_type(req->async.private,
|
||||
struct nbtd_iface_name);
|
||||
NTSTATUS status;
|
||||
struct nbt_name_refresh io;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(iname);
|
||||
@ -74,8 +75,8 @@ static void refresh_completion_handler(struct nbt_name_request *req)
|
||||
static void name_refresh_handler(struct event_context *ev, struct timed_event *te,
|
||||
struct timeval t, void *private)
|
||||
{
|
||||
struct nbt_iface_name *iname = talloc_get_type(private, struct nbt_iface_name);
|
||||
struct nbt_interface *iface = iname->iface;
|
||||
struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
|
||||
struct nbtd_interface *iface = iname->iface;
|
||||
struct nbt_name_register io;
|
||||
struct nbt_name_request *req;
|
||||
|
||||
@ -92,6 +93,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
|
||||
io.in.register_demand = False;
|
||||
io.in.broadcast = True;
|
||||
io.in.timeout = 3;
|
||||
io.in.retries = 0;
|
||||
|
||||
req = nbt_name_register_send(iface->nbtsock, &io);
|
||||
if (req == NULL) return;
|
||||
@ -104,7 +106,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
|
||||
/*
|
||||
start a timer to refresh this name
|
||||
*/
|
||||
static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
|
||||
static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
|
||||
{
|
||||
uint32_t refresh_time;
|
||||
uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
|
||||
@ -123,8 +125,8 @@ static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
|
||||
*/
|
||||
static void nbtd_register_handler(struct composite_context *req)
|
||||
{
|
||||
struct nbt_iface_name *iname = talloc_get_type(req->async.private,
|
||||
struct nbt_iface_name);
|
||||
struct nbtd_iface_name *iname = talloc_get_type(req->async.private,
|
||||
struct nbtd_iface_name);
|
||||
NTSTATUS status;
|
||||
|
||||
status = nbt_name_register_bcast_recv(req);
|
||||
@ -150,16 +152,16 @@ static void nbtd_register_handler(struct composite_context *req)
|
||||
/*
|
||||
register a name on a network interface
|
||||
*/
|
||||
static void nbtd_register_name_iface(struct nbt_interface *iface,
|
||||
static void nbtd_register_name_iface(struct nbtd_interface *iface,
|
||||
const char *name, enum nbt_name_type type,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbtd_iface_name *iname;
|
||||
const char *scope = lp_netbios_scope();
|
||||
struct nbt_name_register_bcast io;
|
||||
struct composite_context *req;
|
||||
|
||||
iname = talloc(iface, struct nbt_iface_name);
|
||||
iname = talloc(iface, struct nbtd_iface_name);
|
||||
if (!iname) return;
|
||||
|
||||
iname->iface = iface;
|
||||
@ -173,8 +175,9 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
|
||||
iname->nb_flags = nb_flags;
|
||||
iname->ttl = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
|
||||
iname->registration_time = timeval_zero();
|
||||
iname->wins_server = NULL;
|
||||
|
||||
DLIST_ADD_END(iface->names, iname, struct nbt_iface_name *);
|
||||
DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
|
||||
|
||||
if (nb_flags & NBT_NM_PERMANENT) {
|
||||
/* permanent names are not announced and are immediately active */
|
||||
@ -183,6 +186,13 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
|
||||
return;
|
||||
}
|
||||
|
||||
/* if this is the wins interface, then we need to do a special
|
||||
wins name registration */
|
||||
if (iface == iface->nbtsrv->wins_interface) {
|
||||
nbtd_winsclient_refresh(iname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup a broadcast name registration request */
|
||||
io.in.name = iname->name;
|
||||
io.in.dest_addr = iface->bcast_address;
|
||||
@ -201,11 +211,11 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
|
||||
/*
|
||||
register one name on all our interfaces
|
||||
*/
|
||||
static void nbtd_register_name(struct nbt_server *nbtsrv,
|
||||
static void nbtd_register_name(struct nbtd_server *nbtsrv,
|
||||
const char *name, enum nbt_name_type type,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_interface *iface;
|
||||
struct nbtd_interface *iface;
|
||||
|
||||
/* register with all the local interfaces */
|
||||
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
|
||||
@ -218,14 +228,17 @@ static void nbtd_register_name(struct nbt_server *nbtsrv,
|
||||
nb_flags | NBT_NM_PERMANENT);
|
||||
}
|
||||
|
||||
/* TODO: register with our WINS servers */
|
||||
/* register with our WINS servers */
|
||||
if (nbtsrv->wins_interface) {
|
||||
nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
register our names on all interfaces
|
||||
*/
|
||||
void nbtd_register_names(struct nbt_server *nbtsrv)
|
||||
void nbtd_register_names(struct nbtd_server *nbtsrv)
|
||||
{
|
||||
uint16_t nb_flags = NBT_NODE_M;
|
||||
const char **aliases;
|
||||
|
123
source/nbt_server/winsclient.c
Normal file
123
source/nbt_server/winsclient.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
wins client name registration and refresh
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "smbd/service_task.h"
|
||||
|
||||
|
||||
/*
|
||||
refresh a WINS name registration
|
||||
*/
|
||||
static void nbtd_refresh_wins_refresh(struct event_context *ev, struct timed_event *te,
|
||||
struct timeval t, void *private)
|
||||
{
|
||||
struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
|
||||
nbtd_winsclient_refresh(iname);
|
||||
}
|
||||
|
||||
/*
|
||||
called when a wins name refresh has completed
|
||||
*/
|
||||
static void nbtd_refresh_wins_handler(struct composite_context *c)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct nbt_name_refresh_wins io;
|
||||
struct nbtd_iface_name *iname = talloc_get_type(c->async.private,
|
||||
struct nbtd_iface_name);
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(iname);
|
||||
|
||||
status = nbt_name_refresh_wins_recv(c, tmp_ctx, &io);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
|
||||
/* none of the WINS servers responded - try again
|
||||
periodically */
|
||||
int wins_retry_time = lp_parm_int(-1, "nbt", "wins_retry", 300);
|
||||
event_add_timed(iname->iface->nbtsrv->task->event_ctx,
|
||||
iname,
|
||||
timeval_current_ofs(wins_retry_time, 0),
|
||||
nbtd_refresh_wins_refresh,
|
||||
iname);
|
||||
talloc_free(tmp_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1,("Name refresh failure with WINS for %s<%02x> - %s\n",
|
||||
iname->name.name, iname->name.type, nt_errstr(status)));
|
||||
talloc_free(tmp_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (io.out.rcode != 0) {
|
||||
DEBUG(1,("WINS server %s rejected name refresh of %s<%02x> - rcode %d\n",
|
||||
io.out.wins_server, iname->name.name, iname->name.type, io.out.rcode));
|
||||
iname->nb_flags |= NBT_NM_CONFLICT;
|
||||
talloc_free(tmp_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* success - start a periodic name refresh */
|
||||
iname->nb_flags |= NBT_NM_ACTIVE;
|
||||
if (iname->wins_server) {
|
||||
talloc_free(iname->wins_server);
|
||||
}
|
||||
iname->wins_server = talloc_steal(iname, io.out.wins_server);
|
||||
|
||||
iname->registration_time = timeval_current();
|
||||
event_add_timed(iname->iface->nbtsrv->task->event_ctx,
|
||||
iname,
|
||||
timeval_add(&iname->registration_time, iname->ttl/2, 0),
|
||||
nbtd_refresh_wins_refresh,
|
||||
iname);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
refresh a name with our WINS servers
|
||||
*/
|
||||
void nbtd_winsclient_refresh(struct nbtd_iface_name *iname)
|
||||
{
|
||||
struct nbtd_interface *iface = iname->iface;
|
||||
struct nbt_name_refresh_wins io;
|
||||
struct composite_context *c;
|
||||
|
||||
/* setup a wins name refresh request */
|
||||
io.in.name = iname->name;
|
||||
io.in.wins_servers = lp_wins_server_list();
|
||||
io.in.addresses = nbtd_address_list(iface->nbtsrv, iname);
|
||||
io.in.nb_flags = iname->nb_flags;
|
||||
io.in.ttl = iname->ttl;
|
||||
|
||||
c = nbt_name_refresh_wins_send(iface->nbtsock, &io);
|
||||
if (c == NULL) {
|
||||
talloc_free(io.in.addresses);
|
||||
return;
|
||||
}
|
||||
talloc_steal(c, io.in.addresses);
|
||||
|
||||
c->async.fn = nbtd_refresh_wins_handler;
|
||||
c->async.private = iname;
|
||||
}
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "dlinklist.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user