1
0
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:
Samba Release Account 0001-01-01 00:00:00 +00:00
parent 801fe1066e
commit 6e932e4bae
18 changed files with 386 additions and 194 deletions

View File

@ -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;

View File

@ -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,11 +442,13 @@ 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,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip);
@ -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 */

View File

@ -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 ||

View File

@ -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,7 +306,46 @@ 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 (wins_iface && server_type != 0)
{
/* wins pseudo-ip interface */
if (!AM_MASTER(work))
{
/* 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
*/
}
}
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
{
if (AM_MASTER(work))
{
DEBUG(3,("sending local master announce to %s for %s(1e)\n",
@ -321,7 +363,8 @@ void announce_server(struct subnet_record *d, struct work_record *work,
/* XXXX should we do a domain-announce-kill? */
if (server_type != 0)
{
if (AM_DOMCTL(work)) {
if (AM_DOMCTL(work))
{
domain_type |= SV_TYPE_DOMAIN_CTRL;
}
do_announce_host(ANN_DomainAnnouncement,
@ -343,6 +386,7 @@ void announce_server(struct subnet_record *d, struct work_record *work,
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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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,6 +271,7 @@ 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,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
{
@ -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);

View File

@ -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++;
}

View File

@ -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,30 +356,28 @@ 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 */
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);
/* 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 */
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 */
/* put name type and netbios flags in buffer */
buf[15] = name_type;
buf[16] = n->nb_flags;
@ -385,6 +385,25 @@ void reply_name_status(struct packet_struct *p)
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);
@ -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

View File

@ -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_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_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_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)));

View File

@ -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. */
/* 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);
work->work_group,30,ip,True);
}
}
/*******************************************************************
@ -323,7 +318,7 @@ static void process_master_announce(struct packet_struct *p,char *buf)
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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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);
@ -181,15 +181,13 @@ int main(int argc,char *argv[])
*iface_bcast(ipzero),&ip,NULL))
{
printf("%s %s\n",inet_ntoa(ip),lookup);
}
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);