mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r5114: the nbtd task can now act as a basic B-node server. It registers its
names on the network and answers name queries. Lots of details are
still missing, but at least this now means you don't need a Samba3
nmbd to use Samba4.
missing pieces include:
- name registrations should be "shout 3 times, then demand"
- no WINS server yet
- no master browser code
(This used to be commit d7d31fdc66
)
This commit is contained in:
parent
37449657a8
commit
414f6c80b2
@ -150,7 +150,7 @@ struct nbt_name_packet;
|
||||
struct nbt_name_socket;
|
||||
struct nbt_name_query;
|
||||
struct nbt_name_status;
|
||||
|
||||
struct nbt_name_register;
|
||||
|
||||
struct messaging_context;
|
||||
struct stream_connection;
|
||||
@ -159,3 +159,4 @@ struct model_ops;
|
||||
struct stream_server_ops;
|
||||
|
||||
struct nbt_server;
|
||||
struct nbt_interface;
|
||||
|
@ -330,6 +330,20 @@ struct ipv4_addr *iface_n_bcast(int n)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
return netmask of the Nth interface
|
||||
**************************************************************************/
|
||||
struct ipv4_addr *iface_n_netmask(int n)
|
||||
{
|
||||
struct interface *i;
|
||||
|
||||
for (i=local_interfaces;i && n;i=i->next)
|
||||
n--;
|
||||
|
||||
if (i) return &i->nmask;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* these 3 functions return the ip/bcast/nmask for the interface
|
||||
most appropriate for the given ip address. If they can't find
|
||||
an appropriate interface they return the requested field of the
|
||||
|
@ -152,173 +152,5 @@ void str_list_free(char ***list)
|
||||
SAFE_FREE(*list);
|
||||
}
|
||||
|
||||
BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
|
||||
{
|
||||
char *p, *s, *t;
|
||||
ssize_t ls, lp, li, ld, i, d;
|
||||
|
||||
if (!list)
|
||||
return False;
|
||||
if (!pattern)
|
||||
return False;
|
||||
if (!insert)
|
||||
return False;
|
||||
|
||||
lp = (ssize_t)strlen(pattern);
|
||||
li = (ssize_t)strlen(insert);
|
||||
ld = li -lp;
|
||||
|
||||
while (*list) {
|
||||
s = *list;
|
||||
ls = (ssize_t)strlen(s);
|
||||
|
||||
while ((p = strstr(s, pattern))) {
|
||||
t = *list;
|
||||
d = p -t;
|
||||
if (ld) {
|
||||
t = (char *) malloc(ls +ld +1);
|
||||
if (!t) {
|
||||
DEBUG(0,("str_list_substitute: Unable to allocate memory"));
|
||||
return False;
|
||||
}
|
||||
memcpy(t, *list, d);
|
||||
memcpy(t +d +li, p +lp, ls -d -lp +1);
|
||||
SAFE_FREE(*list);
|
||||
*list = t;
|
||||
ls += ld;
|
||||
s = t +d +li;
|
||||
}
|
||||
|
||||
for (i = 0; i < li; i++) {
|
||||
switch (insert[i]) {
|
||||
case '`':
|
||||
case '"':
|
||||
case '\'':
|
||||
case ';':
|
||||
case '$':
|
||||
case '%':
|
||||
case '\r':
|
||||
case '\n':
|
||||
t[d +i] = '_';
|
||||
break;
|
||||
default:
|
||||
t[d +i] = insert[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list++;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
#define IPSTR_LIST_SEP ","
|
||||
|
||||
/**
|
||||
* Add ip string representation to ipstr list. Used also
|
||||
* as part of @function ipstr_list_make
|
||||
*
|
||||
* @param ipstr_list pointer to string containing ip list;
|
||||
* MUST BE already allocated and IS reallocated if necessary
|
||||
* @param ipstr_size pointer to current size of ipstr_list (might be changed
|
||||
* as a result of reallocation)
|
||||
* @param ip IP address which is to be added to list
|
||||
* @return pointer to string appended with new ip and possibly
|
||||
* reallocated to new length
|
||||
**/
|
||||
|
||||
char* ipstr_list_add(char** ipstr_list, const struct ipv4_addr *ip)
|
||||
{
|
||||
char* new_ipstr = NULL;
|
||||
|
||||
/* arguments checking */
|
||||
if (!ipstr_list || !ip) return NULL;
|
||||
|
||||
/* attempt to convert ip to a string and append colon separator to it */
|
||||
if (*ipstr_list) {
|
||||
asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,sys_inet_ntoa(*ip));
|
||||
SAFE_FREE(*ipstr_list);
|
||||
} else {
|
||||
asprintf(&new_ipstr, "%s", sys_inet_ntoa(*ip));
|
||||
}
|
||||
*ipstr_list = new_ipstr;
|
||||
return *ipstr_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and initialise an ipstr list using ip adresses
|
||||
* passed as arguments.
|
||||
*
|
||||
* @param ipstr_list pointer to string meant to be allocated and set
|
||||
* @param ip_list array of ip addresses to place in the list
|
||||
* @param ip_count number of addresses stored in ip_list
|
||||
* @return pointer to allocated ip string
|
||||
**/
|
||||
|
||||
char* ipstr_list_make(char** ipstr_list, const struct ipv4_addr* ip_list, int ip_count)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* arguments checking */
|
||||
if (!ip_list && !ipstr_list) return 0;
|
||||
|
||||
*ipstr_list = NULL;
|
||||
|
||||
/* process ip addresses given as arguments */
|
||||
for (i = 0; i < ip_count; i++)
|
||||
*ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
|
||||
|
||||
return (*ipstr_list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse given ip string list into array of ip addresses
|
||||
* (as in_addr structures)
|
||||
*
|
||||
* @param ipstr ip string list to be parsed
|
||||
* @param ip_list pointer to array of ip addresses which is
|
||||
* allocated by this function and must be freed by caller
|
||||
* @return number of succesfully parsed addresses
|
||||
**/
|
||||
|
||||
int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list)
|
||||
{
|
||||
fstring token_str;
|
||||
int count;
|
||||
|
||||
if (!ipstr_list || !ip_list) return 0;
|
||||
|
||||
for (*ip_list = NULL, count = 0;
|
||||
next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
|
||||
count++) {
|
||||
|
||||
struct ipv4_addr addr;
|
||||
|
||||
/* convert single token to ip address */
|
||||
if ( (addr.addr = sys_inet_addr(token_str)) == INADDR_NONE )
|
||||
break;
|
||||
|
||||
/* prepare place for another in_addr structure */
|
||||
*ip_list = realloc_p(*ip_list, struct ipv4_addr, count + 1);
|
||||
if (!*ip_list) return -1;
|
||||
|
||||
(*ip_list)[count] = addr;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Safely free ip string list
|
||||
*
|
||||
* @param ipstr_list ip string list to be freed
|
||||
**/
|
||||
|
||||
void ipstr_list_free(char* ipstr_list)
|
||||
{
|
||||
SAFE_FREE(ipstr_list);
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ ADD_OBJ_FILES = \
|
||||
ADD_OBJ_FILES = \
|
||||
libcli/nbt/nbtname.o \
|
||||
libcli/nbt/nbtsocket.o \
|
||||
libcli/nbt/namequery.o
|
||||
libcli/nbt/namequery.o \
|
||||
libcli/nbt/nameregister.o
|
||||
REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET
|
||||
|
||||
[SUBSYSTEM::LIBCLI_RESOLVE]
|
||||
|
@ -113,7 +113,8 @@ struct nbt_name_query {
|
||||
struct {
|
||||
const char *reply_from;
|
||||
struct nbt_name name;
|
||||
const char *reply_addr;
|
||||
int16_t num_addrs;
|
||||
const char **reply_addrs;
|
||||
} out;
|
||||
};
|
||||
|
||||
@ -130,3 +131,23 @@ struct nbt_name_status {
|
||||
struct nbt_rdata_status status;
|
||||
} out;
|
||||
};
|
||||
|
||||
/* a name registration request */
|
||||
struct nbt_name_register {
|
||||
struct {
|
||||
struct nbt_name name;
|
||||
const char *dest_addr;
|
||||
const char *address;
|
||||
uint16_t nb_flags;
|
||||
BOOL register_demand;
|
||||
BOOL broadcast;
|
||||
uint32_t ttl;
|
||||
int timeout; /* in seconds */
|
||||
} in;
|
||||
struct {
|
||||
const char *reply_from;
|
||||
struct nbt_name name;
|
||||
const char *reply_addr;
|
||||
uint8_t rcode;
|
||||
} out;
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ failed:
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a name query replu
|
||||
wait for a name query reply
|
||||
*/
|
||||
NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
|
||||
@ -75,6 +75,7 @@ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
|
||||
struct nbt_name_packet *packet;
|
||||
const char *addr;
|
||||
struct in_addr in;
|
||||
int i;
|
||||
|
||||
status = nbt_name_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(status) ||
|
||||
@ -94,13 +95,23 @@ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
|
||||
}
|
||||
|
||||
io->out.name = packet->answers[0].name;
|
||||
in.s_addr = htonl(packet->answers[0].rdata.netbios.ipaddr);
|
||||
addr = inet_ntoa(in);
|
||||
if (addr == NULL) {
|
||||
io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6;
|
||||
io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs);
|
||||
if (io->out.reply_addrs == NULL) {
|
||||
talloc_free(req);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
io->out.reply_addr = talloc_strdup(mem_ctx, addr);
|
||||
|
||||
for (i=0;i<io->out.num_addrs;i++) {
|
||||
in.s_addr = htonl(packet->answers[0].rdata.netbios.addresses[i].ipaddr);
|
||||
addr = inet_ntoa(in);
|
||||
if (addr == NULL) {
|
||||
talloc_free(req);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
io->out.reply_addrs[i] = talloc_strdup(mem_ctx, addr);
|
||||
}
|
||||
|
||||
talloc_steal(mem_ctx, io->out.name.name);
|
||||
talloc_steal(mem_ctx, io->out.name.scope);
|
||||
|
||||
@ -110,7 +121,7 @@ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a name query replu
|
||||
wait for a name query reply
|
||||
*/
|
||||
NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
|
||||
@ -156,7 +167,7 @@ failed:
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a name status replu
|
||||
wait for a name status reply
|
||||
*/
|
||||
NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
|
||||
@ -199,7 +210,7 @@ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a name status replu
|
||||
wait for a name status reply
|
||||
*/
|
||||
NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
|
||||
|
140
source4/libcli/nbt/nameregister.c
Normal file
140
source4/libcli/nbt/nameregister.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
send out a name registration request
|
||||
|
||||
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 "libcli/nbt/libnbt.h"
|
||||
#include "system/network.h"
|
||||
|
||||
/*
|
||||
send a nbt name registration request
|
||||
*/
|
||||
struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_register *io)
|
||||
{
|
||||
struct nbt_name_request *req;
|
||||
struct nbt_name_packet *packet;
|
||||
|
||||
packet = talloc_zero(nbtsock, struct nbt_name_packet);
|
||||
if (packet == NULL) return NULL;
|
||||
|
||||
packet->qdcount = 1;
|
||||
packet->arcount = 1;
|
||||
packet->operation = NBT_OPCODE_REGISTER;
|
||||
if (io->in.broadcast) {
|
||||
packet->operation |= NBT_FLAG_BROADCAST;
|
||||
}
|
||||
if (io->in.register_demand) {
|
||||
packet->operation |= NBT_FLAG_RECURSION_DESIRED;
|
||||
}
|
||||
|
||||
packet->questions = talloc_array(packet, struct nbt_name_question, 1);
|
||||
if (packet->questions == NULL) goto failed;
|
||||
|
||||
packet->questions[0].name = io->in.name;
|
||||
packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
|
||||
packet->questions[0].question_class = NBT_QCLASS_IP;
|
||||
|
||||
packet->additional = talloc_array(packet, struct nbt_res_rec, 1);
|
||||
if (packet->additional == NULL) goto failed;
|
||||
|
||||
packet->additional[0].name = io->in.name;
|
||||
packet->additional[0].rr_type = NBT_QTYPE_NETBIOS;
|
||||
packet->additional[0].rr_class = NBT_QCLASS_IP;
|
||||
packet->additional[0].ttl = io->in.ttl;
|
||||
packet->additional[0].rdata.netbios.length = 6;
|
||||
packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional,
|
||||
struct nbt_rdata_address, 1);
|
||||
if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed;
|
||||
packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags;
|
||||
packet->additional[0].rdata.netbios.addresses[0].ipaddr = htonl(inet_addr(io->in.address));
|
||||
|
||||
req = nbt_name_request_send(nbtsock, io->in.dest_addr, lp_nbt_port(), packet,
|
||||
timeval_current_ofs(io->in.timeout, 0), False);
|
||||
if (req == NULL) goto failed;
|
||||
|
||||
talloc_steal(req, packet);
|
||||
|
||||
return req;
|
||||
|
||||
failed:
|
||||
talloc_free(packet);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a registration reply
|
||||
*/
|
||||
NTSTATUS nbt_name_register_recv(struct nbt_name_request *req,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct nbt_name_packet *packet;
|
||||
const char *addr;
|
||||
struct in_addr in;
|
||||
|
||||
status = nbt_name_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(status) ||
|
||||
req->num_replies == 0) {
|
||||
talloc_free(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
packet = req->replies[0].packet;
|
||||
io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr);
|
||||
|
||||
if (packet->ancount != 1 ||
|
||||
packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
|
||||
packet->answers[0].rr_class != NBT_QCLASS_IP) {
|
||||
talloc_free(req);
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
|
||||
io->out.rcode = packet->operation & NBT_RCODE;
|
||||
io->out.name = packet->answers[0].name;
|
||||
if (packet->answers[0].rdata.netbios.length < 6) {
|
||||
talloc_free(req);
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
in.s_addr = htonl(packet->answers[0].rdata.netbios.addresses[0].ipaddr);
|
||||
addr = inet_ntoa(in);
|
||||
if (addr == NULL) {
|
||||
talloc_free(req);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
io->out.reply_addr = talloc_strdup(mem_ctx, addr);
|
||||
talloc_steal(mem_ctx, io->out.name.name);
|
||||
talloc_steal(mem_ctx, io->out.name.scope);
|
||||
|
||||
talloc_free(req);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
synchronous name registration request
|
||||
*/
|
||||
NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock,
|
||||
TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
|
||||
{
|
||||
struct nbt_name_request *req = nbt_name_register_send(nbtsock, io);
|
||||
return nbt_name_register_recv(req, mem_ctx, io);
|
||||
}
|
@ -41,7 +41,8 @@ static int nbt_name_request_destructor(void *ptr)
|
||||
if (req->state == NBT_REQUEST_WAIT) {
|
||||
req->nbtsock->num_pending--;
|
||||
}
|
||||
if (req->request->name_trn_id != 0) {
|
||||
if (req->request->name_trn_id != 0 &&
|
||||
!(req->request->operation & NBT_FLAG_REPLY)) {
|
||||
idr_remove(req->nbtsock->idr, req->request->name_trn_id);
|
||||
req->request->name_trn_id = 0;
|
||||
}
|
||||
@ -65,7 +66,7 @@ static int nbt_name_request_destructor(void *ptr)
|
||||
static void nbt_name_socket_send(struct nbt_name_socket *nbtsock)
|
||||
{
|
||||
struct nbt_name_request *req = nbtsock->send_queue;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(req);
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(nbtsock);
|
||||
NTSTATUS status;
|
||||
|
||||
while ((req = nbtsock->send_queue)) {
|
||||
@ -98,9 +99,13 @@ static void nbt_name_socket_send(struct nbt_name_socket *nbtsock)
|
||||
}
|
||||
|
||||
DLIST_REMOVE(nbtsock->send_queue, req);
|
||||
req->state = NBT_REQUEST_WAIT;
|
||||
nbtsock->fde->flags |= EVENT_FD_READ;
|
||||
nbtsock->num_pending++;
|
||||
if (req->request->operation & NBT_FLAG_REPLY) {
|
||||
talloc_free(req);
|
||||
} else {
|
||||
req->state = NBT_REQUEST_WAIT;
|
||||
nbtsock->fde->flags |= EVENT_FD_READ;
|
||||
nbtsock->num_pending++;
|
||||
}
|
||||
}
|
||||
|
||||
nbtsock->fde->flags &= ~EVENT_FD_WRITE;
|
||||
@ -317,7 +322,8 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
|
||||
if (req == NULL) goto failed;
|
||||
|
||||
req->nbtsock = nbtsock;
|
||||
req->dest_addr = dest_addr;
|
||||
req->dest_addr = talloc_strdup(req, dest_addr);
|
||||
if (req->dest_addr == NULL) goto failed;
|
||||
req->dest_port = dest_port;
|
||||
req->request = talloc_reference(req, request);
|
||||
req->allow_multiple_replies = allow_multiple_replies;
|
||||
@ -361,6 +367,39 @@ failed:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send off a nbt name reply
|
||||
*/
|
||||
NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
|
||||
const char *dest_addr, int dest_port,
|
||||
struct nbt_name_packet *request)
|
||||
{
|
||||
struct nbt_name_request *req;
|
||||
|
||||
req = talloc_zero(nbtsock, struct nbt_name_request);
|
||||
NT_STATUS_HAVE_NO_MEMORY(req);
|
||||
|
||||
req->nbtsock = nbtsock;
|
||||
req->dest_addr = talloc_strdup(req, dest_addr);
|
||||
if (req->dest_addr == NULL) goto failed;
|
||||
req->dest_port = dest_port;
|
||||
req->request = talloc_reference(req, request);
|
||||
req->state = NBT_REQUEST_SEND;
|
||||
|
||||
talloc_set_destructor(req, nbt_name_request_destructor);
|
||||
|
||||
DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
|
||||
|
||||
nbtsock->fde->flags |= EVENT_FD_WRITE;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
|
||||
failed:
|
||||
talloc_free(req);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
wait for a nbt request to complete
|
||||
*/
|
||||
@ -392,7 +431,6 @@ NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock,
|
||||
nbtsock->incoming.handler = handler;
|
||||
nbtsock->incoming.private = private;
|
||||
nbtsock->fde->flags |= EVENT_FD_READ;
|
||||
socket_set_option(nbtsock->sock, "SO_BROADCAST", "1");
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,12 @@ interface nbt
|
||||
typedef struct {
|
||||
nb_flags nb_flags;
|
||||
uint32 ipaddr;
|
||||
} nbt_rdata_netbios;
|
||||
} nbt_rdata_address;
|
||||
|
||||
typedef struct {
|
||||
uint16 length;
|
||||
nbt_rdata_address addresses[length/6];
|
||||
} nbt_rdata_netbios;
|
||||
|
||||
typedef struct {
|
||||
uint8 unit_id[6];
|
||||
@ -135,14 +139,16 @@ interface nbt
|
||||
nb_flags nb_flags;
|
||||
} nbt_status_name;
|
||||
|
||||
typedef struct {
|
||||
typedef [gensize] struct {
|
||||
[value(ndr_size_nbt_rdata_status(r, ndr->flags)-2)] uint16 length;
|
||||
uint8 num_names;
|
||||
nbt_status_name names[num_names];
|
||||
nbt_statistics statistics;
|
||||
} nbt_rdata_status;
|
||||
|
||||
typedef struct {
|
||||
[flag(NDR_REMAINING)] DATA_BLOB data;
|
||||
uint16 length;
|
||||
uint8 data[length];
|
||||
} nbt_rdata_data;
|
||||
|
||||
typedef [nodiscriminant] union {
|
||||
@ -156,7 +162,7 @@ interface nbt
|
||||
nbt_qtype rr_type;
|
||||
nbt_qclass rr_class;
|
||||
uint32 ttl;
|
||||
[subcontext(2),switch_is(rr_type)] nbt_rdata rdata;
|
||||
[switch_is(rr_type)] nbt_rdata rdata;
|
||||
} nbt_res_rec;
|
||||
|
||||
typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct {
|
||||
|
@ -6,7 +6,11 @@
|
||||
INIT_OBJ_FILES = \
|
||||
nbt_server/nbt_server.o
|
||||
ADD_OBJ_FILES = \
|
||||
nbt_server/interfaces.o
|
||||
nbt_server/interfaces.o \
|
||||
nbt_server/register.o \
|
||||
nbt_server/query.o \
|
||||
nbt_server/winsserver.o \
|
||||
nbt_server/packet.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
LIBCLI_NBT
|
||||
# End SUBSYSTEM SMB
|
||||
|
@ -24,13 +24,72 @@
|
||||
#include "dlinklist.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
#include "smbd/service_task.h"
|
||||
#include "libcli/nbt/libnbt.h"
|
||||
|
||||
/*
|
||||
find a registered name on an interface
|
||||
*/
|
||||
struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_name *name,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
for (iname=iface->names;iname;iname=iname->next) {
|
||||
if (iname->name.type == name->type &&
|
||||
StrCaseCmp(name->name, iname->name.name) == 0 &&
|
||||
((iname->nb_flags & nb_flags) == nb_flags)) {
|
||||
return iname;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
see if a src address matches an interface
|
||||
*/
|
||||
static BOOL nbt_iface_match(struct nbt_interface *iface, const char *src_address)
|
||||
{
|
||||
struct ipv4_addr ip1, ip2, mask;
|
||||
ip1 = interpret_addr2(iface->ip_address);
|
||||
ip2 = interpret_addr2(src_address);
|
||||
mask = interpret_addr2(iface->netmask);
|
||||
return same_net(ip1, ip2, mask);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
find the appropriate interface for a incoming packet. If a local interface isn't
|
||||
found then the general broadcast interface is used
|
||||
*/
|
||||
struct nbt_interface *nbt_iface_find(struct nbt_name_socket *nbtsock, const char *src_address)
|
||||
{
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbt_interface);
|
||||
struct nbt_server *nbtsrv = iface->nbtsrv;
|
||||
|
||||
/* it might have been received by one of our specific bound
|
||||
addresses */
|
||||
if (iface != nbtsrv->bcast_interface) {
|
||||
return iface;
|
||||
}
|
||||
|
||||
/* it came in on our broadcast interface - try to find a match */
|
||||
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
|
||||
if (nbt_iface_match(iface, src_address)) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
/* it didn't match any specific interface - use our general broadcast interface */
|
||||
return nbtsrv->bcast_interface;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
start listening on the given address
|
||||
*/
|
||||
static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
|
||||
const char *address, const char *bcast)
|
||||
const char *bind_address,
|
||||
const char *address,
|
||||
const char *bcast,
|
||||
const char *netmask)
|
||||
{
|
||||
struct nbt_interface *iface;
|
||||
NTSTATUS status;
|
||||
@ -38,14 +97,16 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
|
||||
iface = talloc(nbtsrv, struct nbt_interface);
|
||||
NT_STATUS_HAVE_NO_MEMORY(iface);
|
||||
|
||||
iface->nbtsrv = nbtsrv;
|
||||
iface->nbtsrv = nbtsrv;
|
||||
iface->bcast_address = talloc_steal(iface, bcast);
|
||||
iface->ip_address = talloc_steal(iface, address);
|
||||
iface->ip_address = talloc_steal(iface, address);
|
||||
iface->netmask = talloc_steal(iface, netmask);
|
||||
iface->names = NULL;
|
||||
|
||||
iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
|
||||
NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
|
||||
|
||||
status = socket_listen(iface->nbtsock->sock, address, lp_nbt_port(), 0, 0);
|
||||
status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to %s:%d - %s\n",
|
||||
address, lp_nbt_port(), nt_errstr(status)));
|
||||
@ -53,7 +114,13 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
|
||||
return status;
|
||||
}
|
||||
|
||||
DLIST_ADD(nbtsrv->interfaces, iface);
|
||||
socket_set_option(iface->nbtsock->sock, "SO_BROADCAST", "1");
|
||||
|
||||
if (strcmp(netmask, "0.0.0.0") == 0) {
|
||||
DLIST_ADD(nbtsrv->bcast_interface, iface);
|
||||
} else {
|
||||
DLIST_ADD(nbtsrv->interfaces, iface);
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -68,17 +135,29 @@ NTSTATUS nbt_startup_interfaces(struct nbt_server *nbtsrv)
|
||||
int i;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
|
||||
NTSTATUS status;
|
||||
const char *primary_address;
|
||||
|
||||
/* the primary address is the address we will return for non-WINS queries
|
||||
not made on a specific interface */
|
||||
if (num_interfaces > 0) {
|
||||
primary_address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(0)));
|
||||
} else {
|
||||
primary_address = sys_inet_ntoa(interpret_addr2(lp_netbios_name()));
|
||||
}
|
||||
|
||||
status = nbt_add_socket(nbtsrv,
|
||||
talloc_strdup(tmp_ctx, "0.0.0.0"),
|
||||
talloc_strdup(tmp_ctx, "255.255.255.255"));
|
||||
"0.0.0.0",
|
||||
primary_address,
|
||||
talloc_strdup(tmp_ctx, "255.255.255.255"),
|
||||
talloc_strdup(tmp_ctx, "0.0.0.0"));
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
for (i=0; i<num_interfaces; i++) {
|
||||
const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i)));
|
||||
const char *bcast = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i)));
|
||||
const char *netmask = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_netmask(i)));
|
||||
|
||||
status = nbt_add_socket(nbtsrv, address, bcast);
|
||||
status = nbt_add_socket(nbtsrv, address, address, bcast, netmask);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "events.h"
|
||||
#include "libcli/nbt/libnbt.h"
|
||||
#include "smbd/service_task.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
@ -36,9 +35,12 @@ static void nbt_request_handler(struct nbt_name_socket *nbtsock,
|
||||
{
|
||||
struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
|
||||
struct nbt_interface);
|
||||
DEBUG(0,("nbtd request from %s:%d\n", src_address, src_port));
|
||||
|
||||
NDR_PRINT_DEBUG(nbt_name_packet, packet);
|
||||
switch (packet->operation & NBT_OPCODE) {
|
||||
case NBT_OPCODE_QUERY:
|
||||
nbt_request_query(nbtsock, packet, src_address, src_port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -57,8 +59,9 @@ static void nbtd_task_init(struct task_server *task)
|
||||
return;
|
||||
}
|
||||
|
||||
nbtsrv->task = task;
|
||||
nbtsrv->interfaces = NULL;
|
||||
nbtsrv->task = task;
|
||||
nbtsrv->interfaces = NULL;
|
||||
nbtsrv->bcast_interface = NULL;
|
||||
|
||||
/* start listening on the configured network interfaces */
|
||||
status = nbt_startup_interfaces(nbtsrv);
|
||||
@ -71,6 +74,11 @@ static void nbtd_task_init(struct task_server *task)
|
||||
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
|
||||
nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface);
|
||||
}
|
||||
nbt_set_incoming_handler(nbtsrv->bcast_interface->nbtsock, nbt_request_handler,
|
||||
nbtsrv->bcast_interface);
|
||||
|
||||
/* start the process of registering our names on all interfaces */
|
||||
nbt_register_names(nbtsrv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,14 +20,30 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "libcli/nbt/libnbt.h"
|
||||
|
||||
/*
|
||||
a list of our registered names on each interface
|
||||
*/
|
||||
struct nbt_iface_name {
|
||||
struct nbt_iface_name *next, *prev;
|
||||
struct nbt_interface *iface;
|
||||
struct nbt_name name;
|
||||
uint16_t nb_flags;
|
||||
struct timeval registration_time;
|
||||
uint32_t ttl;
|
||||
};
|
||||
|
||||
|
||||
/* a list of network interfaces we are listening on */
|
||||
struct nbt_interface {
|
||||
struct nbt_interface *next, *prev;
|
||||
struct nbt_server *nbtsrv;
|
||||
const char *ip_address;
|
||||
const char *bcast_address;
|
||||
const char *netmask;
|
||||
struct nbt_name_socket *nbtsock;
|
||||
struct nbt_server *nbtsrv;
|
||||
struct nbt_iface_name *names;
|
||||
};
|
||||
|
||||
|
||||
@ -37,7 +53,11 @@ struct nbt_interface {
|
||||
struct nbt_server {
|
||||
struct task_server *task;
|
||||
|
||||
/* the list of local network interfaces */
|
||||
struct nbt_interface *interfaces;
|
||||
|
||||
/* broadcast interface used for receiving packets only */
|
||||
struct nbt_interface *bcast_interface;
|
||||
};
|
||||
|
||||
|
||||
|
38
source4/nbt_server/packet.c
Normal file
38
source4/nbt_server/packet.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
packet utility functions
|
||||
|
||||
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 "dlinklist.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
/*
|
||||
we received a badly formed packet - log it
|
||||
*/
|
||||
void nbt_bad_packet(struct nbt_name_packet *packet,
|
||||
const char *src_address, const char *reason)
|
||||
{
|
||||
DEBUG(2,("nbtd: bad packet '%s' from %s\n", reason, src_address));
|
||||
if (DEBUGLVL(5)) {
|
||||
NDR_PRINT_DEBUG(nbt_name_packet, packet);
|
||||
}
|
||||
}
|
||||
|
122
source4/nbt_server/query.c
Normal file
122
source4/nbt_server/query.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
answer name queries
|
||||
|
||||
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 "dlinklist.h"
|
||||
#include "system/network.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
/* check a condition on an incoming packet */
|
||||
#define NBT_ASSERT_PACKET(packet, src_address, test) do { \
|
||||
if (!(test)) { \
|
||||
nbt_bad_packet(packet, src_address, #test); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
send a name query reply
|
||||
*/
|
||||
static void nbt_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)
|
||||
{
|
||||
struct nbt_name_packet *packet;
|
||||
|
||||
packet = talloc_zero(nbtsock, struct nbt_name_packet);
|
||||
if (packet == NULL) return;
|
||||
|
||||
packet->name_trn_id = request_packet->name_trn_id;
|
||||
packet->ancount = 1;
|
||||
packet->operation =
|
||||
NBT_FLAG_REPLY |
|
||||
NBT_OPCODE_QUERY |
|
||||
NBT_FLAG_AUTHORITIVE |
|
||||
NBT_FLAG_RECURSION_DESIRED |
|
||||
NBT_FLAG_RECURSION_AVAIL;
|
||||
|
||||
packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
|
||||
if (packet->answers == NULL) goto failed;
|
||||
|
||||
packet->answers[0].name = *name;
|
||||
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);
|
||||
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 = htonl(inet_addr(address));
|
||||
|
||||
DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n",
|
||||
name->name, name->type, src_address, address, src_port));
|
||||
|
||||
nbt_name_reply_send(nbtsock, src_address, src_port, packet);
|
||||
|
||||
failed:
|
||||
talloc_free(packet);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
answer a name query
|
||||
*/
|
||||
void nbt_request_query(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
struct nbt_interface *iface;
|
||||
struct nbt_iface_name *iname;
|
||||
struct nbt_name *name;
|
||||
|
||||
/* if its a WINS query then direct to our WINS server */
|
||||
if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
|
||||
!(packet->operation & NBT_FLAG_BROADCAST)) {
|
||||
nbt_query_wins(nbtsock, packet, src_address, src_port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the interface for this query */
|
||||
iface = nbt_iface_find(nbtsock, src_address);
|
||||
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
|
||||
NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
|
||||
|
||||
/* see if we have the requested name on this interface */
|
||||
name = &packet->questions[0].name;
|
||||
|
||||
iname = nbt_find_iname(iface, name, NBT_NM_ACTIVE);
|
||||
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;
|
||||
}
|
||||
|
||||
nbt_name_query_reply(nbtsock, packet, src_address, src_port,
|
||||
&iname->name, iname->ttl, iname->nb_flags,
|
||||
iface->ip_address);
|
||||
}
|
161
source4/nbt_server/register.c
Normal file
161
source4/nbt_server/register.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
register our names
|
||||
|
||||
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 "dlinklist.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
/*
|
||||
start a timer to refresh this name
|
||||
*/
|
||||
static void nbt_start_refresh_timer(struct nbt_iface_name *iname)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
a name registration has completed
|
||||
*/
|
||||
static void nbt_register_handler(struct nbt_name_request *req)
|
||||
{
|
||||
struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
|
||||
NTSTATUS status;
|
||||
struct nbt_name_register io;
|
||||
|
||||
status = nbt_name_register_recv(req, iname, &io);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
|
||||
/* good - nobody complained about our registration */
|
||||
iname->nb_flags |= NBT_NM_ACTIVE;
|
||||
DEBUG(3,("Registered %s<%02x> on interface %s\n",
|
||||
iname->name.name, iname->name.type, iname->iface->bcast_address));
|
||||
nbt_start_refresh_timer(iname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1,("Error registering %s<%02x> on interface %s - %s\n",
|
||||
iname->name.name, iname->name.type, iname->iface->bcast_address,
|
||||
nt_errstr(status)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* someone must have replied with an objection! */
|
||||
iname->nb_flags |= NBT_NM_CONFLICT;
|
||||
|
||||
DEBUG(1,("Name conflict registering %s<%02x> on interface %s - rcode %d from %s for %s\n",
|
||||
iname->name.name, iname->name.type, iname->iface->bcast_address,
|
||||
io.out.rcode, io.out.reply_from, io.out.reply_addr));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
register a name on a network interface
|
||||
*/
|
||||
static void nbt_register_name_iface(struct nbt_interface *iface,
|
||||
const char *name, enum nbt_name_type type,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_iface_name *iname;
|
||||
const char *scope = lp_netbios_scope();
|
||||
struct nbt_name_register io;
|
||||
struct nbt_name_request *req;
|
||||
|
||||
iname = talloc(iface, struct nbt_iface_name);
|
||||
if (!iname) return;
|
||||
|
||||
iname->iface = iface;
|
||||
iname->name.name = talloc_strdup(iname, name);
|
||||
iname->name.type = type;
|
||||
if (scope && *scope) {
|
||||
iname->name.scope = talloc_strdup(iname, scope);
|
||||
} else {
|
||||
iname->name.scope = NULL;
|
||||
}
|
||||
iname->nb_flags = nb_flags;
|
||||
iname->ttl = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
|
||||
iname->registration_time = timeval_zero();
|
||||
|
||||
DLIST_ADD(iface->names, iname);
|
||||
|
||||
if (nb_flags & NBT_NM_PERMANENT) {
|
||||
/* permanent names are not announced and are immediately active */
|
||||
iname->nb_flags |= NBT_NM_ACTIVE;
|
||||
iname->ttl = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup a broadcast name registration request */
|
||||
io.in.name = iname->name;
|
||||
io.in.dest_addr = iface->bcast_address;
|
||||
io.in.address = iface->ip_address;
|
||||
io.in.nb_flags = nb_flags;
|
||||
io.in.register_demand = False;
|
||||
io.in.broadcast = True;
|
||||
io.in.ttl = iname->ttl;
|
||||
io.in.timeout = 1;
|
||||
|
||||
req = nbt_name_register_send(iface->nbtsock, &io);
|
||||
if (req == NULL) return;
|
||||
|
||||
req->async.fn = nbt_register_handler;
|
||||
req->async.private = iname;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
register one name on all our interfaces
|
||||
*/
|
||||
static void nbt_register_name(struct nbt_server *nbtsrv,
|
||||
const char *name, enum nbt_name_type type,
|
||||
uint16_t nb_flags)
|
||||
{
|
||||
struct nbt_interface *iface;
|
||||
|
||||
/* register with all the local interfaces */
|
||||
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
|
||||
nbt_register_name_iface(iface, name, type, nb_flags);
|
||||
}
|
||||
|
||||
/* register on our general broadcast interface as a permanent name */
|
||||
nbt_register_name_iface(nbtsrv->bcast_interface, name, type, nb_flags | NBT_NM_PERMANENT);
|
||||
|
||||
/* TODO: register with our WINS servers */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
register our names on all interfaces
|
||||
*/
|
||||
void nbt_register_names(struct nbt_server *nbtsrv)
|
||||
{
|
||||
uint16_t nb_flags = NBT_NODE_M;
|
||||
|
||||
/* note that we don't initially mark the names "ACTIVE". They are
|
||||
marked active once registration is successful */
|
||||
nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_CLIENT, nb_flags);
|
||||
nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_USER, nb_flags);
|
||||
nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_SERVER, nb_flags);
|
||||
nbt_register_name(nbtsrv, lp_workgroup(), NBT_NAME_CLIENT, nb_flags | NBT_NM_GROUP);
|
||||
nbt_register_name(nbtsrv, lp_workgroup(), NBT_NAME_SERVER, nb_flags | NBT_NM_GROUP);
|
||||
nbt_register_name(nbtsrv, "__SAMBA__", NBT_NAME_CLIENT, nb_flags | NBT_NM_PERMANENT);
|
||||
nbt_register_name(nbtsrv, "__SAMBA__", NBT_NAME_SERVER, nb_flags | NBT_NM_PERMANENT);
|
||||
}
|
35
source4/nbt_server/winsserver.c
Normal file
35
source4/nbt_server/winsserver.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
core wins server handling
|
||||
|
||||
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 "dlinklist.h"
|
||||
#include "nbt_server/nbt_server.h"
|
||||
|
||||
/*
|
||||
answer a name query
|
||||
*/
|
||||
void nbt_query_wins(struct nbt_name_socket *nbtsock,
|
||||
struct nbt_name_packet *packet,
|
||||
const char *src_address, int src_port)
|
||||
{
|
||||
DEBUG(0,("WINS query from %s\n", src_address));
|
||||
}
|
@ -141,6 +141,7 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
|
||||
{
|
||||
struct nbt_name_query io;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
|
||||
io.in.name.name = node_name;
|
||||
io.in.name.type = node_type;
|
||||
@ -151,14 +152,16 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
|
||||
io.in.timeout = 3;
|
||||
|
||||
status = nbt_name_query(nbtsock, nbtsock, &io);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
for (i=0;i<io.out.num_addrs;i++) {
|
||||
printf("%s %s<%02x>\n",
|
||||
io.out.reply_addr,
|
||||
io.out.reply_addrs[i],
|
||||
io.out.name.name,
|
||||
io.out.name.type);
|
||||
if (options.node_status) {
|
||||
do_node_status(nbtsock, io.out.reply_addr);
|
||||
}
|
||||
}
|
||||
if (options.node_status && io.out.num_addrs > 0) {
|
||||
do_node_status(nbtsock, io.out.reply_addrs[0]);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
Loading…
Reference in New Issue
Block a user