mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
Fix the character set handling properly in nmbd. Also fix bug where
iconv wasn't re-initialised on reading of "charset" parameters. This caused workgroup name to be set incorrectly if it contained an extended character. Jeremy.
This commit is contained in:
parent
e855dc8c91
commit
84ae44678a
@ -825,8 +825,7 @@ void make_nmb_name( struct nmb_name *n, const char *name, int type)
|
||||
memset( (char *)n, '\0', sizeof(struct nmb_name) );
|
||||
push_ascii(n->name, name, sizeof(n->name), STR_TERMINATE|STR_UPPER);
|
||||
n->name_type = (unsigned int)type & 0xFF;
|
||||
StrnCpy( n->scope, global_scope(), 63 );
|
||||
strupper_m( n->scope );
|
||||
push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -26,27 +26,26 @@
|
||||
|
||||
static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
|
||||
{
|
||||
int name_type = question->name_type;
|
||||
char *qname = question->name;
|
||||
|
||||
|
||||
if (!addr.s_addr) {
|
||||
/* add the fail to WINS cache of names. give it 1 hour in the cache */
|
||||
DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
|
||||
(void)add_name_to_subnet( wins_server_subnet, qname, name_type,
|
||||
NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
|
||||
return( NULL );
|
||||
}
|
||||
int name_type = question->name_type;
|
||||
nstring qname;
|
||||
|
||||
/* add it to our WINS cache of names. give it 2 hours in the cache */
|
||||
DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
|
||||
pull_ascii_nstring(qname, question->name);
|
||||
|
||||
if (!addr.s_addr) {
|
||||
/* add the fail to WINS cache of names. give it 1 hour in the cache */
|
||||
DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
|
||||
(void)add_name_to_subnet( wins_server_subnet, qname, name_type,
|
||||
NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( add_name_to_subnet( wins_server_subnet, qname, name_type,
|
||||
/* add it to our WINS cache of names. give it 2 hours in the cache */
|
||||
DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
|
||||
|
||||
return( add_name_to_subnet( wins_server_subnet, qname, name_type,
|
||||
NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef SYNC_DNS
|
||||
|
||||
static int fd_in = -1, fd_out = -1;
|
||||
@ -70,6 +69,7 @@ static struct packet_struct *dns_current;
|
||||
return the fd used to gather async dns replies. This is added to the select
|
||||
loop
|
||||
****************************************************************************/
|
||||
|
||||
int asyncdns_fd(void)
|
||||
{
|
||||
return fd_in;
|
||||
@ -110,7 +110,7 @@ static void asyncdns_process(void)
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
_exit(0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -224,10 +224,10 @@ void run_dns_queue(void)
|
||||
if (query_current(&r)) {
|
||||
DEBUG(3,("DNS calling send_wins_name_query_response\n"));
|
||||
in_dns = 1;
|
||||
if(namerec == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, dns_current, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0,dns_current,namerec);
|
||||
if(namerec == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, dns_current, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0,dns_current,namerec);
|
||||
in_dns = 0;
|
||||
}
|
||||
|
||||
@ -245,10 +245,10 @@ void run_dns_queue(void)
|
||||
if (nmb_name_equal(question, &r.name)) {
|
||||
DEBUG(3,("DNS calling send_wins_name_query_response\n"));
|
||||
in_dns = 1;
|
||||
if(namerec == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, p, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0,p,namerec);
|
||||
if(namerec == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, p, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0,p,namerec);
|
||||
in_dns = 0;
|
||||
p->locked = False;
|
||||
|
||||
@ -269,7 +269,8 @@ void run_dns_queue(void)
|
||||
if (dns_queue) {
|
||||
dns_current = dns_queue;
|
||||
dns_queue = dns_queue->next;
|
||||
if (dns_queue) dns_queue->prev = NULL;
|
||||
if (dns_queue)
|
||||
dns_queue->prev = NULL;
|
||||
dns_current->next = NULL;
|
||||
|
||||
if (!write_child(dns_current)) {
|
||||
@ -277,12 +278,12 @@ void run_dns_queue(void)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
queue a DNS query
|
||||
****************************************************************************/
|
||||
|
||||
BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
|
||||
struct name_record **n)
|
||||
{
|
||||
@ -315,11 +316,14 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
|
||||
/***************************************************************************
|
||||
we use this when we can't do async DNS lookups
|
||||
****************************************************************************/
|
||||
|
||||
BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
|
||||
struct name_record **n)
|
||||
{
|
||||
char *qname = question->name;
|
||||
struct in_addr dns_ip;
|
||||
nstring qname;
|
||||
|
||||
pull_ascii_nstring(qname, question->name);
|
||||
|
||||
DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));
|
||||
|
||||
@ -332,18 +336,19 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
|
||||
BlockSignals(True, SIGTERM);
|
||||
|
||||
*n = add_dns_result(question, dns_ip);
|
||||
if(*n == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, p, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0, p, *n);
|
||||
if(*n == NULL)
|
||||
send_wins_name_query_response(NAM_ERR, p, NULL);
|
||||
else
|
||||
send_wins_name_query_response(0, p, *n);
|
||||
return False;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
With sync dns there is no child to kill on SIGTERM.
|
||||
****************************************************************************/
|
||||
|
||||
void kill_async_dns_child(void)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -231,7 +231,8 @@ static BOOL reload_interfaces(time_t t)
|
||||
DEBUG(2,("Found new interface %s\n",
|
||||
inet_ntoa(iface->ip)));
|
||||
subrec = make_normal_subnet(iface);
|
||||
if (subrec) register_my_workgroup_one_subnet(subrec);
|
||||
if (subrec)
|
||||
register_my_workgroup_one_subnet(subrec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ static void send_election_dgram(struct subnet_record *subrec, const char *workgr
|
||||
p += 13;
|
||||
fstrcpy(srv_name, server_name);
|
||||
strupper_m(srv_name);
|
||||
/* The following call does UNIX -> DOS charset conversion. */
|
||||
pstrcpy_base(p, srv_name, outbuf);
|
||||
p = skip_string(p,1);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -33,18 +33,18 @@ Send a name release response.
|
||||
|
||||
static void send_name_release_response(int rcode, struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
char rdata[6];
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
char rdata[6];
|
||||
|
||||
memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
|
||||
memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
|
||||
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
rcode, /* Result code. */
|
||||
NMB_REL, /* nmbd type code. */
|
||||
NMB_NAME_RELEASE_OPCODE, /* opcode. */
|
||||
0, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
6); /* data length. */
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
rcode, /* Result code. */
|
||||
NMB_REL, /* nmbd type code. */
|
||||
NMB_NAME_RELEASE_OPCODE, /* opcode. */
|
||||
0, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
6); /* data length. */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -55,76 +55,74 @@ Ignore it if it's not one of our names.
|
||||
void process_name_release_request(struct subnet_record *subrec,
|
||||
struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct in_addr owner_ip;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
|
||||
BOOL group = (nb_flags & NB_GROUP) ? True : False;
|
||||
struct name_record *namerec;
|
||||
int rcode = 0;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct in_addr owner_ip;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
nstring qname;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
|
||||
BOOL group = (nb_flags & NB_GROUP) ? True : False;
|
||||
struct name_record *namerec;
|
||||
int rcode = 0;
|
||||
|
||||
putip((char *)&owner_ip,&nmb->additional->rdata[2]);
|
||||
putip((char *)&owner_ip,&nmb->additional->rdata[2]);
|
||||
|
||||
if(!bcast)
|
||||
{
|
||||
/* We should only get broadcast name release packets here.
|
||||
Anyone trying to release unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_release_request: unicast name release request \
|
||||
if(!bcast) {
|
||||
/* We should only get broadcast name release packets here.
|
||||
Anyone trying to release unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_release_request: unicast name release request \
|
||||
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
|
||||
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
|
||||
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
|
||||
|
||||
send_name_release_response(FMT_ERR, p);
|
||||
return;
|
||||
}
|
||||
send_name_release_response(FMT_ERR, p);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(3,("process_name_release_request: Name release on name %s, \
|
||||
DEBUG(3,("process_name_release_request: Name release on name %s, \
|
||||
subnet %s from owner IP %s\n",
|
||||
nmb_namestr(&nmb->question.question_name),
|
||||
subrec->subnet_name, inet_ntoa(owner_ip)));
|
||||
nmb_namestr(&nmb->question.question_name),
|
||||
subrec->subnet_name, inet_ntoa(owner_ip)));
|
||||
|
||||
/* If someone is releasing a broadcast group name, just ignore it. */
|
||||
if( group && !ismyip(owner_ip) )
|
||||
return;
|
||||
/* If someone is releasing a broadcast group name, just ignore it. */
|
||||
if( group && !ismyip(owner_ip) )
|
||||
return;
|
||||
|
||||
/*
|
||||
* Code to work around a bug in FTP OnNet software NBT implementation.
|
||||
* They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
|
||||
* names and *don't set the group bit* !!!!!
|
||||
*/
|
||||
/*
|
||||
* Code to work around a bug in FTP OnNet software NBT implementation.
|
||||
* They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
|
||||
* names and *don't set the group bit* !!!!!
|
||||
*/
|
||||
|
||||
if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) &&
|
||||
((question->name_type == 0x0) || (question->name_type == 0x1e)))
|
||||
{
|
||||
DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
|
||||
pull_ascii_nstring(qname, question->name);
|
||||
if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) &&
|
||||
((question->name_type == 0x0) || (question->name_type == 0x1e))) {
|
||||
DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
|
||||
group release name %s from IP %s on subnet %s with no group bit set.\n",
|
||||
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
|
||||
return;
|
||||
}
|
||||
nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
|
||||
return;
|
||||
}
|
||||
|
||||
namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
|
||||
namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
|
||||
|
||||
/* We only care about someone trying to release one of our names. */
|
||||
if( namerec
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME) ) )
|
||||
{
|
||||
rcode = ACT_ERR;
|
||||
DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
|
||||
/* We only care about someone trying to release one of our names. */
|
||||
if( namerec && ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME) ) ) {
|
||||
rcode = ACT_ERR;
|
||||
DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
|
||||
on subnet %s being rejected as it is one of our names.\n",
|
||||
nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
|
||||
}
|
||||
nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
|
||||
}
|
||||
|
||||
if(rcode == 0)
|
||||
return;
|
||||
if(rcode == 0)
|
||||
return;
|
||||
|
||||
/* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
|
||||
send_name_release_response(rcode, p);
|
||||
/* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
|
||||
send_name_release_response(rcode, p);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -133,18 +131,18 @@ Send a name registration response.
|
||||
|
||||
static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
char rdata[6];
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
char rdata[6];
|
||||
|
||||
memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
|
||||
memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
|
||||
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
rcode, /* Result code. */
|
||||
NMB_REG, /* nmbd type code. */
|
||||
NMB_NAME_REG_OPCODE, /* opcode. */
|
||||
ttl, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
6); /* data length. */
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
rcode, /* Result code. */
|
||||
NMB_REG, /* nmbd type code. */
|
||||
NMB_NAME_REG_OPCODE, /* opcode. */
|
||||
ttl, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
6); /* data length. */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -154,38 +152,34 @@ Process a name refresh request on a broadcast subnet.
|
||||
void process_name_refresh_request(struct subnet_record *subrec,
|
||||
struct packet_struct *p)
|
||||
{
|
||||
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
struct in_addr from_ip;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
struct in_addr from_ip;
|
||||
|
||||
putip((char *)&from_ip,&nmb->additional->rdata[2]);
|
||||
putip((char *)&from_ip,&nmb->additional->rdata[2]);
|
||||
|
||||
if(!bcast)
|
||||
{
|
||||
/* We should only get broadcast name refresh packets here.
|
||||
Anyone trying to refresh unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_refresh_request: unicast name registration request \
|
||||
if(!bcast) {
|
||||
/* We should only get broadcast name refresh packets here.
|
||||
Anyone trying to refresh unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_refresh_request: unicast name registration request \
|
||||
received for name %s from IP %s on subnet %s.\n",
|
||||
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
DEBUG(0,("Error - should be sent to WINS server\n"));
|
||||
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
DEBUG(0,("Error - should be sent to WINS server\n"));
|
||||
|
||||
send_name_registration_response(FMT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
send_name_registration_response(FMT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Just log a message. We really don't care about broadcast name
|
||||
refreshes. */
|
||||
/* Just log a message. We really don't care about broadcast name refreshes. */
|
||||
|
||||
DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
|
||||
DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
|
||||
IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -195,92 +189,83 @@ Process a name registration request on a broadcast subnet.
|
||||
void process_name_registration_request(struct subnet_record *subrec,
|
||||
struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
|
||||
BOOL group = (nb_flags & NB_GROUP) ? True : False;
|
||||
struct name_record *namerec = NULL;
|
||||
int ttl = nmb->additional->ttl;
|
||||
struct in_addr from_ip;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question = &nmb->question.question_name;
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
|
||||
BOOL group = (nb_flags & NB_GROUP) ? True : False;
|
||||
struct name_record *namerec = NULL;
|
||||
int ttl = nmb->additional->ttl;
|
||||
struct in_addr from_ip;
|
||||
|
||||
putip((char *)&from_ip,&nmb->additional->rdata[2]);
|
||||
putip((char *)&from_ip,&nmb->additional->rdata[2]);
|
||||
|
||||
if(!bcast)
|
||||
{
|
||||
/* We should only get broadcast name registration packets here.
|
||||
Anyone trying to register unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_registration_request: unicast name registration request \
|
||||
if(!bcast) {
|
||||
/* We should only get broadcast name registration packets here.
|
||||
Anyone trying to register unicast should be going to a WINS
|
||||
server. If the code gets here, then either we are not a wins
|
||||
server and they sent it anyway, or we are a WINS server and
|
||||
the request was malformed. Either way, log an error here.
|
||||
and send an error reply back.
|
||||
*/
|
||||
DEBUG(0,("process_name_registration_request: unicast name registration request \
|
||||
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
|
||||
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
|
||||
send_name_registration_response(FMT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
send_name_registration_response(FMT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(3,("process_name_registration_request: Name registration for name %s \
|
||||
DEBUG(3,("process_name_registration_request: Name registration for name %s \
|
||||
IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
|
||||
|
||||
/* See if the name already exists. */
|
||||
namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
|
||||
/* See if the name already exists. */
|
||||
namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
|
||||
|
||||
/*
|
||||
* If the name being registered exists and is a WINS_PROXY_NAME
|
||||
* then delete the WINS proxy name entry so we don't reply erroneously
|
||||
* later to queries.
|
||||
*/
|
||||
/*
|
||||
* If the name being registered exists and is a WINS_PROXY_NAME
|
||||
* then delete the WINS proxy name entry so we don't reply erroneously
|
||||
* later to queries.
|
||||
*/
|
||||
|
||||
if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
|
||||
{
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
namerec = NULL;
|
||||
}
|
||||
if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
namerec = NULL;
|
||||
}
|
||||
|
||||
if (!group)
|
||||
{
|
||||
/* Unique name. */
|
||||
if (!group) {
|
||||
/* Unique name. */
|
||||
|
||||
if( (namerec != NULL)
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME)
|
||||
|| NAME_GROUP(namerec) ) )
|
||||
{
|
||||
/* No-one can register one of Samba's names, nor can they
|
||||
register a name that's a group name as a unique name */
|
||||
if( (namerec != NULL)
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME)
|
||||
|| NAME_GROUP(namerec) ) ) {
|
||||
/* No-one can register one of Samba's names, nor can they
|
||||
register a name that's a group name as a unique name */
|
||||
|
||||
send_name_registration_response(ACT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
else if(namerec != NULL)
|
||||
{
|
||||
/* Update the namelist record with the new information. */
|
||||
namerec->data.ip[0] = from_ip;
|
||||
update_name_ttl(namerec, ttl);
|
||||
send_name_registration_response(ACT_ERR, 0, p);
|
||||
return;
|
||||
} else if(namerec != NULL) {
|
||||
/* Update the namelist record with the new information. */
|
||||
namerec->data.ip[0] = from_ip;
|
||||
update_name_ttl(namerec, ttl);
|
||||
|
||||
DEBUG(3,("process_name_registration_request: Updated name record %s \
|
||||
DEBUG(3,("process_name_registration_request: Updated name record %s \
|
||||
with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Group name. */
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Group name. */
|
||||
|
||||
if( (namerec != NULL)
|
||||
&& !NAME_GROUP(namerec)
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME) ) )
|
||||
{
|
||||
/* Disallow group names when we have a unique name. */
|
||||
send_name_registration_response(ACT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( (namerec != NULL)
|
||||
&& !NAME_GROUP(namerec)
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME) ) ) {
|
||||
/* Disallow group names when we have a unique name. */
|
||||
send_name_registration_response(ACT_ERR, 0, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -290,147 +275,150 @@ We put our own names first, then in alphabetical order.
|
||||
|
||||
static int status_compare(char *n1,char *n2)
|
||||
{
|
||||
int l1,l2,l3;
|
||||
nstring name1, name2;
|
||||
int l1,l2,l3;
|
||||
|
||||
/* It's a bit tricky because the names are space padded */
|
||||
for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
|
||||
for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
|
||||
l3 = strlen(global_myname());
|
||||
pull_ascii_nstring(name1, n1);
|
||||
pull_ascii_nstring(name2, n2);
|
||||
n1 = name1;
|
||||
n2 = name2;
|
||||
|
||||
if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 &&
|
||||
(l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
|
||||
return -1;
|
||||
/* It's a bit tricky because the names are space padded */
|
||||
for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
|
||||
;
|
||||
for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
|
||||
;
|
||||
l3 = strlen(global_myname());
|
||||
|
||||
if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 &&
|
||||
(l1!=l3 || strncmp(n1,global_myname(),l3) != 0))
|
||||
return 1;
|
||||
if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 &&
|
||||
(l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
|
||||
return -1;
|
||||
|
||||
return memcmp(n1,n2,18);
|
||||
if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 &&
|
||||
(l1!=l3 || strncmp(n1,global_myname(),l3) != 0))
|
||||
return 1;
|
||||
|
||||
return memcmp(n1,n2,sizeof(nstring));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Process a node status query
|
||||
****************************************************************************/
|
||||
|
||||
void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
char *qname = nmb->question.question_name.name;
|
||||
int ques_type = nmb->question.question_name.name_type;
|
||||
char rdata[MAX_DGRAM_SIZE];
|
||||
char *countptr, *buf, *bufend, *buf0;
|
||||
int names_added,i;
|
||||
struct name_record *namerec;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
nstring qname;
|
||||
int ques_type = nmb->question.question_name.name_type;
|
||||
char rdata[MAX_DGRAM_SIZE];
|
||||
char *countptr, *buf, *bufend, *buf0;
|
||||
int names_added,i;
|
||||
struct name_record *namerec;
|
||||
|
||||
DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
|
||||
subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
|
||||
subrec->subnet_name));
|
||||
pull_ascii_nstring(qname, nmb->question.question_name.name);
|
||||
|
||||
if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
|
||||
FIND_SELF_NAME)) == 0)
|
||||
{
|
||||
DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
|
||||
DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
|
||||
subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
|
||||
|
||||
if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) {
|
||||
DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
|
||||
subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
|
||||
inet_ntoa(p->ip), subrec->subnet_name));
|
||||
inet_ntoa(p->ip), subrec->subnet_name));
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* this is not an exact calculation. the 46 is for the stats buffer
|
||||
and the 60 is to leave room for the header etc */
|
||||
bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
|
||||
countptr = buf = rdata;
|
||||
buf += 1;
|
||||
buf0 = buf;
|
||||
/* this is not an exact calculation. the 46 is for the stats buffer
|
||||
and the 60 is to leave room for the header etc */
|
||||
bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
|
||||
countptr = buf = rdata;
|
||||
buf += 1;
|
||||
buf0 = buf;
|
||||
|
||||
names_added = 0;
|
||||
names_added = 0;
|
||||
|
||||
namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
|
||||
while (buf < bufend)
|
||||
{
|
||||
if( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == PERMANENT_NAME) )
|
||||
{
|
||||
int name_type = namerec->name.name_type;
|
||||
|
||||
if (!strequal(namerec->name.name,"*") &&
|
||||
!strequal(namerec->name.name,"__SAMBA__") &&
|
||||
(name_type < 0x1b || name_type >= 0x20 ||
|
||||
ques_type < 0x1b || ques_type >= 0x20 ||
|
||||
strequal(qname, namerec->name.name)))
|
||||
{
|
||||
/* Start with the name. */
|
||||
memset(buf,'\0',18);
|
||||
slprintf(buf, 17, "%-15.15s",namerec->name.name);
|
||||
strupper_m(buf);
|
||||
|
||||
/* Put the name type and netbios flags in the buffer. */
|
||||
buf[15] = name_type;
|
||||
set_nb_flags( &buf[16],namerec->data.nb_flags );
|
||||
buf[16] |= NB_ACTIVE; /* all our names are active */
|
||||
while (buf < bufend) {
|
||||
if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
|
||||
int name_type = namerec->name.name_type;
|
||||
nstring name;
|
||||
|
||||
buf += 18;
|
||||
pull_ascii_nstring(name, namerec->name.name);
|
||||
strupper_m(name);
|
||||
if (!strequal(name,"*") &&
|
||||
!strequal(name,"__SAMBA__") &&
|
||||
(name_type < 0x1b || name_type >= 0x20 ||
|
||||
ques_type < 0x1b || ques_type >= 0x20 ||
|
||||
strequal(qname, name))) {
|
||||
/* Start with the name. */
|
||||
nstring tmp_name;
|
||||
memset(tmp_name,'\0',sizeof(tmp_name));
|
||||
snprintf(tmp_name, sizeof(tmp_name), "%-15.15s",name);
|
||||
push_ascii_nstring(buf, tmp_name);
|
||||
|
||||
names_added++;
|
||||
}
|
||||
}
|
||||
/* Put the name type and netbios flags in the buffer. */
|
||||
|
||||
/* Remove duplicate names. */
|
||||
if (names_added > 1) {
|
||||
qsort( buf0, names_added, 18, QSORT_CAST status_compare );
|
||||
}
|
||||
buf[15] = name_type;
|
||||
set_nb_flags( &buf[16],namerec->data.nb_flags );
|
||||
buf[16] |= NB_ACTIVE; /* all our names are active */
|
||||
|
||||
for( i=1; i < names_added ; i++ )
|
||||
{
|
||||
if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0)
|
||||
{
|
||||
names_added--;
|
||||
if (names_added == i)
|
||||
break;
|
||||
memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
buf += 18;
|
||||
|
||||
buf = buf0 + 18*names_added;
|
||||
names_added++;
|
||||
}
|
||||
}
|
||||
|
||||
namerec = (struct name_record *)ubi_trNext( namerec );
|
||||
/* Remove duplicate names. */
|
||||
if (names_added > 1) {
|
||||
qsort( buf0, names_added, 18, QSORT_CAST status_compare );
|
||||
}
|
||||
|
||||
if (!namerec)
|
||||
{
|
||||
/* End of the subnet specific name list. Now
|
||||
add the names on the unicast subnet . */
|
||||
struct subnet_record *uni_subrec = unicast_subnet;
|
||||
for( i=1; i < names_added ; i++ ) {
|
||||
if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
|
||||
names_added--;
|
||||
if (names_added == i)
|
||||
break;
|
||||
memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (uni_subrec != subrec)
|
||||
{
|
||||
subrec = uni_subrec;
|
||||
namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
}
|
||||
}
|
||||
if (!namerec)
|
||||
break;
|
||||
buf = buf0 + 18*names_added;
|
||||
|
||||
}
|
||||
namerec = (struct name_record *)ubi_trNext( namerec );
|
||||
|
||||
if (!namerec) {
|
||||
/* End of the subnet specific name list. Now
|
||||
add the names on the unicast subnet . */
|
||||
struct subnet_record *uni_subrec = unicast_subnet;
|
||||
|
||||
if (uni_subrec != subrec) {
|
||||
subrec = uni_subrec;
|
||||
namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
}
|
||||
}
|
||||
if (!namerec)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
SCVAL(countptr,0,names_added);
|
||||
SCVAL(countptr,0,names_added);
|
||||
|
||||
/* We don't send any stats as they could be used to attack
|
||||
the protocol. */
|
||||
memset(buf,'\0',46);
|
||||
/* We don't send any stats as they could be used to attack
|
||||
the protocol. */
|
||||
memset(buf,'\0',46);
|
||||
|
||||
buf += 46;
|
||||
buf += 46;
|
||||
|
||||
/* Send a NODE STATUS RESPONSE */
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
0, /* Result code. */
|
||||
NMB_STATUS, /* nmbd type code. */
|
||||
NMB_NAME_QUERY_OPCODE, /* opcode. */
|
||||
0, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
PTR_DIFF(buf,rdata)); /* data length. */
|
||||
/* Send a NODE STATUS RESPONSE */
|
||||
reply_netbios_packet(p, /* Packet to reply to. */
|
||||
0, /* Result code. */
|
||||
NMB_STATUS, /* nmbd type code. */
|
||||
NMB_NAME_QUERY_OPCODE, /* opcode. */
|
||||
0, /* ttl. */
|
||||
rdata, /* data to send. */
|
||||
PTR_DIFF(buf,rdata)); /* data length. */
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,50 +28,46 @@
|
||||
/****************************************************************************
|
||||
Load a lmhosts file.
|
||||
****************************************************************************/
|
||||
|
||||
void load_lmhosts_file(char *fname)
|
||||
{
|
||||
pstring name;
|
||||
int name_type;
|
||||
struct in_addr ipaddr;
|
||||
XFILE *fp = startlmhosts( fname );
|
||||
pstring name;
|
||||
int name_type;
|
||||
struct in_addr ipaddr;
|
||||
XFILE *fp = startlmhosts( fname );
|
||||
|
||||
if (!fp) {
|
||||
DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
|
||||
fname, strerror(errno)));
|
||||
return;
|
||||
}
|
||||
if (!fp) {
|
||||
DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
|
||||
fname, strerror(errno)));
|
||||
return;
|
||||
}
|
||||
|
||||
while (getlmhostsent(fp, name, &name_type, &ipaddr) )
|
||||
{
|
||||
struct subnet_record *subrec = NULL;
|
||||
enum name_source source = LMHOSTS_NAME;
|
||||
while (getlmhostsent(fp, name, &name_type, &ipaddr) ) {
|
||||
struct subnet_record *subrec = NULL;
|
||||
enum name_source source = LMHOSTS_NAME;
|
||||
|
||||
/* We find a relevent subnet to put this entry on, then add it. */
|
||||
/* Go through all the broadcast subnets and see if the mask matches. */
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip))
|
||||
break;
|
||||
}
|
||||
/* We find a relevent subnet to put this entry on, then add it. */
|
||||
/* Go through all the broadcast subnets and see if the mask matches. */
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If none match add the name to the remote_broadcast_subnet. */
|
||||
if(subrec == NULL)
|
||||
subrec = remote_broadcast_subnet;
|
||||
/* If none match add the name to the remote_broadcast_subnet. */
|
||||
if(subrec == NULL)
|
||||
subrec = remote_broadcast_subnet;
|
||||
|
||||
if(name_type == -1)
|
||||
{
|
||||
/* Add the (0) and (0x20) names directly into the namelist for this subnet. */
|
||||
(void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
(void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add the given name type to the subnet namelist. */
|
||||
(void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
}
|
||||
}
|
||||
if(name_type == -1) {
|
||||
/* Add the (0) and (0x20) names directly into the namelist for this subnet. */
|
||||
(void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
(void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
} else {
|
||||
/* Add the given name type to the subnet namelist. */
|
||||
(void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
|
||||
}
|
||||
}
|
||||
|
||||
endlmhosts(fp);
|
||||
endlmhosts(fp);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -82,17 +78,16 @@ void load_lmhosts_file(char *fname)
|
||||
|
||||
BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
*namerecp = NULL;
|
||||
*namerecp = NULL;
|
||||
|
||||
if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname,
|
||||
FIND_ANY_NAME))==NULL)
|
||||
return False;
|
||||
if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, FIND_ANY_NAME))==NULL)
|
||||
return False;
|
||||
|
||||
if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME))
|
||||
return False;
|
||||
if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME))
|
||||
return False;
|
||||
|
||||
*namerecp = namerec;
|
||||
return True;
|
||||
*namerecp = namerec;
|
||||
return True;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -29,38 +29,40 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
|
||||
|
||||
/****************************************************************************
|
||||
Fail to become a Logon server on a subnet.
|
||||
****************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
static void become_logon_server_fail(struct subnet_record *subrec,
|
||||
struct response_record *rrec,
|
||||
struct nmb_name *fail_name)
|
||||
{
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
|
||||
struct server_record *servrec;
|
||||
nstring failname;
|
||||
struct work_record *work;
|
||||
struct server_record *servrec;
|
||||
|
||||
if(!work)
|
||||
{
|
||||
DEBUG(0,("become_logon_server_fail: Error - cannot find \
|
||||
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
|
||||
return;
|
||||
}
|
||||
pull_ascii_nstring(failname, fail_name->name);
|
||||
work = find_workgroup_on_subnet(subrec, failname);
|
||||
if(!work) {
|
||||
DEBUG(0,("become_logon_server_fail: Error - cannot find \
|
||||
workgroup %s on subnet %s\n", failname, subrec->subnet_name));
|
||||
return;
|
||||
}
|
||||
|
||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
||||
{
|
||||
DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \
|
||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
|
||||
DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \
|
||||
in workgroup %s on subnet %s\n",
|
||||
global_myname(), fail_name->name, subrec->subnet_name));
|
||||
work->log_state = LOGON_NONE;
|
||||
return;
|
||||
}
|
||||
global_myname(), failname, subrec->subnet_name));
|
||||
work->log_state = LOGON_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the state back to LOGON_NONE. */
|
||||
work->log_state = LOGON_NONE;
|
||||
/* Set the state back to LOGON_NONE. */
|
||||
work->log_state = LOGON_NONE;
|
||||
|
||||
servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL;
|
||||
servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL;
|
||||
|
||||
DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \
|
||||
DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \
|
||||
workgroup %s on subnet %s. Couldn't register name %s.\n",
|
||||
work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
|
||||
work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
|
||||
|
||||
}
|
||||
|
||||
@ -74,49 +76,51 @@ static void become_logon_server_success(struct subnet_record *subrec,
|
||||
uint16 nb_flags,
|
||||
int ttl, struct in_addr registered_ip)
|
||||
{
|
||||
struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
|
||||
struct server_record *servrec;
|
||||
nstring reg_name;
|
||||
struct work_record *work;
|
||||
struct server_record *servrec;
|
||||
|
||||
if(!work)
|
||||
{
|
||||
DEBUG(0,("become_logon_server_success: Error - cannot find \
|
||||
workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
|
||||
return;
|
||||
}
|
||||
pull_ascii_nstring(reg_name, registered_name->name);
|
||||
work = find_workgroup_on_subnet( subrec, reg_name);
|
||||
if(!work) {
|
||||
DEBUG(0,("become_logon_server_success: Error - cannot find \
|
||||
workgroup %s on subnet %s\n", reg_name, subrec->subnet_name));
|
||||
return;
|
||||
}
|
||||
|
||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
||||
{
|
||||
DEBUG(0,("become_logon_server_success: Error - cannot find server %s \
|
||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
|
||||
DEBUG(0,("become_logon_server_success: Error - cannot find server %s \
|
||||
in workgroup %s on subnet %s\n",
|
||||
global_myname(), registered_name->name, subrec->subnet_name));
|
||||
work->log_state = LOGON_NONE;
|
||||
return;
|
||||
}
|
||||
global_myname(), reg_name, subrec->subnet_name));
|
||||
work->log_state = LOGON_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the state in the workgroup structure. */
|
||||
work->log_state = LOGON_SRV; /* Become domain master. */
|
||||
/* Set the state in the workgroup structure. */
|
||||
work->log_state = LOGON_SRV; /* Become domain master. */
|
||||
|
||||
/* Update our server status. */
|
||||
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER);
|
||||
/* To allow Win95 policies to load we need to set type domain
|
||||
controller.
|
||||
*/
|
||||
servrec->serv.type |= SV_TYPE_DOMAIN_CTRL;
|
||||
/* Update our server status. */
|
||||
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER);
|
||||
/* To allow Win95 policies to load we need to set type domain
|
||||
controller.
|
||||
*/
|
||||
servrec->serv.type |= SV_TYPE_DOMAIN_CTRL;
|
||||
|
||||
/* Tell the namelist writer to write out a change. */
|
||||
subrec->work_changed = True;
|
||||
/* Tell the namelist writer to write out a change. */
|
||||
subrec->work_changed = True;
|
||||
|
||||
/*
|
||||
* Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address
|
||||
* for this subnet so we will respond to queries on this name.
|
||||
*/
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
make_nmb_name(&nmbname,lp_workgroup(),0x1c);
|
||||
insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c);
|
||||
}
|
||||
/*
|
||||
* Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address
|
||||
* for this subnet so we will respond to queries on this name.
|
||||
*/
|
||||
|
||||
DEBUG(0,("become_logon_server_success: Samba is now a logon server \
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
make_nmb_name(&nmbname,lp_workgroup(),0x1c);
|
||||
insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c);
|
||||
}
|
||||
|
||||
DEBUG(0,("become_logon_server_success: Samba is now a logon server \
|
||||
for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
|
||||
}
|
||||
|
||||
@ -128,45 +132,42 @@ for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
|
||||
static void become_logon_server(struct subnet_record *subrec,
|
||||
struct work_record *work)
|
||||
{
|
||||
DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \
|
||||
DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \
|
||||
on subnet %s\n", work->work_group,subrec->subnet_name));
|
||||
|
||||
DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n",
|
||||
work->work_group));
|
||||
work->log_state = LOGON_WAIT;
|
||||
DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n",
|
||||
work->work_group));
|
||||
work->log_state = LOGON_WAIT;
|
||||
|
||||
register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP,
|
||||
become_logon_server_success,
|
||||
become_logon_server_fail, NULL);
|
||||
register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP,
|
||||
become_logon_server_success,
|
||||
become_logon_server_fail, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Add the internet group <1c> logon names by unicast and broadcast.
|
||||
****************************************************************************/
|
||||
|
||||
void add_logon_names(void)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct subnet_record *subrec;
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
|
||||
if (work && (work->log_state == LOGON_NONE))
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
make_nmb_name(&nmbname,lp_workgroup(),0x1c);
|
||||
if (work && (work->log_state == LOGON_NONE)) {
|
||||
struct nmb_name nmbname;
|
||||
make_nmb_name(&nmbname,lp_workgroup(),0x1c);
|
||||
|
||||
if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
dbgtext( "add_domain_logon_names:\n" );
|
||||
dbgtext( "Attempting to become logon server " );
|
||||
dbgtext( "for workgroup %s ", lp_workgroup() );
|
||||
dbgtext( "on subnet %s\n", subrec->subnet_name );
|
||||
}
|
||||
become_logon_server(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
dbgtext( "add_domain_logon_names:\n" );
|
||||
dbgtext( "Attempting to become logon server " );
|
||||
dbgtext( "for workgroup %s ", lp_workgroup() );
|
||||
dbgtext( "on subnet %s\n", subrec->subnet_name );
|
||||
}
|
||||
become_logon_server(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -27,20 +27,21 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
|
||||
|
||||
/****************************************************************************
|
||||
Fail funtion when registering my netbios names.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
static void my_name_register_failed(struct subnet_record *subrec,
|
||||
struct response_record *rrec, struct nmb_name *nmbname)
|
||||
{
|
||||
DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n",
|
||||
nmb_namestr(nmbname), subrec->subnet_name));
|
||||
DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n",
|
||||
nmb_namestr(nmbname), subrec->subnet_name));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Add my workgroup and my given names to one subnet
|
||||
Also add the magic Samba names.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
void register_my_workgroup_one_subnet(struct subnet_record *subrec)
|
||||
{
|
||||
int i;
|
||||
@ -84,111 +85,104 @@ Exiting.\n", lp_workgroup(), subrec->subnet_name));
|
||||
static void insert_refresh_name_into_unicast( struct subnet_record *subrec,
|
||||
struct nmb_name *nmbname, uint16 nb_type )
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
if (!we_are_a_wins_client()) {
|
||||
insert_permanent_name_into_unicast(subrec, nmbname, nb_type);
|
||||
return;
|
||||
}
|
||||
if (!we_are_a_wins_client()) {
|
||||
insert_permanent_name_into_unicast(subrec, nmbname, nb_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
|
||||
{
|
||||
/* The name needs to be created on the unicast subnet. */
|
||||
(void)add_name_to_subnet( unicast_subnet, nmbname->name,
|
||||
nmbname->name_type, nb_type,
|
||||
MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The name already exists on the unicast subnet. Add our local
|
||||
IP for the given broadcast subnet to the name. */
|
||||
add_ip_to_name_record( namerec, subrec->myip);
|
||||
}
|
||||
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
|
||||
nstring name;
|
||||
pull_ascii_nstring(name, nmbname->name);
|
||||
/* The name needs to be created on the unicast subnet. */
|
||||
(void)add_name_to_subnet( unicast_subnet, name,
|
||||
nmbname->name_type, nb_type,
|
||||
MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip);
|
||||
} else {
|
||||
/* The name already exists on the unicast subnet. Add our local
|
||||
IP for the given broadcast subnet to the name. */
|
||||
add_ip_to_name_record( namerec, subrec->myip);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Add my workgroup and my given names to the subnet lists.
|
||||
Also add the magic Samba names.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
BOOL register_my_workgroup_and_names(void)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
int i;
|
||||
struct subnet_record *subrec;
|
||||
int i;
|
||||
|
||||
for(subrec = FIRST_SUBNET;
|
||||
subrec;
|
||||
subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
register_my_workgroup_one_subnet(subrec);
|
||||
}
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
register_my_workgroup_one_subnet(subrec);
|
||||
}
|
||||
|
||||
/* We still need to add the magic Samba
|
||||
names and the netbios names to the unicast subnet directly. This is
|
||||
to allow unicast node status requests and queries to still work
|
||||
in a broadcast only environment. */
|
||||
/* We still need to add the magic Samba
|
||||
names and the netbios names to the unicast subnet directly. This is
|
||||
to allow unicast node status requests and queries to still work
|
||||
in a broadcast only environment. */
|
||||
|
||||
add_samba_names_to_subnet(unicast_subnet);
|
||||
add_samba_names_to_subnet(unicast_subnet);
|
||||
|
||||
for (i=0; my_netbios_names(i); i++)
|
||||
{
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
/*
|
||||
* Ensure all the IP addresses are added if we are multihomed.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
for (i=0; my_netbios_names(i); i++) {
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
/*
|
||||
* Ensure all the IP addresses are added if we are multihomed.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x20);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x20);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x3);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x3);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x0);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
}
|
||||
}
|
||||
make_nmb_name(&nmbname, my_netbios_names(i),0x0);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet
|
||||
* also for the same reasons.
|
||||
*/
|
||||
/*
|
||||
* Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet
|
||||
* also for the same reasons.
|
||||
*/
|
||||
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
/*
|
||||
* Ensure all the IP addresses are added if we are multihomed.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
/*
|
||||
* Ensure all the IP addresses are added if we are multihomed.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
|
||||
make_nmb_name(&nmbname, lp_workgroup(), 0x0);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
|
||||
make_nmb_name(&nmbname, lp_workgroup(), 0x0);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
|
||||
|
||||
make_nmb_name(&nmbname, lp_workgroup(), 0x1e);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
|
||||
}
|
||||
make_nmb_name(&nmbname, lp_workgroup(), 0x1e);
|
||||
insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to add the Samba names to the remote broadcast subnet,
|
||||
* as NT 4.x does directed broadcast requests to the *<0x0> name.
|
||||
*/
|
||||
add_samba_names_to_subnet(remote_broadcast_subnet);
|
||||
/*
|
||||
* We need to add the Samba names to the remote broadcast subnet,
|
||||
* as NT 4.x does directed broadcast requests to the *<0x0> name.
|
||||
*/
|
||||
|
||||
return True;
|
||||
add_samba_names_to_subnet(remote_broadcast_subnet);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Remove all the names we registered.
|
||||
**************************************************************************/
|
||||
|
||||
void release_wins_names(void)
|
||||
{
|
||||
struct subnet_record *subrec = unicast_subnet;
|
||||
struct name_record *namerec, *nextnamerec;
|
||||
|
||||
for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
namerec;
|
||||
namerec = nextnamerec) {
|
||||
for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) {
|
||||
nextnamerec = (struct name_record *)ubi_trNext( namerec );
|
||||
if( (namerec->data.source == SELF_NAME)
|
||||
&& !NAME_IS_DEREGISTERING(namerec) )
|
||||
@ -199,12 +193,14 @@ void release_wins_names(void)
|
||||
|
||||
/*******************************************************************
|
||||
Refresh our registered names with WINS
|
||||
******************************************************************/
|
||||
******************************************************************/
|
||||
|
||||
void refresh_my_names(time_t t)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
|
||||
if (wins_srv_count() < 1) return;
|
||||
if (wins_srv_count() < 1)
|
||||
return;
|
||||
|
||||
for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist);
|
||||
namerec;
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -26,152 +26,149 @@
|
||||
uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
|
||||
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Set Samba's NetBIOS name type.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
/**************************************************************************
|
||||
Set Samba's NetBIOS name type.
|
||||
***************************************************************************/
|
||||
|
||||
void set_samba_nb_type(void)
|
||||
{
|
||||
if( lp_wins_support() || wins_srv_count() )
|
||||
samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */
|
||||
else
|
||||
samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */
|
||||
} /* set_samba_nb_type */
|
||||
{
|
||||
if( lp_wins_support() || wins_srv_count() )
|
||||
samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */
|
||||
else
|
||||
samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Convert a NetBIOS name to upper case.
|
||||
***************************************************************************/
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Convert a NetBIOS name to upper case.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
static void upcase_name( struct nmb_name *target, struct nmb_name *source )
|
||||
{
|
||||
int i;
|
||||
{
|
||||
int i;
|
||||
nstring targ;
|
||||
fstring scope;
|
||||
|
||||
if( NULL != source )
|
||||
(void)memcpy( target, source, sizeof( struct nmb_name ) );
|
||||
if( NULL != source )
|
||||
memcpy( target, source, sizeof( struct nmb_name ) );
|
||||
|
||||
strupper_m( target->name );
|
||||
strupper_m( target->scope );
|
||||
pull_ascii_nstring(targ, target->name);
|
||||
strupper_m( targ );
|
||||
push_ascii_nstring( target->name, targ);
|
||||
|
||||
/* fudge... We're using a byte-by-byte compare, so we must be sure that
|
||||
* unused space doesn't have garbage in it.
|
||||
*/
|
||||
for( i = strlen( target->name ); i < sizeof( target->name ); i++ )
|
||||
target->name[i] = '\0';
|
||||
for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ )
|
||||
target->scope[i] = '\0';
|
||||
} /* upcase_name */
|
||||
pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE);
|
||||
strupper_m( scope );
|
||||
push_ascii(target->scope, scope, 64, STR_TERMINATE);
|
||||
|
||||
/* fudge... We're using a byte-by-byte compare, so we must be sure that
|
||||
* unused space doesn't have garbage in it.
|
||||
*/
|
||||
|
||||
for( i = strlen( target->name ); i < sizeof( target->name ); i++ )
|
||||
target->name[i] = '\0';
|
||||
for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ )
|
||||
target->scope[i] = '\0';
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Add a new or overwrite an existing namelist entry.
|
||||
***************************************************************************/
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Add a new or overwrite an existing namelist entry.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
static void update_name_in_namelist( struct subnet_record *subrec,
|
||||
struct name_record *namerec )
|
||||
{
|
||||
struct name_record *oldrec = NULL;
|
||||
{
|
||||
struct name_record *oldrec = NULL;
|
||||
|
||||
(void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec );
|
||||
if( oldrec )
|
||||
{
|
||||
SAFE_FREE( oldrec->data.ip );
|
||||
SAFE_FREE( oldrec );
|
||||
}
|
||||
} /* update_name_in_namelist */
|
||||
ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec );
|
||||
if( oldrec ) {
|
||||
SAFE_FREE( oldrec->data.ip );
|
||||
SAFE_FREE( oldrec );
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Remove a name from the namelist.
|
||||
***************************************************************************/
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Remove a name from the namelist.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
void remove_name_from_namelist( struct subnet_record *subrec,
|
||||
struct name_record *namerec )
|
||||
{
|
||||
(void)ubi_trRemove( subrec->namelist, namerec );
|
||||
{
|
||||
ubi_trRemove( subrec->namelist, namerec );
|
||||
SAFE_FREE(namerec->data.ip);
|
||||
ZERO_STRUCTP(namerec);
|
||||
SAFE_FREE(namerec);
|
||||
subrec->namelist_changed = True;
|
||||
}
|
||||
|
||||
SAFE_FREE(namerec->data.ip);
|
||||
/**************************************************************************
|
||||
Find a name in a subnet.
|
||||
**************************************************************************/
|
||||
|
||||
ZERO_STRUCTP(namerec);
|
||||
SAFE_FREE(namerec);
|
||||
|
||||
subrec->namelist_changed = True;
|
||||
} /* remove_name_from_namelist */
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Find a name in a subnet.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
struct name_record *find_name_on_subnet( struct subnet_record *subrec,
|
||||
struct nmb_name *nmbname,
|
||||
BOOL self_only )
|
||||
{
|
||||
struct nmb_name uc_name[1];
|
||||
struct name_record *name_ret;
|
||||
{
|
||||
struct nmb_name uc_name[1];
|
||||
struct name_record *name_ret;
|
||||
|
||||
upcase_name( uc_name, nmbname );
|
||||
name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name );
|
||||
if( name_ret )
|
||||
{
|
||||
/* Self names only - these include permanent names. */
|
||||
if( self_only
|
||||
&& (name_ret->data.source != SELF_NAME)
|
||||
&& (name_ret->data.source != PERMANENT_NAME) )
|
||||
{
|
||||
DEBUG( 9,
|
||||
( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname) ) );
|
||||
return( NULL );
|
||||
}
|
||||
DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
|
||||
return( name_ret );
|
||||
}
|
||||
DEBUG( 9,
|
||||
( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname) ) );
|
||||
return( NULL );
|
||||
} /* find_name_on_subnet */
|
||||
upcase_name( uc_name, nmbname );
|
||||
name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name );
|
||||
if( name_ret ) {
|
||||
/* Self names only - these include permanent names. */
|
||||
if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) {
|
||||
DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname) ) );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
|
||||
return( name_ret );
|
||||
}
|
||||
|
||||
DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
|
||||
subrec->subnet_name, nmb_namestr(nmbname) ) );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Find a name over all known broadcast subnets.
|
||||
************************************************************************/
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Find a name over all known broadcast subnets.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
struct name_record *find_name_for_remote_broadcast_subnet(
|
||||
struct nmb_name *nmbname,
|
||||
BOOL self_only )
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct name_record *namerec = NULL;
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct name_record *namerec = NULL;
|
||||
|
||||
for( subrec = FIRST_SUBNET;
|
||||
subrec;
|
||||
subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
|
||||
{
|
||||
if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) )
|
||||
break;
|
||||
}
|
||||
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) {
|
||||
if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) )
|
||||
break;
|
||||
}
|
||||
|
||||
return( namerec );
|
||||
} /* find_name_for_remote_broadcast_subnet */
|
||||
return( namerec );
|
||||
}
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Update the ttl of an entry in a subnet name list.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
/**************************************************************************
|
||||
Update the ttl of an entry in a subnet name list.
|
||||
***************************************************************************/
|
||||
|
||||
void update_name_ttl( struct name_record *namerec, int ttl )
|
||||
{
|
||||
time_t time_now = time(NULL);
|
||||
time_t time_now = time(NULL);
|
||||
|
||||
if( namerec->data.death_time != PERMANENT_TTL )
|
||||
namerec->data.death_time = time_now + ttl;
|
||||
if( namerec->data.death_time != PERMANENT_TTL )
|
||||
namerec->data.death_time = time_now + ttl;
|
||||
|
||||
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
|
||||
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
|
||||
|
||||
namerec->subnet->namelist_changed = True;
|
||||
} /* update_name_ttl */
|
||||
namerec->subnet->namelist_changed = True;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Add an entry to a subnet name list.
|
||||
***********************************************************************/
|
||||
|
||||
/* ************************************************************************** **
|
||||
* Add an entry to a subnet name list.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
struct name_record *add_name_to_subnet( struct subnet_record *subrec,
|
||||
const char *name,
|
||||
int type,
|
||||
@ -181,70 +178,66 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
|
||||
int num_ips,
|
||||
struct in_addr *iplist)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
time_t time_now = time(NULL);
|
||||
struct name_record *namerec;
|
||||
time_t time_now = time(NULL);
|
||||
|
||||
namerec = (struct name_record *)malloc( sizeof(*namerec) );
|
||||
if( NULL == namerec )
|
||||
{
|
||||
DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
|
||||
return( NULL );
|
||||
}
|
||||
namerec = (struct name_record *)malloc( sizeof(*namerec) );
|
||||
if( NULL == namerec ) {
|
||||
DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
memset( (char *)namerec, '\0', sizeof(*namerec) );
|
||||
namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr)
|
||||
* num_ips );
|
||||
if( NULL == namerec->data.ip )
|
||||
{
|
||||
DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
|
||||
memset( (char *)namerec, '\0', sizeof(*namerec) );
|
||||
namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) * num_ips );
|
||||
if( NULL == namerec->data.ip ) {
|
||||
DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
|
||||
ZERO_STRUCTP(namerec);
|
||||
SAFE_FREE(namerec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(namerec);
|
||||
SAFE_FREE(namerec);
|
||||
return NULL;
|
||||
}
|
||||
namerec->subnet = subrec;
|
||||
|
||||
namerec->subnet = subrec;
|
||||
make_nmb_name(&namerec->name, name, type);
|
||||
upcase_name(&namerec->name, NULL );
|
||||
|
||||
make_nmb_name(&namerec->name, name, type);
|
||||
upcase_name(&namerec->name, NULL );
|
||||
/* Enter the name as active. */
|
||||
namerec->data.nb_flags = nb_flags | NB_ACTIVE;
|
||||
namerec->data.wins_flags = WINS_ACTIVE;
|
||||
|
||||
/* Enter the name as active. */
|
||||
namerec->data.nb_flags = nb_flags | NB_ACTIVE;
|
||||
namerec->data.wins_flags = WINS_ACTIVE;
|
||||
/* If it's our primary name, flag it as so. */
|
||||
if( strequal( my_netbios_names(0), name ) )
|
||||
namerec->data.nb_flags |= NB_PERM;
|
||||
|
||||
/* If it's our primary name, flag it as so. */
|
||||
if( strequal( my_netbios_names(0), name ) )
|
||||
namerec->data.nb_flags |= NB_PERM;
|
||||
/* Copy the IPs. */
|
||||
namerec->data.num_ips = num_ips;
|
||||
memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
|
||||
|
||||
/* Copy the IPs. */
|
||||
namerec->data.num_ips = num_ips;
|
||||
memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
|
||||
/* Data source. */
|
||||
namerec->data.source = source;
|
||||
|
||||
/* Data source. */
|
||||
namerec->data.source = source;
|
||||
/* Setup the death_time and refresh_time. */
|
||||
if( ttl == PERMANENT_TTL )
|
||||
namerec->data.death_time = PERMANENT_TTL;
|
||||
else
|
||||
namerec->data.death_time = time_now + ttl;
|
||||
|
||||
/* Setup the death_time and refresh_time. */
|
||||
if( ttl == PERMANENT_TTL )
|
||||
namerec->data.death_time = PERMANENT_TTL;
|
||||
else
|
||||
namerec->data.death_time = time_now + ttl;
|
||||
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
|
||||
|
||||
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
|
||||
/* Now add the record to the name list. */
|
||||
update_name_in_namelist( subrec, namerec );
|
||||
|
||||
/* Now add the record to the name list. */
|
||||
update_name_in_namelist( subrec, namerec );
|
||||
|
||||
DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
|
||||
DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
|
||||
ttl=%d nb_flags=%2x to subnet %s\n",
|
||||
nmb_namestr( &namerec->name ),
|
||||
inet_ntoa( *iplist ),
|
||||
ttl,
|
||||
(unsigned int)nb_flags,
|
||||
subrec->subnet_name ) );
|
||||
nmb_namestr( &namerec->name ),
|
||||
inet_ntoa( *iplist ),
|
||||
ttl,
|
||||
(unsigned int)nb_flags,
|
||||
subrec->subnet_name ) );
|
||||
|
||||
subrec->namelist_changed = True;
|
||||
subrec->namelist_changed = True;
|
||||
|
||||
return(namerec);
|
||||
return(namerec);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -258,14 +251,17 @@ void standard_success_register(struct subnet_record *subrec,
|
||||
struct nmb_name *nmbname, uint16 nb_flags, int ttl,
|
||||
struct in_addr registered_ip)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
|
||||
if( NULL == namerec )
|
||||
(void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type,
|
||||
nb_flags, ttl, SELF_NAME, 1, ®istered_ip );
|
||||
else
|
||||
update_name_ttl( namerec, ttl );
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
|
||||
if( NULL == namerec ) {
|
||||
nstring name;
|
||||
pull_ascii_nstring(name, nmbname->name);
|
||||
add_name_to_subnet( subrec, name, nmbname->name_type,
|
||||
nb_flags, ttl, SELF_NAME, 1, ®istered_ip );
|
||||
} else {
|
||||
update_name_ttl( namerec, ttl );
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -279,17 +275,16 @@ void standard_fail_register( struct subnet_record *subrec,
|
||||
struct response_record *rrec,
|
||||
struct nmb_name *nmbname )
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
|
||||
|
||||
DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
|
||||
on subnet %s\n",
|
||||
nmb_namestr(nmbname), subrec->subnet_name) );
|
||||
DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
|
||||
on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) );
|
||||
|
||||
/* Remove the name from the subnet. */
|
||||
if( namerec )
|
||||
remove_name_from_namelist(subrec, namerec);
|
||||
/* Remove the name from the subnet. */
|
||||
if( namerec )
|
||||
remove_name_from_namelist(subrec, namerec);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -298,13 +293,13 @@ on subnet %s\n",
|
||||
|
||||
static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
|
||||
{
|
||||
if( ind != namerec->data.num_ips )
|
||||
memmove( (char *)(&namerec->data.ip[ind]),
|
||||
(char *)(&namerec->data.ip[ind+1]),
|
||||
( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
|
||||
if( ind != namerec->data.num_ips )
|
||||
memmove( (char *)(&namerec->data.ip[ind]),
|
||||
(char *)(&namerec->data.ip[ind+1]),
|
||||
( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
|
||||
|
||||
namerec->data.num_ips--;
|
||||
namerec->subnet->namelist_changed = True;
|
||||
namerec->data.num_ips--;
|
||||
namerec->subnet->namelist_changed = True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -313,13 +308,13 @@ static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
|
||||
|
||||
BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < namerec->data.num_ips; i++)
|
||||
if(ip_equal( namerec->data.ip[i], ip))
|
||||
return True;
|
||||
for(i = 0; i < namerec->data.num_ips; i++)
|
||||
if(ip_equal( namerec->data.ip[i], ip))
|
||||
return True;
|
||||
|
||||
return False;
|
||||
return False;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -328,30 +323,26 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
|
||||
|
||||
void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
|
||||
{
|
||||
struct in_addr *new_list;
|
||||
struct in_addr *new_list;
|
||||
|
||||
/* Don't add one we already have. */
|
||||
if( find_ip_in_name_record( namerec, new_ip ) )
|
||||
return;
|
||||
/* Don't add one we already have. */
|
||||
if( find_ip_in_name_record( namerec, new_ip ) )
|
||||
return;
|
||||
|
||||
new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1)
|
||||
* sizeof(struct in_addr) );
|
||||
if( NULL == new_list )
|
||||
{
|
||||
DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) * sizeof(struct in_addr) );
|
||||
if( NULL == new_list ) {
|
||||
DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( (char *)new_list,
|
||||
(char *)namerec->data.ip,
|
||||
namerec->data.num_ips * sizeof(struct in_addr) );
|
||||
new_list[namerec->data.num_ips] = new_ip;
|
||||
memcpy( (char *)new_list, (char *)namerec->data.ip, namerec->data.num_ips * sizeof(struct in_addr) );
|
||||
new_list[namerec->data.num_ips] = new_ip;
|
||||
|
||||
SAFE_FREE(namerec->data.ip);
|
||||
namerec->data.ip = new_list;
|
||||
namerec->data.num_ips += 1;
|
||||
SAFE_FREE(namerec->data.ip);
|
||||
namerec->data.ip = new_list;
|
||||
namerec->data.num_ips += 1;
|
||||
|
||||
namerec->subnet->namelist_changed = True;
|
||||
namerec->subnet->namelist_changed = True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -361,16 +352,16 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
|
||||
void remove_ip_from_name_record( struct name_record *namerec,
|
||||
struct in_addr remove_ip )
|
||||
{
|
||||
/* Try and find the requested ip address - remove it. */
|
||||
int i;
|
||||
int orig_num = namerec->data.num_ips;
|
||||
/* Try and find the requested ip address - remove it. */
|
||||
int i;
|
||||
int orig_num = namerec->data.num_ips;
|
||||
|
||||
for(i = 0; i < orig_num; i++)
|
||||
if( ip_equal( remove_ip, namerec->data.ip[i]) )
|
||||
{
|
||||
remove_nth_ip_in_record( namerec, i);
|
||||
break;
|
||||
}
|
||||
for(i = 0; i < orig_num; i++) {
|
||||
if( ip_equal( remove_ip, namerec->data.ip[i]) ) {
|
||||
remove_nth_ip_in_record( namerec, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -384,85 +375,67 @@ void standard_success_release( struct subnet_record *subrec,
|
||||
struct nmb_name *nmbname,
|
||||
struct in_addr released_ip )
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME );
|
||||
namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME );
|
||||
if( namerec == NULL ) {
|
||||
DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
|
||||
on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(released_ip),
|
||||
subrec->subnet_name) );
|
||||
return;
|
||||
} else {
|
||||
int orig_num = namerec->data.num_ips;
|
||||
|
||||
if( namerec == NULL )
|
||||
{
|
||||
DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
|
||||
on subnet %s. Name was not found on subnet.\n",
|
||||
nmb_namestr(nmbname),
|
||||
inet_ntoa(released_ip),
|
||||
subrec->subnet_name) );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int orig_num = namerec->data.num_ips;
|
||||
remove_ip_from_name_record( namerec, released_ip );
|
||||
|
||||
remove_ip_from_name_record( namerec, released_ip );
|
||||
if( namerec->data.num_ips == orig_num )
|
||||
DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
|
||||
on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) );
|
||||
}
|
||||
|
||||
if( namerec->data.num_ips == orig_num )
|
||||
DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
|
||||
on subnet %s. This ip is not known for this name.\n",
|
||||
nmb_namestr(nmbname),
|
||||
inet_ntoa(released_ip),
|
||||
subrec->subnet_name ) );
|
||||
}
|
||||
|
||||
if( namerec->data.num_ips == 0 )
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
if( namerec->data.num_ips == 0 )
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Expires old names in a subnet namelist.
|
||||
******************************************************************/
|
||||
******************************************************************/
|
||||
|
||||
void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *next_namerec;
|
||||
struct name_record *namerec;
|
||||
struct name_record *next_namerec;
|
||||
|
||||
for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
namerec;
|
||||
namerec = next_namerec )
|
||||
{
|
||||
next_namerec = (struct name_record *)ubi_trNext( namerec );
|
||||
if( (namerec->data.death_time != PERMANENT_TTL)
|
||||
&& (namerec->data.death_time < t) )
|
||||
{
|
||||
if( namerec->data.source == SELF_NAME )
|
||||
{
|
||||
DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
|
||||
name %s\n",
|
||||
subrec->subnet_name, nmb_namestr(&namerec->name) ) );
|
||||
namerec->data.death_time += 300;
|
||||
namerec->subnet->namelist_changed = True;
|
||||
continue;
|
||||
}
|
||||
DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
|
||||
subrec->subnet_name, nmb_namestr(&namerec->name)));
|
||||
for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) {
|
||||
next_namerec = (struct name_record *)ubi_trNext( namerec );
|
||||
if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
|
||||
if( namerec->data.source == SELF_NAME ) {
|
||||
DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
|
||||
name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) );
|
||||
namerec->data.death_time += 300;
|
||||
namerec->subnet->namelist_changed = True;
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
|
||||
subrec->subnet_name, nmb_namestr(&namerec->name)));
|
||||
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
}
|
||||
}
|
||||
remove_name_from_namelist( subrec, namerec );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Expires old names in all subnet namelists.
|
||||
******************************************************************/
|
||||
******************************************************************/
|
||||
|
||||
void expire_names(time_t t)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct subnet_record *subrec;
|
||||
|
||||
for( subrec = FIRST_SUBNET;
|
||||
subrec;
|
||||
subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
|
||||
{
|
||||
expire_names_on_subnet( subrec, t );
|
||||
}
|
||||
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) {
|
||||
expire_names_on_subnet( subrec, t );
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -475,46 +448,39 @@ void expire_names(time_t t)
|
||||
|
||||
void add_samba_names_to_subnet( struct subnet_record *subrec )
|
||||
{
|
||||
struct in_addr *iplist = &subrec->myip;
|
||||
int num_ips = 1;
|
||||
struct in_addr *iplist = &subrec->myip;
|
||||
int num_ips = 1;
|
||||
|
||||
/* These names are added permanently (ttl of zero) and will NOT be
|
||||
refreshed. */
|
||||
/* These names are added permanently (ttl of zero) and will NOT be refreshed. */
|
||||
|
||||
if( (subrec == unicast_subnet)
|
||||
|| (subrec == wins_server_subnet)
|
||||
|| (subrec == remote_broadcast_subnet) )
|
||||
{
|
||||
struct subnet_record *bcast_subrecs;
|
||||
int i;
|
||||
/* Create an IP list containing all our known subnets. */
|
||||
if( (subrec == unicast_subnet) || (subrec == wins_server_subnet) || (subrec == remote_broadcast_subnet) ) {
|
||||
struct subnet_record *bcast_subrecs;
|
||||
int i;
|
||||
|
||||
num_ips = iface_count();
|
||||
iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) );
|
||||
if( NULL == iplist )
|
||||
{
|
||||
DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
/* Create an IP list containing all our known subnets. */
|
||||
|
||||
for( bcast_subrecs = FIRST_SUBNET, i = 0;
|
||||
bcast_subrecs;
|
||||
bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ )
|
||||
iplist[i] = bcast_subrecs->myip;
|
||||
num_ips = iface_count();
|
||||
iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) );
|
||||
if( NULL == iplist ) {
|
||||
DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
for( bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs; bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ )
|
||||
iplist[i] = bcast_subrecs->myip;
|
||||
}
|
||||
|
||||
(void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
(void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
(void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
(void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
|
||||
PERMANENT_NAME, num_ips, iplist);
|
||||
|
||||
if(iplist != &subrec->myip)
|
||||
SAFE_FREE(iplist);
|
||||
if(iplist != &subrec->myip)
|
||||
SAFE_FREE(iplist);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -524,68 +490,65 @@ void add_samba_names_to_subnet( struct subnet_record *subrec )
|
||||
|
||||
static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
const char *src_type;
|
||||
struct tm *tm;
|
||||
int i;
|
||||
struct name_record *namerec;
|
||||
const char *src_type;
|
||||
struct tm *tm;
|
||||
int i;
|
||||
|
||||
x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
|
||||
for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
|
||||
namerec;
|
||||
namerec = (struct name_record *)ubi_trNext( namerec ) )
|
||||
{
|
||||
x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
|
||||
switch(namerec->data.source)
|
||||
{
|
||||
case LMHOSTS_NAME:
|
||||
src_type = "LMHOSTS_NAME";
|
||||
break;
|
||||
case WINS_PROXY_NAME:
|
||||
src_type = "WINS_PROXY_NAME";
|
||||
break;
|
||||
case REGISTER_NAME:
|
||||
src_type = "REGISTER_NAME";
|
||||
break;
|
||||
case SELF_NAME:
|
||||
src_type = "SELF_NAME";
|
||||
break;
|
||||
case DNS_NAME:
|
||||
src_type = "DNS_NAME";
|
||||
break;
|
||||
case DNSFAIL_NAME:
|
||||
src_type = "DNSFAIL_NAME";
|
||||
break;
|
||||
case PERMANENT_NAME:
|
||||
src_type = "PERMANENT_NAME";
|
||||
break;
|
||||
default:
|
||||
src_type = "unknown!";
|
||||
break;
|
||||
}
|
||||
x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
|
||||
x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
|
||||
for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec;
|
||||
namerec = (struct name_record *)ubi_trNext( namerec ) ) {
|
||||
|
||||
if(namerec->data.death_time != PERMANENT_TTL)
|
||||
{
|
||||
tm = LocalTime(&namerec->data.death_time);
|
||||
x_fprintf(fp, "death_time = %s\t", asctime(tm));
|
||||
}
|
||||
else
|
||||
x_fprintf(fp, "death_time = PERMANENT\t");
|
||||
x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
|
||||
switch(namerec->data.source) {
|
||||
case LMHOSTS_NAME:
|
||||
src_type = "LMHOSTS_NAME";
|
||||
break;
|
||||
case WINS_PROXY_NAME:
|
||||
src_type = "WINS_PROXY_NAME";
|
||||
break;
|
||||
case REGISTER_NAME:
|
||||
src_type = "REGISTER_NAME";
|
||||
break;
|
||||
case SELF_NAME:
|
||||
src_type = "SELF_NAME";
|
||||
break;
|
||||
case DNS_NAME:
|
||||
src_type = "DNS_NAME";
|
||||
break;
|
||||
case DNSFAIL_NAME:
|
||||
src_type = "DNSFAIL_NAME";
|
||||
break;
|
||||
case PERMANENT_NAME:
|
||||
src_type = "PERMANENT_NAME";
|
||||
break;
|
||||
default:
|
||||
src_type = "unknown!";
|
||||
break;
|
||||
}
|
||||
|
||||
if(namerec->data.refresh_time != PERMANENT_TTL)
|
||||
{
|
||||
tm = LocalTime(&namerec->data.refresh_time);
|
||||
x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
|
||||
}
|
||||
else
|
||||
x_fprintf(fp, "refresh_time = PERMANENT\n");
|
||||
x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
|
||||
|
||||
x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
|
||||
for(i = 0; i < namerec->data.num_ips; i++)
|
||||
x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
|
||||
if(namerec->data.death_time != PERMANENT_TTL) {
|
||||
tm = LocalTime(&namerec->data.death_time);
|
||||
x_fprintf(fp, "death_time = %s\t", asctime(tm));
|
||||
} else {
|
||||
x_fprintf(fp, "death_time = PERMANENT\t");
|
||||
}
|
||||
|
||||
x_fprintf(fp, "\n\n");
|
||||
}
|
||||
if(namerec->data.refresh_time != PERMANENT_TTL) {
|
||||
tm = LocalTime(&namerec->data.refresh_time);
|
||||
x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
|
||||
} else {
|
||||
x_fprintf(fp, "refresh_time = PERMANENT\n");
|
||||
}
|
||||
|
||||
x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
|
||||
for(i = 0; i < namerec->data.num_ips; i++)
|
||||
x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
|
||||
|
||||
x_fprintf(fp, "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -595,30 +558,27 @@ static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
|
||||
|
||||
void dump_all_namelists(void)
|
||||
{
|
||||
XFILE *fp;
|
||||
struct subnet_record *subrec;
|
||||
XFILE *fp;
|
||||
struct subnet_record *subrec;
|
||||
|
||||
fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
|
||||
"namelist.debug",strerror(errno)));
|
||||
return;
|
||||
}
|
||||
if (!fp) {
|
||||
DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
|
||||
"namelist.debug",strerror(errno)));
|
||||
return;
|
||||
}
|
||||
|
||||
for( subrec = FIRST_SUBNET;
|
||||
subrec;
|
||||
subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
|
||||
dump_subnet_namelist( subrec, fp );
|
||||
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
|
||||
dump_subnet_namelist( subrec, fp );
|
||||
|
||||
if( !we_are_a_wins_client() )
|
||||
dump_subnet_namelist( unicast_subnet, fp );
|
||||
if( !we_are_a_wins_client() )
|
||||
dump_subnet_namelist( unicast_subnet, fp );
|
||||
|
||||
if( remote_broadcast_subnet->namelist != NULL )
|
||||
dump_subnet_namelist( remote_broadcast_subnet, fp );
|
||||
if( remote_broadcast_subnet->namelist != NULL )
|
||||
dump_subnet_namelist( remote_broadcast_subnet, fp );
|
||||
|
||||
if( wins_server_subnet != NULL )
|
||||
dump_subnet_namelist( wins_server_subnet, fp );
|
||||
x_fclose( fp );
|
||||
if( wins_server_subnet != NULL )
|
||||
dump_subnet_namelist( wins_server_subnet, fp );
|
||||
x_fclose( fp );
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -31,106 +31,95 @@ static void query_name_response( struct subnet_record *subrec,
|
||||
struct response_record *rrec,
|
||||
struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
BOOL success = False;
|
||||
struct nmb_name *question_name =
|
||||
&rrec->packet->packet.nmb.question.question_name;
|
||||
struct in_addr answer_ip;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
BOOL success = False;
|
||||
struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
|
||||
struct in_addr answer_ip;
|
||||
|
||||
zero_ip(&answer_ip);
|
||||
zero_ip(&answer_ip);
|
||||
|
||||
/* Ensure we don't retry the query but leave the response record cleanup
|
||||
to the timeout code. We may get more answer responses in which case
|
||||
we should mark the name in conflict.. */
|
||||
rrec->repeat_count = 0;
|
||||
/* Ensure we don't retry the query but leave the response record cleanup
|
||||
to the timeout code. We may get more answer responses in which case
|
||||
we should mark the name in conflict.. */
|
||||
rrec->repeat_count = 0;
|
||||
|
||||
if(rrec->num_msgs == 1)
|
||||
{
|
||||
/* This is the first response. */
|
||||
if(rrec->num_msgs == 1) {
|
||||
/* This is the first response. */
|
||||
|
||||
if(nmb->header.opcode == NMB_WACK_OPCODE)
|
||||
{
|
||||
/* WINS server is telling us to wait. Pretend we didn't get
|
||||
the response but don't send out any more query requests. */
|
||||
if(nmb->header.opcode == NMB_WACK_OPCODE) {
|
||||
/* WINS server is telling us to wait. Pretend we didn't get
|
||||
the response but don't send out any more query requests. */
|
||||
|
||||
if( DEBUGLVL( 5 ) )
|
||||
{
|
||||
dbgtext( "query_name_response: " );
|
||||
dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "in querying name %s ", nmb_namestr(question_name) );
|
||||
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
||||
}
|
||||
if( DEBUGLVL( 5 ) ) {
|
||||
dbgtext( "query_name_response: " );
|
||||
dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "in querying name %s ", nmb_namestr(question_name) );
|
||||
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
||||
}
|
||||
|
||||
rrec->repeat_count = 0;
|
||||
/* How long we should wait for. */
|
||||
rrec->repeat_time = p->timestamp + nmb->answers->ttl;
|
||||
rrec->num_msgs--;
|
||||
return;
|
||||
}
|
||||
else if(nmb->header.rcode != 0)
|
||||
{
|
||||
success = False;
|
||||
rrec->repeat_count = 0;
|
||||
/* How long we should wait for. */
|
||||
rrec->repeat_time = p->timestamp + nmb->answers->ttl;
|
||||
rrec->num_msgs--;
|
||||
return;
|
||||
} else if(nmb->header.rcode != 0) {
|
||||
|
||||
if( DEBUGLVL( 5 ) )
|
||||
{
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "for name %s. ", nmb_namestr(question_name) );
|
||||
dbgtext( "Error code was %d.\n", nmb->header.rcode );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!nmb->answers)
|
||||
{
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "returned a success response with no answer\n" );
|
||||
return;
|
||||
}
|
||||
success = False;
|
||||
|
||||
success = True;
|
||||
if( DEBUGLVL( 5 ) ) {
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "for name %s. ", nmb_namestr(question_name) );
|
||||
dbgtext( "Error code was %d.\n", nmb->header.rcode );
|
||||
}
|
||||
} else {
|
||||
if (!nmb->answers) {
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "returned a success response with no answer\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
putip((char *)&answer_ip,&nmb->answers->rdata[2]);
|
||||
if( DEBUGLVL( 5 ) )
|
||||
{
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "for name %s. ", nmb_namestr(question_name) );
|
||||
dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
|
||||
}
|
||||
success = True;
|
||||
|
||||
/* Interestingly, we could add these names to our namelists, and
|
||||
change nmbd to a model that checked its own name cache first,
|
||||
before sending out a query. This is a task for another day, though.
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if( rrec->num_msgs > 1)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
if (nmb->answers)
|
||||
putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
|
||||
dbgtext( "query_name_response: " );
|
||||
dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
|
||||
dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
|
||||
dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
|
||||
dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
|
||||
}
|
||||
putip((char *)&answer_ip,&nmb->answers->rdata[2]);
|
||||
|
||||
if( DEBUGLVL( 5 ) ) {
|
||||
dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
|
||||
dbgtext( "for name %s. ", nmb_namestr(question_name) );
|
||||
dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
|
||||
}
|
||||
|
||||
/* We have already called the success or fail function, so we
|
||||
don't call again here. Leave the response record around in
|
||||
case we get more responses. */
|
||||
/* Interestingly, we could add these names to our namelists, and
|
||||
change nmbd to a model that checked its own name cache first,
|
||||
before sending out a query. This is a task for another day, though.
|
||||
*/
|
||||
}
|
||||
} else if( rrec->num_msgs > 1) {
|
||||
|
||||
return;
|
||||
}
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
if (nmb->answers)
|
||||
putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
|
||||
dbgtext( "query_name_response: " );
|
||||
dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
|
||||
dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
|
||||
dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
|
||||
dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
|
||||
dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
|
||||
}
|
||||
|
||||
/* We have already called the success or fail function, so we
|
||||
don't call again here. Leave the response record around in
|
||||
case we get more responses. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(success && rrec->success_fn)
|
||||
(*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
|
||||
else if( rrec->fail_fn)
|
||||
(*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
|
||||
if(success && rrec->success_fn)
|
||||
(*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
|
||||
else if( rrec->fail_fn)
|
||||
(*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
|
||||
|
||||
}
|
||||
|
||||
@ -141,32 +130,30 @@ static void query_name_response( struct subnet_record *subrec,
|
||||
static void query_name_timeout_response(struct subnet_record *subrec,
|
||||
struct response_record *rrec)
|
||||
{
|
||||
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
|
||||
/* We can only fail here, never succeed. */
|
||||
BOOL failed = True;
|
||||
struct nmb_name *question_name = &sent_nmb->question.question_name;
|
||||
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
|
||||
/* We can only fail here, never succeed. */
|
||||
BOOL failed = True;
|
||||
struct nmb_name *question_name = &sent_nmb->question.question_name;
|
||||
|
||||
if(rrec->num_msgs != 0)
|
||||
{
|
||||
/* We got at least one response, and have called the success/fail
|
||||
function already. */
|
||||
if(rrec->num_msgs != 0) {
|
||||
/* We got at least one response, and have called the success/fail
|
||||
function already. */
|
||||
|
||||
failed = False;
|
||||
}
|
||||
failed = False;
|
||||
}
|
||||
|
||||
if(failed)
|
||||
{
|
||||
if( DEBUGLVL( 5 ) )
|
||||
{
|
||||
dbgtext( "query_name_timeout_response: No response to " );
|
||||
dbgtext( "query for name %s ", nmb_namestr(question_name) );
|
||||
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
||||
}
|
||||
if(rrec->fail_fn)
|
||||
(*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
|
||||
}
|
||||
if(failed) {
|
||||
if( DEBUGLVL( 5 ) ) {
|
||||
dbgtext( "query_name_timeout_response: No response to " );
|
||||
dbgtext( "query for name %s ", nmb_namestr(question_name) );
|
||||
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
||||
}
|
||||
|
||||
remove_response_record(subrec, rrec);
|
||||
if(rrec->fail_fn)
|
||||
(*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
|
||||
}
|
||||
|
||||
remove_response_record(subrec, rrec);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -177,24 +164,21 @@ static void query_name_timeout_response(struct subnet_record *subrec,
|
||||
static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
|
||||
struct name_record **namerecp)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct name_record *namerec;
|
||||
|
||||
*namerecp = NULL;
|
||||
*namerecp = NULL;
|
||||
|
||||
if(find_name_in_lmhosts(nmbname, namerecp))
|
||||
return True;
|
||||
if(find_name_in_lmhosts(nmbname, namerecp))
|
||||
return True;
|
||||
|
||||
if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
|
||||
return False;
|
||||
if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
|
||||
return False;
|
||||
|
||||
if( NAME_IS_ACTIVE(namerec)
|
||||
&& ( (namerec->data.source == SELF_NAME)
|
||||
|| (namerec->data.source == LMHOSTS_NAME) ) )
|
||||
{
|
||||
*namerecp = namerec;
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
if( NAME_IS_ACTIVE(namerec) && ( (namerec->data.source == SELF_NAME) || (namerec->data.source == LMHOSTS_NAME) ) ) {
|
||||
*namerecp = namerec;
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -206,69 +190,57 @@ BOOL query_name(struct subnet_record *subrec, const char *name, int type,
|
||||
query_name_fail_function fail_fn,
|
||||
struct userdata_struct *userdata)
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
struct name_record *namerec;
|
||||
struct nmb_name nmbname;
|
||||
struct name_record *namerec;
|
||||
|
||||
make_nmb_name(&nmbname, name, type);
|
||||
make_nmb_name(&nmbname, name, type);
|
||||
|
||||
/*
|
||||
* We need to check our local namelists first.
|
||||
* It may be an magic name, lmhosts name or just
|
||||
* a name we have registered.
|
||||
*/
|
||||
/*
|
||||
* We need to check our local namelists first.
|
||||
* It may be an magic name, lmhosts name or just
|
||||
* a name we have registered.
|
||||
*/
|
||||
|
||||
if(query_local_namelists(subrec, &nmbname, &namerec) == True)
|
||||
{
|
||||
struct res_rec rrec;
|
||||
int i;
|
||||
if(query_local_namelists(subrec, &nmbname, &namerec) == True) {
|
||||
struct res_rec rrec;
|
||||
int i;
|
||||
|
||||
memset((char *)&rrec, '\0', sizeof(struct res_rec));
|
||||
memset((char *)&rrec, '\0', sizeof(struct res_rec));
|
||||
|
||||
/* Fake up the needed res_rec just in case it's used. */
|
||||
rrec.rr_name = nmbname;
|
||||
rrec.rr_type = RR_TYPE_NB;
|
||||
rrec.rr_class = RR_CLASS_IN;
|
||||
rrec.ttl = PERMANENT_TTL;
|
||||
rrec.rdlength = namerec->data.num_ips * 6;
|
||||
if(rrec.rdlength > MAX_DGRAM_SIZE)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
dbgtext( "query_name: nmbd internal error - " );
|
||||
dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
|
||||
dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return False;
|
||||
}
|
||||
/* Fake up the needed res_rec just in case it's used. */
|
||||
rrec.rr_name = nmbname;
|
||||
rrec.rr_type = RR_TYPE_NB;
|
||||
rrec.rr_class = RR_CLASS_IN;
|
||||
rrec.ttl = PERMANENT_TTL;
|
||||
rrec.rdlength = namerec->data.num_ips * 6;
|
||||
if(rrec.rdlength > MAX_DGRAM_SIZE) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
dbgtext( "query_name: nmbd internal error - " );
|
||||
dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
|
||||
dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
for( i = 0; i < namerec->data.num_ips; i++)
|
||||
{
|
||||
set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
|
||||
putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
|
||||
}
|
||||
for( i = 0; i < namerec->data.num_ips; i++) {
|
||||
set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
|
||||
putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
|
||||
}
|
||||
|
||||
/* Call the success function directly. */
|
||||
if(success_fn)
|
||||
(*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
|
||||
return False;
|
||||
}
|
||||
/* Call the success function directly. */
|
||||
if(success_fn)
|
||||
(*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
|
||||
return False;
|
||||
}
|
||||
|
||||
if(queue_query_name( subrec,
|
||||
query_name_response,
|
||||
query_name_timeout_response,
|
||||
success_fn,
|
||||
fail_fn,
|
||||
userdata,
|
||||
&nmbname) == NULL)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
dbgtext( "query_name: Failed to send packet " );
|
||||
dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
if(queue_query_name( subrec, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
dbgtext( "query_name: Failed to send packet " );
|
||||
dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -281,24 +253,16 @@ BOOL query_name_from_wins_server(struct in_addr ip_to,
|
||||
query_name_fail_function fail_fn,
|
||||
struct userdata_struct *userdata)
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
struct nmb_name nmbname;
|
||||
|
||||
make_nmb_name(&nmbname, name, type);
|
||||
make_nmb_name(&nmbname, name, type);
|
||||
|
||||
if(queue_query_name_from_wins_server( ip_to,
|
||||
query_name_response,
|
||||
query_name_timeout_response,
|
||||
success_fn,
|
||||
fail_fn,
|
||||
userdata,
|
||||
&nmbname) == NULL)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
dbgtext( "query_name_from_wins_server: Failed to send packet " );
|
||||
dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
if(queue_query_name_from_wins_server( ip_to, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
dbgtext( "query_name_from_wins_server: Failed to send packet " );
|
||||
dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -85,7 +85,9 @@ static void register_name_response(struct subnet_record *subrec,
|
||||
*/
|
||||
|
||||
#if 1 /* OLD_SAMBA_SERVER_HACK */
|
||||
if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), answer_name->name) &&
|
||||
nstring ans_name;
|
||||
pull_ascii_nstring(ans_name, answer_name->name);
|
||||
if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
|
||||
(answer_name->name_type == 0x1b)) {
|
||||
/* Pretend we did not get this. */
|
||||
rrec->num_msgs--;
|
||||
@ -161,10 +163,10 @@ static void register_name_response(struct subnet_record *subrec,
|
||||
remove_response_record(subrec, rrec);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Deal with a timeout of a WINS registration request
|
||||
****************************************************************************/
|
||||
|
||||
static void wins_registration_timeout(struct subnet_record *subrec,
|
||||
struct response_record *rrec)
|
||||
{
|
||||
@ -233,7 +235,6 @@ static void wins_registration_timeout(struct subnet_record *subrec,
|
||||
us trying to register with each of our failover wins servers */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Deal with a timeout when registering one of our names.
|
||||
****************************************************************************/
|
||||
@ -290,10 +291,10 @@ static void register_name_timeout_response(struct subnet_record *subrec,
|
||||
remove_response_record(subrec, rrec);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
initiate one multi-homed name registration packet
|
||||
Initiate one multi-homed name registration packet.
|
||||
****************************************************************************/
|
||||
|
||||
static void multihomed_register_one(struct nmb_name *nmbname,
|
||||
uint16 nb_flags,
|
||||
register_name_success_function success_fn,
|
||||
@ -336,11 +337,11 @@ static void multihomed_register_one(struct nmb_name *nmbname,
|
||||
free(userdata);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
we have finished the registration of one IP and need to see if we have
|
||||
any more IPs left to register with this group of wins server for this name
|
||||
We have finished the registration of one IP and need to see if we have
|
||||
any more IPs left to register with this group of wins server for this name.
|
||||
****************************************************************************/
|
||||
|
||||
static void wins_next_registration(struct response_record *rrec)
|
||||
{
|
||||
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
|
||||
@ -388,6 +389,7 @@ static void wins_next_registration(struct response_record *rrec)
|
||||
/****************************************************************************
|
||||
Try and register one of our names on the unicast subnet - multihomed.
|
||||
****************************************************************************/
|
||||
|
||||
static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
|
||||
register_name_success_function success_fn,
|
||||
register_name_fail_function fail_fn)
|
||||
@ -416,6 +418,7 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
|
||||
struct subnet_record *subrec;
|
||||
char **wins_tags;
|
||||
struct in_addr *ip_list;
|
||||
nstring name;
|
||||
|
||||
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
|
||||
num_ips++;
|
||||
@ -431,7 +434,8 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
|
||||
ip_list[i] = subrec->myip;
|
||||
}
|
||||
|
||||
add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
|
||||
pull_ascii_nstring(name, nmbname->name);
|
||||
add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
|
||||
nb_flags, lp_max_ttl(), SELF_NAME,
|
||||
num_ips, ip_list);
|
||||
|
||||
@ -456,10 +460,10 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
|
||||
SAFE_FREE(ip_list);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Try and register one of our names.
|
||||
****************************************************************************/
|
||||
|
||||
void register_name(struct subnet_record *subrec,
|
||||
const char *name, int type, uint16 nb_flags,
|
||||
register_name_success_function success_fn,
|
||||
@ -498,10 +502,10 @@ void register_name(struct subnet_record *subrec,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Try and refresh one of our names. This is *only* called for WINS refresh
|
||||
****************************************************************************/
|
||||
|
||||
void wins_refresh_name(struct name_record *namerec)
|
||||
{
|
||||
int t;
|
||||
|
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
|
||||
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
|
||||
@ -26,52 +26,52 @@
|
||||
/****************************************************************************
|
||||
Deal with a successful node status response.
|
||||
****************************************************************************/
|
||||
|
||||
static void node_status_response(struct subnet_record *subrec,
|
||||
struct response_record *rrec, struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
|
||||
struct nmb_name *answer_name = &nmb->answers->rr_name;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
|
||||
struct nmb_name *answer_name = &nmb->answers->rr_name;
|
||||
|
||||
/* Sanity check. Ensure that the answer name in the incoming packet is the
|
||||
same as the requested name in the outgoing packet. */
|
||||
/* Sanity check. Ensure that the answer name in the incoming packet is the
|
||||
same as the requested name in the outgoing packet. */
|
||||
|
||||
if(!nmb_name_equal(question_name, answer_name))
|
||||
{
|
||||
DEBUG(0,("node_status_response: Answer name %s differs from question \
|
||||
if(!nmb_name_equal(question_name, answer_name)) {
|
||||
DEBUG(0,("node_status_response: Answer name %s differs from question \
|
||||
name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name)));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(5,("node_status_response: response from name %s on subnet %s.\n",
|
||||
nmb_namestr(answer_name), subrec->subnet_name));
|
||||
DEBUG(5,("node_status_response: response from name %s on subnet %s.\n",
|
||||
nmb_namestr(answer_name), subrec->subnet_name));
|
||||
|
||||
/* Just send the whole answer resource record for the success function
|
||||
to parse. */
|
||||
if(rrec->success_fn)
|
||||
(*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip);
|
||||
/* Just send the whole answer resource record for the success function to parse. */
|
||||
if(rrec->success_fn)
|
||||
(*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip);
|
||||
|
||||
/* Ensure we don't retry. */
|
||||
remove_response_record(subrec, rrec);
|
||||
/* Ensure we don't retry. */
|
||||
remove_response_record(subrec, rrec);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Deal with a timeout when requesting a node status.
|
||||
****************************************************************************/
|
||||
|
||||
static void node_status_timeout_response(struct subnet_record *subrec,
|
||||
struct response_record *rrec)
|
||||
{
|
||||
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
|
||||
struct nmb_name *question_name = &sent_nmb->question.question_name;
|
||||
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
|
||||
struct nmb_name *question_name = &sent_nmb->question.question_name;
|
||||
|
||||
DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n",
|
||||
nmb_namestr(question_name), subrec->subnet_name));
|
||||
DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n",
|
||||
nmb_namestr(question_name), subrec->subnet_name));
|
||||
|
||||
if( rrec->fail_fn)
|
||||
(*rrec->fail_fn)(subrec, rrec);
|
||||
if( rrec->fail_fn)
|
||||
(*rrec->fail_fn)(subrec, rrec);
|
||||
|
||||
/* Ensure we don't retry. */
|
||||
remove_response_record(subrec, rrec);
|
||||
/* Ensure we don't retry. */
|
||||
remove_response_record(subrec, rrec);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -82,13 +82,11 @@ BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname,
|
||||
struct in_addr send_ip, node_status_success_function success_fn,
|
||||
node_status_fail_function fail_fn, struct userdata_struct *userdata)
|
||||
{
|
||||
if(queue_node_status( subrec,
|
||||
node_status_response, node_status_timeout_response,
|
||||
success_fn, fail_fn, userdata, nmbname, send_ip)==NULL)
|
||||
{
|
||||
DEBUG(0,("node_status: Failed to send packet trying to get node status for \
|
||||
if(queue_node_status( subrec, node_status_response, node_status_timeout_response,
|
||||
success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) {
|
||||
DEBUG(0,("node_status: Failed to send packet trying to get node status for \
|
||||
name %s, IP address %s\n", nmb_namestr(nmbname), inet_ntoa(send_ip)));
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1998
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-1998
|
||||
Copyright (C) Jeremy Allison 1994-2003
|
||||
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -35,6 +35,7 @@ struct sam_database_info {
|
||||
/****************************************************************************
|
||||
Send a message to smbd to do a sam delta sync
|
||||
**************************************************************************/
|
||||
|
||||
static void send_repl_message(uint32 low_serial)
|
||||
{
|
||||
TDB_CONTEXT *tdb;
|
||||
@ -64,432 +65,452 @@ Process a domain logon packet
|
||||
void process_logon_packet(struct packet_struct *p, char *buf,int len,
|
||||
const char *mailslot)
|
||||
{
|
||||
struct dgram_packet *dgram = &p->packet.dgram;
|
||||
pstring my_name;
|
||||
fstring reply_name;
|
||||
pstring outbuf;
|
||||
int code;
|
||||
uint16 token = 0;
|
||||
uint32 ntversion = 0;
|
||||
uint16 lmnttoken = 0;
|
||||
uint16 lm20token = 0;
|
||||
uint32 domainsidsize;
|
||||
BOOL short_request = False;
|
||||
char *getdc;
|
||||
char *uniuser; /* Unicode user name. */
|
||||
pstring ascuser;
|
||||
char *unicomp; /* Unicode computer name. */
|
||||
struct dgram_packet *dgram = &p->packet.dgram;
|
||||
pstring my_name;
|
||||
fstring reply_name;
|
||||
pstring outbuf;
|
||||
int code;
|
||||
uint16 token = 0;
|
||||
uint32 ntversion = 0;
|
||||
uint16 lmnttoken = 0;
|
||||
uint16 lm20token = 0;
|
||||
uint32 domainsidsize;
|
||||
BOOL short_request = False;
|
||||
char *getdc;
|
||||
char *uniuser; /* Unicode user name. */
|
||||
pstring ascuser;
|
||||
char *unicomp; /* Unicode computer name. */
|
||||
|
||||
memset(outbuf, 0, sizeof(outbuf));
|
||||
memset(outbuf, 0, sizeof(outbuf));
|
||||
|
||||
if (!lp_domain_logons())
|
||||
{
|
||||
DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \
|
||||
if (!lp_domain_logons()) {
|
||||
DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \
|
||||
logons are not enabled.\n", inet_ntoa(p->ip) ));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pstrcpy(my_name, global_myname());
|
||||
pstrcpy(my_name, global_myname());
|
||||
|
||||
code = SVAL(buf,0);
|
||||
DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code));
|
||||
code = SVAL(buf,0);
|
||||
DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code));
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
char *q = buf + 2;
|
||||
char *machine = q;
|
||||
char *user = skip_string(machine,1);
|
||||
switch (code) {
|
||||
case 0:
|
||||
{
|
||||
fstring mach_str, user_str, getdc_str;
|
||||
char *q = buf + 2;
|
||||
char *machine = q;
|
||||
char *user = skip_string(machine,1);
|
||||
|
||||
getdc = skip_string(user,1);
|
||||
q = skip_string(getdc,1);
|
||||
token = SVAL(q,3);
|
||||
getdc = skip_string(user,1);
|
||||
q = skip_string(getdc,1);
|
||||
token = SVAL(q,3);
|
||||
|
||||
fstrcpy(reply_name,my_name);
|
||||
fstrcpy(reply_name,my_name);
|
||||
|
||||
DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n",
|
||||
machine,inet_ntoa(p->ip),user,token));
|
||||
pull_ascii_fstring(mach_str, machine);
|
||||
pull_ascii_fstring(user_str, user);
|
||||
pull_ascii_fstring(getdc_str, getdc);
|
||||
|
||||
q = outbuf;
|
||||
SSVAL(q, 0, 6);
|
||||
q += 2;
|
||||
DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n",
|
||||
mach_str,inet_ntoa(p->ip),user_str,token));
|
||||
|
||||
fstrcpy(reply_name, "\\\\");
|
||||
fstrcat(reply_name, my_name);
|
||||
fstrcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */
|
||||
q = outbuf;
|
||||
SSVAL(q, 0, 6);
|
||||
q += 2;
|
||||
|
||||
SSVAL(q, 0, token);
|
||||
q += 2;
|
||||
fstrcpy(reply_name, "\\\\");
|
||||
fstrcat(reply_name, my_name);
|
||||
push_ascii_fstring(q, reply_name);
|
||||
q = skip_string(q, 1); /* PDC name */
|
||||
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
SSVAL(q, 0, token);
|
||||
q += 2;
|
||||
|
||||
send_mailslot(True, getdc,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
machine,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
break;
|
||||
}
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
|
||||
case QUERYFORPDC:
|
||||
{
|
||||
char *q = buf + 2;
|
||||
char *machine = q;
|
||||
send_mailslot(True, getdc_str,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
mach_str,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lp_domain_master())
|
||||
{
|
||||
/* We're not Primary Domain Controller -- ignore this */
|
||||
return;
|
||||
}
|
||||
case QUERYFORPDC:
|
||||
{
|
||||
fstring mach_str, getdc_str;
|
||||
nstring source_name;
|
||||
char *q = buf + 2;
|
||||
char *machine = q;
|
||||
|
||||
getdc = skip_string(machine,1);
|
||||
q = skip_string(getdc,1);
|
||||
q = ALIGN2(q, buf);
|
||||
if (!lp_domain_master()) {
|
||||
/* We're not Primary Domain Controller -- ignore this */
|
||||
return;
|
||||
}
|
||||
|
||||
/* at this point we can work out if this is a W9X or NT style
|
||||
request. Experiments show that the difference is wether the
|
||||
packet ends here. For a W9X request we now end with a pair of
|
||||
bytes (usually 0xFE 0xFF) whereas with NT we have two further
|
||||
strings - the following is a simple way of detecting this */
|
||||
if (len - PTR_DIFF(q, buf) <= 3) {
|
||||
short_request = True;
|
||||
} else {
|
||||
unicomp = q;
|
||||
getdc = skip_string(machine,1);
|
||||
q = skip_string(getdc,1);
|
||||
q = ALIGN2(q, buf);
|
||||
|
||||
/* A full length (NT style) request */
|
||||
q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp));
|
||||
/* At this point we can work out if this is a W9X or NT style
|
||||
request. Experiments show that the difference is wether the
|
||||
packet ends here. For a W9X request we now end with a pair of
|
||||
bytes (usually 0xFE 0xFF) whereas with NT we have two further
|
||||
strings - the following is a simple way of detecting this */
|
||||
|
||||
if (len - PTR_DIFF(q, buf) > 8) {
|
||||
if (len - PTR_DIFF(q, buf) <= 3) {
|
||||
short_request = True;
|
||||
} else {
|
||||
unicomp = q;
|
||||
|
||||
/* A full length (NT style) request */
|
||||
q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp));
|
||||
|
||||
if (len - PTR_DIFF(q, buf) > 8) {
|
||||
/* with NT5 clients we can sometimes
|
||||
get additional data - a length specificed string
|
||||
containing the domain name, then 16 bytes of
|
||||
data (no idea what it is) */
|
||||
int dom_len = CVAL(q, 0);
|
||||
q++;
|
||||
if (dom_len != 0) {
|
||||
q += dom_len + 1;
|
||||
}
|
||||
q += 16;
|
||||
}
|
||||
ntversion = IVAL(q, 0);
|
||||
lmnttoken = SVAL(q, 4);
|
||||
lm20token = SVAL(q, 6);
|
||||
}
|
||||
|
||||
/* Construct reply. */
|
||||
q = outbuf;
|
||||
SSVAL(q, 0, QUERYFORPDC_R);
|
||||
q += 2;
|
||||
|
||||
fstrcpy(reply_name,my_name);
|
||||
push_ascii_fstring(q, reply_name);
|
||||
q = skip_string(q, 1); /* PDC name */
|
||||
|
||||
/* PDC and domain name */
|
||||
if (!short_request) {
|
||||
/* Make a full reply */
|
||||
q = ALIGN2(q, outbuf);
|
||||
|
||||
q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */
|
||||
q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/
|
||||
SIVAL(q, 0, 1); /* our nt version */
|
||||
SSVAL(q, 4, 0xffff); /* our lmnttoken */
|
||||
SSVAL(q, 6, 0xffff); /* our lm20token */
|
||||
q += 8;
|
||||
}
|
||||
|
||||
/* RJS, 21-Feb-2000, we send a short reply if the request was short */
|
||||
|
||||
pull_ascii_fstring(mach_str, machine);
|
||||
|
||||
DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \
|
||||
reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
|
||||
mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(),
|
||||
QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken,
|
||||
(uint32)lm20token ));
|
||||
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
|
||||
pull_ascii_fstring(getdc_str, getdc);
|
||||
pull_ascii_nstring(source_name, dgram->source_name.name);
|
||||
|
||||
send_mailslot(True, getdc_str,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
source_name,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
return;
|
||||
}
|
||||
|
||||
case SAMLOGON:
|
||||
|
||||
{
|
||||
fstring getdc_str;
|
||||
nstring source_name;
|
||||
char *q = buf + 2;
|
||||
fstring asccomp;
|
||||
|
||||
q += 2;
|
||||
unicomp = q;
|
||||
uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp));
|
||||
getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser));
|
||||
q = skip_string(getdc,1);
|
||||
q += 4; /* Account Control Bits - indicating username type */
|
||||
domainsidsize = IVAL(q, 0);
|
||||
q += 4;
|
||||
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len));
|
||||
|
||||
if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) {
|
||||
q += domainsidsize;
|
||||
q = ALIGN4(q, buf);
|
||||
}
|
||||
|
||||
DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
|
||||
|
||||
if (len - PTR_DIFF(q, buf) > 8) {
|
||||
/* with NT5 clients we can sometimes
|
||||
get additional data - a length specificed string
|
||||
containing the domain name, then 16 bytes of
|
||||
data (no idea what it is) */
|
||||
get additional data - a length specificed string
|
||||
containing the domain name, then 16 bytes of
|
||||
data (no idea what it is) */
|
||||
int dom_len = CVAL(q, 0);
|
||||
q++;
|
||||
if (dom_len != 0) {
|
||||
if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) {
|
||||
q += dom_len + 1;
|
||||
}
|
||||
q += 16;
|
||||
}
|
||||
ntversion = IVAL(q, 0);
|
||||
lmnttoken = SVAL(q, 4);
|
||||
lm20token = SVAL(q, 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct reply. */
|
||||
q = outbuf;
|
||||
SSVAL(q, 0, QUERYFORPDC_R);
|
||||
q += 2;
|
||||
ntversion = IVAL(q, 0);
|
||||
lmnttoken = SVAL(q, 4);
|
||||
lm20token = SVAL(q, 6);
|
||||
q += 8;
|
||||
|
||||
fstrcpy(reply_name,my_name);
|
||||
fstrcpy(q, reply_name);
|
||||
q = skip_string(q, 1); /* PDC name */
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
|
||||
|
||||
/* PDC and domain name */
|
||||
if (!short_request) /* Make a full reply */
|
||||
{
|
||||
q = ALIGN2(q, outbuf);
|
||||
/*
|
||||
* we respond regadless of whether the machine is in our password
|
||||
* database. If it isn't then we let smbd send an appropriate error.
|
||||
* Let's ignore the SID.
|
||||
*/
|
||||
pull_ucs2_pstring(ascuser, uniuser);
|
||||
pull_ucs2_fstring(asccomp, unicomp);
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
|
||||
|
||||
q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */
|
||||
q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/
|
||||
SIVAL(q, 0, 1); /* our nt version */
|
||||
SSVAL(q, 4, 0xffff); /* our lmnttoken */
|
||||
SSVAL(q, 6, 0xffff); /* our lm20token */
|
||||
q += 8;
|
||||
}
|
||||
fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */
|
||||
fstrcat(reply_name, my_name);
|
||||
|
||||
/* RJS, 21-Feb-2000, we send a short reply if the request was short */
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
|
||||
asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(),
|
||||
SAMLOGON_R ,lmnttoken));
|
||||
|
||||
DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \
|
||||
reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
|
||||
machine,inet_ntoa(p->ip), reply_name, lp_workgroup(),
|
||||
QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken,
|
||||
(uint32)lm20token ));
|
||||
/* Construct reply. */
|
||||
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
q = outbuf;
|
||||
/* we want the simple version unless we are an ADS PDC..which means */
|
||||
/* never, at least for now */
|
||||
if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) {
|
||||
if (SVAL(uniuser, 0) == 0) {
|
||||
SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
|
||||
} else {
|
||||
SSVAL(q, 0, SAMLOGON_R);
|
||||
}
|
||||
|
||||
send_mailslot(True, getdc,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
dgram->source_name.name,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
return;
|
||||
}
|
||||
q += 2;
|
||||
|
||||
case SAMLOGON:
|
||||
{
|
||||
char *q = buf + 2;
|
||||
fstring asccomp;
|
||||
|
||||
q += 2;
|
||||
unicomp = q;
|
||||
uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp));
|
||||
getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser));
|
||||
q = skip_string(getdc,1);
|
||||
q += 4; /* Account Control Bits - indicating username type */
|
||||
domainsidsize = IVAL(q, 0);
|
||||
q += 4;
|
||||
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len));
|
||||
|
||||
if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) {
|
||||
q += domainsidsize;
|
||||
q = ALIGN4(q, buf);
|
||||
}
|
||||
|
||||
DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
|
||||
|
||||
if (len - PTR_DIFF(q, buf) > 8) {
|
||||
/* with NT5 clients we can sometimes
|
||||
get additional data - a length specificed string
|
||||
containing the domain name, then 16 bytes of
|
||||
data (no idea what it is) */
|
||||
int dom_len = CVAL(q, 0);
|
||||
q++;
|
||||
if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) {
|
||||
q += dom_len + 1;
|
||||
}
|
||||
q += 16;
|
||||
}
|
||||
|
||||
ntversion = IVAL(q, 0);
|
||||
lmnttoken = SVAL(q, 4);
|
||||
lm20token = SVAL(q, 6);
|
||||
q += 8;
|
||||
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
|
||||
|
||||
/*
|
||||
* we respond regadless of whether the machine is in our password
|
||||
* database. If it isn't then we let smbd send an appropriate error.
|
||||
* Let's ignore the SID.
|
||||
*/
|
||||
pull_ucs2_pstring(ascuser, uniuser);
|
||||
pull_ucs2_fstring(asccomp, unicomp);
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
|
||||
|
||||
fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */
|
||||
fstrcat(reply_name, my_name);
|
||||
|
||||
DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
|
||||
asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(),
|
||||
SAMLOGON_R ,lmnttoken));
|
||||
|
||||
/* Construct reply. */
|
||||
|
||||
q = outbuf;
|
||||
/* we want the simple version unless we are an ADS PDC..which means */
|
||||
/* never, at least for now */
|
||||
if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) {
|
||||
if (SVAL(uniuser, 0) == 0) {
|
||||
SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
|
||||
} else {
|
||||
SSVAL(q, 0, SAMLOGON_R);
|
||||
}
|
||||
|
||||
q += 2;
|
||||
|
||||
q += dos_PutUniCode(q, reply_name,sizeof(pstring), True);
|
||||
q += dos_PutUniCode(q, ascuser, sizeof(pstring), True);
|
||||
q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True);
|
||||
}
|
||||
q += dos_PutUniCode(q, reply_name,sizeof(pstring), True);
|
||||
q += dos_PutUniCode(q, ascuser, sizeof(pstring), True);
|
||||
q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True);
|
||||
}
|
||||
#ifdef HAVE_ADS
|
||||
else {
|
||||
GUID domain_guid;
|
||||
pstring domain;
|
||||
pstring hostname;
|
||||
char *component, *dc, *q1;
|
||||
uint8 size;
|
||||
char *q_orig = q;
|
||||
int str_offset;
|
||||
else {
|
||||
GUID domain_guid;
|
||||
pstring domain;
|
||||
pstring hostname;
|
||||
char *component, *dc, *q1;
|
||||
uint8 size;
|
||||
char *q_orig = q;
|
||||
int str_offset;
|
||||
|
||||
get_mydomname(domain);
|
||||
get_myname(hostname);
|
||||
get_mydomname(domain);
|
||||
get_myname(hostname);
|
||||
|
||||
if (SVAL(uniuser, 0) == 0) {
|
||||
SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */
|
||||
} else {
|
||||
SIVAL(q, 0, SAMLOGON_AD_R);
|
||||
}
|
||||
q += 4;
|
||||
if (SVAL(uniuser, 0) == 0) {
|
||||
SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */
|
||||
} else {
|
||||
SIVAL(q, 0, SAMLOGON_AD_R);
|
||||
}
|
||||
q += 4;
|
||||
|
||||
SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS|
|
||||
ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE);
|
||||
q += 4;
|
||||
SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS|
|
||||
ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE);
|
||||
q += 4;
|
||||
|
||||
/* Push Domain GUID */
|
||||
if (False == secrets_fetch_domain_guid(domain, &domain_guid)) {
|
||||
DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain));
|
||||
return;
|
||||
}
|
||||
memcpy(q, &domain_guid, sizeof(domain_guid));
|
||||
q += sizeof(domain_guid);
|
||||
/* Push Domain GUID */
|
||||
if (False == secrets_fetch_domain_guid(domain, &domain_guid)) {
|
||||
DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain));
|
||||
return;
|
||||
}
|
||||
memcpy(q, &domain_guid, sizeof(domain_guid));
|
||||
q += sizeof(domain_guid);
|
||||
|
||||
/* Forest */
|
||||
str_offset = q - q_orig;
|
||||
dc = domain;
|
||||
q1 = q;
|
||||
while ((component = strtok(dc, "."))) {
|
||||
dc = NULL;
|
||||
size = push_ascii(&q[1], component, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
}
|
||||
/* Forest */
|
||||
str_offset = q - q_orig;
|
||||
dc = domain;
|
||||
q1 = q;
|
||||
while ((component = strtok(dc, "."))) {
|
||||
dc = NULL;
|
||||
size = push_ascii(&q[1], component, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
}
|
||||
|
||||
/* Unk0 */
|
||||
SCVAL(q, 0, 0); q++;
|
||||
/* Unk0 */
|
||||
SCVAL(q, 0, 0);
|
||||
q++;
|
||||
|
||||
/* Domain */
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
/* Domain */
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
|
||||
/* Hostname */
|
||||
size = push_ascii(&q[1], hostname, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
/* Hostname */
|
||||
size = push_ascii(&q[1], hostname, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
|
||||
/* NETBIOS of domain */
|
||||
size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
/* NETBIOS of domain */
|
||||
size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
|
||||
/* Unk1 */
|
||||
SCVAL(q, 0, 0); q++;
|
||||
/* Unk1 */
|
||||
SCVAL(q, 0, 0);
|
||||
q++;
|
||||
|
||||
/* NETBIOS of hostname */
|
||||
size = push_ascii(&q[1], my_name, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
/* NETBIOS of hostname */
|
||||
size = push_ascii(&q[1], my_name, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
|
||||
/* Unk2 */
|
||||
SCVAL(q, 0, 0); q++;
|
||||
/* Unk2 */
|
||||
SCVAL(q, 0, 0);
|
||||
q++;
|
||||
|
||||
/* User name */
|
||||
if (SVAL(uniuser, 0) != 0) {
|
||||
size = push_ascii(&q[1], ascuser, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
}
|
||||
/* User name */
|
||||
if (SVAL(uniuser, 0) != 0) {
|
||||
size = push_ascii(&q[1], ascuser, -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
}
|
||||
|
||||
q_orig = q;
|
||||
/* Site name */
|
||||
size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
q_orig = q;
|
||||
/* Site name */
|
||||
size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0);
|
||||
SCVAL(q, 0, size);
|
||||
q += (size + 1);
|
||||
|
||||
/* Site name (2) */
|
||||
str_offset = q - q_orig;
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
/* Site name (2) */
|
||||
str_offset = q - q_orig;
|
||||
SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
|
||||
SCVAL(q, 1, str_offset & 0xFF);
|
||||
q += 2;
|
||||
|
||||
SCVAL(q, 0, PTR_DIFF(q,q1));
|
||||
SCVAL(q, 1, 0x10); /* unknown */
|
||||
SCVAL(q, 0, PTR_DIFF(q,q1));
|
||||
SCVAL(q, 1, 0x10); /* unknown */
|
||||
|
||||
SIVAL(q, 0, 0x00000002); q += 4; /* unknown */
|
||||
SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4;
|
||||
SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
|
||||
SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
|
||||
}
|
||||
SIVAL(q, 0, 0x00000002);
|
||||
q += 4; /* unknown */
|
||||
SIVAL(q, 0, (iface_ip(p->ip))->s_addr);
|
||||
q += 4;
|
||||
SIVAL(q, 0, 0x00000000);
|
||||
q += 4; /* unknown */
|
||||
SIVAL(q, 0, 0x00000000);
|
||||
q += 4; /* unknown */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* tell the client what version we are */
|
||||
SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13);
|
||||
/* our ntversion */
|
||||
SSVAL(q, 4, 0xffff); /* our lmnttoken */
|
||||
SSVAL(q, 6, 0xffff); /* our lm20token */
|
||||
q += 8;
|
||||
/* tell the client what version we are */
|
||||
SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13);
|
||||
/* our ntversion */
|
||||
SSVAL(q, 4, 0xffff); /* our lmnttoken */
|
||||
SSVAL(q, 6, 0xffff); /* our lm20token */
|
||||
q += 8;
|
||||
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
dump_data(4, outbuf, PTR_DIFF(q, outbuf));
|
||||
|
||||
send_mailslot(True, getdc,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
dgram->source_name.name,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
break;
|
||||
}
|
||||
pull_ascii_fstring(getdc_str, getdc);
|
||||
pull_ascii_nstring(source_name, dgram->source_name.name);
|
||||
|
||||
/* Announce change to UAS or SAM. Send by the domain controller when a
|
||||
replication event is required. */
|
||||
send_mailslot(True, getdc,
|
||||
outbuf,PTR_DIFF(q,outbuf),
|
||||
global_myname(), 0x0,
|
||||
dgram->source_name.name,
|
||||
dgram->source_name.name_type,
|
||||
p->ip, *iface_ip(p->ip), p->port);
|
||||
break;
|
||||
}
|
||||
|
||||
case SAM_UAS_CHANGE: {
|
||||
struct sam_database_info *db_info;
|
||||
char *q = buf + 2;
|
||||
int i, db_count;
|
||||
uint32 low_serial;
|
||||
/* Announce change to UAS or SAM. Send by the domain controller when a
|
||||
replication event is required. */
|
||||
|
||||
case SAM_UAS_CHANGE:
|
||||
{
|
||||
struct sam_database_info *db_info;
|
||||
char *q = buf + 2;
|
||||
int i, db_count;
|
||||
uint32 low_serial;
|
||||
|
||||
/* Header */
|
||||
/* Header */
|
||||
|
||||
low_serial = IVAL(q, 0); q += 4; /* Low serial number */
|
||||
low_serial = IVAL(q, 0); q += 4; /* Low serial number */
|
||||
|
||||
q += 4; /* Date/time */
|
||||
q += 4; /* Pulse */
|
||||
q += 4; /* Random */
|
||||
q += 4; /* Date/time */
|
||||
q += 4; /* Pulse */
|
||||
q += 4; /* Random */
|
||||
|
||||
/* Domain info */
|
||||
/* Domain info */
|
||||
|
||||
q = skip_string(q, 1); /* PDC name */
|
||||
q = skip_string(q, 1); /* Domain name */
|
||||
q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */
|
||||
q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */
|
||||
q = skip_string(q, 1); /* PDC name */
|
||||
q = skip_string(q, 1); /* Domain name */
|
||||
q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */
|
||||
q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */
|
||||
|
||||
/* Database info */
|
||||
/* Database info */
|
||||
|
||||
db_count = SVAL(q, 0); q += 2;
|
||||
db_count = SVAL(q, 0); q += 2;
|
||||
|
||||
db_info = (struct sam_database_info *)
|
||||
malloc(sizeof(struct sam_database_info) * db_count);
|
||||
db_info = (struct sam_database_info *)
|
||||
malloc(sizeof(struct sam_database_info) * db_count);
|
||||
|
||||
if (db_info == NULL) {
|
||||
DEBUG(3, ("out of memory allocating info for %d databases\n",
|
||||
db_count));
|
||||
return;
|
||||
}
|
||||
if (db_info == NULL) {
|
||||
DEBUG(3, ("out of memory allocating info for %d databases\n", db_count));
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < db_count; i++) {
|
||||
db_info[i].index = IVAL(q, 0);
|
||||
db_info[i].serial_lo = IVAL(q, 4);
|
||||
db_info[i].serial_hi = IVAL(q, 8);
|
||||
db_info[i].date_lo = IVAL(q, 12);
|
||||
db_info[i].date_hi = IVAL(q, 16);
|
||||
q += 20;
|
||||
}
|
||||
for (i = 0; i < db_count; i++) {
|
||||
db_info[i].index = IVAL(q, 0);
|
||||
db_info[i].serial_lo = IVAL(q, 4);
|
||||
db_info[i].serial_hi = IVAL(q, 8);
|
||||
db_info[i].date_lo = IVAL(q, 12);
|
||||
db_info[i].date_hi = IVAL(q, 16);
|
||||
q += 20;
|
||||
}
|
||||
|
||||
/* Domain SID */
|
||||
/* Domain SID */
|
||||
|
||||
q += IVAL(q, 0) + 4; /* 4 byte length plus data */
|
||||
q += IVAL(q, 0) + 4; /* 4 byte length plus data */
|
||||
|
||||
q += 2; /* Alignment? */
|
||||
q += 2; /* Alignment? */
|
||||
|
||||
/* Misc other info */
|
||||
/* Misc other info */
|
||||
|
||||
q += 4; /* NT version (0x1) */
|
||||
q += 2; /* LMNT token (0xff) */
|
||||
q += 2; /* LM20 token (0xff) */
|
||||
q += 4; /* NT version (0x1) */
|
||||
q += 2; /* LMNT token (0xff) */
|
||||
q += 2; /* LM20 token (0xff) */
|
||||
|
||||
SAFE_FREE(db_info); /* Not sure whether we need to do anything
|
||||
useful with these */
|
||||
SAFE_FREE(db_info); /* Not sure whether we need to do anything useful with these */
|
||||
|
||||
/* Send message to smbd */
|
||||
/* Send message to smbd */
|
||||
|
||||
send_repl_message(low_serial);
|
||||
send_repl_message(low_serial);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code));
|
||||
return;
|
||||
}
|
||||
}
|
||||
default:
|
||||
DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -34,27 +34,26 @@ int num_response_packets = 0;
|
||||
static void add_response_record(struct subnet_record *subrec,
|
||||
struct response_record *rrec)
|
||||
{
|
||||
struct response_record *rrec2;
|
||||
struct response_record *rrec2;
|
||||
|
||||
num_response_packets++; /* count of total number of packets still around */
|
||||
num_response_packets++; /* count of total number of packets still around */
|
||||
|
||||
DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
|
||||
rrec->response_id, subrec->subnet_name, num_response_packets));
|
||||
DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
|
||||
rrec->response_id, subrec->subnet_name, num_response_packets));
|
||||
|
||||
if (!subrec->responselist)
|
||||
{
|
||||
subrec->responselist = rrec;
|
||||
rrec->prev = NULL;
|
||||
rrec->next = NULL;
|
||||
return;
|
||||
}
|
||||
if (!subrec->responselist) {
|
||||
subrec->responselist = rrec;
|
||||
rrec->prev = NULL;
|
||||
rrec->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next)
|
||||
;
|
||||
for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next)
|
||||
;
|
||||
|
||||
rrec2->next = rrec;
|
||||
rrec->next = NULL;
|
||||
rrec->prev = rrec2;
|
||||
rrec2->next = rrec;
|
||||
rrec->next = NULL;
|
||||
rrec->prev = rrec2;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -64,32 +63,31 @@ static void add_response_record(struct subnet_record *subrec,
|
||||
void remove_response_record(struct subnet_record *subrec,
|
||||
struct response_record *rrec)
|
||||
{
|
||||
if (rrec->prev)
|
||||
rrec->prev->next = rrec->next;
|
||||
if (rrec->next)
|
||||
rrec->next->prev = rrec->prev;
|
||||
if (rrec->prev)
|
||||
rrec->prev->next = rrec->next;
|
||||
if (rrec->next)
|
||||
rrec->next->prev = rrec->prev;
|
||||
|
||||
if (subrec->responselist == rrec)
|
||||
subrec->responselist = rrec->next;
|
||||
if (subrec->responselist == rrec)
|
||||
subrec->responselist = rrec->next;
|
||||
|
||||
if(rrec->userdata)
|
||||
{
|
||||
if(rrec->userdata->free_fn) {
|
||||
(*rrec->userdata->free_fn)(rrec->userdata);
|
||||
} else {
|
||||
ZERO_STRUCTP(rrec->userdata);
|
||||
SAFE_FREE(rrec->userdata);
|
||||
}
|
||||
}
|
||||
if(rrec->userdata) {
|
||||
if(rrec->userdata->free_fn) {
|
||||
(*rrec->userdata->free_fn)(rrec->userdata);
|
||||
} else {
|
||||
ZERO_STRUCTP(rrec->userdata);
|
||||
SAFE_FREE(rrec->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure we can delete. */
|
||||
rrec->packet->locked = False;
|
||||
free_packet(rrec->packet);
|
||||
/* Ensure we can delete. */
|
||||
rrec->packet->locked = False;
|
||||
free_packet(rrec->packet);
|
||||
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
|
||||
num_response_packets--; /* count of total number of packets still around */
|
||||
num_response_packets--; /* count of total number of packets still around */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -104,77 +102,70 @@ struct response_record *make_response_record( struct subnet_record *subrec,
|
||||
fail_function fail_fn,
|
||||
struct userdata_struct *userdata)
|
||||
{
|
||||
struct response_record *rrec;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
struct response_record *rrec;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
|
||||
if (!(rrec = (struct response_record *)malloc(sizeof(*rrec))))
|
||||
{
|
||||
DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n"));
|
||||
return NULL;
|
||||
}
|
||||
if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) {
|
||||
DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset((char *)rrec, '\0', sizeof(*rrec));
|
||||
memset((char *)rrec, '\0', sizeof(*rrec));
|
||||
|
||||
rrec->response_id = nmb->header.name_trn_id;
|
||||
rrec->response_id = nmb->header.name_trn_id;
|
||||
|
||||
rrec->resp_fn = resp_fn;
|
||||
rrec->timeout_fn = timeout_fn;
|
||||
rrec->success_fn = success_fn;
|
||||
rrec->fail_fn = fail_fn;
|
||||
rrec->resp_fn = resp_fn;
|
||||
rrec->timeout_fn = timeout_fn;
|
||||
rrec->success_fn = success_fn;
|
||||
rrec->fail_fn = fail_fn;
|
||||
|
||||
rrec->packet = p;
|
||||
rrec->packet = p;
|
||||
|
||||
if(userdata)
|
||||
{
|
||||
/* Intelligent userdata. */
|
||||
if(userdata->copy_fn)
|
||||
{
|
||||
if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL)
|
||||
{
|
||||
DEBUG(0,("make_response_queue_record: copy fail for userdata.\n"));
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primitive userdata, do a memcpy. */
|
||||
if((rrec->userdata = (struct userdata_struct *)
|
||||
malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL)
|
||||
{
|
||||
DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n"));
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
return NULL;
|
||||
}
|
||||
rrec->userdata->copy_fn = userdata->copy_fn;
|
||||
rrec->userdata->free_fn = userdata->free_fn;
|
||||
rrec->userdata->userdata_len = userdata->userdata_len;
|
||||
memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
rrec->userdata = NULL;
|
||||
if(userdata) {
|
||||
/* Intelligent userdata. */
|
||||
if(userdata->copy_fn) {
|
||||
if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) {
|
||||
DEBUG(0,("make_response_queue_record: copy fail for userdata.\n"));
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* Primitive userdata, do a memcpy. */
|
||||
if((rrec->userdata = (struct userdata_struct *)
|
||||
malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) {
|
||||
DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n"));
|
||||
ZERO_STRUCTP(rrec);
|
||||
SAFE_FREE(rrec);
|
||||
return NULL;
|
||||
}
|
||||
rrec->userdata->copy_fn = userdata->copy_fn;
|
||||
rrec->userdata->free_fn = userdata->free_fn;
|
||||
rrec->userdata->userdata_len = userdata->userdata_len;
|
||||
memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len);
|
||||
}
|
||||
} else {
|
||||
rrec->userdata = NULL;
|
||||
}
|
||||
|
||||
rrec->num_msgs = 0;
|
||||
rrec->num_msgs = 0;
|
||||
|
||||
if(!nmb->header.nm_flags.bcast)
|
||||
rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */
|
||||
else
|
||||
rrec->repeat_interval = 1; /* XXXX should be in ms */
|
||||
rrec->repeat_count = 3; /* 3 retries */
|
||||
rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */
|
||||
if(!nmb->header.nm_flags.bcast)
|
||||
rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */
|
||||
else
|
||||
rrec->repeat_interval = 1; /* XXXX should be in ms */
|
||||
rrec->repeat_count = 3; /* 3 retries */
|
||||
rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */
|
||||
|
||||
/* This packet is not being processed. */
|
||||
rrec->in_expiration_processing = False;
|
||||
/* This packet is not being processed. */
|
||||
rrec->in_expiration_processing = False;
|
||||
|
||||
/* Lock the packet so we won't lose it while it's on the list. */
|
||||
p->locked = True;
|
||||
/* Lock the packet so we won't lose it while it's on the list. */
|
||||
p->locked = True;
|
||||
|
||||
add_response_record(subrec, rrec);
|
||||
add_response_record(subrec, rrec);
|
||||
|
||||
return rrec;
|
||||
return rrec;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -184,18 +175,16 @@ struct response_record *make_response_record( struct subnet_record *subrec,
|
||||
static struct response_record *find_response_record_on_subnet(
|
||||
struct subnet_record *subrec, uint16 id)
|
||||
{
|
||||
struct response_record *rrec = NULL;
|
||||
struct response_record *rrec = NULL;
|
||||
|
||||
for (rrec = subrec->responselist; rrec; rrec = rrec->next)
|
||||
{
|
||||
if (rrec->response_id == id)
|
||||
{
|
||||
DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n",
|
||||
id, subrec->subnet_name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rrec;
|
||||
for (rrec = subrec->responselist; rrec; rrec = rrec->next) {
|
||||
if (rrec->response_id == id) {
|
||||
DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n",
|
||||
id, subrec->subnet_name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rrec;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -205,37 +194,34 @@ static struct response_record *find_response_record_on_subnet(
|
||||
struct response_record *find_response_record(struct subnet_record **ppsubrec,
|
||||
uint16 id)
|
||||
{
|
||||
struct response_record *rrec = NULL;
|
||||
struct response_record *rrec = NULL;
|
||||
|
||||
for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec);
|
||||
(*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec))
|
||||
{
|
||||
if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL)
|
||||
return rrec;
|
||||
}
|
||||
for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec);
|
||||
(*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) {
|
||||
if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL)
|
||||
return rrec;
|
||||
}
|
||||
|
||||
/* There should never be response records on the remote_broadcast subnet.
|
||||
Sanity check to ensure this is so. */
|
||||
if(remote_broadcast_subnet->responselist != NULL)
|
||||
{
|
||||
DEBUG(0,("find_response_record: response record found on subnet %s. This should \
|
||||
/* There should never be response records on the remote_broadcast subnet.
|
||||
Sanity check to ensure this is so. */
|
||||
if(remote_broadcast_subnet->responselist != NULL) {
|
||||
DEBUG(0,("find_response_record: response record found on subnet %s. This should \
|
||||
never happen !\n", remote_broadcast_subnet->subnet_name));
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check the WINS server subnet if it exists. */
|
||||
if(wins_server_subnet != NULL)
|
||||
{
|
||||
*ppsubrec = wins_server_subnet;
|
||||
if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL)
|
||||
return rrec;
|
||||
}
|
||||
/* Now check the WINS server subnet if it exists. */
|
||||
if(wins_server_subnet != NULL) {
|
||||
*ppsubrec = wins_server_subnet;
|
||||
if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL)
|
||||
return rrec;
|
||||
}
|
||||
|
||||
DEBUG(0,("find_response_record: response packet id %hu received with no \
|
||||
DEBUG(0,("find_response_record: response packet id %hu received with no \
|
||||
matching record.\n", id));
|
||||
|
||||
*ppsubrec = NULL;
|
||||
*ppsubrec = NULL;
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -244,21 +230,19 @@ matching record.\n", id));
|
||||
|
||||
BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec)
|
||||
{
|
||||
struct response_record *rrec = NULL;
|
||||
struct response_record *rrec = NULL;
|
||||
|
||||
for (rrec = subrec->responselist; rrec; rrec = rrec->next)
|
||||
{
|
||||
struct packet_struct *p = rrec->packet;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
for (rrec = subrec->responselist; rrec; rrec = rrec->next) {
|
||||
struct packet_struct *p = rrec->packet;
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
|
||||
if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
|
||||
(nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9))
|
||||
{
|
||||
/* Yes it's a queued refresh - check if the name is correct. */
|
||||
if(nmb_name_equal(&nmb->question.question_name, &namerec->name))
|
||||
return True;
|
||||
}
|
||||
}
|
||||
if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
|
||||
(nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) {
|
||||
/* Yes it's a queued refresh - check if the name is correct. */
|
||||
if(nmb_name_equal(&nmb->question.question_name, &namerec->name))
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
@ -35,21 +35,21 @@ extern BOOL found_lm_clients;
|
||||
|
||||
void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip)
|
||||
{
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
|
||||
DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
|
||||
reset_type, to_name, to_type, inet_ntoa(to_ip) ));
|
||||
DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
|
||||
reset_type, to_name, to_type, inet_ntoa(to_ip) ));
|
||||
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_ResetBrowserState);
|
||||
p++;
|
||||
SCVAL(p,0,reset_type);
|
||||
p++;
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_ResetBrowserState);
|
||||
p++;
|
||||
SCVAL(p,0,reset_type);
|
||||
p++;
|
||||
|
||||
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, to_name, to_type, to_ip,
|
||||
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, to_name, to_type, to_ip,
|
||||
FIRST_SUBNET->myip, DGRAM_PORT);
|
||||
}
|
||||
|
||||
@ -60,25 +60,25 @@ void send_browser_reset(int reset_type, const char *to_name, int to_type, struct
|
||||
|
||||
void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work)
|
||||
{
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
|
||||
work->needannounce = True;
|
||||
work->needannounce = True;
|
||||
|
||||
DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
|
||||
DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
|
||||
to subnet %s\n", work->work_group, subrec->subnet_name));
|
||||
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_AnnouncementRequest);
|
||||
p++;
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_AnnouncementRequest);
|
||||
p++;
|
||||
|
||||
SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */
|
||||
p++;
|
||||
p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */
|
||||
p++;
|
||||
p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
|
||||
send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip,
|
||||
send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip,
|
||||
subrec->myip, DGRAM_PORT);
|
||||
}
|
||||
|
||||
@ -91,33 +91,33 @@ static void send_announcement(struct subnet_record *subrec, int announce_type,
|
||||
time_t announce_interval,
|
||||
const char *server_name, int server_type, const char *server_comment)
|
||||
{
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf+1;
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf+1;
|
||||
|
||||
SCVAL(outbuf,0,announce_type);
|
||||
SCVAL(outbuf,0,announce_type);
|
||||
|
||||
/* Announcement parameters. */
|
||||
SCVAL(p,0,updatecount);
|
||||
SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
|
||||
/* Announcement parameters. */
|
||||
SCVAL(p,0,updatecount);
|
||||
SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
|
||||
|
||||
push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
|
||||
SCVAL(p,21,lp_major_announce_version()); /* Major version. */
|
||||
SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */
|
||||
SCVAL(p,21,lp_major_announce_version()); /* Major version. */
|
||||
SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */
|
||||
|
||||
SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
|
||||
/* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */
|
||||
SSVAL(p,27,BROWSER_ELECTION_VERSION);
|
||||
SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
|
||||
SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
|
||||
/* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */
|
||||
SSVAL(p,27,BROWSER_ELECTION_VERSION);
|
||||
SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
|
||||
|
||||
p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE);
|
||||
p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE);
|
||||
|
||||
send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||
from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
|
||||
DGRAM_PORT);
|
||||
send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||
from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
|
||||
DGRAM_PORT);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -129,28 +129,23 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type
|
||||
time_t announce_interval,
|
||||
char *server_name, int server_type, char *server_comment)
|
||||
{
|
||||
pstring outbuf;
|
||||
char *p=outbuf;
|
||||
pstring outbuf;
|
||||
char *p=outbuf;
|
||||
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
|
||||
SSVAL(p,0,announce_type);
|
||||
SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
|
||||
SCVAL(p,6,lp_major_announce_version()); /* Major version. */
|
||||
SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */
|
||||
SSVAL(p,8,announce_interval); /* In seconds - according to spec. */
|
||||
SSVAL(p,0,announce_type);
|
||||
SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
|
||||
SCVAL(p,6,lp_major_announce_version()); /* Major version. */
|
||||
SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */
|
||||
SSVAL(p,8,announce_interval); /* In seconds - according to spec. */
|
||||
|
||||
p += 10;
|
||||
/*StrnCpy(p,server_name,15);
|
||||
strupper_m(p);
|
||||
p = skip_string(p,1);
|
||||
pstrcpy(p,server_comment);
|
||||
p = skip_string(p,1);*/
|
||||
p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
p += 10;
|
||||
p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE);
|
||||
|
||||
send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||
from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
|
||||
send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||
from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
|
||||
DGRAM_PORT);
|
||||
}
|
||||
|
||||
@ -161,20 +156,20 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type
|
||||
static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work,
|
||||
struct server_record *servrec)
|
||||
{
|
||||
/* Ensure we don't have the prohibited bit set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
/* Ensure we don't have the prohibited bit set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
|
||||
DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
|
||||
type, global_myname(), subrec->subnet_name, work->work_group));
|
||||
DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
|
||||
type, global_myname(), subrec->subnet_name, work->work_group));
|
||||
|
||||
send_announcement(subrec, ANN_LocalMasterAnnouncement,
|
||||
global_myname(), /* From nbt name. */
|
||||
work->work_group, 0x1e, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
global_myname(), /* Name to announce. */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
send_announcement(subrec, ANN_LocalMasterAnnouncement,
|
||||
global_myname(), /* From nbt name. */
|
||||
work->work_group, 0x1e, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
global_myname(), /* Name to announce. */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -183,17 +178,17 @@ static void send_local_master_announcement(struct subnet_record *subrec, struct
|
||||
|
||||
static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work)
|
||||
{
|
||||
DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n",
|
||||
subrec->subnet_name, work->work_group));
|
||||
DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n",
|
||||
subrec->subnet_name, work->work_group));
|
||||
|
||||
send_announcement(subrec, ANN_DomainAnnouncement,
|
||||
global_myname(), /* From nbt name. */
|
||||
MSBROWSE, 0x1, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
work->work_group, /* Name to announce. */
|
||||
SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */
|
||||
global_myname()); /* From name as comment. */
|
||||
send_announcement(subrec, ANN_DomainAnnouncement,
|
||||
global_myname(), /* From nbt name. */
|
||||
MSBROWSE, 0x1, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
work->work_group, /* Name to announce. */
|
||||
SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */
|
||||
global_myname()); /* From name as comment. */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -203,20 +198,20 @@ static void send_workgroup_announcement(struct subnet_record *subrec, struct wor
|
||||
static void send_host_announcement(struct subnet_record *subrec, struct work_record *work,
|
||||
struct server_record *servrec)
|
||||
{
|
||||
/* Ensure we don't have the prohibited bits set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
/* Ensure we don't have the prohibited bits set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
|
||||
DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
|
||||
type, servrec->serv.name, subrec->subnet_name, work->work_group));
|
||||
DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
|
||||
type, servrec->serv.name, subrec->subnet_name, work->work_group));
|
||||
|
||||
send_announcement(subrec, ANN_HostAnnouncement,
|
||||
servrec->serv.name, /* From nbt name. */
|
||||
work->work_group, 0x1d, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
servrec->serv.name, /* Name to announce. */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
send_announcement(subrec, ANN_HostAnnouncement,
|
||||
servrec->serv.name, /* From nbt name. */
|
||||
work->work_group, 0x1d, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
work->announce_interval, /* Time until next announce. */
|
||||
servrec->serv.name, /* Name to announce. */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -226,20 +221,20 @@ static void send_host_announcement(struct subnet_record *subrec, struct work_rec
|
||||
static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work,
|
||||
struct server_record *servrec, int lm_interval)
|
||||
{
|
||||
/* Ensure we don't have the prohibited bits set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
/* Ensure we don't have the prohibited bits set. */
|
||||
uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
|
||||
|
||||
DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
|
||||
type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval));
|
||||
DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
|
||||
type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval));
|
||||
|
||||
send_lm_announcement(subrec, ANN_HostAnnouncement,
|
||||
servrec->serv.name, /* From nbt name. */
|
||||
work->work_group, 0x00, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
lm_interval, /* Time until next announce. */
|
||||
servrec->serv.name, /* Name to announce. */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
send_lm_announcement(subrec, ANN_HostAnnouncement,
|
||||
servrec->serv.name, /* From nbt name. */
|
||||
work->work_group, 0x00, /* To nbt name. */
|
||||
subrec->bcast_ip, /* To ip. */
|
||||
lm_interval, /* Time until next announce. */
|
||||
servrec->serv.name, /* Name to announce (fstring not netbios name struct). */
|
||||
type, /* Type field. */
|
||||
servrec->serv.comment);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -249,18 +244,15 @@ static void send_lm_host_announcement(struct subnet_record *subrec, struct work_
|
||||
static void announce_server(struct subnet_record *subrec, struct work_record *work,
|
||||
struct server_record *servrec)
|
||||
{
|
||||
/* Only do domain announcements if we are a master and it's
|
||||
our primary name we're being asked to announce. */
|
||||
/* Only do domain announcements if we are a master and it's
|
||||
our primary name we're being asked to announce. */
|
||||
|
||||
if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name))
|
||||
{
|
||||
send_local_master_announcement(subrec, work, servrec);
|
||||
send_workgroup_announcement(subrec, work);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_host_announcement(subrec, work, servrec);
|
||||
}
|
||||
if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) {
|
||||
send_local_master_announcement(subrec, work, servrec);
|
||||
send_workgroup_announcement(subrec, work);
|
||||
} else {
|
||||
send_host_announcement(subrec, work, servrec);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -270,43 +262,39 @@ static void announce_server(struct subnet_record *subrec, struct work_record *wo
|
||||
|
||||
void announce_my_server_names(time_t t)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct subnet_record *subrec;
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
|
||||
if(work)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
if(work) {
|
||||
struct server_record *servrec;
|
||||
|
||||
if (work->needannounce)
|
||||
{
|
||||
/* Drop back to a max 3 minute announce. This is to prevent a
|
||||
single lost packet from breaking things for too long. */
|
||||
if (work->needannounce) {
|
||||
/* Drop back to a max 3 minute announce. This is to prevent a
|
||||
single lost packet from breaking things for too long. */
|
||||
|
||||
work->announce_interval = MIN(work->announce_interval,
|
||||
CHECK_TIME_MIN_HOST_ANNCE*60);
|
||||
work->lastannounce_time = t - (work->announce_interval+1);
|
||||
work->needannounce = False;
|
||||
}
|
||||
work->announce_interval = MIN(work->announce_interval,
|
||||
CHECK_TIME_MIN_HOST_ANNCE*60);
|
||||
work->lastannounce_time = t - (work->announce_interval+1);
|
||||
work->needannounce = False;
|
||||
}
|
||||
|
||||
/* Announce every minute at first then progress to every 12 mins */
|
||||
if ((t - work->lastannounce_time) < work->announce_interval)
|
||||
continue;
|
||||
/* Announce every minute at first then progress to every 12 mins */
|
||||
if ((t - work->lastannounce_time) < work->announce_interval)
|
||||
continue;
|
||||
|
||||
if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
|
||||
work->announce_interval += 60;
|
||||
if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
|
||||
work->announce_interval += 60;
|
||||
|
||||
work->lastannounce_time = t;
|
||||
work->lastannounce_time = t;
|
||||
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next)
|
||||
{
|
||||
if (is_myname(servrec->serv.name))
|
||||
announce_server(subrec, work, servrec);
|
||||
}
|
||||
} /* if work */
|
||||
} /* for subrec */
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next) {
|
||||
if (is_myname(servrec->serv.name))
|
||||
announce_server(subrec, work, servrec);
|
||||
}
|
||||
} /* if work */
|
||||
} /* for subrec */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -316,47 +304,42 @@ void announce_my_server_names(time_t t)
|
||||
|
||||
void announce_my_lm_server_names(time_t t)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
static time_t last_lm_announce_time=0;
|
||||
int announce_interval = lp_lm_interval();
|
||||
int lm_announce = lp_lm_announce();
|
||||
struct subnet_record *subrec;
|
||||
static time_t last_lm_announce_time=0;
|
||||
int announce_interval = lp_lm_interval();
|
||||
int lm_announce = lp_lm_announce();
|
||||
|
||||
if ((announce_interval <= 0) || (lm_announce <= 0))
|
||||
{
|
||||
/* user absolutely does not want LM announcements to be sent. */
|
||||
return;
|
||||
}
|
||||
if ((announce_interval <= 0) || (lm_announce <= 0)) {
|
||||
/* user absolutely does not want LM announcements to be sent. */
|
||||
return;
|
||||
}
|
||||
|
||||
if ((lm_announce >= 2) && (!found_lm_clients))
|
||||
{
|
||||
/* has been set to 2 (Auto) but no LM clients detected (yet). */
|
||||
return;
|
||||
}
|
||||
if ((lm_announce >= 2) && (!found_lm_clients)) {
|
||||
/* has been set to 2 (Auto) but no LM clients detected (yet). */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise: must have been set to 1 (Yes), or LM clients *have*
|
||||
been detected. */
|
||||
/* Otherwise: must have been set to 1 (Yes), or LM clients *have*
|
||||
been detected. */
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
|
||||
|
||||
if(work)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
if(work) {
|
||||
struct server_record *servrec;
|
||||
|
||||
if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
|
||||
continue;
|
||||
if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
|
||||
continue;
|
||||
|
||||
last_lm_announce_time = t;
|
||||
last_lm_announce_time = t;
|
||||
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next)
|
||||
{
|
||||
if (is_myname(servrec->serv.name))
|
||||
/* skipping equivalent of announce_server() */
|
||||
send_lm_host_announcement(subrec, work, servrec, announce_interval);
|
||||
}
|
||||
} /* if work */
|
||||
} /* for subrec */
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next) {
|
||||
if (is_myname(servrec->serv.name))
|
||||
/* skipping equivalent of announce_server() */
|
||||
send_lm_host_announcement(subrec, work, servrec, announce_interval);
|
||||
}
|
||||
} /* if work */
|
||||
} /* for subrec */
|
||||
}
|
||||
|
||||
/* Announce timer. Moved into global static so it can be reset
|
||||
@ -370,7 +353,7 @@ static time_t announce_timer_last=0;
|
||||
|
||||
void reset_announce_timer(void)
|
||||
{
|
||||
announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
|
||||
announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -379,45 +362,40 @@ void reset_announce_timer(void)
|
||||
|
||||
void announce_myself_to_domain_master_browser(time_t t)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct work_record *work;
|
||||
struct subnet_record *subrec;
|
||||
struct work_record *work;
|
||||
|
||||
if(!we_are_a_wins_client())
|
||||
{
|
||||
DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
|
||||
return;
|
||||
}
|
||||
if(!we_are_a_wins_client()) {
|
||||
DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!announce_timer_last)
|
||||
announce_timer_last = t;
|
||||
if (!announce_timer_last)
|
||||
announce_timer_last = t;
|
||||
|
||||
if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60))
|
||||
{
|
||||
DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
|
||||
(int)t, (int)announce_timer_last,
|
||||
CHECK_TIME_MST_ANNOUNCE * 60 ));
|
||||
return;
|
||||
}
|
||||
if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) {
|
||||
DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
|
||||
(int)t, (int)announce_timer_last,
|
||||
CHECK_TIME_MST_ANNOUNCE * 60 ));
|
||||
return;
|
||||
}
|
||||
|
||||
announce_timer_last = t;
|
||||
announce_timer_last = t;
|
||||
|
||||
/* Look over all our broadcast subnets to see if any of them
|
||||
has the state set as local master browser. */
|
||||
/* Look over all our broadcast subnets to see if any of them
|
||||
has the state set as local master browser. */
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
for (work = subrec->workgrouplist; work; work = work->next)
|
||||
{
|
||||
if (AM_LOCAL_MASTER_BROWSER(work))
|
||||
{
|
||||
DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||
if (AM_LOCAL_MASTER_BROWSER(work)) {
|
||||
DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
|
||||
workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
|
||||
|
||||
/* Look in nmbd_browsersync.c for the rest of this code. */
|
||||
announce_and_sync_with_domain_master_browser(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Look in nmbd_browsersync.c for the rest of this code. */
|
||||
announce_and_sync_with_domain_master_browser(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -427,49 +405,43 @@ This must *only* be called on shutdown.
|
||||
|
||||
void announce_my_servers_removed(void)
|
||||
{
|
||||
int announce_interval = lp_lm_interval();
|
||||
int lm_announce = lp_lm_announce();
|
||||
struct subnet_record *subrec;
|
||||
int announce_interval = lp_lm_interval();
|
||||
int lm_announce = lp_lm_announce();
|
||||
struct subnet_record *subrec;
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *work;
|
||||
for (work = subrec->workgrouplist; work; work = work->next)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *work;
|
||||
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||
struct server_record *servrec;
|
||||
|
||||
work->announce_interval = 0;
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next)
|
||||
{
|
||||
if (!is_myname(servrec->serv.name))
|
||||
continue;
|
||||
servrec->serv.type = 0;
|
||||
if(AM_LOCAL_MASTER_BROWSER(work))
|
||||
send_local_master_announcement(subrec, work, servrec);
|
||||
send_host_announcement(subrec, work, servrec);
|
||||
work->announce_interval = 0;
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next) {
|
||||
if (!is_myname(servrec->serv.name))
|
||||
continue;
|
||||
servrec->serv.type = 0;
|
||||
if(AM_LOCAL_MASTER_BROWSER(work))
|
||||
send_local_master_announcement(subrec, work, servrec);
|
||||
send_host_announcement(subrec, work, servrec);
|
||||
|
||||
if ((announce_interval <= 0) || (lm_announce <= 0)) {
|
||||
/* user absolutely does not want LM announcements to be sent. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((announce_interval <= 0) || (lm_announce <= 0))
|
||||
{
|
||||
/* user absolutely does not want LM announcements to be sent. */
|
||||
continue;
|
||||
}
|
||||
if ((lm_announce >= 2) && (!found_lm_clients)) {
|
||||
/* has been set to 2 (Auto) but no LM clients detected (yet). */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((lm_announce >= 2) && (!found_lm_clients))
|
||||
{
|
||||
/* has been set to 2 (Auto) but no LM clients detected (yet). */
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* lm announce was set or we have seen lm announcements, so do
|
||||
* a lm announcement of host removed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* lm announce was set or we have seen lm announcements, so do
|
||||
* a lm announcement of host removed.
|
||||
*/
|
||||
|
||||
send_lm_host_announcement(subrec, work, servrec, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
send_lm_host_announcement(subrec, work, servrec, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -480,132 +452,127 @@ void announce_my_servers_removed(void)
|
||||
|
||||
void announce_remote(time_t t)
|
||||
{
|
||||
char *s;
|
||||
const char *ptr;
|
||||
static time_t last_time = 0;
|
||||
pstring s2;
|
||||
struct in_addr addr;
|
||||
char *comment;
|
||||
int stype = lp_default_server_announce();
|
||||
char *s;
|
||||
const char *ptr;
|
||||
static time_t last_time = 0;
|
||||
pstring s2;
|
||||
struct in_addr addr;
|
||||
char *comment;
|
||||
int stype = lp_default_server_announce();
|
||||
|
||||
if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
|
||||
return;
|
||||
if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
|
||||
return;
|
||||
|
||||
last_time = t;
|
||||
last_time = t;
|
||||
|
||||
s = lp_remote_announce();
|
||||
if (!*s)
|
||||
return;
|
||||
s = lp_remote_announce();
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH);
|
||||
comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH);
|
||||
|
||||
for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); )
|
||||
{
|
||||
/* The entries are of the form a.b.c.d/WORKGROUP with
|
||||
WORKGROUP being optional */
|
||||
const char *wgroup;
|
||||
char *pwgroup;
|
||||
int i;
|
||||
for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) {
|
||||
/* The entries are of the form a.b.c.d/WORKGROUP with
|
||||
WORKGROUP being optional */
|
||||
const char *wgroup;
|
||||
char *pwgroup;
|
||||
int i;
|
||||
|
||||
pwgroup = strchr_m(s2,'/');
|
||||
if (pwgroup)
|
||||
*pwgroup++ = 0;
|
||||
if (!pwgroup || !*pwgroup)
|
||||
wgroup = lp_workgroup();
|
||||
else
|
||||
wgroup = pwgroup;
|
||||
pwgroup = strchr_m(s2,'/');
|
||||
if (pwgroup)
|
||||
*pwgroup++ = 0;
|
||||
if (!pwgroup || !*pwgroup)
|
||||
wgroup = lp_workgroup();
|
||||
else
|
||||
wgroup = pwgroup;
|
||||
|
||||
addr = *interpret_addr2(s2);
|
||||
addr = *interpret_addr2(s2);
|
||||
|
||||
/* Announce all our names including aliases */
|
||||
/* Give the ip address as the address of our first
|
||||
broadcast subnet. */
|
||||
/* Announce all our names including aliases */
|
||||
/* Give the ip address as the address of our first
|
||||
broadcast subnet. */
|
||||
|
||||
for(i=0; my_netbios_names(i); i++)
|
||||
{
|
||||
const char *name = my_netbios_names(i);
|
||||
for(i=0; my_netbios_names(i); i++) {
|
||||
const char *name = my_netbios_names(i);
|
||||
|
||||
DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n",
|
||||
name, inet_ntoa(addr) ));
|
||||
DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n",
|
||||
name, inet_ntoa(addr) ));
|
||||
|
||||
send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
|
||||
name, /* From nbt name. */
|
||||
wgroup, 0x1d, /* To nbt name. */
|
||||
addr, /* To ip. */
|
||||
REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */
|
||||
name, /* Name to announce. */
|
||||
stype, /* Type field. */
|
||||
comment);
|
||||
}
|
||||
}
|
||||
send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
|
||||
name, /* From nbt name. */
|
||||
wgroup, 0x1d, /* To nbt name. */
|
||||
addr, /* To ip. */
|
||||
REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */
|
||||
name, /* Name to announce. */
|
||||
stype, /* Type field. */
|
||||
comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Implement the 'remote browse sync' feature Andrew added.
|
||||
These are used to put our browse lists into remote browse lists.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
void browse_sync_remote(time_t t)
|
||||
{
|
||||
char *s;
|
||||
const char *ptr;
|
||||
static time_t last_time = 0;
|
||||
pstring s2;
|
||||
struct in_addr addr;
|
||||
struct work_record *work;
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
fstring myname;
|
||||
char *s;
|
||||
const char *ptr;
|
||||
static time_t last_time = 0;
|
||||
pstring s2;
|
||||
struct in_addr addr;
|
||||
struct work_record *work;
|
||||
pstring outbuf;
|
||||
char *p;
|
||||
fstring myname;
|
||||
|
||||
if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
|
||||
return;
|
||||
if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
|
||||
return;
|
||||
|
||||
last_time = t;
|
||||
last_time = t;
|
||||
|
||||
s = lp_remote_browse_sync();
|
||||
if (!*s)
|
||||
return;
|
||||
s = lp_remote_browse_sync();
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We only do this if we are the local master browser
|
||||
* for our workgroup on the firsst subnet.
|
||||
*/
|
||||
/*
|
||||
* We only do this if we are the local master browser
|
||||
* for our workgroup on the firsst subnet.
|
||||
*/
|
||||
|
||||
if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL)
|
||||
{
|
||||
DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
|
||||
lp_workgroup(), FIRST_SUBNET->subnet_name ));
|
||||
return;
|
||||
}
|
||||
if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {
|
||||
DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
|
||||
lp_workgroup(), FIRST_SUBNET->subnet_name ));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!AM_LOCAL_MASTER_BROWSER(work))
|
||||
{
|
||||
DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
|
||||
if(!AM_LOCAL_MASTER_BROWSER(work)) {
|
||||
DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
|
||||
for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name ));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_MasterAnnouncement);
|
||||
p++;
|
||||
memset(outbuf,'\0',sizeof(outbuf));
|
||||
p = outbuf;
|
||||
SCVAL(p,0,ANN_MasterAnnouncement);
|
||||
p++;
|
||||
|
||||
fstrcpy(myname, global_myname());
|
||||
strupper_m(myname);
|
||||
myname[15]='\0';
|
||||
push_pstring_base(p, myname, outbuf);
|
||||
fstrcpy(myname, global_myname());
|
||||
strupper_m(myname);
|
||||
myname[15]='\0';
|
||||
push_pstring_base(p, myname, outbuf);
|
||||
|
||||
p = skip_string(p,1);
|
||||
p = skip_string(p,1);
|
||||
|
||||
for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); )
|
||||
{
|
||||
/* The entries are of the form a.b.c.d */
|
||||
addr = *interpret_addr2(s2);
|
||||
for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) {
|
||||
/* The entries are of the form a.b.c.d */
|
||||
addr = *interpret_addr2(s2);
|
||||
|
||||
DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
|
||||
global_myname(), inet_ntoa(addr) ));
|
||||
DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
|
||||
global_myname(), inet_ntoa(addr) ));
|
||||
|
||||
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT);
|
||||
}
|
||||
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
|
||||
global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT);
|
||||
}
|
||||
}
|
||||
|
@ -33,28 +33,26 @@ int updatecount = 0;
|
||||
|
||||
void remove_all_servers(struct work_record *work)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
struct server_record *nexts;
|
||||
struct server_record *servrec;
|
||||
struct server_record *nexts;
|
||||
|
||||
for (servrec = work->serverlist; servrec; servrec = nexts)
|
||||
{
|
||||
DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name));
|
||||
nexts = servrec->next;
|
||||
for (servrec = work->serverlist; servrec; servrec = nexts) {
|
||||
DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name));
|
||||
nexts = servrec->next;
|
||||
|
||||
if (servrec->prev)
|
||||
servrec->prev->next = servrec->next;
|
||||
if (servrec->next)
|
||||
servrec->next->prev = servrec->prev;
|
||||
if (servrec->prev)
|
||||
servrec->prev->next = servrec->next;
|
||||
if (servrec->next)
|
||||
servrec->next->prev = servrec->prev;
|
||||
|
||||
if (work->serverlist == servrec)
|
||||
work->serverlist = servrec->next;
|
||||
if (work->serverlist == servrec)
|
||||
work->serverlist = servrec->next;
|
||||
|
||||
ZERO_STRUCTP(servrec);
|
||||
SAFE_FREE(servrec);
|
||||
ZERO_STRUCTP(servrec);
|
||||
SAFE_FREE(servrec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
work->subnet->work_changed = True;
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -64,23 +62,22 @@ void remove_all_servers(struct work_record *work)
|
||||
static void add_server_to_workgroup(struct work_record *work,
|
||||
struct server_record *servrec)
|
||||
{
|
||||
struct server_record *servrec2;
|
||||
struct server_record *servrec2;
|
||||
|
||||
if (!work->serverlist)
|
||||
{
|
||||
work->serverlist = servrec;
|
||||
servrec->prev = NULL;
|
||||
servrec->next = NULL;
|
||||
return;
|
||||
}
|
||||
if (!work->serverlist) {
|
||||
work->serverlist = servrec;
|
||||
servrec->prev = NULL;
|
||||
servrec->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next)
|
||||
;
|
||||
for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next)
|
||||
;
|
||||
|
||||
servrec2->next = servrec;
|
||||
servrec->next = NULL;
|
||||
servrec->prev = servrec2;
|
||||
work->subnet->work_changed = True;
|
||||
servrec2->next = servrec;
|
||||
servrec->next = NULL;
|
||||
servrec->prev = servrec2;
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -89,14 +86,13 @@ static void add_server_to_workgroup(struct work_record *work,
|
||||
|
||||
struct server_record *find_server_in_workgroup(struct work_record *work, const char *name)
|
||||
{
|
||||
struct server_record *ret;
|
||||
struct server_record *ret;
|
||||
|
||||
for (ret = work->serverlist; ret; ret = ret->next)
|
||||
{
|
||||
if (strequal(ret->serv.name,name))
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
for (ret = work->serverlist; ret; ret = ret->next) {
|
||||
if (strequal(ret->serv.name,name))
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -106,17 +102,17 @@ struct server_record *find_server_in_workgroup(struct work_record *work, const c
|
||||
|
||||
void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec)
|
||||
{
|
||||
if (servrec->prev)
|
||||
servrec->prev->next = servrec->next;
|
||||
if (servrec->next)
|
||||
servrec->next->prev = servrec->prev;
|
||||
if (servrec->prev)
|
||||
servrec->prev->next = servrec->next;
|
||||
if (servrec->next)
|
||||
servrec->next->prev = servrec->prev;
|
||||
|
||||
if (work->serverlist == servrec)
|
||||
work->serverlist = servrec->next;
|
||||
if (work->serverlist == servrec)
|
||||
work->serverlist = servrec->next;
|
||||
|
||||
ZERO_STRUCTP(servrec);
|
||||
SAFE_FREE(servrec);
|
||||
work->subnet->work_changed = True;
|
||||
ZERO_STRUCTP(servrec);
|
||||
SAFE_FREE(servrec);
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -127,47 +123,44 @@ struct server_record *create_server_on_workgroup(struct work_record *work,
|
||||
const char *name,int servertype,
|
||||
int ttl, const char *comment)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
struct server_record *servrec;
|
||||
|
||||
if (name[0] == '*')
|
||||
{
|
||||
DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n",
|
||||
name));
|
||||
return (NULL);
|
||||
}
|
||||
if (name[0] == '*') {
|
||||
DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n",
|
||||
name));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if((servrec = find_server_in_workgroup(work, name)) != NULL)
|
||||
{
|
||||
DEBUG(0,("create_server_on_workgroup: Server %s already exists on \
|
||||
if((servrec = find_server_in_workgroup(work, name)) != NULL) {
|
||||
DEBUG(0,("create_server_on_workgroup: Server %s already exists on \
|
||||
workgroup %s. This is a bug.\n", name, work->work_group));
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL)
|
||||
{
|
||||
DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n"));
|
||||
return NULL;
|
||||
}
|
||||
if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) {
|
||||
DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset((char *)servrec,'\0',sizeof(*servrec));
|
||||
memset((char *)servrec,'\0',sizeof(*servrec));
|
||||
|
||||
servrec->subnet = work->subnet;
|
||||
servrec->subnet = work->subnet;
|
||||
|
||||
fstrcpy(servrec->serv.name,name);
|
||||
fstrcpy(servrec->serv.comment,comment);
|
||||
strupper_m(servrec->serv.name);
|
||||
servrec->serv.type = servertype;
|
||||
fstrcpy(servrec->serv.name,name);
|
||||
fstrcpy(servrec->serv.comment,comment);
|
||||
strupper_m(servrec->serv.name);
|
||||
servrec->serv.type = servertype;
|
||||
|
||||
update_server_ttl(servrec, ttl);
|
||||
update_server_ttl(servrec, ttl);
|
||||
|
||||
add_server_to_workgroup(work, servrec);
|
||||
add_server_to_workgroup(work, servrec);
|
||||
|
||||
DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \
|
||||
DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \
|
||||
workgroup %s.\n", name,servertype,comment, work->work_group));
|
||||
|
||||
work->subnet->work_changed = True;
|
||||
work->subnet->work_changed = True;
|
||||
|
||||
return(servrec);
|
||||
return(servrec);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -176,15 +169,15 @@ workgroup %s.\n", name,servertype,comment, work->work_group));
|
||||
|
||||
void update_server_ttl(struct server_record *servrec, int ttl)
|
||||
{
|
||||
if(ttl > lp_max_ttl())
|
||||
ttl = lp_max_ttl();
|
||||
if(ttl > lp_max_ttl())
|
||||
ttl = lp_max_ttl();
|
||||
|
||||
if(is_myname(servrec->serv.name))
|
||||
servrec->death_time = PERMANENT_TTL;
|
||||
else
|
||||
servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
|
||||
if(is_myname(servrec->serv.name))
|
||||
servrec->death_time = PERMANENT_TTL;
|
||||
else
|
||||
servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
|
||||
|
||||
servrec->subnet->work_changed = True;
|
||||
servrec->subnet->work_changed = True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -195,20 +188,18 @@ void update_server_ttl(struct server_record *servrec, int ttl)
|
||||
|
||||
void expire_servers(struct work_record *work, time_t t)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
struct server_record *nexts;
|
||||
struct server_record *servrec;
|
||||
struct server_record *nexts;
|
||||
|
||||
for (servrec = work->serverlist; servrec; servrec = nexts)
|
||||
{
|
||||
nexts = servrec->next;
|
||||
for (servrec = work->serverlist; servrec; servrec = nexts) {
|
||||
nexts = servrec->next;
|
||||
|
||||
if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t)))
|
||||
{
|
||||
DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name));
|
||||
remove_server_from_workgroup(work, servrec);
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
}
|
||||
if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) {
|
||||
DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name));
|
||||
remove_server_from_workgroup(work, servrec);
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -221,33 +212,30 @@ static uint32 write_this_server_name( struct subnet_record *subrec,
|
||||
struct work_record *work,
|
||||
struct server_record *servrec)
|
||||
{
|
||||
struct subnet_record *ssub;
|
||||
struct work_record *iwork;
|
||||
struct subnet_record *ssub;
|
||||
struct work_record *iwork;
|
||||
|
||||
/* Go through all the subnets we have already seen. */
|
||||
for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub))
|
||||
{
|
||||
for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next)
|
||||
{
|
||||
if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL)
|
||||
{
|
||||
/*
|
||||
* We have already written out this server record, don't
|
||||
* do it again. This gives precedence to servers we have seen
|
||||
* on the broadcast subnets over servers that may have been
|
||||
* added via a sync on the unicast_subet.
|
||||
*
|
||||
* The correct way to do this is to have a serverlist file
|
||||
* per subnet - this means changes to smbd as well. I may
|
||||
* add this at a later date (JRA).
|
||||
*/
|
||||
/* Go through all the subnets we have already seen. */
|
||||
for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) {
|
||||
for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) {
|
||||
if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) {
|
||||
/*
|
||||
* We have already written out this server record, don't
|
||||
* do it again. This gives precedence to servers we have seen
|
||||
* on the broadcast subnets over servers that may have been
|
||||
* added via a sync on the unicast_subet.
|
||||
*
|
||||
* The correct way to do this is to have a serverlist file
|
||||
* per subnet - this means changes to smbd as well. I may
|
||||
* add this at a later date (JRA).
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return servrec->serv.type;
|
||||
return servrec->serv.type;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -261,30 +249,29 @@ static uint32 write_this_server_name( struct subnet_record *subrec,
|
||||
static uint32 write_this_workgroup_name( struct subnet_record *subrec,
|
||||
struct work_record *work)
|
||||
{
|
||||
struct subnet_record *ssub;
|
||||
struct subnet_record *ssub;
|
||||
|
||||
if(strequal(lp_workgroup(), work->work_group))
|
||||
return 0;
|
||||
if(strequal(lp_workgroup(), work->work_group))
|
||||
return 0;
|
||||
|
||||
/* This is a workgroup we have seen on a broadcast subnet. All
|
||||
these have the same type. */
|
||||
/* This is a workgroup we have seen on a broadcast subnet. All
|
||||
these have the same type. */
|
||||
|
||||
if(subrec != unicast_subnet)
|
||||
return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
|
||||
if(subrec != unicast_subnet)
|
||||
return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
|
||||
|
||||
for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub))
|
||||
{
|
||||
/* This is the unicast subnet so check if we've already written out
|
||||
this subnet when we passed over the broadcast subnets. */
|
||||
for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) {
|
||||
/* This is the unicast subnet so check if we've already written out
|
||||
this subnet when we passed over the broadcast subnets. */
|
||||
|
||||
if(find_workgroup_on_subnet( ssub, work->work_group) != NULL)
|
||||
return 0;
|
||||
}
|
||||
if(find_workgroup_on_subnet( ssub, work->work_group) != NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* All workgroups on the unicast subnet (except our own, which we
|
||||
have already written out) cannot be local. */
|
||||
/* All workgroups on the unicast subnet (except our own, which we
|
||||
have already written out) cannot be local. */
|
||||
|
||||
return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT);
|
||||
return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -306,143 +293,130 @@ void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type,
|
||||
|
||||
void write_browse_list(time_t t, BOOL force_write)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct work_record *work;
|
||||
struct server_record *servrec;
|
||||
pstring fname,fnamenew;
|
||||
uint32 stype;
|
||||
int i;
|
||||
XFILE *fp;
|
||||
BOOL list_changed = force_write;
|
||||
static time_t lasttime = 0;
|
||||
struct subnet_record *subrec;
|
||||
struct work_record *work;
|
||||
struct server_record *servrec;
|
||||
pstring fname,fnamenew;
|
||||
uint32 stype;
|
||||
int i;
|
||||
XFILE *fp;
|
||||
BOOL list_changed = force_write;
|
||||
static time_t lasttime = 0;
|
||||
|
||||
/* Always dump if we're being told to by a signal. */
|
||||
if(force_write == False)
|
||||
{
|
||||
if (!lasttime)
|
||||
lasttime = t;
|
||||
if (t - lasttime < 5)
|
||||
return;
|
||||
}
|
||||
/* Always dump if we're being told to by a signal. */
|
||||
if(force_write == False) {
|
||||
if (!lasttime)
|
||||
lasttime = t;
|
||||
if (t - lasttime < 5)
|
||||
return;
|
||||
}
|
||||
|
||||
lasttime = t;
|
||||
lasttime = t;
|
||||
|
||||
dump_workgroups(force_write);
|
||||
dump_workgroups(force_write);
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
if(subrec->work_changed)
|
||||
{
|
||||
list_changed = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
if(subrec->work_changed) {
|
||||
list_changed = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!list_changed)
|
||||
return;
|
||||
if(!list_changed)
|
||||
return;
|
||||
|
||||
updatecount++;
|
||||
updatecount++;
|
||||
|
||||
pstrcpy(fname,lp_lockdir());
|
||||
trim_string(fname,NULL,"/");
|
||||
pstrcat(fname,"/");
|
||||
pstrcat(fname,SERVER_LIST);
|
||||
pstrcpy(fnamenew,fname);
|
||||
pstrcat(fnamenew,".");
|
||||
pstrcpy(fname,lp_lockdir());
|
||||
trim_string(fname,NULL,"/");
|
||||
pstrcat(fname,"/");
|
||||
pstrcat(fname,SERVER_LIST);
|
||||
pstrcpy(fnamenew,fname);
|
||||
pstrcat(fnamenew,".");
|
||||
|
||||
fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n",
|
||||
fnamenew,strerror(errno)));
|
||||
return;
|
||||
}
|
||||
if (!fp) {
|
||||
DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n",
|
||||
fnamenew,strerror(errno)));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a record for our workgroup. Use the record from the first
|
||||
* subnet.
|
||||
*/
|
||||
/*
|
||||
* Write out a record for our workgroup. Use the record from the first
|
||||
* subnet.
|
||||
*/
|
||||
|
||||
if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL)
|
||||
{
|
||||
DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n",
|
||||
lp_workgroup()));
|
||||
x_fclose(fp);
|
||||
return;
|
||||
}
|
||||
if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {
|
||||
DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n",
|
||||
lp_workgroup()));
|
||||
x_fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
write_browse_list_entry(fp, work->work_group,
|
||||
SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY,
|
||||
work->local_master_browser_name, work->work_group);
|
||||
write_browse_list_entry(fp, work->work_group,
|
||||
SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY,
|
||||
work->local_master_browser_name, work->work_group);
|
||||
|
||||
/*
|
||||
* We need to do something special for our own names.
|
||||
* This is due to the fact that we may be a local master browser on
|
||||
* one of our broadcast subnets, and a domain master on the unicast
|
||||
* subnet. We iterate over the subnets and only write out the name
|
||||
* once.
|
||||
*/
|
||||
/*
|
||||
* We need to do something special for our own names.
|
||||
* This is due to the fact that we may be a local master browser on
|
||||
* one of our broadcast subnets, and a domain master on the unicast
|
||||
* subnet. We iterate over the subnets and only write out the name
|
||||
* once.
|
||||
*/
|
||||
|
||||
for (i=0; my_netbios_names(i); i++)
|
||||
{
|
||||
stype = 0;
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL)
|
||||
continue;
|
||||
if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL)
|
||||
continue;
|
||||
for (i=0; my_netbios_names(i); i++) {
|
||||
stype = 0;
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL)
|
||||
continue;
|
||||
if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL)
|
||||
continue;
|
||||
|
||||
stype |= servrec->serv.type;
|
||||
}
|
||||
stype |= servrec->serv.type;
|
||||
}
|
||||
|
||||
/* Output server details, plus what workgroup they're in. */
|
||||
write_browse_list_entry(fp, my_netbios_names(i), stype,
|
||||
string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup());
|
||||
}
|
||||
/* Output server details, plus what workgroup they're in. */
|
||||
write_browse_list_entry(fp, my_netbios_names(i), stype,
|
||||
string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup());
|
||||
}
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
subrec->work_changed = False;
|
||||
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
subrec->work_changed = False;
|
||||
|
||||
for (work = subrec->workgrouplist; work ; work = work->next)
|
||||
{
|
||||
/* Write out a workgroup record for a workgroup. */
|
||||
uint32 wg_type = write_this_workgroup_name( subrec, work);
|
||||
for (work = subrec->workgrouplist; work ; work = work->next) {
|
||||
/* Write out a workgroup record for a workgroup. */
|
||||
uint32 wg_type = write_this_workgroup_name( subrec, work);
|
||||
|
||||
if(wg_type)
|
||||
{
|
||||
write_browse_list_entry(fp, work->work_group, wg_type,
|
||||
work->local_master_browser_name,
|
||||
work->work_group);
|
||||
}
|
||||
if(wg_type) {
|
||||
write_browse_list_entry(fp, work->work_group, wg_type,
|
||||
work->local_master_browser_name,
|
||||
work->work_group);
|
||||
}
|
||||
|
||||
/* Now write out any server records a workgroup may have. */
|
||||
/* Now write out any server records a workgroup may have. */
|
||||
|
||||
for (servrec = work->serverlist; servrec ; servrec = servrec->next)
|
||||
{
|
||||
uint32 serv_type;
|
||||
for (servrec = work->serverlist; servrec ; servrec = servrec->next) {
|
||||
uint32 serv_type;
|
||||
|
||||
/* We have already written our names here. */
|
||||
if(is_myname(servrec->serv.name))
|
||||
continue;
|
||||
/* We have already written our names here. */
|
||||
if(is_myname(servrec->serv.name))
|
||||
continue;
|
||||
|
||||
serv_type = write_this_server_name(subrec, work, servrec);
|
||||
|
||||
if(serv_type)
|
||||
{
|
||||
/* Output server details, plus what workgroup they're in. */
|
||||
write_browse_list_entry(fp, servrec->serv.name, serv_type,
|
||||
servrec->serv.comment, work->work_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
serv_type = write_this_server_name(subrec, work, servrec);
|
||||
if(serv_type) {
|
||||
/* Output server details, plus what workgroup they're in. */
|
||||
write_browse_list_entry(fp, servrec->serv.name, serv_type,
|
||||
servrec->serv.comment, work->work_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x_fclose(fp);
|
||||
unlink(fname);
|
||||
chmod(fnamenew,0644);
|
||||
rename(fnamenew,fname);
|
||||
DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname));
|
||||
x_fclose(fp);
|
||||
unlink(fname);
|
||||
chmod(fnamenew,0644);
|
||||
rename(fnamenew,fname);
|
||||
DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname));
|
||||
}
|
||||
|
@ -63,28 +63,27 @@ static void add_subnet(struct subnet_record *subrec)
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
|
||||
{
|
||||
struct name_record *NR = (struct name_record *)Node;
|
||||
{
|
||||
struct name_record *NR = (struct name_record *)Node;
|
||||
|
||||
if( DEBUGLVL( 10 ) )
|
||||
{
|
||||
struct nmb_name *Iname = (struct nmb_name *)Item;
|
||||
if( DEBUGLVL( 10 ) ) {
|
||||
struct nmb_name *Iname = (struct nmb_name *)Item;
|
||||
|
||||
Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
|
||||
Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
|
||||
memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
|
||||
nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
|
||||
}
|
||||
|
||||
return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
|
||||
} /* namelist_entry_compare */
|
||||
Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
|
||||
Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
|
||||
memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
|
||||
nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
|
||||
}
|
||||
|
||||
return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
stop listening on a subnet
|
||||
we don't free the record as we don't have proper reference counting for it
|
||||
yet and it may be in use by a response record
|
||||
****************************************************************************/
|
||||
|
||||
void close_subnet(struct subnet_record *subrec)
|
||||
{
|
||||
DLIST_REMOVE(subnetlist, subrec);
|
||||
@ -99,8 +98,6 @@ void close_subnet(struct subnet_record *subrec)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create a subnet entry.
|
||||
****************************************************************************/
|
||||
@ -109,102 +106,90 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
|
||||
struct in_addr myip, struct in_addr bcast_ip,
|
||||
struct in_addr mask_ip)
|
||||
{
|
||||
struct subnet_record *subrec = NULL;
|
||||
int nmb_sock, dgram_sock;
|
||||
struct subnet_record *subrec = NULL;
|
||||
int nmb_sock, dgram_sock;
|
||||
|
||||
/* Check if we are creating a non broadcast subnet - if so don't create
|
||||
sockets.
|
||||
*/
|
||||
/* Check if we are creating a non broadcast subnet - if so don't create
|
||||
sockets. */
|
||||
|
||||
if(type != NORMAL_SUBNET)
|
||||
{
|
||||
nmb_sock = -1;
|
||||
dgram_sock = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Attempt to open the sockets on port 137/138 for this interface
|
||||
* and bind them.
|
||||
* Fail the subnet creation if this fails.
|
||||
*/
|
||||
if(type != NORMAL_SUBNET) {
|
||||
nmb_sock = -1;
|
||||
dgram_sock = -1;
|
||||
} else {
|
||||
/*
|
||||
* Attempt to open the sockets on port 137/138 for this interface
|
||||
* and bind them.
|
||||
* Fail the subnet creation if this fails.
|
||||
*/
|
||||
|
||||
if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
||||
Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
|
||||
Debug1( "for port %d. ", global_nmb_port );
|
||||
Debug1( "Error was %s\n", strerror(errno) );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
||||
Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
|
||||
Debug1( "for port %d. ", global_nmb_port );
|
||||
Debug1( "Error was %s\n", strerror(errno) );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1)
|
||||
{
|
||||
if( DEBUGLVL( 0 ) )
|
||||
{
|
||||
Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
||||
Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
|
||||
Debug1( "for port %d. ", DGRAM_PORT );
|
||||
Debug1( "Error was %s\n", strerror(errno) );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) {
|
||||
if( DEBUGLVL( 0 ) ) {
|
||||
Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
||||
Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
|
||||
Debug1( "for port %d. ", DGRAM_PORT );
|
||||
Debug1( "Error was %s\n", strerror(errno) );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make sure we can broadcast from these sockets. */
|
||||
set_socket_options(nmb_sock,"SO_BROADCAST");
|
||||
set_socket_options(dgram_sock,"SO_BROADCAST");
|
||||
/* Make sure we can broadcast from these sockets. */
|
||||
set_socket_options(nmb_sock,"SO_BROADCAST");
|
||||
set_socket_options(dgram_sock,"SO_BROADCAST");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
subrec = (struct subnet_record *)malloc(sizeof(*subrec));
|
||||
subrec = (struct subnet_record *)malloc(sizeof(*subrec));
|
||||
if (!subrec) {
|
||||
DEBUG(0,("make_subnet: malloc fail !\n"));
|
||||
close(nmb_sock);
|
||||
close(dgram_sock);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (!subrec)
|
||||
{
|
||||
DEBUG(0,("make_subnet: malloc fail !\n"));
|
||||
close(nmb_sock);
|
||||
close(dgram_sock);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
memset( (char *)subrec, '\0', sizeof(*subrec) );
|
||||
(void)ubi_trInitTree( subrec->namelist,
|
||||
namelist_entry_compare,
|
||||
ubi_trOVERWRITE );
|
||||
memset( (char *)subrec, '\0', sizeof(*subrec) );
|
||||
(void)ubi_trInitTree( subrec->namelist,
|
||||
namelist_entry_compare,
|
||||
ubi_trOVERWRITE );
|
||||
|
||||
if((subrec->subnet_name = strdup(name)) == NULL)
|
||||
{
|
||||
DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
|
||||
close(nmb_sock);
|
||||
close(dgram_sock);
|
||||
ZERO_STRUCTP(subrec);
|
||||
SAFE_FREE(subrec);
|
||||
return(NULL);
|
||||
}
|
||||
if((subrec->subnet_name = strdup(name)) == NULL) {
|
||||
DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
|
||||
close(nmb_sock);
|
||||
close(dgram_sock);
|
||||
ZERO_STRUCTP(subrec);
|
||||
SAFE_FREE(subrec);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
DEBUG(2, ("making subnet name:%s ", name ));
|
||||
DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
|
||||
DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
|
||||
DEBUG(2, ("making subnet name:%s ", name ));
|
||||
DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
|
||||
DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
|
||||
|
||||
subrec->namelist_changed = False;
|
||||
subrec->work_changed = False;
|
||||
subrec->namelist_changed = False;
|
||||
subrec->work_changed = False;
|
||||
|
||||
subrec->bcast_ip = bcast_ip;
|
||||
subrec->mask_ip = mask_ip;
|
||||
subrec->myip = myip;
|
||||
subrec->type = type;
|
||||
subrec->nmb_sock = nmb_sock;
|
||||
subrec->dgram_sock = dgram_sock;
|
||||
subrec->bcast_ip = bcast_ip;
|
||||
subrec->mask_ip = mask_ip;
|
||||
subrec->myip = myip;
|
||||
subrec->type = type;
|
||||
subrec->nmb_sock = nmb_sock;
|
||||
subrec->dgram_sock = dgram_sock;
|
||||
|
||||
return subrec;
|
||||
return subrec;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create a normal subnet
|
||||
**************************************************************************/
|
||||
|
||||
struct subnet_record *make_normal_subnet(struct interface *iface)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
@ -217,100 +202,99 @@ struct subnet_record *make_normal_subnet(struct interface *iface)
|
||||
return subrec;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create subnet entries.
|
||||
**************************************************************************/
|
||||
|
||||
BOOL create_subnets(void)
|
||||
{
|
||||
int num_interfaces = iface_count();
|
||||
int i;
|
||||
struct in_addr unicast_ip, ipzero;
|
||||
extern struct in_addr loopback_ip;
|
||||
int num_interfaces = iface_count();
|
||||
int i;
|
||||
struct in_addr unicast_ip, ipzero;
|
||||
extern struct in_addr loopback_ip;
|
||||
|
||||
if(num_interfaces == 0) {
|
||||
DEBUG(0,("create_subnets: No local interfaces !\n"));
|
||||
DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
|
||||
while (iface_count() == 0) {
|
||||
sleep(5);
|
||||
load_interfaces();
|
||||
}
|
||||
}
|
||||
if(num_interfaces == 0) {
|
||||
DEBUG(0,("create_subnets: No local interfaces !\n"));
|
||||
DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
|
||||
while (iface_count() == 0) {
|
||||
sleep(5);
|
||||
load_interfaces();
|
||||
}
|
||||
}
|
||||
|
||||
num_interfaces = iface_count();
|
||||
num_interfaces = iface_count();
|
||||
|
||||
/*
|
||||
* Create subnets from all the local interfaces and thread them onto
|
||||
* the linked list.
|
||||
*/
|
||||
/*
|
||||
* Create subnets from all the local interfaces and thread them onto
|
||||
* the linked list.
|
||||
*/
|
||||
|
||||
for (i = 0 ; i < num_interfaces; i++)
|
||||
{
|
||||
struct interface *iface = get_interface(i);
|
||||
for (i = 0 ; i < num_interfaces; i++) {
|
||||
struct interface *iface = get_interface(i);
|
||||
|
||||
/*
|
||||
* We don't want to add a loopback interface, in case
|
||||
* someone has added 127.0.0.1 for smbd, nmbd needs to
|
||||
* ignore it here. JRA.
|
||||
*/
|
||||
/*
|
||||
* We don't want to add a loopback interface, in case
|
||||
* someone has added 127.0.0.1 for smbd, nmbd needs to
|
||||
* ignore it here. JRA.
|
||||
*/
|
||||
|
||||
if (ip_equal(iface->ip, loopback_ip)) {
|
||||
DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
|
||||
continue;
|
||||
}
|
||||
if (ip_equal(iface->ip, loopback_ip)) {
|
||||
DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!make_normal_subnet(iface)) return False;
|
||||
}
|
||||
if (!make_normal_subnet(iface))
|
||||
return False;
|
||||
}
|
||||
|
||||
if (lp_we_are_a_wins_server()) {
|
||||
/* Pick the first interface ip address as the WINS server ip. */
|
||||
unicast_ip = *iface_n_ip(0);
|
||||
} else {
|
||||
/* note that we do not set the wins server IP here. We just
|
||||
set it at zero and let the wins registration code cope
|
||||
with getting the IPs right for each packet */
|
||||
zero_ip(&unicast_ip);
|
||||
}
|
||||
if (lp_we_are_a_wins_server()) {
|
||||
/* Pick the first interface ip address as the WINS server ip. */
|
||||
unicast_ip = *iface_n_ip(0);
|
||||
} else {
|
||||
/* note that we do not set the wins server IP here. We just
|
||||
set it at zero and let the wins registration code cope
|
||||
with getting the IPs right for each packet */
|
||||
zero_ip(&unicast_ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the unicast and remote broadcast subnets.
|
||||
* Don't put these onto the linked list.
|
||||
* The ip address of the unicast subnet is set to be
|
||||
* the WINS server address, if it exists, or ipzero if not.
|
||||
*/
|
||||
/*
|
||||
* Create the unicast and remote broadcast subnets.
|
||||
* Don't put these onto the linked list.
|
||||
* The ip address of the unicast subnet is set to be
|
||||
* the WINS server address, if it exists, or ipzero if not.
|
||||
*/
|
||||
|
||||
unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
|
||||
unicast_ip, unicast_ip, unicast_ip);
|
||||
unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
|
||||
unicast_ip, unicast_ip, unicast_ip);
|
||||
|
||||
zero_ip(&ipzero);
|
||||
zero_ip(&ipzero);
|
||||
|
||||
remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
|
||||
REMOTE_BROADCAST_SUBNET,
|
||||
ipzero, ipzero, ipzero);
|
||||
remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
|
||||
REMOTE_BROADCAST_SUBNET,
|
||||
ipzero, ipzero, ipzero);
|
||||
|
||||
if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
|
||||
return False;
|
||||
if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
|
||||
return False;
|
||||
|
||||
/*
|
||||
* If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
|
||||
* the linked list.
|
||||
*/
|
||||
/*
|
||||
* If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
|
||||
* the linked list.
|
||||
*/
|
||||
|
||||
if (lp_we_are_a_wins_server())
|
||||
{
|
||||
if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
|
||||
WINS_SERVER_SUBNET,
|
||||
ipzero, ipzero, ipzero )) == NULL )
|
||||
return False;
|
||||
}
|
||||
if (lp_we_are_a_wins_server()) {
|
||||
if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
|
||||
WINS_SERVER_SUBNET,
|
||||
ipzero, ipzero, ipzero )) == NULL )
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
return True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Function to tell us if we can use the unicast subnet.
|
||||
******************************************************************/
|
||||
|
||||
BOOL we_are_a_wins_client(void)
|
||||
{
|
||||
if (wins_srv_count() > 0) {
|
||||
@ -326,12 +310,12 @@ Access function used by NEXT_SUBNET_INCLUDING_UNICAST
|
||||
|
||||
struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
|
||||
{
|
||||
if(subrec == unicast_subnet)
|
||||
return NULL;
|
||||
else if((subrec->next == NULL) && we_are_a_wins_client())
|
||||
return unicast_subnet;
|
||||
else
|
||||
return subrec->next;
|
||||
if(subrec == unicast_subnet)
|
||||
return NULL;
|
||||
else if((subrec->next == NULL) && we_are_a_wins_client())
|
||||
return unicast_subnet;
|
||||
else
|
||||
return subrec->next;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -343,19 +327,18 @@ struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec
|
||||
|
||||
struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
|
||||
{
|
||||
if(subrec == unicast_subnet)
|
||||
{
|
||||
if(wins_server_subnet)
|
||||
return wins_server_subnet;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if(subrec == unicast_subnet) {
|
||||
if(wins_server_subnet)
|
||||
return wins_server_subnet;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(wins_server_subnet && subrec == wins_server_subnet)
|
||||
return NULL;
|
||||
if(wins_server_subnet && subrec == wins_server_subnet)
|
||||
return NULL;
|
||||
|
||||
if((subrec->next == NULL) && we_are_a_wins_client())
|
||||
return unicast_subnet;
|
||||
else
|
||||
return subrec->next;
|
||||
if((subrec->next == NULL) && we_are_a_wins_client())
|
||||
return unicast_subnet;
|
||||
else
|
||||
return subrec->next;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ static XFILE *fp;
|
||||
This is the NetServerEnum callback.
|
||||
Note sname and comment are in UNIX codepage format.
|
||||
******************************************************************/
|
||||
|
||||
static void callback(const char *sname, uint32 stype,
|
||||
const char *comment, void *state)
|
||||
{
|
||||
@ -58,6 +59,7 @@ static void callback(const char *sname, uint32 stype,
|
||||
Log in on the remote server's SMB port to their IPC$ service,
|
||||
do a NetServerEnum and record the results in fname
|
||||
******************************************************************/
|
||||
|
||||
static void sync_child(char *name, int nm_type,
|
||||
char *workgroup,
|
||||
struct in_addr ip, BOOL local, BOOL servers,
|
||||
@ -78,10 +80,9 @@ static void sync_child(char *name, int nm_type,
|
||||
}
|
||||
|
||||
make_nmb_name(&calling, local_machine, 0x0);
|
||||
make_nmb_name(&called , name , nm_type);
|
||||
make_nmb_name(&called , name, nm_type);
|
||||
|
||||
if (!cli_session_request(&cli, &calling, &called))
|
||||
{
|
||||
if (!cli_session_request(&cli, &calling, &called)) {
|
||||
cli_shutdown(&cli);
|
||||
return;
|
||||
}
|
||||
@ -120,12 +121,12 @@ static void sync_child(char *name, int nm_type,
|
||||
cli_shutdown(&cli);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
initialise a browse sync with another browse server. Log in on the
|
||||
remote server's SMB port to their IPC$ service, do a NetServerEnum
|
||||
and record the results
|
||||
******************************************************************/
|
||||
|
||||
void sync_browse_lists(struct work_record *work,
|
||||
char *name, int nm_type,
|
||||
struct in_addr ip, BOOL local, BOOL servers)
|
||||
@ -182,8 +183,9 @@ done:
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
handle one line from a completed sync file
|
||||
Handle one line from a completed sync file.
|
||||
**********************************************************************/
|
||||
|
||||
static void complete_one(struct sync_record *s,
|
||||
char *sname, uint32 stype, char *comment)
|
||||
{
|
||||
@ -235,10 +237,10 @@ static void complete_one(struct sync_record *s,
|
||||
create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
read the completed sync info
|
||||
**********************************************************************/
|
||||
Read the completed sync info.
|
||||
**********************************************************************/
|
||||
|
||||
static void complete_sync(struct sync_record *s)
|
||||
{
|
||||
XFILE *f;
|
||||
@ -251,11 +253,13 @@ static void complete_sync(struct sync_record *s)
|
||||
|
||||
f = x_fopen(s->fname,O_RDONLY, 0);
|
||||
|
||||
if (!f) return;
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
while (!x_feof(f)) {
|
||||
|
||||
if (!fgets_slash(line,sizeof(pstring),f)) continue;
|
||||
if (!fgets_slash(line,sizeof(pstring),f))
|
||||
continue;
|
||||
|
||||
ptr = line;
|
||||
|
||||
@ -281,8 +285,9 @@ static void complete_sync(struct sync_record *s)
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
check for completion of any of the child processes
|
||||
**********************************************************************/
|
||||
Check for completion of any of the child processes.
|
||||
**********************************************************************/
|
||||
|
||||
void sync_check_completion(void)
|
||||
{
|
||||
struct sync_record *s, *next;
|
||||
|
@ -30,92 +30,85 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
|
||||
struct userdata_struct *userdata,
|
||||
struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec)
|
||||
{
|
||||
struct packet_struct *original_packet;
|
||||
struct subnet_record *orig_broadcast_subnet;
|
||||
struct name_record *namerec;
|
||||
uint16 nb_flags;
|
||||
int num_ips;
|
||||
int i;
|
||||
int ttl = 3600; /* By default one hour in the cache. */
|
||||
struct in_addr *iplist;
|
||||
nstring name;
|
||||
struct packet_struct *original_packet;
|
||||
struct subnet_record *orig_broadcast_subnet;
|
||||
struct name_record *namerec;
|
||||
uint16 nb_flags;
|
||||
int num_ips;
|
||||
int i;
|
||||
int ttl = 3600; /* By default one hour in the cache. */
|
||||
struct in_addr *iplist;
|
||||
|
||||
/* Extract the original packet and the original broadcast subnet from
|
||||
the userdata. */
|
||||
/* Extract the original packet and the original broadcast subnet from
|
||||
the userdata. */
|
||||
|
||||
memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) );
|
||||
memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
|
||||
sizeof(struct packet_struct *) );
|
||||
memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) );
|
||||
memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
|
||||
sizeof(struct packet_struct *) );
|
||||
|
||||
nb_flags = get_nb_flags( rrec->rdata );
|
||||
nb_flags = get_nb_flags( rrec->rdata );
|
||||
|
||||
num_ips = rrec->rdlength / 6;
|
||||
if(num_ips == 0)
|
||||
{
|
||||
DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
|
||||
num_ips = rrec->rdlength / 6;
|
||||
if(num_ips == 0) {
|
||||
DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
|
||||
returned for name %s.\n", nmb_namestr(nmbname) ));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(num_ips == 1)
|
||||
iplist = &ip;
|
||||
else
|
||||
{
|
||||
if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
|
||||
{
|
||||
DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
if(num_ips == 1) {
|
||||
iplist = &ip;
|
||||
} else {
|
||||
if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) {
|
||||
DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < num_ips; i++)
|
||||
putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
|
||||
}
|
||||
for(i = 0; i < num_ips; i++)
|
||||
putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
|
||||
}
|
||||
|
||||
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
|
||||
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
|
||||
|
||||
if(rrec == PERMANENT_TTL)
|
||||
ttl = lp_max_ttl();
|
||||
if(rrec == PERMANENT_TTL)
|
||||
ttl = lp_max_ttl();
|
||||
|
||||
namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name,
|
||||
nmbname->name_type, nb_flags, ttl,
|
||||
WINS_PROXY_NAME, num_ips, iplist );
|
||||
pull_ascii_nstring(name, nmbname->name);
|
||||
namerec = add_name_to_subnet( orig_broadcast_subnet, name,
|
||||
nmbname->name_type, nb_flags, ttl,
|
||||
WINS_PROXY_NAME, num_ips, iplist );
|
||||
|
||||
if(iplist != &ip)
|
||||
SAFE_FREE(iplist);
|
||||
if(iplist != &ip)
|
||||
SAFE_FREE(iplist);
|
||||
|
||||
/*
|
||||
* Check that none of the IP addresses we are returning is on the
|
||||
* same broadcast subnet as the original requesting packet. If it
|
||||
* is then don't reply (although we still need to add the name
|
||||
* to the cache) as the actual machine will be replying also
|
||||
* and we don't want two replies to a broadcast query.
|
||||
*/
|
||||
/*
|
||||
* Check that none of the IP addresses we are returning is on the
|
||||
* same broadcast subnet as the original requesting packet. If it
|
||||
* is then don't reply (although we still need to add the name
|
||||
* to the cache) as the actual machine will be replying also
|
||||
* and we don't want two replies to a broadcast query.
|
||||
*/
|
||||
|
||||
if(namerec && original_packet->packet.nmb.header.nm_flags.bcast)
|
||||
{
|
||||
for( i = 0; i < namerec->data.num_ips; i++)
|
||||
{
|
||||
if( same_net( namerec->data.ip[i],
|
||||
orig_broadcast_subnet->myip,
|
||||
orig_broadcast_subnet->mask_ip ) )
|
||||
{
|
||||
DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \
|
||||
if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) {
|
||||
for( i = 0; i < namerec->data.num_ips; i++) {
|
||||
if( same_net( namerec->data.ip[i], orig_broadcast_subnet->myip,
|
||||
orig_broadcast_subnet->mask_ip ) ) {
|
||||
DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \
|
||||
proxy name and is also on the same subnet (%s) as the requestor. \
|
||||
Not replying.\n",
|
||||
nmb_namestr(&namerec->name),
|
||||
orig_broadcast_subnet->subnet_name ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Not replying.\n", nmb_namestr(&namerec->name), orig_broadcast_subnet->subnet_name ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally reply to the original name query. */
|
||||
reply_netbios_packet(original_packet, /* Packet to reply to. */
|
||||
0, /* Result code. */
|
||||
NMB_QUERY, /* nmbd type code. */
|
||||
NMB_NAME_QUERY_OPCODE, /* opcode. */
|
||||
ttl, /* ttl. */
|
||||
rrec->rdata, /* data to send. */
|
||||
rrec->rdlength); /* data length. */
|
||||
/* Finally reply to the original name query. */
|
||||
reply_netbios_packet(original_packet, /* Packet to reply to. */
|
||||
0, /* Result code. */
|
||||
NMB_QUERY, /* nmbd type code. */
|
||||
NMB_NAME_QUERY_OPCODE, /* opcode. */
|
||||
ttl, /* ttl. */
|
||||
rrec->rdata, /* data to send. */
|
||||
rrec->rdlength); /* data length. */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -126,7 +119,7 @@ static void wins_proxy_name_query_request_fail(struct subnet_record *subrec,
|
||||
struct response_record *rrec,
|
||||
struct nmb_name *question_name, int fail_code)
|
||||
{
|
||||
DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
|
||||
DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
|
||||
of name %s.\n", fail_code, nmb_namestr(question_name) ));
|
||||
}
|
||||
|
||||
@ -137,38 +130,35 @@ proxy query returns.
|
||||
|
||||
static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata)
|
||||
{
|
||||
struct packet_struct *p, *copy_of_p;
|
||||
struct userdata_struct *new_userdata =
|
||||
(struct userdata_struct *)malloc( userdata->userdata_len );
|
||||
struct packet_struct *p, *copy_of_p;
|
||||
struct userdata_struct *new_userdata = (struct userdata_struct *)malloc( userdata->userdata_len );
|
||||
|
||||
if(new_userdata == NULL)
|
||||
return NULL;
|
||||
if(new_userdata == NULL)
|
||||
return NULL;
|
||||
|
||||
new_userdata->copy_fn = userdata->copy_fn;
|
||||
new_userdata->free_fn = userdata->free_fn;
|
||||
new_userdata->userdata_len = userdata->userdata_len;
|
||||
new_userdata->copy_fn = userdata->copy_fn;
|
||||
new_userdata->free_fn = userdata->free_fn;
|
||||
new_userdata->userdata_len = userdata->userdata_len;
|
||||
|
||||
/* Copy the subnet_record pointer. */
|
||||
memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) );
|
||||
/* Copy the subnet_record pointer. */
|
||||
memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) );
|
||||
|
||||
/* Extract the pointer to the packet struct */
|
||||
memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
|
||||
sizeof(struct packet_struct *) );
|
||||
/* Extract the pointer to the packet struct */
|
||||
memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], sizeof(struct packet_struct *) );
|
||||
|
||||
/* Do a deep copy of the packet. */
|
||||
if((copy_of_p = copy_packet(p)) == NULL)
|
||||
{
|
||||
SAFE_FREE(new_userdata);
|
||||
return NULL;
|
||||
}
|
||||
/* Do a deep copy of the packet. */
|
||||
if((copy_of_p = copy_packet(p)) == NULL) {
|
||||
SAFE_FREE(new_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Lock the copy. */
|
||||
copy_of_p->locked = True;
|
||||
/* Lock the copy. */
|
||||
copy_of_p->locked = True;
|
||||
|
||||
memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p,
|
||||
sizeof(struct packet_struct *) );
|
||||
memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p,
|
||||
sizeof(struct packet_struct *) );
|
||||
|
||||
return new_userdata;
|
||||
return new_userdata;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -178,18 +168,18 @@ proxy query returned.
|
||||
|
||||
static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata)
|
||||
{
|
||||
struct packet_struct *p;
|
||||
struct packet_struct *p;
|
||||
|
||||
/* Extract the pointer to the packet struct */
|
||||
memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
|
||||
sizeof(struct packet_struct *));
|
||||
/* Extract the pointer to the packet struct */
|
||||
memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
|
||||
sizeof(struct packet_struct *));
|
||||
|
||||
/* Unlock the packet. */
|
||||
p->locked = False;
|
||||
/* Unlock the packet. */
|
||||
p->locked = False;
|
||||
|
||||
free_packet(p);
|
||||
ZERO_STRUCTP(userdata);
|
||||
SAFE_FREE(userdata);
|
||||
free_packet(p);
|
||||
ZERO_STRUCTP(userdata);
|
||||
SAFE_FREE(userdata);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -200,22 +190,24 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec,
|
||||
struct packet_struct *incoming_packet,
|
||||
struct nmb_name *question_name)
|
||||
{
|
||||
long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) +
|
||||
sizeof(struct packet_struct *))/sizeof(long *) + 1];
|
||||
struct userdata_struct *userdata = (struct userdata_struct *)ud;
|
||||
long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) +
|
||||
sizeof(struct packet_struct *))/sizeof(long *) + 1];
|
||||
struct userdata_struct *userdata = (struct userdata_struct *)ud;
|
||||
nstring qname;
|
||||
|
||||
memset(ud, '\0', sizeof(ud));
|
||||
memset(ud, '\0', sizeof(ud));
|
||||
|
||||
userdata->copy_fn = wins_proxy_userdata_copy_fn;
|
||||
userdata->free_fn = wins_proxy_userdata_free_fn;
|
||||
userdata->userdata_len = sizeof(ud);
|
||||
memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *));
|
||||
memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet,
|
||||
sizeof(struct packet_struct *));
|
||||
userdata->copy_fn = wins_proxy_userdata_copy_fn;
|
||||
userdata->free_fn = wins_proxy_userdata_free_fn;
|
||||
userdata->userdata_len = sizeof(ud);
|
||||
memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *));
|
||||
memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet,
|
||||
sizeof(struct packet_struct *));
|
||||
|
||||
/* Now use the unicast subnet to query the name with the WINS server. */
|
||||
query_name( unicast_subnet, question_name->name, question_name->name_type,
|
||||
wins_proxy_name_query_request_success,
|
||||
wins_proxy_name_query_request_fail,
|
||||
userdata);
|
||||
/* Now use the unicast subnet to query the name with the WINS server. */
|
||||
pull_ascii_nstring(qname, question_name->name);
|
||||
query_name( unicast_subnet, qname, question_name->name_type,
|
||||
wins_proxy_name_query_request_success,
|
||||
wins_proxy_name_query_request_fail,
|
||||
userdata);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */
|
||||
|
||||
/****************************************************************************
|
||||
Add a workgroup into the list.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
static void add_workgroup(struct subnet_record *subrec, struct work_record *work)
|
||||
{
|
||||
@ -42,164 +42,153 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work
|
||||
|
||||
/****************************************************************************
|
||||
Create an empty workgroup.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
static struct work_record *create_workgroup(const char *name, int ttl)
|
||||
{
|
||||
struct work_record *work;
|
||||
struct subnet_record *subrec;
|
||||
int t = -1;
|
||||
struct work_record *work;
|
||||
struct subnet_record *subrec;
|
||||
int t = -1;
|
||||
|
||||
if((work = (struct work_record *)malloc(sizeof(*work))) == NULL)
|
||||
{
|
||||
DEBUG(0,("create_workgroup: malloc fail !\n"));
|
||||
return NULL;
|
||||
}
|
||||
memset((char *)work, '\0', sizeof(*work));
|
||||
if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) {
|
||||
DEBUG(0,("create_workgroup: malloc fail !\n"));
|
||||
return NULL;
|
||||
}
|
||||
memset((char *)work, '\0', sizeof(*work));
|
||||
|
||||
fstrcpy(work->work_group,name);
|
||||
work->serverlist = NULL;
|
||||
fstrcpy(work->work_group,name);
|
||||
work->serverlist = NULL;
|
||||
|
||||
work->RunningElection = False;
|
||||
work->ElectionCount = 0;
|
||||
work->announce_interval = 0;
|
||||
work->needelection = False;
|
||||
work->needannounce = True;
|
||||
work->lastannounce_time = time(NULL);
|
||||
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
||||
work->dom_state = DOMAIN_NONE;
|
||||
work->log_state = LOGON_NONE;
|
||||
work->RunningElection = False;
|
||||
work->ElectionCount = 0;
|
||||
work->announce_interval = 0;
|
||||
work->needelection = False;
|
||||
work->needannounce = True;
|
||||
work->lastannounce_time = time(NULL);
|
||||
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
||||
work->dom_state = DOMAIN_NONE;
|
||||
work->log_state = LOGON_NONE;
|
||||
|
||||
work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
|
||||
work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
|
||||
|
||||
/* Make sure all token representations of workgroups are unique. */
|
||||
/* Make sure all token representations of workgroups are unique. */
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec && (t == -1);
|
||||
subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *w;
|
||||
for (w = subrec->workgrouplist; w && t == -1; w = w->next)
|
||||
{
|
||||
if (strequal(w->work_group, work->work_group))
|
||||
t = w->token;
|
||||
}
|
||||
}
|
||||
for (subrec = FIRST_SUBNET; subrec && (t == -1); subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *w;
|
||||
for (w = subrec->workgrouplist; w && t == -1; w = w->next) {
|
||||
if (strequal(w->work_group, work->work_group))
|
||||
t = w->token;
|
||||
}
|
||||
}
|
||||
|
||||
if (t == -1)
|
||||
work->token = ++workgroup_count;
|
||||
else
|
||||
work->token = t;
|
||||
if (t == -1)
|
||||
work->token = ++workgroup_count;
|
||||
else
|
||||
work->token = t;
|
||||
|
||||
/* No known local master browser as yet. */
|
||||
*work->local_master_browser_name = '\0';
|
||||
/* No known local master browser as yet. */
|
||||
*work->local_master_browser_name = '\0';
|
||||
|
||||
/* No known domain master browser as yet. */
|
||||
*work->dmb_name.name = '\0';
|
||||
zero_ip(&work->dmb_addr);
|
||||
/* No known domain master browser as yet. */
|
||||
*work->dmb_name.name = '\0';
|
||||
zero_ip(&work->dmb_addr);
|
||||
|
||||
/* WfWg uses 01040b01 */
|
||||
/* Win95 uses 01041501 */
|
||||
/* NTAS uses ???????? */
|
||||
work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8);
|
||||
work->ElectionCriterion |= (lp_os_level() << 24);
|
||||
if (lp_domain_master())
|
||||
work->ElectionCriterion |= 0x80;
|
||||
/* WfWg uses 01040b01 */
|
||||
/* Win95 uses 01041501 */
|
||||
/* NTAS uses ???????? */
|
||||
work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8);
|
||||
work->ElectionCriterion |= (lp_os_level() << 24);
|
||||
if (lp_domain_master())
|
||||
work->ElectionCriterion |= 0x80;
|
||||
|
||||
return work;
|
||||
return work;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Remove a workgroup.
|
||||
******************************************************************/
|
||||
******************************************************************/
|
||||
|
||||
static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec,
|
||||
struct work_record *work)
|
||||
{
|
||||
struct work_record *ret_work = NULL;
|
||||
struct work_record *ret_work = NULL;
|
||||
|
||||
DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group));
|
||||
DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group));
|
||||
|
||||
ret_work = work->next;
|
||||
ret_work = work->next;
|
||||
|
||||
remove_all_servers(work);
|
||||
remove_all_servers(work);
|
||||
|
||||
if (!work->serverlist)
|
||||
{
|
||||
if (work->prev)
|
||||
work->prev->next = work->next;
|
||||
if (work->next)
|
||||
work->next->prev = work->prev;
|
||||
if (!work->serverlist) {
|
||||
if (work->prev)
|
||||
work->prev->next = work->next;
|
||||
if (work->next)
|
||||
work->next->prev = work->prev;
|
||||
|
||||
if (subrec->workgrouplist == work)
|
||||
subrec->workgrouplist = work->next;
|
||||
if (subrec->workgrouplist == work)
|
||||
subrec->workgrouplist = work->next;
|
||||
|
||||
ZERO_STRUCTP(work);
|
||||
SAFE_FREE(work);
|
||||
}
|
||||
ZERO_STRUCTP(work);
|
||||
SAFE_FREE(work);
|
||||
}
|
||||
|
||||
subrec->work_changed = True;
|
||||
subrec->work_changed = True;
|
||||
|
||||
return ret_work;
|
||||
return ret_work;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Find a workgroup in the workgroup list of a subnet.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
|
||||
const char *name)
|
||||
{
|
||||
struct work_record *ret;
|
||||
struct work_record *ret;
|
||||
|
||||
DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
|
||||
name, subrec->subnet_name));
|
||||
DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
|
||||
name, subrec->subnet_name));
|
||||
|
||||
for (ret = subrec->workgrouplist; ret; ret = ret->next)
|
||||
{
|
||||
if (!strcmp(ret->work_group,name))
|
||||
{
|
||||
DEBUGADD(4, ("found.\n"));
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
DEBUGADD(4, ("not found.\n"));
|
||||
return NULL;
|
||||
for (ret = subrec->workgrouplist; ret; ret = ret->next) {
|
||||
if (strequal(ret->work_group,name)) {
|
||||
DEBUGADD(4, ("found.\n"));
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
DEBUGADD(4, ("not found.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Create a workgroup in the workgroup list of the subnet.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec,
|
||||
const char *name, int ttl)
|
||||
{
|
||||
struct work_record *work = NULL;
|
||||
struct work_record *work = NULL;
|
||||
|
||||
DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n",
|
||||
name, subrec->subnet_name));
|
||||
DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n",
|
||||
name, subrec->subnet_name));
|
||||
|
||||
if ((work = create_workgroup(name, ttl)))
|
||||
{
|
||||
add_workgroup(subrec, work);
|
||||
if ((work = create_workgroup(name, ttl))) {
|
||||
add_workgroup(subrec, work);
|
||||
subrec->work_changed = True;
|
||||
return(work);
|
||||
}
|
||||
|
||||
subrec->work_changed = True;
|
||||
|
||||
return(work);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Update a workgroup ttl.
|
||||
**************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
void update_workgroup_ttl(struct work_record *work, int ttl)
|
||||
{
|
||||
if(work->death_time != PERMANENT_TTL)
|
||||
work->death_time = time(NULL)+(ttl*3);
|
||||
work->subnet->work_changed = True;
|
||||
if(work->death_time != PERMANENT_TTL)
|
||||
work->death_time = time(NULL)+(ttl*3);
|
||||
work->subnet->work_changed = True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -210,8 +199,8 @@ void update_workgroup_ttl(struct work_record *work, int ttl)
|
||||
static void fail_register(struct subnet_record *subrec, struct response_record *rrec,
|
||||
struct nmb_name *nmbname)
|
||||
{
|
||||
DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n",
|
||||
nmb_namestr(nmbname), subrec->subnet_name));
|
||||
DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n",
|
||||
nmb_namestr(nmbname), subrec->subnet_name));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -220,50 +209,38 @@ static void fail_register(struct subnet_record *subrec, struct response_record *
|
||||
|
||||
void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if(!strequal(lp_workgroup(), work->work_group))
|
||||
return;
|
||||
if(!strequal(lp_workgroup(), work->work_group))
|
||||
return;
|
||||
|
||||
/* If this is a broadcast subnet then start elections on it
|
||||
if we are so configured. */
|
||||
/* If this is a broadcast subnet then start elections on it if we are so configured. */
|
||||
|
||||
if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) &&
|
||||
(subrec != wins_server_subnet) && lp_preferred_master() &&
|
||||
lp_local_master())
|
||||
{
|
||||
DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \
|
||||
if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) &&
|
||||
(subrec != wins_server_subnet) && lp_preferred_master() && lp_local_master()) {
|
||||
DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \
|
||||
workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
|
||||
work->needelection = True;
|
||||
work->ElectionCriterion |= (1<<3);
|
||||
}
|
||||
work->needelection = True;
|
||||
work->ElectionCriterion |= (1<<3);
|
||||
}
|
||||
|
||||
/* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */
|
||||
/* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */
|
||||
|
||||
register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP,
|
||||
NULL,
|
||||
fail_register,NULL);
|
||||
|
||||
register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP,
|
||||
NULL,
|
||||
fail_register,NULL);
|
||||
|
||||
for( i = 0; my_netbios_names(i); i++)
|
||||
{
|
||||
const char *name = my_netbios_names(i);
|
||||
int stype = lp_default_server_announce() | (lp_local_master() ?
|
||||
SV_TYPE_POTENTIAL_BROWSER : 0 );
|
||||
register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, NULL, fail_register,NULL);
|
||||
register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, NULL, fail_register,NULL);
|
||||
|
||||
for( i = 0; my_netbios_names(i); i++) {
|
||||
const char *name = my_netbios_names(i);
|
||||
int stype = lp_default_server_announce() | (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0 );
|
||||
|
||||
if(!strequal(global_myname(), name))
|
||||
stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
|
||||
SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
|
||||
if(!strequal(global_myname(), name))
|
||||
stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
|
||||
|
||||
create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY,
|
||||
PERMANENT_TTL,
|
||||
string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
|
||||
DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \
|
||||
create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, PERMANENT_TTL,
|
||||
string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
|
||||
DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \
|
||||
on subnet %s\n", name, subrec->subnet_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -272,43 +249,34 @@ on subnet %s\n", name, subrec->subnet_name));
|
||||
|
||||
void dump_workgroups(BOOL force_write)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
int debuglevel = force_write ? 0 : 4;
|
||||
struct subnet_record *subrec;
|
||||
int debuglevel = force_write ? 0 : 4;
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
if (subrec->workgrouplist)
|
||||
{
|
||||
struct work_record *work;
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
if (subrec->workgrouplist) {
|
||||
struct work_record *work;
|
||||
|
||||
if( DEBUGLVL( debuglevel ) )
|
||||
{
|
||||
dbgtext( "dump_workgroups()\n " );
|
||||
dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name );
|
||||
dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) );
|
||||
}
|
||||
|
||||
for (work = subrec->workgrouplist; work; work = work->next)
|
||||
{
|
||||
DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n",
|
||||
work->work_group,
|
||||
work->token,
|
||||
*work->local_master_browser_name
|
||||
? work->local_master_browser_name : "UNKNOWN" ) );
|
||||
if (work->serverlist)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next)
|
||||
{
|
||||
DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n",
|
||||
servrec->serv.name,
|
||||
servrec->serv.type,
|
||||
servrec->serv.comment ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( DEBUGLVL( debuglevel ) ) {
|
||||
dbgtext( "dump_workgroups()\n " );
|
||||
dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name );
|
||||
dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) );
|
||||
}
|
||||
|
||||
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||
DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", work->work_group,
|
||||
work->token, *work->local_master_browser_name ? work->local_master_browser_name : "UNKNOWN" ) );
|
||||
if (work->serverlist) {
|
||||
struct server_record *servrec;
|
||||
for (servrec = work->serverlist; servrec; servrec = servrec->next) {
|
||||
DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n",
|
||||
servrec->serv.name,
|
||||
servrec->serv.type,
|
||||
servrec->serv.comment ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -318,25 +286,22 @@ void dump_workgroups(BOOL force_write)
|
||||
|
||||
void expire_workgroups_and_servers(time_t t)
|
||||
{
|
||||
struct subnet_record *subrec;
|
||||
struct subnet_record *subrec;
|
||||
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
|
||||
{
|
||||
struct work_record *work;
|
||||
struct work_record *nextwork;
|
||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
|
||||
struct work_record *work;
|
||||
struct work_record *nextwork;
|
||||
|
||||
for (work = subrec->workgrouplist; work; work = nextwork)
|
||||
{
|
||||
nextwork = work->next;
|
||||
expire_servers(work, t);
|
||||
for (work = subrec->workgrouplist; work; work = nextwork) {
|
||||
nextwork = work->next;
|
||||
expire_servers(work, t);
|
||||
|
||||
if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) &&
|
||||
((t == -1) || (work->death_time < t)))
|
||||
{
|
||||
DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n",
|
||||
work->work_group));
|
||||
remove_workgroup_from_subnet(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) &&
|
||||
((t == -1) || (work->death_time < t))) {
|
||||
DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n",
|
||||
work->work_group));
|
||||
remove_workgroup_from_subnet(subrec, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -563,6 +563,7 @@ static BOOL handle_debug_list( const char *pszParmValue, char **ptr );
|
||||
static BOOL handle_workgroup( const char *pszParmValue, char **ptr );
|
||||
static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr );
|
||||
static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr );
|
||||
static BOOL handle_charset( const char *pszParmValue, char **ptr );
|
||||
|
||||
static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr );
|
||||
static BOOL handle_ldap_sub_suffix ( const char *pszParmValue, char **ptr );
|
||||
@ -753,9 +754,9 @@ static const struct enum_list enum_map_to_guest[] = {
|
||||
static struct parm_struct parm_table[] = {
|
||||
{"Base Options", P_SEP, P_SEPARATOR},
|
||||
|
||||
{"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED},
|
||||
{"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED},
|
||||
{"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED},
|
||||
{"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED},
|
||||
{"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED},
|
||||
{"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
|
||||
@ -2701,7 +2702,6 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr)
|
||||
|
||||
standard_sub_basic(current_user_info.smb_name, netbios_name,sizeof(netbios_name));
|
||||
|
||||
|
||||
ret = set_global_myname(netbios_name);
|
||||
string_set(&Globals.szNetbiosName,global_myname());
|
||||
|
||||
@ -2711,6 +2711,13 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL handle_charset(const char *pszParmValue, char **ptr)
|
||||
{
|
||||
string_set(ptr, pszParmValue);
|
||||
init_iconv();
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL handle_workgroup(const char *pszParmValue, char **ptr)
|
||||
{
|
||||
BOOL ret;
|
||||
|
Loading…
Reference in New Issue
Block a user