mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
local_only NetServerEnum syncs can now be issued.
bug spotted in nameservresp.c - arguments to test subnet the response is received on (same_net()) were the wrong way round (ccm@shentel.net) samba was adding WORKGROUP(1e) as a unique not a group name: fixed this bug in reply_name_status() and reply_name_query(): WINS entries weren't being looked up. name status reply adds local SELF entries to WINS SELF entries: some SELF entries are only added locally, while others are only added via WINS. name status needs to have both, combined. a sync will only occur when an ANN_LocalMasterAnnouncement is received, NOT an ANN_HostAnnouncement or an ANN_DomainAnnouncement. when samba is a member of a workgroup, it looks for (using a wins server) and announces to its domain master. NAME_QUERY_ANNOUNCE_HOST - yet another 'state' - has been created to do this: do the name query on the wins server and send the announce host to the answer to this query. jeremy @ vantive wrote the original code to do this, which used the name_query() function. i'm trying to avoid name_query: it times out and generally messes things up, but using queue_netbios_packet() and queue_netbios_pkt_wins() is... not intuitive? lkcl with help from jra
This commit is contained in:
parent
801fe1066e
commit
6e932e4bae
@ -48,10 +48,10 @@
|
||||
#define NB_ACTIVE 0x04
|
||||
#define NB_CONFL 0x08
|
||||
#define NB_DEREG 0x10
|
||||
#define NB_BFLAG 0x00
|
||||
#define NB_PFLAG 0x20
|
||||
#define NB_MFLAG 0x40
|
||||
#define NB__FLAG 0x60
|
||||
#define NB_BFLAG 0x00 /* broadcast node type */
|
||||
#define NB_PFLAG 0x20 /* point-to-point node type */
|
||||
#define NB_MFLAG 0x40 /* mixed bcast & p-p node type */
|
||||
#define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */
|
||||
#define NB_FLGMSK 0x60
|
||||
|
||||
#define REFRESH_TIME (15*60)
|
||||
@ -68,7 +68,7 @@
|
||||
#define NAME_BFLAG(p) (((p) & NB_FLGMSK) == NB_BFLAG)
|
||||
#define NAME_PFLAG(p) (((p) & NB_FLGMSK) == NB_PFLAG)
|
||||
#define NAME_MFLAG(p) (((p) & NB_FLGMSK) == NB_MFLAG)
|
||||
#define NAME__FLAG(p) (((p) & NB_FLGMSK) == NB__FLAG)
|
||||
#define NAME_HFLAG(p) (((p) & NB_FLGMSK) == NB_HFLAG)
|
||||
|
||||
/* server type identifiers */
|
||||
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
|
||||
@ -99,14 +99,16 @@ enum master_state
|
||||
|
||||
enum state_type
|
||||
{
|
||||
NAME_STATUS_PDC_SRV_CHK,
|
||||
NAME_STATUS_DOM_SRV_CHK,
|
||||
NAME_STATUS_SRV_CHK,
|
||||
NAME_REGISTER_CHALLENGE,
|
||||
NAME_REGISTER,
|
||||
NAME_RELEASE,
|
||||
NAME_QUERY_CONFIRM,
|
||||
NAME_QUERY_SYNC,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
NAME_QUERY_ANNOUNCE_HOST,
|
||||
NAME_QUERY_SYNC_LOCAL,
|
||||
NAME_QUERY_SYNC_REMOTE,
|
||||
NAME_QUERY_DOM_SRV_CHK,
|
||||
NAME_QUERY_SRV_CHK,
|
||||
NAME_QUERY_FIND_MST,
|
||||
NAME_QUERY_MST_CHK
|
||||
@ -147,6 +149,7 @@ struct browse_cache_record
|
||||
struct in_addr ip;
|
||||
time_t sync_time;
|
||||
BOOL synced;
|
||||
BOOL local;
|
||||
};
|
||||
|
||||
/* this is used to hold the list of servers in my domain, and is */
|
||||
@ -190,6 +193,8 @@ struct work_record
|
||||
};
|
||||
|
||||
/* initiated name queries recorded in this list to track any responses... */
|
||||
/* sadly, we need to group everything together. i suppose that if this
|
||||
gets unwieldy, then a union ought to be considered. oh for c++... */
|
||||
struct response_record
|
||||
{
|
||||
struct response_record *next;
|
||||
@ -204,6 +209,10 @@ struct response_record
|
||||
int nb_flags;
|
||||
time_t ttl;
|
||||
|
||||
int server_type;
|
||||
fstring my_name;
|
||||
fstring my_comment;
|
||||
|
||||
BOOL bcast;
|
||||
BOOL recurse;
|
||||
struct in_addr send_ip;
|
||||
|
@ -295,6 +295,11 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
|
||||
int name_type,
|
||||
struct in_addr ip);
|
||||
void announce_backup(void);
|
||||
void do_announce_host(int command,
|
||||
char *from_name, int from_type, struct in_addr from_ip,
|
||||
char *to_name , int to_type , struct in_addr to_ip,
|
||||
time_t announce_interval,
|
||||
char *server_name, int server_type, char *server_comment);
|
||||
void remove_my_servers(void);
|
||||
void announce_server(struct subnet_record *d, struct work_record *work,
|
||||
char *name, char *comment, time_t ttl, int server_type);
|
||||
@ -305,11 +310,15 @@ void announce_master(void);
|
||||
|
||||
void expire_browse_cache(time_t t);
|
||||
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
|
||||
time_t ttl, struct in_addr ip);
|
||||
time_t ttl, struct in_addr ip, BOOL local);
|
||||
void do_browser_lists(void);
|
||||
|
||||
/*The following definitions come from namedb.c */
|
||||
|
||||
|
||||
/*The following definitions come from namedbname.c */
|
||||
|
||||
void set_samba_nb_type(void);
|
||||
BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2);
|
||||
BOOL ms_browser_name(char *name, int type);
|
||||
void remove_name(struct subnet_record *d, struct name_record *n);
|
||||
@ -342,6 +351,7 @@ void remove_response_record(struct subnet_record *d,
|
||||
struct response_record *make_response_queue_record(enum state_type state,
|
||||
int id,uint16 fd,
|
||||
int quest_type, char *name,int type, int nb_flags, time_t ttl,
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip);
|
||||
struct response_record *find_response_record(struct subnet_record **d,
|
||||
@ -432,13 +442,15 @@ void expire_netbios_response_entries();
|
||||
struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
int fd,int quest_type,enum state_type state,
|
||||
char *name,int name_type,int nb_flags, time_t ttl,
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip);
|
||||
struct response_record *queue_netbios_packet(struct subnet_record *d,
|
||||
int fd,int quest_type,enum state_type state,char *name,
|
||||
int name_type,int nb_flags, time_t ttl,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip);
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip);
|
||||
|
||||
/*The following definitions come from nameserv.c */
|
||||
|
||||
@ -502,7 +514,7 @@ int main(int argc,char *argv[]);
|
||||
|
||||
char *getsmbpass(char *pass);
|
||||
void sync_browse_lists(struct subnet_record *d, struct work_record *work,
|
||||
char *name, int nm_type, struct in_addr ip);
|
||||
char *name, int nm_type, struct in_addr ip, BOOL local);
|
||||
|
||||
/*The following definitions come from params.c */
|
||||
|
||||
|
@ -54,7 +54,7 @@ static void _interpret_node_status(char *p, char *master,char *rname)
|
||||
if ((p[0] & 0x60) == 0x00) strcat(flags,"B ");
|
||||
if ((p[0] & 0x60) == 0x20) strcat(flags,"P ");
|
||||
if ((p[0] & 0x60) == 0x40) strcat(flags,"M ");
|
||||
if ((p[0] & 0x60) == 0x60) strcat(flags,"_ ");
|
||||
if ((p[0] & 0x60) == 0x60) strcat(flags,"H ");
|
||||
if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
|
||||
if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
|
||||
if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
|
||||
@ -109,8 +109,8 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
|
||||
nmb->header.opcode = 0;
|
||||
nmb->header.response = False;
|
||||
nmb->header.nm_flags.bcast = False;
|
||||
nmb->header.nm_flags.recursion_available = 0;
|
||||
nmb->header.nm_flags.recursion_desired = 1;
|
||||
nmb->header.nm_flags.recursion_available = False;
|
||||
nmb->header.nm_flags.recursion_desired = False;
|
||||
nmb->header.nm_flags.trunc = False;
|
||||
nmb->header.nm_flags.authoritative = False;
|
||||
nmb->header.rcode = 0;
|
||||
@ -152,6 +152,8 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
|
||||
if ((p2=receive_packet(fd,NMB_PACKET,90)))
|
||||
{
|
||||
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
||||
debug_nmb_packet(p2);
|
||||
|
||||
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
|
||||
!nmb2->header.response) {
|
||||
/* its not for us - maybe deal with it later */
|
||||
@ -173,8 +175,6 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
|
||||
continue;
|
||||
}
|
||||
|
||||
debug_nmb_packet(p2);
|
||||
|
||||
_interpret_node_status(&nmb2->answers->rdata[0], master,rname);
|
||||
free_packet(p2);
|
||||
return(True);
|
||||
@ -257,6 +257,8 @@ BOOL name_query(int fd,char *name,int name_type,
|
||||
if ((p2=receive_packet(fd,NMB_PACKET,90)))
|
||||
{
|
||||
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
||||
debug_nmb_packet(p2);
|
||||
|
||||
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
|
||||
!nmb2->header.response) {
|
||||
/* its not for us - maybe deal with it later
|
||||
@ -268,8 +270,6 @@ BOOL name_query(int fd,char *name,int name_type,
|
||||
continue;
|
||||
}
|
||||
|
||||
debug_nmb_packet(p2);
|
||||
|
||||
if (nmb2->header.opcode != 0 ||
|
||||
nmb2->header.nm_flags.bcast ||
|
||||
nmb2->header.rcode ||
|
||||
|
@ -120,9 +120,12 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
|
||||
int name_type,
|
||||
struct in_addr ip)
|
||||
{
|
||||
add_browser_entry(serv_name, name_type, work_name, 0, ip);
|
||||
/* with a domain master we can get the whole list (not local only list) */
|
||||
BOOL local_only = state != NAME_STATUS_DOM_SRV_CHK;
|
||||
|
||||
if (state == NAME_STATUS_PDC_SRV_CHK)
|
||||
add_browser_entry(serv_name, name_type, work_name, 0, ip, local_only);
|
||||
|
||||
if (state == NAME_STATUS_DOM_SRV_CHK)
|
||||
{
|
||||
/* announce ourselves as a master browser to serv_name */
|
||||
do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
|
||||
@ -230,7 +233,7 @@ void announce_backup(void)
|
||||
/****************************************************************************
|
||||
send a host announcement packet
|
||||
**************************************************************************/
|
||||
static void do_announce_host(int command,
|
||||
void do_announce_host(int command,
|
||||
char *from_name, int from_type, struct in_addr from_ip,
|
||||
char *to_name , int to_type , struct in_addr to_ip,
|
||||
time_t announce_interval,
|
||||
@ -303,45 +306,86 @@ void announce_server(struct subnet_record *d, struct work_record *work,
|
||||
char *name, char *comment, time_t ttl, int server_type)
|
||||
{
|
||||
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_SERVER_UNIX;
|
||||
BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
|
||||
|
||||
if (AM_MASTER(work))
|
||||
if (wins_iface && server_type != 0)
|
||||
{
|
||||
DEBUG(3,("sending local master announce to %s for %s(1e)\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
|
||||
do_announce_host(ANN_LocalMasterAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
work->work_group, 0x1e, d->bcast_ip,
|
||||
ttl*1000,
|
||||
name, server_type, comment);
|
||||
|
||||
DEBUG(3,("sending domain announce to %s for %s\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
|
||||
/* XXXX should we do a domain-announce-kill? */
|
||||
if (server_type != 0)
|
||||
/* wins pseudo-ip interface */
|
||||
if (!AM_MASTER(work))
|
||||
{
|
||||
if (AM_DOMCTL(work)) {
|
||||
domain_type |= SV_TYPE_DOMAIN_CTRL;
|
||||
/* non-master announce by unicast to the domain master */
|
||||
if (!lp_wins_support() && *lp_wins_server())
|
||||
{
|
||||
/* look up the domain master with the WINS server */
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
|
||||
NAME_QUERY_ANNOUNCE_HOST,
|
||||
work->work_group,0x1b,0,ttl*1000,
|
||||
server_type,name,comment,
|
||||
False, False, ipzero, d->bcast_ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we are the WINS server, but not the domain master.
|
||||
what's going on??? and we're not going to deal with
|
||||
this case, right now
|
||||
*/
|
||||
}
|
||||
do_announce_host(ANN_DomainAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
MSBROWSE, 0x01, d->bcast_ip,
|
||||
ttl*1000,
|
||||
work->work_group, server_type ? domain_type : 0,
|
||||
comment);
|
||||
}
|
||||
|
||||
if (AM_DOMCTL(work))
|
||||
{
|
||||
/* XXXX announce to backup domain masters? */
|
||||
}
|
||||
|
||||
/* XXXX any other kinds of announcements we need to consider here?
|
||||
e.g local master browsers... no. local master browsers do
|
||||
local master announcements to their domain master. they even
|
||||
use WINS lookup of the domain master if another wins server
|
||||
is being used!
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(3,("sending host announce to %s for %s(1d)\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
if (AM_MASTER(work))
|
||||
{
|
||||
DEBUG(3,("sending local master announce to %s for %s(1e)\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
|
||||
do_announce_host(ANN_HostAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
work->work_group, 0x1d, d->bcast_ip,
|
||||
ttl*1000,
|
||||
name, server_type, comment);
|
||||
do_announce_host(ANN_LocalMasterAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
work->work_group, 0x1e, d->bcast_ip,
|
||||
ttl*1000,
|
||||
name, server_type, comment);
|
||||
|
||||
DEBUG(3,("sending domain announce to %s for %s\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
|
||||
/* XXXX should we do a domain-announce-kill? */
|
||||
if (server_type != 0)
|
||||
{
|
||||
if (AM_DOMCTL(work))
|
||||
{
|
||||
domain_type |= SV_TYPE_DOMAIN_CTRL;
|
||||
}
|
||||
do_announce_host(ANN_DomainAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
MSBROWSE, 0x01, d->bcast_ip,
|
||||
ttl*1000,
|
||||
work->work_group, server_type ? domain_type : 0,
|
||||
comment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(3,("sending host announce to %s for %s(1d)\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group));
|
||||
|
||||
do_announce_host(ANN_HostAnnouncement,
|
||||
name , 0x00, d->myip,
|
||||
work->work_group, 0x1d, d->bcast_ip,
|
||||
ttl*1000,
|
||||
name, server_type, comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,7 +477,7 @@ void announce_host(void)
|
||||
least 15 minutes.
|
||||
|
||||
this actually gets done in search_and_sync_workgroups() via the
|
||||
NAME_QUERY_PDC_SRV_CHK command, if there is a response from the
|
||||
NAME_QUERY_DOM_SRV_CHK command, if there is a response from the
|
||||
name query initiated here. see response_name_query()
|
||||
**************************************************************************/
|
||||
void announce_master(void)
|
||||
@ -473,7 +517,7 @@ void announce_master(void)
|
||||
{
|
||||
if (strequal(s->serv.name, myname)) continue;
|
||||
|
||||
/* all PDCs (which should also be master browsers) */
|
||||
/* all DOMs (which should also be master browsers) */
|
||||
if (s->serv.type & SV_TYPE_DOMAIN_CTRL)
|
||||
{
|
||||
/* check the existence of a pdc for this workgroup, and if
|
||||
@ -485,13 +529,10 @@ void announce_master(void)
|
||||
{
|
||||
if (!lp_wins_support() && *lp_wins_server())
|
||||
{
|
||||
struct in_addr ip;
|
||||
ip = ipzero;
|
||||
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,
|
||||
False, False, ip, ip);
|
||||
NAME_QUERY_DOM_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,0,NULL,NULL,
|
||||
False, False, ipzero, ipzero);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -499,8 +540,8 @@ void announce_master(void)
|
||||
for (d2 = subnetlist; d2; d2 = d2->next)
|
||||
{
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,
|
||||
NAME_QUERY_DOM_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,0,NULL,NULL,
|
||||
True, False, d2->bcast_ip, d2->bcast_ip);
|
||||
}
|
||||
}
|
||||
@ -527,14 +568,14 @@ void announce_master(void)
|
||||
bcast = True;
|
||||
}
|
||||
|
||||
DEBUG(2, ("Searching for PDC %s at %s\n",
|
||||
DEBUG(2, ("Searching for DOM %s at %s\n",
|
||||
lp_domain_controller(), inet_ntoa(ip)));
|
||||
|
||||
/* check the existence of a pdc for this workgroup, and if
|
||||
one exists at the specified ip, sync with it and announce
|
||||
ourselves as a master browser to it */
|
||||
queue_netbios_pkt_wins(d,ClientNMB, NMB_QUERY,NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b, 0, 0,
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,0,NULL,NULL,
|
||||
bcast, False, ip, ip);
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ void expire_browse_cache(time_t t)
|
||||
add a browser entry
|
||||
****************************************************************************/
|
||||
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
|
||||
time_t ttl, struct in_addr ip)
|
||||
time_t ttl, struct in_addr ip, BOOL local)
|
||||
{
|
||||
BOOL newentry=False;
|
||||
|
||||
@ -135,6 +135,7 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
|
||||
|
||||
b->ip = ip;
|
||||
b->type = type;
|
||||
b->local = local; /* local server list sync or complete sync required */
|
||||
|
||||
if (newentry || ttl < b->sync_time)
|
||||
b->sync_time = ttl;
|
||||
@ -176,8 +177,9 @@ static void start_sync_browse_entry(struct browse_cache_record *b)
|
||||
doesn't, the server must have died. o dear. */
|
||||
|
||||
/* see response_netbios_packet() or expire_netbios_response_entries() */
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SYNC,
|
||||
b->group,0x20,0,0,
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
|
||||
b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
|
||||
b->group,0x20,0,0,0,NULL,NULL,
|
||||
False,False,b->ip,b->ip);
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,27 @@ extern struct subnet_record *subnetlist;
|
||||
|
||||
#define WINS_LIST "wins.dat"
|
||||
|
||||
uint16 nb_type = 0; /* samba's NetBIOS name type */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
samba's NetBIOS name type
|
||||
|
||||
XXXX maybe functionality could be set: B, M, P or H name registration
|
||||
and resolution could be set through nb_type. just a thought.
|
||||
****************************************************************************/
|
||||
void set_samba_nb_type(void)
|
||||
{
|
||||
if (lp_wins_support() || (*lp_wins_server()))
|
||||
{
|
||||
nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
|
||||
}
|
||||
else
|
||||
{
|
||||
nb_type = NB_BFLAG; /* samba is broadcast-only node type */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
true if two netbios names are equal
|
||||
@ -390,7 +411,7 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
|
||||
if (!wins && type != 0x1b)
|
||||
{
|
||||
/* the only broadcast (non-WINS) names we are adding are ours
|
||||
(SELF) and PDC type names */
|
||||
(SELF) and Domain Master type names */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ void remove_response_record(struct subnet_record *d,
|
||||
struct response_record *make_response_queue_record(enum state_type state,
|
||||
int id,uint16 fd,
|
||||
int quest_type, char *name,int type, int nb_flags, time_t ttl,
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip)
|
||||
{
|
||||
@ -111,10 +112,13 @@ struct response_record *make_response_queue_record(enum state_type state,
|
||||
make_nmb_name(&n->name, name, type, scope);
|
||||
n->nb_flags = nb_flags;
|
||||
n->ttl = ttl;
|
||||
n->server_type = server_type;
|
||||
n->bcast = bcast;
|
||||
n->recurse = recurse;
|
||||
n->send_ip = send_ip;
|
||||
n->reply_to_ip = reply_to_ip;
|
||||
StrnCpy(my_name , n->my_name , sizeof(n->my_name )-1);
|
||||
StrnCpy(my_comment, n->my_comment, sizeof(n->my_comment)-1);
|
||||
|
||||
n->repeat_interval = 1; /* XXXX should be in ms */
|
||||
n->repeat_count = 3; /* 3 retries */
|
||||
|
@ -50,6 +50,7 @@ extern struct interface *local_interfaces;
|
||||
/* this is our domain/workgroup/server database */
|
||||
struct subnet_record *subnetlist = NULL;
|
||||
|
||||
extern uint16 nb_type; /* samba's NetBIOS name type */
|
||||
|
||||
/****************************************************************************
|
||||
add a domain into the list
|
||||
@ -166,7 +167,7 @@ void add_subnet_interfaces(void)
|
||||
}
|
||||
|
||||
/* add the pseudo-ip interface for WINS: 255.255.255.255 */
|
||||
if (lp_wins_support())
|
||||
if (lp_wins_support() || (*lp_wins_server()))
|
||||
{
|
||||
struct in_addr wins_bcast = ipgrp;
|
||||
struct in_addr wins_nmask = ipzero;
|
||||
@ -231,8 +232,8 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
|
||||
or register with WINS server, if it's our workgroup */
|
||||
if (strequal(lp_workgroup(), name))
|
||||
{
|
||||
add_my_name_entry(d,name,0x1e,NB_ACTIVE|NB_GROUP);
|
||||
add_my_name_entry(d,name,0x0 ,NB_ACTIVE|NB_GROUP);
|
||||
add_my_name_entry(d,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
|
||||
add_my_name_entry(d,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
|
||||
}
|
||||
/* add samba server name to workgroup list. don't add
|
||||
lmhosts server entries to local interfaces */
|
||||
|
@ -181,7 +181,7 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
|
||||
DEBUG(2,("add any workgroups: initiating browser search on %s\n",
|
||||
inet_ntoa(d->bcast_ip)));
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
|
||||
MSBROWSE,0x1,0,0,
|
||||
MSBROWSE,0x1,0,0,0,NULL,NULL,
|
||||
True,False, d->bcast_ip, d->bcast_ip);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ extern time_t StartupTime;
|
||||
|
||||
extern struct subnet_record *subnetlist;
|
||||
|
||||
extern uint16 nb_type; /* samba's NetBIOS name type */
|
||||
|
||||
/*******************************************************************
|
||||
occasionally check to see if the master browser is around
|
||||
@ -81,7 +82,7 @@ void check_master_browser(void)
|
||||
if (!AM_MASTER(work))
|
||||
{
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
|
||||
work->work_group,0x1d,0,0,
|
||||
work->work_group,0x1d,0,0,0,NULL,NULL,
|
||||
True,False,d->bcast_ip,d->bcast_ip);
|
||||
}
|
||||
}
|
||||
@ -268,7 +269,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
|
||||
|
||||
/* add special browser name */
|
||||
add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
|
||||
add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
|
||||
|
||||
/* DON'T do anything else after calling add_my_name_entry() */
|
||||
return;
|
||||
@ -282,7 +283,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
|
||||
|
||||
/* add master name */
|
||||
add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
|
||||
add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
|
||||
|
||||
/* DON'T do anything else after calling add_my_name_entry() */
|
||||
return;
|
||||
@ -320,7 +321,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
DEBUG(3,("domain first stage: register as domain member\n"));
|
||||
|
||||
/* add domain member name */
|
||||
add_my_name_entry(d,work->work_group,0x1e,NB_ACTIVE );
|
||||
add_my_name_entry(d,work->work_group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
|
||||
|
||||
/* DON'T do anything else after calling add_my_name_entry() */
|
||||
return;
|
||||
@ -347,7 +348,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
}
|
||||
|
||||
/* add domain master name */
|
||||
add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
|
||||
add_my_name_entry(d,work->work_group,0x1b,nb_type|NB_ACTIVE );
|
||||
|
||||
/* DON'T do anything else after calling add_my_name_entry() */
|
||||
return;
|
||||
|
@ -224,6 +224,7 @@ void expire_netbios_response_entries()
|
||||
struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
int fd,int quest_type,enum state_type state,
|
||||
char *name,int name_type,int nb_flags, time_t ttl,
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip)
|
||||
{
|
||||
@ -256,6 +257,7 @@ struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
|
||||
return queue_netbios_packet(d,fd, quest_type, state,
|
||||
name, name_type, nb_flags, ttl,
|
||||
server_type,my_name,my_comment,
|
||||
bcast, recurse, send_ip, reply_to_ip);
|
||||
}
|
||||
|
||||
@ -269,8 +271,9 @@ struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
struct response_record *queue_netbios_packet(struct subnet_record *d,
|
||||
int fd,int quest_type,enum state_type state,char *name,
|
||||
int name_type,int nb_flags, time_t ttl,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip)
|
||||
int server_type, char *my_name, char *my_comment,
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip)
|
||||
{
|
||||
struct in_addr wins_ip = ipgrp;
|
||||
struct response_record *n;
|
||||
@ -289,6 +292,7 @@ struct response_record *queue_netbios_packet(struct subnet_record *d,
|
||||
|
||||
if ((n = make_response_queue_record(state,id,fd,
|
||||
quest_type,name,name_type,nb_flags,ttl,
|
||||
server_type,my_name, my_comment,
|
||||
bcast,recurse,send_ip,reply_to_ip)))
|
||||
{
|
||||
add_response_record(d,n);
|
||||
|
@ -43,6 +43,7 @@ extern struct in_addr ipgrp;
|
||||
|
||||
extern struct subnet_record *subnetlist;
|
||||
|
||||
extern uint16 nb_type; /* samba's NetBIOS type */
|
||||
|
||||
/****************************************************************************
|
||||
remove an entry from the name list
|
||||
@ -90,7 +91,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
|
||||
server, or if no reply is received, then we can remove the name */
|
||||
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
|
||||
name, type, 0, 0,
|
||||
name, type, 0, 0,0,NULL,NULL,
|
||||
False, True, ipzero, ipzero);
|
||||
}
|
||||
}
|
||||
@ -101,7 +102,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
|
||||
then we can remove the name. */
|
||||
|
||||
queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
|
||||
name, type, 0, 0,
|
||||
name, type, 0, 0,0,NULL,NULL,
|
||||
True, True, d->bcast_ip, d->bcast_ip);
|
||||
}
|
||||
}
|
||||
@ -151,7 +152,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
|
||||
/* a time-to-live allows us to refresh this name with the WINS server. */
|
||||
queue_netbios_pkt_wins(d,ClientNMB,
|
||||
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
|
||||
name, type, nb_flags, GET_TTL(0),
|
||||
name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
|
||||
False, True, ipzero, ipzero);
|
||||
}
|
||||
}
|
||||
@ -160,7 +161,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
|
||||
/* broadcast the packet, but it comes from ipzero */
|
||||
queue_netbios_packet(d,ClientNMB,
|
||||
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
|
||||
name, type, nb_flags, GET_TTL(0),
|
||||
name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
|
||||
True, True, d->bcast_ip, ipzero);
|
||||
}
|
||||
}
|
||||
@ -186,20 +187,20 @@ void add_my_names(void)
|
||||
{
|
||||
BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
|
||||
|
||||
add_my_name_entry(d, myname,0x20,NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x03,NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x00,NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x1f,NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
|
||||
add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
|
||||
|
||||
/* these names are added permanently (ttl of zero) and will NOT be
|
||||
refreshed with the WINS server */
|
||||
add_netbios_entry(d,"*",0x0,NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
|
||||
|
||||
if (!wins_iface && lp_domain_logons() && lp_domain_master()) {
|
||||
/* XXXX the 0x1c is apparently something to do with domain logons */
|
||||
add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
|
||||
add_my_name_entry(d, my_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
|
||||
}
|
||||
}
|
||||
if (lp_domain_master() && (d = find_subnet(ipgrp)))
|
||||
@ -310,7 +311,7 @@ void query_refresh_names(void)
|
||||
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
|
||||
n->name.name, n->name.name_type,
|
||||
0,0,
|
||||
0,0,0,NULL,NULL,
|
||||
False,False,n->ip,n->ip);
|
||||
count++;
|
||||
}
|
||||
|
@ -294,7 +294,8 @@ void reply_name_reg(struct packet_struct *p)
|
||||
/* initiate some enquiries to the current owner. */
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
|
||||
NAME_REGISTER_CHALLENGE,
|
||||
reply_name->name,reply_name->name_type,nb_flags,0,
|
||||
reply_name->name,reply_name->name_type,
|
||||
nb_flags,0,0,NULL,NULL,
|
||||
False, False, n->ip, p->ip);
|
||||
}
|
||||
else
|
||||
@ -311,8 +312,11 @@ void reply_name_reg(struct packet_struct *p)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
reply to a name status query
|
||||
****************************************************************************/
|
||||
reply to a name status query
|
||||
|
||||
combine the list of the local interface on which the query was made with
|
||||
the names registered via wins.
|
||||
****************************************************************************/
|
||||
void reply_name_status(struct packet_struct *p)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
@ -323,7 +327,7 @@ void reply_name_status(struct packet_struct *p)
|
||||
int names_added;
|
||||
struct name_record *n;
|
||||
struct subnet_record *d = NULL;
|
||||
int search = FIND_SELF;
|
||||
int search = FIND_SELF | FIND_WINS;
|
||||
|
||||
BOOL bcast = nmb->header.nm_flags.bcast;
|
||||
|
||||
@ -338,8 +342,6 @@ void reply_name_status(struct packet_struct *p)
|
||||
namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
|
||||
|
||||
if (bcast)
|
||||
search |= FIND_WINS;
|
||||
else
|
||||
search |= FIND_LOCAL;
|
||||
|
||||
n = find_name_search(&d, &nmb->question.question_name,
|
||||
@ -354,38 +356,55 @@ void reply_name_status(struct packet_struct *p)
|
||||
|
||||
names_added = 0;
|
||||
|
||||
for (n = d->namelist ; n && buf < bufend; n = n->next)
|
||||
n = d->namelist;
|
||||
|
||||
while (buf < bufend)
|
||||
{
|
||||
if (n->source == SELF)
|
||||
{
|
||||
int name_type = n->name.name_type;
|
||||
|
||||
if (n->source != SELF) continue;
|
||||
/* check if we want to exclude other workgroup names
|
||||
from the response. if we don't exclude them, windows clients
|
||||
get confused and will respond with an error for NET VIEW */
|
||||
|
||||
/* start with first bit of putting info in buffer: the name */
|
||||
if (name_type < 0x1b || name_type > 0x20 ||
|
||||
ques_type < 0x1b || ques_type > 0x20 ||
|
||||
strequal(qname, n->name.name))
|
||||
{
|
||||
/* start with first bit of putting info in buffer: the name */
|
||||
bzero(buf,18);
|
||||
sprintf(buf,"%-15.15s",n->name.name);
|
||||
strupper(buf);
|
||||
|
||||
bzero(buf,18);
|
||||
sprintf(buf,"%-15.15s",n->name.name);
|
||||
strupper(buf);
|
||||
/* put name type and netbios flags in buffer */
|
||||
buf[15] = name_type;
|
||||
buf[16] = n->nb_flags;
|
||||
|
||||
/* now check if we want to exclude other workgroup names
|
||||
from the response. if we don't exclude them, windows clients
|
||||
get confused and will respond with an error for NET VIEW */
|
||||
buf += 18;
|
||||
|
||||
if (name_type >= 0x1b && name_type <= 0x20 &&
|
||||
ques_type >= 0x1b && ques_type <= 0x20)
|
||||
{
|
||||
if (!strequal(qname, n->name.name)) continue;
|
||||
}
|
||||
|
||||
/* carry on putting name info in buffer */
|
||||
|
||||
buf[15] = name_type;
|
||||
buf[16] = n->nb_flags;
|
||||
|
||||
buf += 18;
|
||||
|
||||
names_added++;
|
||||
names_added++;
|
||||
}
|
||||
}
|
||||
|
||||
n = n->next;
|
||||
|
||||
if (!n)
|
||||
{
|
||||
/* end of this name list: add wins names too? */
|
||||
struct subnet_record *w_d;
|
||||
|
||||
if (!(w_d = find_subnet(ipgrp))) break;
|
||||
|
||||
if (w_d != d)
|
||||
{
|
||||
d = w_d;
|
||||
n = d->namelist; /* start on the wins name list */
|
||||
}
|
||||
}
|
||||
if (!n) break;
|
||||
}
|
||||
|
||||
SCVAL(countptr,0,names_added);
|
||||
|
||||
/* XXXXXXX we should fill in more fields of the statistics structure */
|
||||
@ -396,9 +415,7 @@ void reply_name_status(struct packet_struct *p)
|
||||
SIVAL(buf,24,num_good_receives);
|
||||
}
|
||||
|
||||
SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */
|
||||
|
||||
buf += 64;
|
||||
buf += 46;
|
||||
|
||||
/* Send a POSITIVE NAME STATUS RESPONSE */
|
||||
reply_netbios_packet(p,nmb->header.name_trn_id,
|
||||
@ -451,14 +468,13 @@ void reply_name_query(struct packet_struct *p)
|
||||
struct name_record *n;
|
||||
|
||||
/* directed queries are for WINS server: broadcasts are local SELF queries.
|
||||
the exception is PDC names. */
|
||||
the exception is Domain Master names. */
|
||||
|
||||
int search = bcast ? FIND_LOCAL | FIND_SELF : FIND_WINS;
|
||||
|
||||
if (name_type == 0x1b)
|
||||
if (name_type == 0x1b || name_type == 0x0 || name_type == 0x20)
|
||||
{
|
||||
/* even if it's a broadcast, we don't ignore queries for PDC names */
|
||||
search = FIND_WINS;
|
||||
search |= FIND_WINS;
|
||||
}
|
||||
|
||||
if (search | FIND_LOCAL)
|
||||
@ -500,10 +516,11 @@ void reply_name_query(struct packet_struct *p)
|
||||
}
|
||||
}
|
||||
|
||||
/* name is directed query, or it's self, or it's a PDC type name, or
|
||||
we're replying on behalf of a caller because they are on a different
|
||||
subnet and cannot hear the broadcast. XXXX lp_wins_proxy should be
|
||||
switched off in environments where broadcasts are forwarded */
|
||||
/* name is directed query, or it's self, or it's a Domain Master type
|
||||
name, or we're replying on behalf of a caller because they are on a
|
||||
different subnet and cannot hear the broadcast. XXXX lp_wins_proxy
|
||||
should be switched off in environments where broadcasts are forwarded
|
||||
*/
|
||||
|
||||
/* XXXX note: for proxy servers, we should forward the query on to
|
||||
another WINS server if the name is not in our database, or we are
|
||||
|
@ -124,7 +124,66 @@ static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
response from a name query server check. states of type NAME_QUERY_PDC_SRV_CHK,
|
||||
response from a name query announce host
|
||||
NAME_QUERY_ANNOUNCE_HOST is dealt with here
|
||||
****************************************************************************/
|
||||
static void response_announce_host(struct nmb_name *ans_name,
|
||||
struct nmb_packet *nmb,
|
||||
struct response_record *n, struct subnet_record *d)
|
||||
{
|
||||
DEBUG(4, ("Name query at %s ip %s - ",
|
||||
namestr(&n->name), inet_ntoa(n->send_ip)));
|
||||
|
||||
if (!name_equal(&n->name, ans_name))
|
||||
{
|
||||
/* someone gave us the wrong name as a reply. oops. */
|
||||
/* XXXX should say to them 'oi! release that name!' */
|
||||
|
||||
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nmb->header.rcode == 0 && nmb->answers->rdata)
|
||||
{
|
||||
/* we had sent out a name query to the current owner
|
||||
of a name because someone else wanted it. now they
|
||||
have responded saying that they still want the name,
|
||||
so the other host can't have it.
|
||||
*/
|
||||
|
||||
/* first check all the details are correct */
|
||||
|
||||
int nb_flags = nmb->answers->rdata[0];
|
||||
struct in_addr found_ip;
|
||||
|
||||
putip((char*)&found_ip,&nmb->answers->rdata[2]);
|
||||
|
||||
if (nb_flags != n->nb_flags)
|
||||
{
|
||||
/* someone gave us the wrong nb_flags as a reply. oops. */
|
||||
/* XXXX should say to them 'oi! release that name!' */
|
||||
|
||||
DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
|
||||
DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
|
||||
return;
|
||||
}
|
||||
|
||||
/* do an announce host */
|
||||
do_announce_host(ANN_HostAnnouncement,
|
||||
n->my_name , 0x00, d->myip,
|
||||
n->name.name, 0x1d, found_ip,
|
||||
n->ttl,
|
||||
n->my_name, n->server_type, n->my_comment);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXXX negative name query response. no master exists. oops */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
response from a name query server check. states of type NAME_QUERY_DOM_SRV_CHK,
|
||||
NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
|
||||
****************************************************************************/
|
||||
static void response_server_check(struct nmb_name *ans_name,
|
||||
@ -132,13 +191,13 @@ static void response_server_check(struct nmb_name *ans_name,
|
||||
{
|
||||
/* issue another state: this time to do a name status check */
|
||||
|
||||
enum state_type cmd = (n->state == NAME_QUERY_PDC_SRV_CHK) ?
|
||||
NAME_STATUS_PDC_SRV_CHK : NAME_STATUS_SRV_CHK;
|
||||
enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
|
||||
NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK;
|
||||
|
||||
/* initiate a name status check on the server that replied */
|
||||
queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
|
||||
ans_name->name, ans_name->name_type,
|
||||
0,0,
|
||||
0,0,0,NULL,NULL,
|
||||
False,False,n->send_ip,n->reply_to_ip);
|
||||
}
|
||||
|
||||
@ -185,7 +244,7 @@ static BOOL interpret_node_status(struct subnet_record *d,
|
||||
if (NAME_BFLAG (nb_flags)) { strcat(flags,"B "); }
|
||||
if (NAME_PFLAG (nb_flags)) { strcat(flags,"P "); }
|
||||
if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); }
|
||||
if (NAME__FLAG (nb_flags)) { strcat(flags,"_ "); }
|
||||
if (NAME_HFLAG (nb_flags)) { strcat(flags,"H "); }
|
||||
if (NAME_DEREG (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
|
||||
if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
|
||||
if (NAME_ACTIVE (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
|
||||
@ -236,7 +295,7 @@ static BOOL interpret_node_status(struct subnet_record *d,
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
response from a name status check. states of type NAME_STATUS_PDC_SRV_CHK
|
||||
response from a name status check. states of type NAME_STATUS_DOM_SRV_CHK
|
||||
and NAME_STATUS_SRV_CHK dealt with here.
|
||||
****************************************************************************/
|
||||
static void response_name_status_check(struct in_addr ip,
|
||||
@ -380,14 +439,17 @@ static void response_name_query_sync(struct nmb_packet *nmb,
|
||||
|
||||
DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
|
||||
|
||||
if (n->state == NAME_QUERY_SYNC)
|
||||
if (n->state == NAME_QUERY_SYNC_LOCAL ||
|
||||
n->state == NAME_QUERY_SYNC_REMOTE)
|
||||
{
|
||||
struct work_record *work = NULL;
|
||||
if ((work = find_workgroupstruct(d, ans_name->name, False)))
|
||||
{
|
||||
BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
|
||||
|
||||
/* the server is there: sync quick before it (possibly) dies! */
|
||||
sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
|
||||
found_ip);
|
||||
found_ip, local_list_only);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -439,17 +501,23 @@ void debug_state_type(int state)
|
||||
/* report the state type to help debugging */
|
||||
switch (state)
|
||||
{
|
||||
case NAME_QUERY_PDC_SRV_CHK : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
|
||||
case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
|
||||
case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
|
||||
case NAME_STATUS_PDC_SRV_CHK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break;
|
||||
case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break;
|
||||
case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
|
||||
case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break;
|
||||
case NAME_REGISTER_CHALLENGE: DEBUG(4,("NAME_REGISTER_CHALLENGE\n")); break;
|
||||
case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break;
|
||||
case NAME_QUERY_CONFIRM : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
|
||||
case NAME_QUERY_SYNC : DEBUG(4,("NAME_QUERY_SYNC\n")); break;
|
||||
case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
|
||||
case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
|
||||
case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
|
||||
case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
|
||||
case NAME_QUERY_CONFIRM : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
|
||||
case NAME_QUERY_SYNC_LOCAL : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break;
|
||||
case NAME_QUERY_SYNC_REMOTE : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break;
|
||||
case NAME_QUERY_ANNOUNCE_HOST: DEBUG(4,("NAME_QUERY_ANNCE_HOST\n"));break;
|
||||
|
||||
case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break;
|
||||
case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break;
|
||||
|
||||
case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break;
|
||||
|
||||
case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STAT_MST_CHK\n")); break;
|
||||
case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -512,7 +580,8 @@ static BOOL response_problem_check(struct response_record *n,
|
||||
/* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */
|
||||
return False;
|
||||
}
|
||||
case NAME_QUERY_PDC_SRV_CHK:
|
||||
case NAME_QUERY_ANNOUNCE_HOST:
|
||||
case NAME_QUERY_DOM_SRV_CHK:
|
||||
case NAME_QUERY_SRV_CHK:
|
||||
case NAME_QUERY_MST_CHK:
|
||||
{
|
||||
@ -576,8 +645,10 @@ static BOOL response_compatible(struct response_record *n,
|
||||
|
||||
case NAME_REGISTER_CHALLENGE: /* this is a query: we then do a register */
|
||||
case NAME_QUERY_CONFIRM:
|
||||
case NAME_QUERY_SYNC:
|
||||
case NAME_QUERY_PDC_SRV_CHK:
|
||||
case NAME_QUERY_ANNOUNCE_HOST:
|
||||
case NAME_QUERY_SYNC_LOCAL:
|
||||
case NAME_QUERY_SYNC_REMOTE:
|
||||
case NAME_QUERY_DOM_SRV_CHK:
|
||||
case NAME_QUERY_SRV_CHK:
|
||||
case NAME_QUERY_FIND_MST:
|
||||
case NAME_QUERY_MST_CHK:
|
||||
@ -590,7 +661,7 @@ static BOOL response_compatible(struct response_record *n,
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_STATUS_PDC_SRV_CHK:
|
||||
case NAME_STATUS_DOM_SRV_CHK:
|
||||
case NAME_STATUS_SRV_CHK:
|
||||
{
|
||||
if (nmb->answers->rr_type != NMB_STATUS)
|
||||
@ -638,7 +709,7 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_QUERY_PDC_SRV_CHK:
|
||||
case NAME_QUERY_DOM_SRV_CHK:
|
||||
case NAME_QUERY_SRV_CHK:
|
||||
case NAME_QUERY_FIND_MST:
|
||||
{
|
||||
@ -646,15 +717,22 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_STATUS_PDC_SRV_CHK:
|
||||
case NAME_STATUS_DOM_SRV_CHK:
|
||||
case NAME_STATUS_SRV_CHK:
|
||||
{
|
||||
response_name_status_check(p->ip, nmb, bcast, n, d);
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_QUERY_ANNOUNCE_HOST:
|
||||
{
|
||||
response_announce_host(ans_name, nmb, n, d);
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_QUERY_CONFIRM:
|
||||
case NAME_QUERY_SYNC:
|
||||
case NAME_QUERY_SYNC_LOCAL:
|
||||
case NAME_QUERY_SYNC_REMOTE:
|
||||
{
|
||||
response_name_query_sync(nmb, ans_name, bcast, n, d);
|
||||
break;
|
||||
@ -702,7 +780,8 @@ void response_netbios_packet(struct packet_struct *p)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!same_net(d->bcast_ip, d->mask_ip, p->ip)) /* copes with WINS 'subnet' */
|
||||
/* args wrong way round: spotted by ccm@shentel.net */
|
||||
if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
|
||||
{
|
||||
DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
|
||||
DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
|
||||
|
@ -284,17 +284,12 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
|
||||
tell_become_backup();
|
||||
#endif
|
||||
|
||||
/* XXXX over-kill: i don't think we should really be doing this,
|
||||
but it doesn't do much harm other than to add extra network
|
||||
traffic. to be more precise, we should (possibly) only
|
||||
sync browse lists with a host that sends an
|
||||
ANN_LocalMasterAnnouncement or an ANN_DomainAnnouncement.
|
||||
possibly.
|
||||
*/
|
||||
|
||||
/* get their browse list from them and add it to ours. */
|
||||
add_browser_entry(serv_name,dgram->dest_name.name_type,
|
||||
work->work_group,30,ip);
|
||||
/* get the local_only browse list from the local master and add it to ours. */
|
||||
if (command == ANN_LocalMasterAnnouncement)
|
||||
{
|
||||
add_browser_entry(serv_name,dgram->dest_name.name_type,
|
||||
work->work_group,30,ip,True);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -319,13 +314,13 @@ static void process_master_announce(struct packet_struct *p,char *buf)
|
||||
if (!lp_domain_master()) return;
|
||||
|
||||
for (work = mydomain->workgrouplist; work; work = work->next)
|
||||
{
|
||||
if (AM_MASTER(work))
|
||||
{
|
||||
if (AM_MASTER(work))
|
||||
{
|
||||
/* merge browse lists with them */
|
||||
add_browser_entry(name,0x1b, work->work_group,30,ip);
|
||||
}
|
||||
add_browser_entry(name,0x1b, work->work_group,30,ip,True);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -394,7 +389,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
|
||||
if (work->token == 0 /* token */)
|
||||
{
|
||||
queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
|
||||
work->work_group,0x1d,0,0,
|
||||
work->work_group,0x1d,
|
||||
0,0,0,NULL,NULL,
|
||||
False,False,back_ip,back_ip);
|
||||
return;
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ time_t StartupTime =0;
|
||||
|
||||
extern struct in_addr ipzero;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
catch a sigterm
|
||||
****************************************************************************/
|
||||
@ -90,6 +89,8 @@ static int sig_hup(void)
|
||||
dump_names();
|
||||
reload_services(True);
|
||||
|
||||
set_samba_nb_type();
|
||||
|
||||
BlockSignals(False);
|
||||
#ifndef DONT_REINSTALL_SIG
|
||||
signal(SIGHUP,SIGNAL_CAST sig_hup);
|
||||
@ -524,6 +525,8 @@ static void usage(char *pname)
|
||||
if (!reload_services(False))
|
||||
return(-1);
|
||||
|
||||
set_samba_nb_type();
|
||||
|
||||
if (*group)
|
||||
add_my_subnets(group);
|
||||
|
||||
|
@ -136,8 +136,10 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
|
||||
do a NetServerEnum and update our server and workgroup databases.
|
||||
******************************************************************/
|
||||
void sync_browse_lists(struct subnet_record *d, struct work_record *work,
|
||||
char *name, int nm_type, struct in_addr ip)
|
||||
char *name, int nm_type, struct in_addr ip, BOOL local)
|
||||
{
|
||||
uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
|
||||
|
||||
if (!d || !work || !AM_MASTER(work)) return;
|
||||
|
||||
pid = getpid();
|
||||
@ -169,8 +171,9 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
|
||||
{
|
||||
if (cli_send_login(NULL,NULL,True,True))
|
||||
{
|
||||
add_info(d, work, SV_TYPE_DOMAIN_ENUM);
|
||||
add_info(d, work, SV_TYPE_ALL&~SV_TYPE_DOMAIN_ENUM);
|
||||
add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM);
|
||||
add_info(d, work, local_type|(SV_TYPE_ALL&
|
||||
~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY)));
|
||||
}
|
||||
|
||||
close_sockets();
|
||||
|
@ -49,7 +49,7 @@ static BOOL open_sockets(void)
|
||||
return False;
|
||||
}
|
||||
|
||||
ServerFD = open_socket_in(SOCK_DGRAM, NMB_PORT,3);
|
||||
ServerFD = open_socket_in(SOCK_DGRAM, 0,3);
|
||||
|
||||
if (ServerFD == -1)
|
||||
return(False);
|
||||
@ -151,7 +151,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
|
||||
for (i=optind;i<argc;i++)
|
||||
{
|
||||
{
|
||||
BOOL bcast = True;
|
||||
int retries = 2;
|
||||
char *p;
|
||||
@ -177,20 +177,18 @@ int main(int argc,char *argv[])
|
||||
retries = 1;
|
||||
}
|
||||
|
||||
if (name_query(ServerFD,lookup,lookup_type,bcast,True,
|
||||
if (name_query(ServerFD,lookup,lookup_type,bcast,True,
|
||||
*iface_bcast(ipzero),&ip,NULL))
|
||||
{
|
||||
printf("%s %s\n",inet_ntoa(ip),lookup);
|
||||
if (find_status)
|
||||
{
|
||||
}
|
||||
if (find_status)
|
||||
{
|
||||
printf("Looking up status of %s\n",inet_ntoa(ip));
|
||||
name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL);
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("couldn't find name %s\n",lookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user