mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
tidied up: code shuffling and documentation.
created namedb*.c nameservresp.c nameservreply.c and namepacket.c
added modules to Makefile, downloading dan's current version first :-)
shuffled docs to match source
created more docs
fixed bug in announce_backup() discovered when going nameannounce.doc:
backup list requests to the master browser should be used when samba is
not a master browser; backup list requests to the primary domain
controller should be used when samba is not a primary domain controller.
fixed bug in sync_server: it would never send MasterAnnounce packets.
removed the code that ignored special browser names: these should only
be ignored (except 0x1b names) when broadcasted name queries are sent,
not when directed registration or directed queries are sent samba as a
WINS server. (note: exactly what's going on is still uncertain).
renamed NAME_QUERY_MST_SRV_CHK to NAME_QUERY_PDC_SRV_CHK (more accurate).
renamed NAME_STATUS_MST_SRV_CHK to NAME_STATUS_PDC_SRV_CHK (more accurate).
added secured WINS name registration: a new 'state' NAME_REGISTER_CHALLENGE;
functions send_name_response(), response_name_query_register(); added
sending of WAIT ACKNOWLEDGEMENT packet; added a reply_to_ip field to
the response record structure so that after the name query challenge,
you know who to inform of the outcome of that challenge.
note: these are all currently untested modifications (yikes!)
lkcl
(This used to be commit b50ff657dd
)
This commit is contained in:
parent
4d314a96e7
commit
b338bce94f
@ -20,6 +20,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
|
||||
|
||||
/* NTAS uses 2, NT uses 1, WfWg uses 0 */
|
||||
#define MAINTAIN_LIST 2
|
||||
#define ELECTION_VERSION 1
|
||||
@ -33,9 +35,13 @@
|
||||
#define NMB_REG 0x05 /* see rfc1002.txt 4.2.2,3,5,6,7,8 */
|
||||
#define NMB_REG_REFRESH 0x09 /* see rfc1002.txt 4.2.4 */
|
||||
#define NMB_REL 0x06 /* see rfc1002.txt 4.2.9,10,11 */
|
||||
#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.17 */
|
||||
#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.16 */
|
||||
/* XXXX what about all the other types?? 0x1, 0x2, 0x3, 0x4, 0x8? */
|
||||
|
||||
#define FIND_SELF 0x01
|
||||
#define FIND_WINS 0x02
|
||||
#define FIND_LOCAL 0x04
|
||||
|
||||
/* NetBIOS flags */
|
||||
#define NB_GROUP 0x80
|
||||
#define NB_PERM 0x02
|
||||
@ -83,13 +89,14 @@ enum master_state { MST_NONE, MST_WON, MST_MSB, MST_BROWSER, MST_DOMAIN };
|
||||
|
||||
enum state_type
|
||||
{
|
||||
NAME_STATUS_MASTER_CHECK,
|
||||
NAME_STATUS_CHECK,
|
||||
NAME_STATUS_PDC_SRV_CHK,
|
||||
NAME_STATUS_SRV_CHK,
|
||||
NAME_REGISTER_CHALLENGE,
|
||||
NAME_REGISTER,
|
||||
NAME_RELEASE,
|
||||
NAME_QUERY_CONFIRM,
|
||||
NAME_QUERY_SYNC,
|
||||
NAME_QUERY_MST_SRV_CHK,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
NAME_QUERY_SRV_CHK,
|
||||
NAME_QUERY_FIND_MST,
|
||||
NAME_QUERY_MST_CHK
|
||||
@ -189,7 +196,8 @@ struct response_record
|
||||
|
||||
BOOL bcast;
|
||||
BOOL recurse;
|
||||
struct in_addr to_ip;
|
||||
struct in_addr send_ip;
|
||||
struct in_addr reply_to_ip;
|
||||
|
||||
int num_msgs;
|
||||
|
||||
|
@ -70,12 +70,16 @@ void announce_request(struct work_record *work, struct in_addr ip)
|
||||
CVAL(p,0) = ANN_AnnouncementRequest;
|
||||
p++;
|
||||
|
||||
CVAL(p,0) = work->token; /* flags?? XXXX probably a token*/
|
||||
CVAL(p,0) = work->token; /* (local) unique workgroup token id */
|
||||
p++;
|
||||
StrnCpy(p,myname,16);
|
||||
strupper(p);
|
||||
p = skip_string(p,1);
|
||||
|
||||
/* XXXX note: if we sent the announcement request to 0x1d instead
|
||||
of 0x1e, then we could get the master browser to announce to
|
||||
us instead of the members of the workgroup. wha-hey! */
|
||||
|
||||
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
|
||||
myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
|
||||
}
|
||||
@ -118,17 +122,21 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
|
||||
{
|
||||
add_browser_entry(serv_name, name_type, work_name, 0, ip);
|
||||
|
||||
if (state == NAME_QUERY_MST_SRV_CHK)
|
||||
{
|
||||
/* announce ourselves as a master browser to serv_name */
|
||||
do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
|
||||
if (state == NAME_STATUS_PDC_SRV_CHK)
|
||||
{
|
||||
/* announce ourselves as a master browser to serv_name */
|
||||
do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
|
||||
0x20, 0, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
construct a host announcement unicast
|
||||
|
||||
this function should not be used heavily, and only when we are _not_
|
||||
a master browser and _not_ a primary domain controller.
|
||||
|
||||
**************************************************************************/
|
||||
void announce_backup(void)
|
||||
{
|
||||
@ -158,18 +166,11 @@ void announce_backup(void)
|
||||
|
||||
if (!work) continue;
|
||||
|
||||
if (AM_MASTER(work) && AM_DOMCTL(work)) continue;
|
||||
|
||||
/* found one: announce it across all domains */
|
||||
for (d = subnetlist; d; d = d->next)
|
||||
{
|
||||
int type=0;
|
||||
|
||||
if (AM_DOMCTL(work)) {
|
||||
type = 0x1b;
|
||||
} else if (AM_MASTER(work)) {
|
||||
type = 0x1d;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(2,("sending announce backup %s workgroup %s(%d)\n",
|
||||
inet_ntoa(d->bcast_ip),work->work_group,
|
||||
@ -185,12 +186,31 @@ void announce_backup(void)
|
||||
p += 5;
|
||||
p++;
|
||||
|
||||
send_mailslot_reply(BROWSE_MAILSLOT,
|
||||
if (!AM_DOMCTL(work))
|
||||
{
|
||||
/* only ask for a list of backup domain controllers
|
||||
if we are not a domain controller ourselves */
|
||||
|
||||
send_mailslot_reply(BROWSE_MAILSLOT,
|
||||
ClientDGRAM,outbuf,
|
||||
PTR_DIFF(p,outbuf),
|
||||
myname, work->work_group,
|
||||
0x0,type,d->bcast_ip,
|
||||
0x0,0x1b,d->bcast_ip,
|
||||
*iface_ip(d->bcast_ip));
|
||||
}
|
||||
|
||||
if (!AM_MASTER(work))
|
||||
{
|
||||
/* only ask for a list of master browsers if we
|
||||
are not a master browser ourselves */
|
||||
|
||||
send_mailslot_reply(BROWSE_MAILSLOT,
|
||||
ClientDGRAM,outbuf,
|
||||
PTR_DIFF(p,outbuf),
|
||||
myname, work->work_group,
|
||||
0x0,0x1b,d->bcast_ip,
|
||||
*iface_ip(d->bcast_ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -222,12 +242,12 @@ static void do_announce_host(int command,
|
||||
StrnCpy(p+5,server_name,16);
|
||||
strupper(p+5);
|
||||
|
||||
CVAL(p,21) = 2; /* major version */
|
||||
CVAL(p,22) = 2; /* minor version */
|
||||
CVAL(p,21) = 0x02; /* major version */
|
||||
CVAL(p,22) = 0x02; /* minor version */
|
||||
|
||||
SIVAL(p,23,server_type);
|
||||
SSVAL(p,27,0xaa55); /* browse signature */
|
||||
SSVAL(p,29,1); /* browse version */
|
||||
SSVAL(p,29,0x001f); /* browse version: CIFS draft 1.0 indicates 0x001f */
|
||||
|
||||
strcpy(p+31,server_comment);
|
||||
p += 31;
|
||||
@ -242,6 +262,28 @@ static void do_announce_host(int command,
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
remove all samba's server entries
|
||||
****************************************************************************/
|
||||
void remove_my_servers(void)
|
||||
{
|
||||
struct subnet_record *d;
|
||||
for (d = subnetlist; d; d = d->next)
|
||||
{
|
||||
struct work_record *work;
|
||||
for (work = d->workgrouplist; work; work = work->next)
|
||||
{
|
||||
struct server_record *s;
|
||||
for (s = work->serverlist; s; s = s->next)
|
||||
{
|
||||
if (!strequal(myname,s->serv.name)) continue;
|
||||
announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
announce a server entry
|
||||
****************************************************************************/
|
||||
@ -309,6 +351,11 @@ void announce_host(void)
|
||||
struct server_record *s;
|
||||
BOOL announce = False;
|
||||
|
||||
/* must work on the code that does announcements at up to
|
||||
30 seconds later if a master browser sends us a request
|
||||
announce.
|
||||
*/
|
||||
|
||||
if (work->needannounce) {
|
||||
/* drop back to a max 3 minute announce - this is to prevent a
|
||||
single lost packet from stuffing things up for too long */
|
||||
@ -364,7 +411,7 @@ void announce_host(void)
|
||||
least 15 minutes.
|
||||
|
||||
this actually gets done in search_and_sync_workgroups() via the
|
||||
NAME_QUERY_MST_SRV_CHK command, if there is a response from the
|
||||
NAME_QUERY_PDC_SRV_CHK command, if there is a response from the
|
||||
name query initiated here. see response_name_query()
|
||||
**************************************************************************/
|
||||
void announce_master(void)
|
||||
@ -419,9 +466,9 @@ void announce_master(void)
|
||||
ip = ipzero;
|
||||
|
||||
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
|
||||
NAME_QUERY_MST_SRV_CHK,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,
|
||||
False, False, ip);
|
||||
False, False, ip, ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -429,9 +476,9 @@ void announce_master(void)
|
||||
for (d2 = subnetlist; d2; d2 = d2->next)
|
||||
{
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
|
||||
NAME_QUERY_MST_SRV_CHK,
|
||||
NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b,0,0,
|
||||
True, False, d2->bcast_ip);
|
||||
True, False, d2->bcast_ip, d2->bcast_ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -463,9 +510,9 @@ void announce_master(void)
|
||||
/* 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_MST_SRV_CHK,
|
||||
queue_netbios_pkt_wins(d,ClientNMB, NMB_QUERY,NAME_QUERY_PDC_SRV_CHK,
|
||||
work->work_group,0x1b, 0, 0,
|
||||
bcast, False, ip);
|
||||
bcast, False, ip, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
137
source3/nameannounce.doc
Normal file
137
source3/nameannounce.doc
Normal file
@ -0,0 +1,137 @@
|
||||
this module deals with announcements: the sending of announcement requests
|
||||
and the sending of announcements either to refresh other servers' records
|
||||
or as a response to announcement requests.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
announce_master()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for announcing samba as a master browser
|
||||
to all known primary domain controllers.
|
||||
|
||||
this announcement is sent out at CHECK_TIME_MST_ANNOUNCE minute
|
||||
intervals, only if samba is a master browser on one or more of
|
||||
its local interfaces.
|
||||
|
||||
if no domain controller has been specified (lp_domain_controller())
|
||||
samba goes through its list of servers looking for primary domain
|
||||
controllers. when it finds one (other than itself) it will either
|
||||
initiate a NAME_QUERY_PDC_SRV_CHK by broadcast or with a WINS
|
||||
server. this will result in a NAME_STATUS_PDC_SRV_CHK, which
|
||||
will result in a sync browse list and an announcement
|
||||
ANN_MasterAnnounce being sent (see sync_server()).
|
||||
|
||||
if a domain controller has been specified, samba will search for
|
||||
a primary domain controller for its workgroup (either by directed
|
||||
packet or by broadcast if it cannot resolve the domain controller
|
||||
name using DNS), which results in the same action as listed above.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
announce_host()
|
||||
*************************************************************************/
|
||||
|
||||
this complex-looking function is responsible for announcing samba's
|
||||
existence to other servers by broadcast. the actual announcement
|
||||
is carried out by announce_server().
|
||||
|
||||
the time period between samba's announcement will stretch from one
|
||||
minute to twelve minutes by one minute. if samba has received an
|
||||
announce request from a master browser, then it should answer at
|
||||
any random interval between zero and thirty seconds after the
|
||||
request is received. this is to ensure that the master browser
|
||||
does not get overloaded with responses!
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
announce_server()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending announcement packets.
|
||||
these packets are received by other servers, which will then
|
||||
update their records accordingly: what services we have, our
|
||||
name, our comment field and our time to live (to name a few).
|
||||
|
||||
if we are a master browser, then using do_announce_host() we
|
||||
must send an announcement notifying members of that workgroup
|
||||
that we are their master browser, and another announcement
|
||||
indicating to all backup browsers and master browsers that
|
||||
we are a master browser.
|
||||
|
||||
(note: if another master browser receives this announcement
|
||||
and thinks that it is also the master browser for this
|
||||
workgroup, it stops being a master browser and forces an
|
||||
election).
|
||||
|
||||
if we are not a master browser, then we send an announcement
|
||||
notifying the master browser that we are a member of its
|
||||
workgroup.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
remove_my_servers()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for informing other servers that
|
||||
samba is about to go down. it announces, on all subnets, that
|
||||
samba's time to live is zero and that it has no services.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
do_announce_host()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending out an announcement
|
||||
MAILSLOT browse packet. it contains information such as the
|
||||
time to live, name of the server, services that the server
|
||||
offers etc.
|
||||
|
||||
the format of this MAILSLOT browse packet is described in
|
||||
draft-heizer-cifs-v1-spec-00.txt 3.9.50.4.1 page 165-6.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
announce_backup()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for getting master browsers and domain
|
||||
controllers to send us lists of backup servers. this is done by
|
||||
sending an ANN_GetBackupListReq browse mailslot.
|
||||
|
||||
the master browser, or primary domain controller, should respond
|
||||
with an ANN_GetBackupListResp browse mailslot containing the list
|
||||
of backup servers.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
sync_server()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for initiating a sync browse list
|
||||
sequence and, if necessary, carrying out an ANN_MasterAnnouncement
|
||||
to the primary domain controller (that we are also sync'ing
|
||||
browse lists with).
|
||||
|
||||
see nameservresp.c:response_name_status_check().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
announce_request()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending an announcement request to
|
||||
another server. this server should respond with an announcement.
|
||||
|
||||
if the announce request is sent to WORKGROUP(0x1e) then members of
|
||||
the workgroup will respond (with ANN_HostAnnounce packets)
|
||||
|
||||
if the announce request is sent to WORKGROUP(0x1d) then the master
|
||||
browser of the workgroup should respond (ANN_LocalMasterAnnounce).
|
||||
this is untested.
|
||||
|
||||
if the announce request is sent to ^1^2__MSBROWSE__^2(0x1) then
|
||||
(and this is pure speculation), all backup browsers and master
|
||||
browsers should respond with ANN_DomainAnnounce packets.
|
||||
this is untested.
|
||||
|
@ -178,7 +178,7 @@ static void start_sync_browse_entry(struct browse_cache_record *b)
|
||||
/* see response_netbios_packet() or expire_netbios_response_entries() */
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SYNC,
|
||||
b->group,0x20,0,0,
|
||||
False,False,b->ip);
|
||||
False,False,b->ip,b->ip);
|
||||
}
|
||||
|
||||
b->synced = True;
|
||||
|
69
source3/namebrowse.doc
Normal file
69
source3/namebrowse.doc
Normal file
@ -0,0 +1,69 @@
|
||||
this module deals with queueing servers that samba must sync browse
|
||||
lists with. it will always issue a name query immediately before
|
||||
actually carrying out the NetServerEnum call, to ensure that time
|
||||
is not wasted by a remote server's failure.
|
||||
|
||||
this module was created to minimise the amount of NetServerEnum calls
|
||||
that samba may be asked to perform, by maintaining the name of a server
|
||||
for up to a minute after the NetServerEnum call was issued, and
|
||||
disallowing further NetServerEnum calls to this remote server until
|
||||
the entry is removed.
|
||||
|
||||
samba can ask for a NetServerEnum call to be issued to grab a remote
|
||||
server's list of servers and workgroups either in its capacity as
|
||||
a primary domain controller (domain master browser), as a local
|
||||
master browser.
|
||||
|
||||
samba does not deal with becoming a backup master browser properly
|
||||
at present.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
do_browser_lists()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for finding an appropriate entry in the
|
||||
sync browser cache, initiating a name query (which results in a
|
||||
NetServerEnum call if there is a positive response), and then
|
||||
removing all entries that have been actioned and have been around
|
||||
for over a minute.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
start_sync_browse_entry()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for initiating a name query. if a
|
||||
positive response is received, then this will result in a
|
||||
NetServerEnum api call.
|
||||
|
||||
samba will only initiate this process if it is a master browser
|
||||
for this workgroup.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_browser_entry()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding a browser into the list of
|
||||
servers to sync browse lists with. if the server entry has already
|
||||
been added and syncing browse lists has already been initiated, it
|
||||
will not be added again.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
expire_browse_cache()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing entries that have had the
|
||||
sync browse list initiated (whether that succeeded or not is beyond
|
||||
this function's scope) and have been in the cache for a while.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_browse_entry()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding a new entry into the list
|
||||
of servers to sync browse lists with at some point in the near future.
|
||||
|
155
source3/namedbname.doc
Normal file
155
source3/namedbname.doc
Normal file
@ -0,0 +1,155 @@
|
||||
this module deals with the NetBIOS name database for samba. it deals
|
||||
directly with adding, removing, finding, loading and saving of names.
|
||||
|
||||
/*************************************************************************
|
||||
search_for_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for finding a name in the appropriate part
|
||||
of samba's NetBIOS name database. if the name cannot be found, then it
|
||||
should look the name up using DNS. later modifications will be to
|
||||
forward the request on to another WINS server, should samba not be able
|
||||
to find out about the requested name (this will be implemented through
|
||||
issuing a new type of samba 'state').
|
||||
|
||||
the name is first searched for in the NetBIOS cache. if it cannot be
|
||||
found, then it if the name looks like it's a server-type name (0x20
|
||||
0x0 or 0x1b) then DNS is used to look for the name.
|
||||
|
||||
if DNS fails, then a record of this failure is kept. if it succeeds, then
|
||||
a new NetBIOS entry is added.
|
||||
|
||||
the successfully found name is returned. on failure, NULL is returned.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
expire_names()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing old NetBIOS names from its
|
||||
database. no further action is required.
|
||||
|
||||
for over-zealous WINS systems, the use of query_refresh_names() is
|
||||
recommended. this function initiates polling of hosts that have
|
||||
registered with samba in its capacity as a WINS server. an alternative
|
||||
means to achieve the same end as query_refresh_names() is to
|
||||
reduce the time to live when the name is registered with samba,
|
||||
except that in this instance the responsibility for refreshing the
|
||||
name is with the owner of the name, not the server with which the name
|
||||
is registered.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_netbios_entry()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding or updating a NetBIOS name
|
||||
in the database. into the local interface records, the only names
|
||||
that will be added are those of primary domain controllers and
|
||||
samba's own names. into the WINS records, all names are added.
|
||||
|
||||
the name to be added / updated will be looked up in the records.
|
||||
if it is found, then we will not overwrite the entry if the flag
|
||||
'newonly' is True, or if the name is being added as a non-SELF
|
||||
(non-samba) name and the records indicate that samba owns the
|
||||
name.
|
||||
|
||||
otherwise, the name is added or updated with the new details.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
remove_netbios_entry()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing a NetBIOS entry from
|
||||
the database. the name is searched for in the records using
|
||||
find_name_search(). if the ip is zero, then the ip is ignored.
|
||||
|
||||
the name is removed if the expected source (e.g SELF, REGISTER)
|
||||
matches that in the database.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
load_netbios_names()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for loading any NetBIOS names that samba,
|
||||
in its WINS capacity, has written out to disk. all the relevant details
|
||||
are recorded in this file, including the time-to-live. should the
|
||||
time left to live be small, the name is not added back in to samba's
|
||||
WINS database.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
dump_names()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for outputting NetBIOS names in two formats.
|
||||
firstly, as debugging information, and secondly, all names that have been
|
||||
registered with samba in its capacity as a WINS server are written to
|
||||
disk.
|
||||
|
||||
writing all WINS names allows two things. firstly, if samba's NetBIOS
|
||||
daemon dies or is terminated, on restarting the daemon most if not all
|
||||
of the registered WINS names will be preserved (which is a good reason
|
||||
why query_netbios_names() should be used).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_name_search()
|
||||
*************************************************************************/
|
||||
|
||||
this function is a wrapper around find_name(). find_name_search() can
|
||||
be told whether to search for the name in a local subnet structure or
|
||||
in the WINS database. on top of this, it can be told to search only
|
||||
for samba's SELF names.
|
||||
|
||||
if it finds the name in the WINS database, it will set the subnet_record
|
||||
and also return the name it finds.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function is a low-level search function that searches a single
|
||||
interface's NetBIOS records for a name. if the ip to be found is
|
||||
zero then the ip address is ignored. this is to enable a name to
|
||||
be found without knowing its ip address, and also to find the exact
|
||||
name if a large number of group names are added with different ip
|
||||
addresses.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
remove_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing a specific NetBIOS entry
|
||||
from a subnet list's records. only if the pointer to the entry is
|
||||
in the list will the name be removed.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding a NetBIOS entry into a
|
||||
subnet list's records.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
ms_browser_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function returns True if the NetBIOS name passed to it is
|
||||
^1^2__MSBROWSE__^2^1
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
name_equal()
|
||||
*************************************************************************/
|
||||
|
||||
this function returns True if the two NetBIOS names passed to it
|
||||
match in name, type and scope: the NetBIOS names are equal.
|
||||
|
||||
|
48
source3/namedbresp.doc
Normal file
48
source3/namedbresp.doc
Normal file
@ -0,0 +1,48 @@
|
||||
module namedbresp deals with the maintenance of the list of expected
|
||||
responses - creating, finding and removal.
|
||||
|
||||
module nameresp deals with the initial transmission, re-transmission
|
||||
and time-out of netbios response records.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_response_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for matching the unique response transaction
|
||||
id with an expected response record. as a side-effect of this search,
|
||||
it will find the subnet (or the WINS pseudo-subnet) that samba expected
|
||||
the response to come from.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
make_response_queue_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for creating a response record, which will
|
||||
be queued awaiting a response.
|
||||
|
||||
the number of retries is set to 4, and the retry period set to 1 second.
|
||||
if no response is received, then the packet is re-transmitted, which is
|
||||
why so much information is stored in the response record.
|
||||
|
||||
the number of expected responses queued is kept, so listen_for_packets()
|
||||
knows it must time-out after 1 second if one or more responses are
|
||||
expected.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
remove_response_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing a response record from the
|
||||
expected response queue. the number of expected responses is decreased.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_response_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding the response record created by
|
||||
make_response_queue_record() into the appropriate response record queue.
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1995
|
||||
Copyright (C) Andrew Tridgell 1994-1996
|
||||
|
||||
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
|
||||
@ -18,11 +18,17 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Module name: nameelect.c
|
||||
|
||||
Revision History:
|
||||
|
||||
14 jan 96: lkcl@pires.co.uk
|
||||
added multiple workgroup domain master support
|
||||
|
||||
04 jul 96: lkcl@pires.co.uk
|
||||
added system to become a master browser by stages.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -75,7 +81,7 @@ void check_master_browser(void)
|
||||
{
|
||||
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
|
||||
work->work_group,0x1d,0,0,
|
||||
True,False,d->bcast_ip);
|
||||
True,False,d->bcast_ip,d->bcast_ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,7 +140,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
|
||||
|
||||
bzero(outbuf,sizeof(outbuf));
|
||||
p = outbuf;
|
||||
CVAL(p,0) = 8; /* election */
|
||||
CVAL(p,0) = ANN_Election; /* election */
|
||||
p++;
|
||||
|
||||
CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
|
||||
@ -166,13 +172,13 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
|
||||
|
||||
if (!(work = find_workgroupstruct(d, name, False))) return;
|
||||
|
||||
if (special_browser_name(name, name_type) ||
|
||||
if (ms_browser_name(name, name_type) ||
|
||||
(AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
|
||||
(name_type == 0x1d || name_type == 0x1b)))
|
||||
{
|
||||
int remove_type = 0;
|
||||
|
||||
if (special_browser_name(name, name_type))
|
||||
if (ms_browser_name(name, name_type))
|
||||
remove_type = SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
|
||||
if (name_type == 0x1d)
|
||||
remove_type = SV_TYPE_MASTER_BROWSER;
|
||||
@ -247,7 +253,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
{
|
||||
case MST_NONE: /* while we were nothing but a server... */
|
||||
{
|
||||
work->state = MST_WON; /* election win was successful */
|
||||
work->state = MST_WON; /* ... an election win was successful */
|
||||
|
||||
work->ElectionCriterion |= 0x5;
|
||||
|
||||
@ -264,7 +270,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
}
|
||||
case MST_WON: /* while nothing had happened except we won an election... */
|
||||
{
|
||||
work->state = MST_MSB; /* registering MSBROWSE was successful */
|
||||
work->state = MST_MSB; /* ... registering MSBROWSE was successful */
|
||||
|
||||
/* add server entry on successful registration of MSBROWSE */
|
||||
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
|
||||
@ -276,9 +282,9 @@ void become_master(struct subnet_record *d, struct work_record *work)
|
||||
|
||||
break;
|
||||
}
|
||||
case MST_MSB: /* while we were still only registered MSBROWSE state */
|
||||
case MST_MSB: /* while we were still only registered MSBROWSE state... */
|
||||
{
|
||||
work->state = MST_BROWSER; /* registering WORKGROUP(1d) was successful */
|
||||
work->state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
|
||||
|
||||
/* update our server status */
|
||||
work->ServerType |= SV_TYPE_MASTER_BROWSER;
|
||||
@ -296,12 +302,16 @@ 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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(2,("samba not configured as a domain master: no third stage.\n"));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MST_BROWSER: /* while we were still a master browser... */
|
||||
{
|
||||
work->state = MST_DOMAIN; /* registering WORKGROUP(1b) was successful */
|
||||
work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */
|
||||
|
||||
/* update our server status */
|
||||
if (lp_domain_master())
|
||||
@ -513,6 +523,11 @@ void process_election(struct packet_struct *p,char *buf)
|
||||
|
||||
/****************************************************************************
|
||||
checks whether a browser election is to be run on any workgroup
|
||||
|
||||
this function really ought to return the time between election
|
||||
packets (which depends on whether samba intends to be a domain
|
||||
master or a master browser) in milliseconds.
|
||||
|
||||
***************************************************************************/
|
||||
BOOL check_elections(void)
|
||||
{
|
||||
|
207
source3/nameelect.doc
Normal file
207
source3/nameelect.doc
Normal file
@ -0,0 +1,207 @@
|
||||
|
||||
the module nameelect.c deals with initiating, winning, losing
|
||||
browsing elections, and checking if browsers are still around,
|
||||
and the consequences of getting involved in all this.
|
||||
|
||||
an election packet can be received at any time, which will initiate
|
||||
an election. samba can also detect that there is no longer a
|
||||
master browser and will initiate an election.
|
||||
|
||||
there is one way to become a master browser, but there are two
|
||||
ways to un-become a master browser. if you lose an election, you
|
||||
must stop being a master browser. if you fail to register your
|
||||
unique special browser names (either on your local subnet or with
|
||||
the WINS server) then you must stop being a master browser.
|
||||
|
||||
this is a double fail-safe mechanism to ensure that there is only
|
||||
one master browser per workgroup per subnet (and one primary domain
|
||||
controller - domain master browser - per domain (workgroup) per
|
||||
wide area network).
|
||||
|
||||
(a wide area network is created when one or more servers on a
|
||||
broadcast-isolated subnet point to the same WINS server).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
check_elections()
|
||||
*************************************************************************/
|
||||
|
||||
this function returns True if samba is in the process of running an
|
||||
election on any of its interfaces. a better version of this function
|
||||
should return the time-out period in between election packets, in
|
||||
milliseconds.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
process_election()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for dealing with the receipt of an election
|
||||
browse MAILSLOT packet.
|
||||
|
||||
if samba is running an election, it checks the criteria in the packet
|
||||
received using win_election() to see if it has lost the election or if
|
||||
it should join in the election.
|
||||
|
||||
if it loses the election, then it becomes a non-master.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
win_election()
|
||||
*************************************************************************/
|
||||
|
||||
this function returns True if samba has won an election. the criteria
|
||||
in order of precedence are:
|
||||
|
||||
the election version; the election criteria; the time since samba was
|
||||
started; and as a last resort, a name comparison is used.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
run_elections()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending out election packets if
|
||||
samba is running in an election. once the fourth packet is sent
|
||||
out, it is assumed that we have won, and samba initiates becoming
|
||||
a master browser.
|
||||
|
||||
(it looks like samba sends out an extra packet just to be sure...)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
become_nonmaster()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for down-grading samba's status from
|
||||
either domain master to master browser or nothing, or master browser
|
||||
to nothing, depending on its current status.
|
||||
|
||||
samba can become a non-master in three ways: by losing an election -
|
||||
see process_election(); by having one of its special browser names
|
||||
de-registered - see name_unregister_work(); by receiving and
|
||||
processing a browser reset packet - see process_reset_browser().
|
||||
|
||||
when samba stops being a domain master, it must release its unique
|
||||
0x1b name. when samba stops being a master browser, it must release
|
||||
its unique 0x1d name.
|
||||
|
||||
becoming non-master is done on a per-subnet basis.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
become_master()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for slowly turning samba into a
|
||||
master browser or a domain master (primary domain controller).
|
||||
|
||||
|
||||
this is done in stages. note that this could take a while,
|
||||
particularly on a broadcast subnet, as we have to wait for
|
||||
the implicit registration of each name to be accepted.
|
||||
|
||||
as each name is successfully registered, become_master() is
|
||||
called again via name_register_work(), in order to initiate
|
||||
the next stage (see dead_netbios_entry() - deals with implicit
|
||||
name registration and response_name_reg() - deals with explicit
|
||||
registration with a WINS server).
|
||||
|
||||
stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1.
|
||||
stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d)
|
||||
stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b)
|
||||
stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...)
|
||||
|
||||
note that this code still does not cope with the distinction
|
||||
between different types of nodes, particularly between M and P
|
||||
nodes (see rfc1001.txt). that will be developed later.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
name_register_work()
|
||||
*************************************************************************/
|
||||
|
||||
this function is called when a NetBIOS name is successfully
|
||||
registered. it will add the registered name into samba's NetBIOS
|
||||
records.
|
||||
|
||||
it has the additional responsibility that when samba is becoming
|
||||
a master browser, it must initiate the next stage in the progress
|
||||
towards becoming a master browser.
|
||||
|
||||
implicit name registration is done through dead_netbios_entry()
|
||||
by time-out. explicit name registration is done through
|
||||
response_name_reg() with a WINS server.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
name_unregister_work()
|
||||
*************************************************************************/
|
||||
|
||||
this function is called when there is an objection to a NetBIOS
|
||||
name being registered. this will always be done through a negative
|
||||
response to a name registration, whether it be by a host that
|
||||
already owns the unique name being registered on a subnet, or
|
||||
by a WINS server.
|
||||
|
||||
the name being objected to must be removed from samba's records.
|
||||
|
||||
it has the additional responsibility of checking whether samba is
|
||||
currently a master browser or not, and if so it should initiate
|
||||
becoming a non-master.
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
send_election()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending a browse mailslot
|
||||
datagram election packet (of type ANN_Election). it constructs
|
||||
the packet with all the relevant info needed to participate:
|
||||
election version; election criteria; time since startup and
|
||||
our name.
|
||||
|
||||
this function can be used to ensure that initiate but lose an
|
||||
election by specifying a criteria and time up of zero. this
|
||||
is necessary if we are a master browser and we are about to
|
||||
go down (politely!) - see nmbd.c:sig_term().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
browser_gone()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for dealing with the instance when
|
||||
the master browser we thought was present on a subnet is no longer
|
||||
responding.
|
||||
|
||||
if it is samba's workgroup, and it's a local interface, samba
|
||||
detects that it can participate in an election on that interface
|
||||
and potentially become a master browser or domain master.
|
||||
|
||||
if it's a remote subnet or not one of samba's workgroups, then
|
||||
samba will force an election (which it is not obliged to do) and
|
||||
will remove that workgroup and the servers contained in it from
|
||||
its records. maybe this functionality isn't a good idea.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
check_master_browser()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for periodically checking whether
|
||||
master browsers that samba expects to be alive are alive. this
|
||||
is done every CHECK_TIME_MST_BROWSE minutes.
|
||||
|
||||
for every workgroup record for which samba is not a master browser,
|
||||
on both local and remote interfaces, samba will initiate a
|
||||
broadcast query for a master browser on that subnet.
|
||||
|
||||
(browser_gone() will be called to deal with the case where no
|
||||
response is received to the NAME_QUERY_MST_CHK initiated here.
|
||||
no action is required when a response _is_ received, however:
|
||||
see nameservresp.c:response_process() and dead_netbios_entry()
|
||||
for details)
|
||||
|
||||
|
9
source3/namelogon.doc
Normal file
9
source3/namelogon.doc
Normal file
@ -0,0 +1,9 @@
|
||||
this module deals with the first stage of domain logons. there is much
|
||||
more work to be done on this: it's all totally undocumented.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
process_logon_packet()
|
||||
*************************************************************************/
|
||||
|
||||
a function that processes logon packets (the most helpful comment yet :-).
|
106
source3/namepacket.doc
Normal file
106
source3/namepacket.doc
Normal file
@ -0,0 +1,106 @@
|
||||
this module deals with packets: sending, receiving, queueing
|
||||
and some basic interpretation (e.g it excludes datagram
|
||||
error packets at the moment).
|
||||
|
||||
the packet queueing mechanism was originally introduced when
|
||||
samba dealt with responses by sending a packet, receiving
|
||||
packets and queueing all packets that didn't match up with
|
||||
the response expected. this is fine in a single-thread
|
||||
environment, but samba now deals with response packets by
|
||||
queueing the responses. to some extent, therefore, this
|
||||
queue_packet mechanism is redundant.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
send_mailslot_reply()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending a MAILSLOT packet.
|
||||
|
||||
it will _not_ send packets to the pseudo WINS subnet's address of
|
||||
255.255.255.255: this would be disastrous.
|
||||
|
||||
each packet sent out has a unique transaction identifier. this is done
|
||||
so that responses can be matched later with the original purpose for
|
||||
the packet being sent out in the first place.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
listen_for_packets()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for reading NMB and DGRAM packets, and then
|
||||
queueing them. it will normally time-out for NMBD_SELECT_LOOP seconds, but
|
||||
if there is an election currently running or we are expecting a response
|
||||
then this time is reduced to 1 second.
|
||||
|
||||
note: the time-out period needs refining to the millisecond level.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
queue_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for queueing any NMB and DGRAM packets passed
|
||||
to it. these packets will be removed from the queue in run_packet_queue().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
run_packet_queue()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for taking a packet off the queue,
|
||||
identifying whether it is an NMB or a DGRAM packet, processing
|
||||
it accordingly and deleting it. this process continues until
|
||||
there are no more packets on the queue.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
process_nmb()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives a packet identified as a netbios packet.
|
||||
it further identifies whether it is a response or a query packet.
|
||||
by identifying the type of packet (name registration, query etc)
|
||||
process_nmb() will call the appropriate function to deal with the
|
||||
type of packet received.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
process_dgram()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for identifying whether the datagram
|
||||
packet received is a browser packet or a domain logon packet. it
|
||||
also does some filtering of certain types of packets (e.g it
|
||||
filters out error packets).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending a reply to another NetBIOS
|
||||
packet from another host. it can be used to send a reply to a name
|
||||
registration, name release, name query or name status request.
|
||||
|
||||
the reply can be either a positive or a negative one.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
initiate_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for construction a netbios packet and sending
|
||||
it. if the packet has not had a unique transaction id allocated to it,
|
||||
then initiate_netbios_packet() will give it one.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
update_name_trn_id()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for allocating unique transaction identifiers
|
||||
for each new packet sent on the network.
|
||||
|
||||
|
56
source3/namequery.doc
Normal file
56
source3/namequery.doc
Normal file
@ -0,0 +1,56 @@
|
||||
this module contains non-threaded versions of name status and name
|
||||
query functions. if a multi-threaded nmbd was to be written, these
|
||||
functions would be the starting point.
|
||||
|
||||
at the moment, the expected response queueing system is used to
|
||||
replace these functions without needing to multi-thread nmbd.
|
||||
|
||||
these functions are used in smbclient and nmblookup at present to
|
||||
avoid having the vast quantities of complex and unused code needed
|
||||
to support even a simple name query (or providing stubs for the
|
||||
unused side of these functions).
|
||||
|
||||
there is a down-side to these functions, which is all microsoft's
|
||||
fault. microsoft machines always always reply to queries on the
|
||||
priveleged ports, rather than following the usual tcp/ip mechanism
|
||||
of replying on the client's port (the exception to this i am led
|
||||
to believe is windows nt 3.50).
|
||||
|
||||
as a result of this, in order to receive a response to a name
|
||||
query from a microsoft machine, we must be able to listen on
|
||||
the priveleged netbios name server ports. this is simply not
|
||||
possible with some versions of unix, unless you have root access.
|
||||
|
||||
it is also not possible if you run smbclient or nmblookup on an
|
||||
interface that already has been claimed by the netbios name server
|
||||
daemon nmbd.
|
||||
|
||||
all in all, i wish that microsoft would fix this.
|
||||
|
||||
a solution does exist: nmbd _does_ actually reply on the client's
|
||||
port, so if smbclient and nmblookup were to use nmbd as a proxy
|
||||
forwarder of queries (or to use samba's WINS capabilities) then
|
||||
a query could be made without needing access to the priveleged
|
||||
ports. in order to do this properly, samba must implement secured
|
||||
netbios name server functionality (see rfc1001.txt 15.1.6).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
name_query()
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
name_status()
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
_interpret_node_status()
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
this is a older version of interpret_node_status().
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
NBT netbios library routines
|
||||
Copyright (C) Andrew Tridgell 1994-1995
|
||||
Copyright (C) Andrew Tridgell 1994-1996
|
||||
|
||||
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
|
||||
@ -18,6 +18,8 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Module name: nameresp.c
|
||||
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -29,68 +31,12 @@ extern struct subnet_record *subnetlist;
|
||||
|
||||
extern int DEBUGLEVEL;
|
||||
|
||||
static uint16 name_trn_id=0;
|
||||
BOOL CanRecurse = True;
|
||||
extern pstring scope;
|
||||
extern pstring myname;
|
||||
extern struct in_addr ipzero;
|
||||
extern struct in_addr ipgrp;
|
||||
|
||||
int num_response_packets = 0;
|
||||
extern int num_response_packets;
|
||||
|
||||
/***************************************************************************
|
||||
updates the unique transaction identifier
|
||||
**************************************************************************/
|
||||
static void update_name_trn_id(void)
|
||||
{
|
||||
if (!name_trn_id)
|
||||
{
|
||||
name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
|
||||
}
|
||||
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
add an expected response record into the list
|
||||
**************************************************************************/
|
||||
static void add_response_record(struct subnet_record *d,
|
||||
struct response_record *n)
|
||||
{
|
||||
struct response_record *n2;
|
||||
|
||||
if (!d) return;
|
||||
|
||||
if (!d->responselist)
|
||||
{
|
||||
d->responselist = n;
|
||||
n->prev = NULL;
|
||||
n->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (n2 = d->responselist; n2->next; n2 = n2->next) ;
|
||||
|
||||
n2->next = n;
|
||||
n->next = NULL;
|
||||
n->prev = n2;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
remove an expected response record from the list
|
||||
**************************************************************************/
|
||||
static void remove_response_record(struct subnet_record *d,
|
||||
struct response_record *n)
|
||||
{
|
||||
if (n->prev) n->prev->next = n->next;
|
||||
if (n->next) n->next->prev = n->prev;
|
||||
|
||||
if (d->responselist == n) d->responselist = n->next;
|
||||
|
||||
free(n);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
deals with an entry before it dies
|
||||
@ -99,7 +45,7 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
struct response_record *n)
|
||||
{
|
||||
DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
|
||||
inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
|
||||
inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
|
||||
|
||||
switch (n->state)
|
||||
{
|
||||
@ -124,7 +70,7 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
see rfc1001.txt 15.5.2
|
||||
*/
|
||||
remove_netbios_name(d1, n->name.name, n->name.name_type,
|
||||
REGISTER, n->to_ip);
|
||||
REGISTER, n->send_ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +85,7 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
/* IMPORTANT: see response_netbios_packet() */
|
||||
|
||||
if (n->num_msgs == 0)
|
||||
browser_gone(n->name.name, n->to_ip);
|
||||
browser_gone(n->name.name, n->send_ip);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -151,7 +97,7 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
|
||||
/* IMPORTANT: see response_name_release() */
|
||||
|
||||
if (ismyip(n->to_ip))
|
||||
if (ismyip(n->send_ip))
|
||||
{
|
||||
name_unregister_work(d,n->name.name,n->name.name_type);
|
||||
}
|
||||
@ -163,6 +109,21 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
break;
|
||||
}
|
||||
|
||||
case NAME_REGISTER_CHALLENGE:
|
||||
{
|
||||
/* name challenge: no reply. we can reply to the person that
|
||||
wanted the unique name and tell them that they can have it
|
||||
*/
|
||||
|
||||
add_netbios_entry(d, n->name.name, n->name.name_type,
|
||||
n->nb_flags, GET_TTL(0), REGISTER,
|
||||
n->reply_to_ip, False, True);
|
||||
|
||||
send_name_response(n->fd, n->response_id, NMB_REG,
|
||||
True, True,
|
||||
&n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip);
|
||||
break;
|
||||
}
|
||||
case NAME_REGISTER:
|
||||
{
|
||||
/* if no response received, and we are using a broadcast registration
|
||||
@ -178,7 +139,7 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
/* IMPORTANT: see response_name_reg() */
|
||||
|
||||
name_register_work(d,n->name.name,n->name.name_type,
|
||||
n->nb_flags, n->ttl, n->to_ip, n->bcast);
|
||||
n->nb_flags, n->ttl, n->send_ip, n->bcast);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -204,88 +165,12 @@ static void dead_netbios_entry(struct subnet_record *d,
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
initiate a netbios packet
|
||||
****************************************************************************/
|
||||
static void initiate_netbios_packet(uint16 *id,
|
||||
int fd,int quest_type,char *name,int name_type,
|
||||
int nb_flags,BOOL bcast,BOOL recurse,
|
||||
struct in_addr to_ip)
|
||||
{
|
||||
struct packet_struct p;
|
||||
struct nmb_packet *nmb = &p.packet.nmb;
|
||||
struct res_rec additional_rec;
|
||||
char *packet_type = "unknown";
|
||||
int opcode = -1;
|
||||
|
||||
if (!id) return;
|
||||
|
||||
if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
|
||||
if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
|
||||
if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
|
||||
if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
|
||||
|
||||
DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
|
||||
packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
|
||||
|
||||
if (opcode == -1) return;
|
||||
|
||||
bzero((char *)&p,sizeof(p));
|
||||
|
||||
update_name_trn_id();
|
||||
|
||||
if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
|
||||
|
||||
nmb->header.name_trn_id = *id;
|
||||
nmb->header.opcode = opcode;
|
||||
nmb->header.response = False;
|
||||
nmb->header.nm_flags.bcast = bcast;
|
||||
nmb->header.nm_flags.recursion_available = CanRecurse;
|
||||
nmb->header.nm_flags.recursion_desired = recurse;
|
||||
nmb->header.nm_flags.trunc = False;
|
||||
nmb->header.nm_flags.authoritative = False;
|
||||
nmb->header.rcode = 0;
|
||||
nmb->header.qdcount = 1;
|
||||
nmb->header.ancount = 0;
|
||||
nmb->header.nscount = 0;
|
||||
nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
|
||||
|
||||
make_nmb_name(&nmb->question.question_name,name,name_type,scope);
|
||||
|
||||
nmb->question.question_type = quest_type;
|
||||
nmb->question.question_class = 0x1;
|
||||
|
||||
if (quest_type == NMB_REG || quest_type == NMB_REL)
|
||||
{
|
||||
nmb->additional = &additional_rec;
|
||||
bzero((char *)nmb->additional,sizeof(*nmb->additional));
|
||||
|
||||
nmb->additional->rr_name = nmb->question.question_name;
|
||||
nmb->additional->rr_type = nmb->question.question_type;
|
||||
nmb->additional->rr_class = nmb->question.question_class;
|
||||
|
||||
nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
|
||||
nmb->additional->rdlength = 6;
|
||||
nmb->additional->rdata[0] = nb_flags;
|
||||
putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
|
||||
}
|
||||
|
||||
p.ip = to_ip;
|
||||
p.port = NMB_PORT;
|
||||
p.fd = fd;
|
||||
p.timestamp = time(NULL);
|
||||
p.packet_type = NMB_PACKET;
|
||||
|
||||
if (!send_packet(&p)) *id = 0xffff;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
remove old name response entries
|
||||
|
||||
XXXX retry code needs to be added, including a retry wait period and a count
|
||||
see name_query() and name_status() for suggested implementation.
|
||||
|
||||
******************************************************************/
|
||||
void expire_netbios_response_entries()
|
||||
{
|
||||
@ -303,7 +188,7 @@ void expire_netbios_response_entries()
|
||||
/* resend the entry */
|
||||
initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
|
||||
n->name.name, n->name.name_type,
|
||||
n->nb_flags, n->bcast, n->recurse, n->to_ip);
|
||||
n->nb_flags, n->bcast, n->recurse, n->send_ip);
|
||||
|
||||
n->repeat_time += n->repeat_interval; /* XXXX ms needed */
|
||||
n->repeat_count--;
|
||||
@ -311,7 +196,6 @@ void expire_netbios_response_entries()
|
||||
else
|
||||
{
|
||||
nextn = n->next;
|
||||
num_response_packets--;
|
||||
|
||||
dead_netbios_entry (d,n); /* process the non-response */
|
||||
remove_response_record(d,n); /* remove the non-response */
|
||||
@ -324,77 +208,16 @@ void expire_netbios_response_entries()
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
reply to a netbios name packet
|
||||
****************************************************************************/
|
||||
void reply_netbios_packet(struct packet_struct *p1,int trn_id,
|
||||
int rcode,int opcode, BOOL recurse,
|
||||
struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
|
||||
char *data,int len)
|
||||
{
|
||||
struct packet_struct p;
|
||||
struct nmb_packet *nmb = &p.packet.nmb;
|
||||
struct res_rec answers;
|
||||
char *packet_type = "unknown";
|
||||
|
||||
p = *p1;
|
||||
|
||||
if (rr_type == NMB_STATUS) packet_type = "nmb_status";
|
||||
if (rr_type == NMB_QUERY ) packet_type = "nmb_query";
|
||||
if (rr_type == NMB_REG ) packet_type = "nmb_reg";
|
||||
if (rr_type == NMB_REL ) packet_type = "nmb_rel";
|
||||
|
||||
DEBUG(4,("replying netbios packet: %s %s\n",
|
||||
packet_type, namestr(rr_name), inet_ntoa(p.ip)));
|
||||
|
||||
nmb->header.name_trn_id = trn_id;
|
||||
nmb->header.opcode = opcode;
|
||||
nmb->header.response = True;
|
||||
nmb->header.nm_flags.bcast = False;
|
||||
nmb->header.nm_flags.recursion_available = recurse;
|
||||
nmb->header.nm_flags.recursion_desired = True;
|
||||
nmb->header.nm_flags.trunc = False;
|
||||
nmb->header.nm_flags.authoritative = True;
|
||||
|
||||
nmb->header.qdcount = 0;
|
||||
nmb->header.ancount = 1;
|
||||
nmb->header.nscount = 0;
|
||||
nmb->header.arcount = 0;
|
||||
nmb->header.rcode = 0;
|
||||
|
||||
bzero((char*)&nmb->question,sizeof(nmb->question));
|
||||
|
||||
nmb->answers = &answers;
|
||||
bzero((char*)nmb->answers,sizeof(*nmb->answers));
|
||||
|
||||
nmb->answers->rr_name = *rr_name;
|
||||
nmb->answers->rr_type = rr_type;
|
||||
nmb->answers->rr_class = rr_class;
|
||||
nmb->answers->ttl = ttl;
|
||||
|
||||
if (data && len)
|
||||
{
|
||||
nmb->answers->rdlength = len;
|
||||
memcpy(nmb->answers->rdata, data, len);
|
||||
}
|
||||
|
||||
p.packet_type = NMB_PACKET;
|
||||
|
||||
debug_nmb_packet(&p);
|
||||
|
||||
send_packet(&p);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
wrapper function to override a broadcast message and send it to the WINS
|
||||
name server instead, if it exists. if wins is false, and there has been no
|
||||
WINS server specified, the packet will NOT be sent.
|
||||
****************************************************************************/
|
||||
void queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
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,
|
||||
BOOL bcast,BOOL recurse,struct in_addr to_ip)
|
||||
BOOL bcast,BOOL recurse,
|
||||
struct in_addr send_ip, struct in_addr reply_to_ip)
|
||||
{
|
||||
/* XXXX note: please see rfc1001.txt section 10 for details on this
|
||||
function: it is currently inappropriate to use this - it will do
|
||||
@ -411,7 +234,7 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
if (!zero_ip(wins_ip))
|
||||
{
|
||||
bcast = False;
|
||||
to_ip = wins_ip;
|
||||
send_ip = wins_ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -421,48 +244,11 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
|
||||
}
|
||||
}
|
||||
|
||||
if (zero_ip(to_ip)) return;
|
||||
if (zero_ip(send_ip)) return NULL;
|
||||
|
||||
queue_netbios_packet(d,fd, quest_type, state,
|
||||
return queue_netbios_packet(d,fd, quest_type, state,
|
||||
name, name_type, nb_flags, ttl,
|
||||
bcast, recurse, to_ip);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
create a name query response record
|
||||
**************************************************************************/
|
||||
static struct response_record *
|
||||
make_response_queue_record(enum state_type state,int id,int fd,
|
||||
int quest_type, char *name,int type, int nb_flags, time_t ttl,
|
||||
BOOL bcast,BOOL recurse, struct in_addr ip)
|
||||
{
|
||||
struct response_record *n;
|
||||
|
||||
if (!name || !name[0]) return NULL;
|
||||
|
||||
if (!(n = (struct response_record *)malloc(sizeof(*n))))
|
||||
return(NULL);
|
||||
|
||||
n->response_id = id;
|
||||
n->state = state;
|
||||
n->fd = fd;
|
||||
n->quest_type = quest_type;
|
||||
make_nmb_name(&n->name, name, type, scope);
|
||||
n->nb_flags = nb_flags;
|
||||
n->ttl = ttl;
|
||||
n->bcast = bcast;
|
||||
n->recurse = recurse;
|
||||
n->to_ip = ip;
|
||||
|
||||
n->repeat_interval = 1; /* XXXX should be in ms */
|
||||
n->repeat_count = 4;
|
||||
n->repeat_time = time(NULL) + n->repeat_interval;
|
||||
|
||||
n->num_msgs = 0;
|
||||
|
||||
num_response_packets++; /* count of total number of packets still around */
|
||||
|
||||
return n;
|
||||
bcast, recurse, send_ip, reply_to_ip);
|
||||
}
|
||||
|
||||
|
||||
@ -472,335 +258,30 @@ make_response_queue_record(enum state_type state,int id,int fd,
|
||||
master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
|
||||
complete lists across a wide area network
|
||||
****************************************************************************/
|
||||
void queue_netbios_packet(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 to_ip)
|
||||
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;
|
||||
uint16 id = 0xffff;
|
||||
|
||||
/* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
|
||||
if (ip_equal(wins_ip, to_ip)) return;
|
||||
if (ip_equal(wins_ip, send_ip)) return NULL;
|
||||
|
||||
initiate_netbios_packet(&id, fd, quest_type, name, name_type,
|
||||
nb_flags, bcast, recurse, to_ip);
|
||||
nb_flags, bcast, recurse, send_ip);
|
||||
|
||||
if (id == 0xffff) return;
|
||||
if (id == 0xffff) return NULL;
|
||||
|
||||
if ((n = make_response_queue_record(state,id,fd,
|
||||
quest_type,name,name_type,nb_flags,ttl,
|
||||
bcast,recurse,to_ip)))
|
||||
bcast,recurse,send_ip,reply_to_ip)))
|
||||
{
|
||||
add_response_record(d,n);
|
||||
return n;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
find a response in a subnet's name query response list.
|
||||
**************************************************************************/
|
||||
struct response_record *find_response_record(struct subnet_record **d,
|
||||
uint16 id)
|
||||
{
|
||||
struct response_record *n;
|
||||
|
||||
if (!d) return NULL;
|
||||
|
||||
for ((*d) = subnetlist; (*d); (*d) = (*d)->next)
|
||||
{
|
||||
for (n = (*d)->responselist; n; n = n->next)
|
||||
{
|
||||
if (n->response_id == id) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*d = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
the global packet linked-list. incoming entries are added to the
|
||||
end of this list. it is supposed to remain fairly short so we
|
||||
won't bother with an end pointer.
|
||||
******************************************************************/
|
||||
static struct packet_struct *packet_queue = NULL;
|
||||
|
||||
/*******************************************************************
|
||||
queue a packet into the packet queue
|
||||
******************************************************************/
|
||||
void queue_packet(struct packet_struct *packet)
|
||||
{
|
||||
struct packet_struct *p;
|
||||
|
||||
if (!packet_queue) {
|
||||
packet->prev = NULL;
|
||||
packet->next = NULL;
|
||||
packet_queue = packet;
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the bottom */
|
||||
for (p=packet_queue;p->next;p=p->next) ;
|
||||
|
||||
p->next = packet;
|
||||
packet->next = NULL;
|
||||
packet->prev = p;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
run elements off the packet queue till its empty
|
||||
******************************************************************/
|
||||
void run_packet_queue()
|
||||
{
|
||||
struct packet_struct *p;
|
||||
|
||||
while ((p=packet_queue))
|
||||
{
|
||||
switch (p->packet_type)
|
||||
{
|
||||
case NMB_PACKET:
|
||||
process_nmb(p);
|
||||
break;
|
||||
|
||||
case DGRAM_PACKET:
|
||||
process_dgram(p);
|
||||
break;
|
||||
}
|
||||
|
||||
packet_queue = packet_queue->next;
|
||||
if (packet_queue) packet_queue->prev = NULL;
|
||||
free_packet(p);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
listens for NMB or DGRAM packets, and queues them
|
||||
***************************************************************************/
|
||||
void listen_for_packets(BOOL run_election)
|
||||
{
|
||||
fd_set fds;
|
||||
int selrtn;
|
||||
struct timeval timeout;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(ClientNMB,&fds);
|
||||
FD_SET(ClientDGRAM,&fds);
|
||||
|
||||
/* during elections and when expecting a netbios response packet we need
|
||||
to send election packets at one second intervals.
|
||||
XXXX actually, it needs to be the interval (in ms) between time now and the
|
||||
time we are expecting the next netbios packet */
|
||||
|
||||
timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
selrtn = sys_select(&fds,&timeout);
|
||||
|
||||
if (FD_ISSET(ClientNMB,&fds))
|
||||
{
|
||||
struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
|
||||
if (packet) {
|
||||
#if 1
|
||||
if (ismyip(packet->ip) &&
|
||||
(packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
|
||||
DEBUG(5,("discarding own packet from %s:%d\n",
|
||||
inet_ntoa(packet->ip),packet->port));
|
||||
free_packet(packet);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
queue_packet(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(ClientDGRAM,&fds))
|
||||
{
|
||||
struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
|
||||
if (packet) {
|
||||
#if 1
|
||||
if (ismyip(packet->ip) &&
|
||||
(packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
|
||||
DEBUG(5,("discarding own packet from %s:%d\n",
|
||||
inet_ntoa(packet->ip),packet->port));
|
||||
free_packet(packet);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
queue_packet(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
interpret a node status response. this is pretty hacked: we need two bits of
|
||||
info. a) the name of the workgroup b) the name of the server. it will also
|
||||
add all the names it finds into the namelist.
|
||||
****************************************************************************/
|
||||
BOOL interpret_node_status(struct subnet_record *d,
|
||||
char *p, struct nmb_name *name,int t,
|
||||
char *serv_name, struct in_addr ip, BOOL bcast)
|
||||
{
|
||||
int level = t==0x20 ? 4 : 0;
|
||||
int numnames = CVAL(p,0);
|
||||
BOOL found = False;
|
||||
|
||||
DEBUG(level,("received %d names\n",numnames));
|
||||
|
||||
p += 1;
|
||||
|
||||
if (serv_name) *serv_name = 0;
|
||||
|
||||
while (numnames--)
|
||||
{
|
||||
char qname[17];
|
||||
int type;
|
||||
fstring flags;
|
||||
int nb_flags;
|
||||
|
||||
BOOL group = False;
|
||||
BOOL add = False;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
StrnCpy(qname,p,15);
|
||||
type = CVAL(p,15);
|
||||
nb_flags = p[16];
|
||||
trim_string(qname,NULL," ");
|
||||
|
||||
p += 18;
|
||||
|
||||
if (NAME_GROUP (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
|
||||
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_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; }
|
||||
if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
|
||||
|
||||
/* might as well update our namelist while we're at it */
|
||||
if (add)
|
||||
{
|
||||
struct in_addr nameip;
|
||||
enum name_source src;
|
||||
|
||||
if (ismyip(ip)) {
|
||||
nameip = ipzero;
|
||||
src = SELF;
|
||||
} else {
|
||||
nameip = ip;
|
||||
src = STATUS_QUERY;
|
||||
}
|
||||
add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
|
||||
}
|
||||
|
||||
/* we want the server name */
|
||||
if (serv_name && !*serv_name && !group && t == 0)
|
||||
{
|
||||
StrnCpy(serv_name,qname,15);
|
||||
serv_name[15] = 0;
|
||||
}
|
||||
|
||||
/* looking for a name and type? */
|
||||
if (name && !found && (t == type))
|
||||
{
|
||||
/* take a guess at some of the name types we're going to ask for.
|
||||
evaluate whether they are group names or no... */
|
||||
if (((t == 0x1b || t == 0x1d ) && !group) ||
|
||||
((t == 0x20 || t == 0x1c || t == 0x1e) && group))
|
||||
{
|
||||
found = True;
|
||||
make_nmb_name(name,qname,type,scope);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
|
||||
}
|
||||
DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
|
||||
IVAL(p,20),IVAL(p,24)));
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
construct and send a netbios DGRAM
|
||||
|
||||
Note that this currently sends all answers to port 138. thats the
|
||||
wrong things to do! I should send to the requestors port. XXX
|
||||
**************************************************************************/
|
||||
BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
|
||||
char *dstname,int src_type,int dest_type,
|
||||
struct in_addr dest_ip,struct in_addr src_ip)
|
||||
{
|
||||
struct packet_struct p;
|
||||
struct dgram_packet *dgram = &p.packet.dgram;
|
||||
struct in_addr wins_ip = ipgrp;
|
||||
char *ptr,*p2;
|
||||
char tmp[4];
|
||||
|
||||
/* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
|
||||
if (ip_equal(wins_ip, dest_ip)) return False;
|
||||
|
||||
bzero((char *)&p,sizeof(p));
|
||||
|
||||
update_name_trn_id();
|
||||
|
||||
dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
|
||||
dgram->header.flags.node_type = M_NODE;
|
||||
dgram->header.flags.first = True;
|
||||
dgram->header.flags.more = False;
|
||||
dgram->header.dgm_id = name_trn_id;
|
||||
dgram->header.source_ip = src_ip;
|
||||
dgram->header.source_port = DGRAM_PORT;
|
||||
dgram->header.dgm_length = 0; /* let build_dgram() handle this */
|
||||
dgram->header.packet_offset = 0;
|
||||
|
||||
make_nmb_name(&dgram->source_name,srcname,src_type,scope);
|
||||
make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
|
||||
|
||||
ptr = &dgram->data[0];
|
||||
|
||||
/* now setup the smb part */
|
||||
ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
|
||||
memcpy(tmp,ptr,4);
|
||||
set_message(ptr,17,17 + len,True);
|
||||
memcpy(ptr,tmp,4);
|
||||
|
||||
CVAL(ptr,smb_com) = SMBtrans;
|
||||
SSVAL(ptr,smb_vwv1,len);
|
||||
SSVAL(ptr,smb_vwv11,len);
|
||||
SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
|
||||
SSVAL(ptr,smb_vwv13,3);
|
||||
SSVAL(ptr,smb_vwv14,1);
|
||||
SSVAL(ptr,smb_vwv15,1);
|
||||
SSVAL(ptr,smb_vwv16,2);
|
||||
p2 = smb_buf(ptr);
|
||||
strcpy(p2,mailslot);
|
||||
p2 = skip_string(p2,1);
|
||||
|
||||
memcpy(p2,buf,len);
|
||||
p2 += len;
|
||||
|
||||
dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
|
||||
|
||||
p.ip = dest_ip;
|
||||
p.port = DGRAM_PORT;
|
||||
p.fd = ClientDGRAM;
|
||||
p.timestamp = time(NULL);
|
||||
p.packet_type = DGRAM_PACKET;
|
||||
|
||||
return(send_packet(&p));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
the netbios expected response code is a key part of samba's NetBIOS
|
||||
handling capabilities. it allows samba to carry on dealing with
|
||||
other things while expecting a response from one or more hosts.
|
||||
|
||||
this allows samba to simultaneously deal with registering its names
|
||||
with another WINS server, register its names on its local subnets,
|
||||
query any hosts that have registered with samba in its capacity as
|
||||
a WINS server, and at a later date it will be also be able handle
|
||||
END-NODE CHALLENGES (see rfc1001.txt 15.2.2.2 and 15.2.2.3 - secured
|
||||
NBNS functionality). all at once!
|
||||
NBNS functionality).
|
||||
|
||||
all at once!
|
||||
|
||||
when a netbios packet is sent out by samba and it expects a response,
|
||||
a record of all the relevant information is kept (most importantly,
|
||||
@ -21,76 +24,15 @@ made (and therefore the type of response can be verified) and
|
||||
appropriate action can be taken.
|
||||
|
||||
when no responses, after a number of retries, are not received, then
|
||||
samba may take appropriate action.
|
||||
samba may take appropriate action. this is a crucial part of samba's
|
||||
operation: for a key number of NetBIOS operations, no response is an
|
||||
implicit positive response.
|
||||
|
||||
nameresp.c deals with the maintenance of the netbios response records:
|
||||
their creation, retransmission, and eventual removal.
|
||||
module nameresp deals with the initial transmission, re-transmission
|
||||
and time-out of netbios response records.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
send_mailslot_reply()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending a MAILSLOT packet.
|
||||
|
||||
it will _not_ send packets to the pseudo WINS subnet's address of
|
||||
255.255.255.255: this would be disastrous.
|
||||
|
||||
each packet sent out has a unique transaction identifier. this is done
|
||||
so that responses can be matched with the original purpose for the packet
|
||||
being sent out in the first place.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
interpret_node_status()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for interpreting the raw data that comes in
|
||||
from a node status reply. in the process, it identifies both the server
|
||||
name and the workgroup name in the node status reply.
|
||||
|
||||
it also updates information in the WINS name database if the names
|
||||
received are not already in samba's records.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
listen_for_packets()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for reading NMB and DGRAM packets, and then
|
||||
queueing them. it will normally time-out for NMBD_SELECT_LOOP seconds, but
|
||||
if there is an election currently running or we are expecting a response
|
||||
then this time is reduced to 1 second.
|
||||
|
||||
note: the time-out period needs refining to the millisecond level.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
queue_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for queueing any NMB and DGRAM packets passed
|
||||
to it. these packets will be removed from the queue in run_packet_queue().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
run_packet_queue()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for taking a packet off the queue,
|
||||
identifying whether it is an NMB or a DGRAM packet, processing
|
||||
it accordingly and deleting it. this process continues until
|
||||
there are no more packets on the queue.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_response_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for matching the unique response transaction
|
||||
id with an expected response record. as a side-effect of this search,
|
||||
it will find the subnet (or the WINS pseudo-subnet) that samba expected
|
||||
the response to come from.
|
||||
module namedbresp deals with the maintenance of the list of expected
|
||||
responses - creation, finding and removal.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@ -105,22 +47,6 @@ if a response is received, response_netbios_packet() will deal with it.
|
||||
otherwise, it will be dealt with in expire_netbios_response_entries().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
make_response_queue_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for creating a response record, which will
|
||||
be queued awaiting a response.
|
||||
|
||||
the number of retries is set to 4, and the retry period set to 1 second.
|
||||
if no response is received, then the packet is re-transmitted, which is
|
||||
why so much information is stored in the response record.
|
||||
|
||||
the number of expected responses queued is kept, so listen_for_packets()
|
||||
knows it must time-out after 1 second if one or more responses are
|
||||
expected.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
queue_netbios_pkt_wins()
|
||||
*************************************************************************/
|
||||
@ -137,17 +63,6 @@ name.
|
||||
this is NOT the case with a P node.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending a reply to another NetBIOS
|
||||
packet from another host. it can be used to send a reply to a name
|
||||
registration, name release, name query or name status request.
|
||||
|
||||
the reply can be either a positive or a negative one.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
expire_netbios_response_entries()
|
||||
*************************************************************************/
|
||||
@ -173,15 +88,6 @@ will no longer time-out for 1 second on account of expecting response
|
||||
packets.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
initiate_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for construction a netbios packet and sending
|
||||
it. if the packet has not had a unique transaction id allocated to it,
|
||||
then initiate_netbios_packet() will give it one.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
dead_netbios_entry()
|
||||
*************************************************************************/
|
||||
@ -225,6 +131,18 @@ samba should take this into account (see rfc1001.txt 10.3).
|
||||
remove_name_entry() issues this samba 'state'
|
||||
response_name_rel() deals with responses to NAME_RELEASE.
|
||||
|
||||
- NAME_REGISTER_CHALLENGE
|
||||
|
||||
when a samba 'state' of type NAME_REGISTER_CHALLENGE is sent, and a
|
||||
response is not received, it is assumed that the server being queried
|
||||
is either dead, deaf or unreachable. the host that wanted this
|
||||
unique name is then informed that it can have it (the name query
|
||||
challenge went unanswered) and that its registration of this name
|
||||
did in fact succeed.
|
||||
|
||||
reply_name_reg() issues this samba 'state'
|
||||
response_name_query_register() deals with responses.
|
||||
|
||||
- NAME_REGISTER
|
||||
|
||||
when a samba 'state' of type NAME_REGISTER is sent, and a response is
|
||||
@ -243,19 +161,3 @@ is not received. this is not to say that action may not be appropriate,
|
||||
just that it's not been looked at yet :-)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
add_response_record()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for adding the response record created by
|
||||
make_response_queue_record() into the appropriate response record queue.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
update_name_trn_id()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for allocating unique transaction identifiers
|
||||
for each new packet sent on the network.
|
||||
|
||||
|
||||
|
1599
source3/nameserv.c
1599
source3/nameserv.c
File diff suppressed because it is too large
Load Diff
@ -1,344 +1,4 @@
|
||||
/*************************************************************************
|
||||
process_nmb()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives a packet identified as a netbios packet.
|
||||
it further identifies whether it is a response or a query packet.
|
||||
by identifying the type of packet (name registration, query etc)
|
||||
process_nmb() will call the appropriate function to deal with the
|
||||
type of packet received.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function received netbios response packets. the samba server
|
||||
(or a rogue tcp/ip system, or nmblookup) will have sent out a packet
|
||||
requesting a response. a client (or a rogue tcp/ip system) responds
|
||||
to that request.
|
||||
|
||||
this function checks the validity of the packet it receives.
|
||||
the expected response records are searched for the transaction id,
|
||||
to see if it's a response expected by the samba server. if it isn't
|
||||
it's reported as such, and ignored.
|
||||
|
||||
if the response is found, then the subnet it was expected from will
|
||||
also have been found. the subnet it actually came in on can be
|
||||
checked against the subnet it was expected from and reported,
|
||||
otherwise this function just carries on.
|
||||
|
||||
the number of responses received is increased, and the number of
|
||||
retries left to be sent is set to zero.
|
||||
|
||||
after debug information is reported, and validation of the netbios
|
||||
packet (e.g only one response from one machine is expected for some
|
||||
functions) has occurred, the packet is processed. when the initial
|
||||
request was sent out, the expected response record was flagged with,
|
||||
for lack of a better word, a samba 'state' type. whenever a
|
||||
response is received, the appropriate function is called to carry on
|
||||
where the program control flow was interrupted while awaiting exactly
|
||||
such a response.
|
||||
|
||||
please note that _not_ receiving a response is dealt with in another
|
||||
area of code - expire_netbios_response_entries().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_query_sync()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_QUERY_SYNC and
|
||||
NAME_QUERY_CONFIRM.
|
||||
|
||||
NAME_QUERY_SYNC: name query a server before synchronising browse lists.
|
||||
NAME_QUERY_CONFIRM: name query a server to check that it's alive.
|
||||
|
||||
a NAME_QUERY_SYNC will be carried out in order to check that a server
|
||||
is alive before syncing browse lists. we don't want to delay the SMB
|
||||
NetServerEnum api just because the server has gone down: we have too
|
||||
much else to do.
|
||||
|
||||
a NAME_QUERY_CONFIRM is just a name query to see whether the server is
|
||||
alive. these queries are sent out by samba's WINS server side, to verify
|
||||
its netbios name database of all machines that have registered with it.
|
||||
|
||||
we don't normally expect a negative response from such a query, although
|
||||
we may do so if the query was sent to another WINS server. the registered
|
||||
entry should be removed if we receive a negative response.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_status_check()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_STATUS_CHECK
|
||||
and NAME_STATUS_MASTER_CHECK
|
||||
|
||||
NAME_STATUS_MASTER_CHECK: name status a primary domain controller,
|
||||
confirm its domain and then initiate syncing
|
||||
its browse list.
|
||||
|
||||
NAME_STATUS_CHECK: same as NAME_STATUS_MASTER_CHECK except the name status
|
||||
is issued to a master browser.
|
||||
|
||||
if we don't know what workgroup a server is responsible for, but we
|
||||
know that there is a master browser at a certain ip, we can issue a
|
||||
name status check. from the response received, there will be
|
||||
a master browser netbios entry. this will allow us to synchronise
|
||||
browse lists with that machine and then add the information to the
|
||||
correct part of samba's workgroup - server database.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_server_check()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_QUERY_MST_SRV_CHK,
|
||||
NAME_QUERY_SRV_CHK and NAME_QUERY_FIND_MST.
|
||||
|
||||
NAME_QUERY_FIND_MST: issued as a broadcast when we wish to find out all
|
||||
master browsers (i.e all servers that have registered
|
||||
the NetBIOS name ^1^2__MSBROWSE__^2(0x1), and then
|
||||
issue a NAME_STATUS_MASTER_CHECK on any servers that
|
||||
respond, which will initiate a sync browse lists.
|
||||
|
||||
NAME_QUERY_MST_SRV_CHK: same as a NAME_QUERY_FIND_MST except this is sent
|
||||
to a primary domain controller.
|
||||
|
||||
NAME_QUERY_SRV_CHK: same as a NAME_QUERY_MST_SRV_CHK except this is sent to
|
||||
a master browser.
|
||||
|
||||
the purpose of each of these states is to do a broadcast name query, or
|
||||
a name query directed at a WINS server, then to all hosts that respond,
|
||||
we issue a name status check, which will confirm for us the workgroup
|
||||
or domain name, and then initiate issuing a sync browse list call with
|
||||
that server.
|
||||
|
||||
a NAME_QUERY_SRV_CHK is sent when samba receives a list of backup
|
||||
browsers. it checks to see if that server is alive (by doing a
|
||||
name query on a server) and then syncs browse lists with it.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_query()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for replying to a NetBIOS name query.
|
||||
|
||||
there are two kinds of name queries: directed, and broadcast. directed
|
||||
queries are usually sent to samba in its WINS capacity. such hosts are
|
||||
termed 'point-to-point' hosts. broadcast queries are usually sent from
|
||||
'broadcast' or 'mixed' hosts.
|
||||
|
||||
broadcasting is used by either older NetBIOS hosts, new NetBIOS hosts that
|
||||
have not had WINS capabilities added and new NetBIOS hosts that think the
|
||||
WINS server has died.
|
||||
|
||||
the samba NetBIOS name database is divided into sections, on a
|
||||
per-subnet basis. there is also a WINS NetBIOS name database, and for
|
||||
convenience this is added as a pseudo-subnet with the ip address of
|
||||
255.255.255.255.
|
||||
|
||||
the local subnet NetBIOS name databases only contain samba's names.
|
||||
the reason for this is that if a broadcast query is received, a NetBIOS
|
||||
hosts is only expected to respond if that query is for one of its own
|
||||
names (the exception to this is if a host is configured as a 'proxy'
|
||||
server, in which case, samba should redirect the query to another WINS
|
||||
server).
|
||||
|
||||
the WINS pseudo-subnet NetBIOS database contains all NetBIOS names
|
||||
that are not 'special browser' type names (regarding this i am a
|
||||
_bit_ confused :-). names of type 0x01, 0x1d and 0x1e i consider to
|
||||
be 'special browser' names. at the moment. maybe.
|
||||
|
||||
the type of search to be initiated is determined. if the NetBIOS name
|
||||
type is a non-special-browser name, then the WINS database is included
|
||||
in the search.
|
||||
|
||||
if the name is not a special browser name, then we need to find the
|
||||
right subnet that the query came from. this is done using
|
||||
find_req_subnet(). this also has the benefit of stopping any queries
|
||||
from subnets that samba does not know about.
|
||||
|
||||
if the query is a broadcast query, then the database of the local subnet
|
||||
is included in the search.
|
||||
|
||||
the name is then searched for in the appropriate NetBIOS data structures.
|
||||
if it is found, then we need to check whether it is appropriate for us
|
||||
to reply to such a query.
|
||||
|
||||
we will only reply if the query is a directed query, the name belongs to
|
||||
samba on that subnet, or the name is a primary domain controller type,
|
||||
or we're doing replies on behalf of hosts on subnets not known to the
|
||||
host issuing the query. in the latter instance, it would be appropriate
|
||||
if samba is using a WINS server for it to forward the name query on to
|
||||
this WINS server.
|
||||
|
||||
reply_name_query() then takes note of all the information that is
|
||||
needed to construct a reply to the caller. a negative reply (if the
|
||||
name is unknown to samba) or a positive reply (the name is known to
|
||||
samba) is then issued.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
search_for_name()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for finding a name in the appropriate part
|
||||
of samba's NetBIOS name database. if the name cannot be found, then it
|
||||
should look the name up using DNS. later modifications will be to
|
||||
forward the request on to another WINS server, should samba not be able
|
||||
to find out about the requested name (this will be implemented through
|
||||
issuing a new type of samba 'state').
|
||||
|
||||
the name is first searched for in the NetBIOS cache. if it cannot be
|
||||
found, then it if the name looks like it's a server-type name (0x20
|
||||
0x0 or 0x1b) then DNS is used to look for the name.
|
||||
|
||||
if DNS fails, then a record of this failure is kept. if it succeeds, then
|
||||
a new NetBIOS entry is added.
|
||||
|
||||
the successfully found name is returned. on failure, NULL is returned.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_status()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for constructing a reply to a NetBIOS
|
||||
name status query. this response contains all samba's NetBIOS names
|
||||
on the subnet that the query came in from.
|
||||
|
||||
a reply will only be made if the NetBIOS name being queried exists.
|
||||
|
||||
see rfc1001.txt and rfc1002.txt for details of the name status reply.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_reg()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for updating the NetBIOS name database
|
||||
from registration packets sent out by hosts wishing to register a
|
||||
name, and for informing them, if necessary, if this is acceptable
|
||||
or not.
|
||||
|
||||
name registration can be done by broadcast or by point-to-point,
|
||||
i.e the registration is sent directly to samba in its capacity as
|
||||
a WINS server.
|
||||
|
||||
if the name registration is done by broadcast (see rfc1001.txt 15.2.1),
|
||||
then samba's involvement in replying is limited to whether that name
|
||||
is owned by samba or not, on the relevant subnet.
|
||||
|
||||
if the name registration is done point-to-point (see rfc1001.txt 15.2.2)
|
||||
then samba will first need to check its WINS name database records and
|
||||
proceed accordingly.
|
||||
|
||||
samba looks for the appropriate subnet record that the registration
|
||||
should be added to / checked against, using find_req_subnet().
|
||||
|
||||
next, the name is searched for in the local database or the WINS
|
||||
database as appropriate.
|
||||
|
||||
if the name is not found, then it is added to the NetBIOS name database,
|
||||
using add_netbios_entry(), which may choose not to add the name (not
|
||||
that this affects the registration of the name on the network in any way).
|
||||
it will only add names to the WINS database, and even then it will only
|
||||
add non-special-browser type names.
|
||||
|
||||
if the name is found, then samba must decide whether to accept the name
|
||||
or not. a group name is always added. for unique names, further checks
|
||||
need to be carried out.
|
||||
|
||||
firstly, if the name in the database is one of samba's names, or if the
|
||||
name in the database is a group name, then it cannot be added as a unique
|
||||
name belonging to someone else. it is therefore rejected.
|
||||
|
||||
secondly, if the ip address of the name being registered does not match
|
||||
against the ip in the database, then the unique name may belong to
|
||||
someone else. a check needs to be carried out with the owner in case
|
||||
they still wish to keep this name. a detailed discussion of what action
|
||||
to take is in rfc1001.txt 15.2.2.2 and 15.2.2.3.
|
||||
|
||||
samba currently implements non-secured WINS, whereupon the responsibility
|
||||
for checking the name is passed on to the host doing the registration.
|
||||
rfc1001.txt refers to this as an END-NODE CHALLENGE REGISTRATION RESPONSE.
|
||||
(samba itself cannot yet cope with receiving such responses if it
|
||||
registers its names with another WINS server).
|
||||
|
||||
having decided what kind of response to send (if any - acceptance of
|
||||
name registrations by broadcast is implicit), samba will send either a
|
||||
positive or negative NAME REGISTRATION RESPONSE, or an END-NODE CHALLENGE
|
||||
REGISTRATION RESPONSE to the host that initially sent the registration.
|
||||
|
||||
whew.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_reg()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for dealing with samba's registration
|
||||
attempts, by broadcast to a local subnet, or point-to-point with
|
||||
another WINS server.
|
||||
|
||||
please note that it cannot cope with END-NODE CHALLENGE REGISTRATION
|
||||
RESPONSEs at present.
|
||||
|
||||
when a response is received, samba determines if the response is a
|
||||
positive or a negative one. if it is a positive response, the name
|
||||
is added to samba's database.
|
||||
|
||||
when a negative response is received, samba will remove the name
|
||||
from its database. if, however, the name is a browser type (0x1b is
|
||||
a primary domain controller type name; or 0x1d, which is a master
|
||||
browser type name) then it must also stop being a primary domain
|
||||
controller or master browser respectively, depending on what kind
|
||||
of name was rejected.
|
||||
|
||||
(when no response is received, then expire_netbios_response_entries()
|
||||
is expected to deal with this. the only case that is dealt with here
|
||||
at present is when the registration was done by broadcast. if there
|
||||
is no challenge to the broadcast registration, it is implicitly
|
||||
assumed that claiming the name is acceptable).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_release()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing samba's NetBIOS name when
|
||||
samba contacts another WINS server with which it had registered the
|
||||
name.
|
||||
|
||||
only positive name releases are expected and dealt with. exactly what
|
||||
to do if a negative name release (i.e someone says 'oi! you have to
|
||||
keep that name!') is received is uncertain.
|
||||
|
||||
(when no response is received, then expire_netbios_response_entries()
|
||||
is expected to deal with this. if there is no challenge to the release
|
||||
of the name, the name is then removed from that subnet's NetBIOS
|
||||
name database).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
expire_names()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing old NetBIOS names from its
|
||||
database. no further action is required.
|
||||
|
||||
for over-zealous WINS systems, the use of query_refresh_names() is
|
||||
recommended. this function initiates polling of hosts that have
|
||||
registered with samba in its capacity as a WINS server. an alternative
|
||||
means to achieve the same end as query_refresh_names() is to
|
||||
reduce the time to live when the name is registered with samba,
|
||||
except that in this instance the responsibility for refreshing the
|
||||
name is with the owner of the name, not the server with which the name
|
||||
is registered.
|
||||
|
||||
this module deals with general maintenance of NetBIOS names.
|
||||
|
||||
/*************************************************************************
|
||||
query_refresh_names()
|
||||
@ -436,45 +96,3 @@ are recorded in this file, including the time-to-live. should the
|
||||
time left to live be small, the name is not added back in to samba's
|
||||
WINS database.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
dump_names()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for outputting NetBIOS names in two formats.
|
||||
firstly, as debugging information, and secondly, all names that have been
|
||||
registered with samba in its capacity as a WINS server are written to
|
||||
disk.
|
||||
|
||||
writing all WINS names allows two things. firstly, if samba's NetBIOS
|
||||
daemon dies or is terminated, on restarting the daemon most if not all
|
||||
of the registered WINS names will be preserved (which is a good reason
|
||||
why query_netbios_names() should be used).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_name_search()
|
||||
*************************************************************************/
|
||||
|
||||
this function is a wrapper around find_name(). find_name_search() can
|
||||
be told whether to search for the name in a local subnet structure or
|
||||
in the WINS database. on top of this, it can be told to search only
|
||||
for samba's SELF names.
|
||||
|
||||
if it finds the name in the WINS database, it will set the subnet_record
|
||||
and also return the name it finds.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
find_req_subnet()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for finding the appropriate subnet record
|
||||
to use. it is assumed that any directed packets are going to need to
|
||||
use the WINS pseudo-subnet records, and that any broadcast transactions
|
||||
received are going to need to use a local subnet record, which is found
|
||||
from the ip address that the transaction was received on.
|
||||
|
||||
a side-effect of this function is that any broadcast packet received
|
||||
on a subnet not known to samba is ignored.
|
||||
|
||||
|
189
source3/nameservreply.doc
Normal file
189
source3/nameservreply.doc
Normal file
@ -0,0 +1,189 @@
|
||||
/*************************************************************************
|
||||
reply_name_query()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for replying to a NetBIOS name query.
|
||||
|
||||
there are two kinds of name queries: directed, and broadcast. directed
|
||||
queries are usually sent to samba in its WINS capacity. such hosts are
|
||||
termed 'point-to-point' hosts. broadcast queries are usually sent from
|
||||
'broadcast' or 'mixed' hosts.
|
||||
|
||||
broadcasting is used by either older NetBIOS hosts, new NetBIOS hosts that
|
||||
have not had WINS capabilities added and new NetBIOS hosts that think the
|
||||
WINS server has died.
|
||||
|
||||
the samba NetBIOS name database is divided into sections, on a
|
||||
per-subnet basis. there is also a WINS NetBIOS name database, and for
|
||||
convenience this is added as a pseudo-subnet with the ip address of
|
||||
255.255.255.255.
|
||||
|
||||
the local subnet NetBIOS name databases only contain samba's names.
|
||||
the reason for this is that if a broadcast query is received, a NetBIOS
|
||||
hosts is only expected to respond if that query is for one of its own
|
||||
names (the exception to this is if a host is configured as a 'proxy'
|
||||
server, in which case, samba should redirect the query to another WINS
|
||||
server).
|
||||
|
||||
the WINS pseudo-subnet NetBIOS database contains all NetBIOS names
|
||||
registered with samba in its capacity as a WINS server.
|
||||
|
||||
the type of search to be initiated is determined. if the packet
|
||||
received is a point-to-point (unicast), then the WINS database
|
||||
is included in the search.
|
||||
|
||||
if the search is not in the WINS database, then we need to find the
|
||||
right subnet that the query came from. this is done using
|
||||
find_req_subnet(). this also has the benefit of stopping any queries
|
||||
from subnets that samba does not know about.
|
||||
|
||||
if the query is a broadcast query, then the database of the local subnet
|
||||
is included in the search.
|
||||
|
||||
the name is then searched for in the appropriate NetBIOS data structures.
|
||||
if it is found, then we need to check whether it is appropriate for us
|
||||
to reply to such a query.
|
||||
|
||||
we will only reply if the query is a directed query, the name belongs to
|
||||
samba on that subnet, or the name is a primary domain controller type,
|
||||
or we're doing replies on behalf of hosts on subnets not known to the
|
||||
host issuing the query. in the latter instance, it would be appropriate
|
||||
if samba is using a WINS server for it to forward the name query on to
|
||||
this WINS server.
|
||||
|
||||
reply_name_query() then takes note of all the information that is
|
||||
needed to construct a reply to the caller. a negative reply (if the
|
||||
name is unknown to samba) or a positive reply (the name is known to
|
||||
samba) is then issued.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_status()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for constructing a reply to a NetBIOS
|
||||
name status query. this response contains all samba's NetBIOS names
|
||||
on the subnet that the query came in from.
|
||||
|
||||
a reply will only be made if the NetBIOS name being queried exists.
|
||||
|
||||
see rfc1001.txt and rfc1002.txt for details of the name status reply.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_reg()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for updating the NetBIOS name database
|
||||
from registration packets sent out by hosts wishing to register a
|
||||
name, and for informing them, if necessary, if this is acceptable
|
||||
or not.
|
||||
|
||||
name registration can be done by broadcast or by point-to-point,
|
||||
i.e the registration is sent directly to samba in its capacity as
|
||||
a WINS server.
|
||||
|
||||
if the name registration is done by broadcast (see rfc1001.txt 15.2.1),
|
||||
then samba's involvement in replying is limited to whether that name
|
||||
is owned by samba or not, on the relevant subnet.
|
||||
|
||||
if the name registration is done point-to-point (see rfc1001.txt 15.2.2)
|
||||
then samba will first need to check its WINS name database records and
|
||||
proceed accordingly.
|
||||
|
||||
samba looks for the appropriate subnet record that the registration
|
||||
should be added to / checked against, using find_req_subnet().
|
||||
|
||||
next, the name is searched for in the local database or the WINS
|
||||
database as appropriate.
|
||||
|
||||
if the name is not found, then it is added to the NetBIOS name database,
|
||||
using add_netbios_entry(), which may choose not to add the name (not
|
||||
that this affects the registration of the name on the network in any way).
|
||||
it will only add non-SELF names to the WINS database.
|
||||
|
||||
if the name is found, then samba must decide whether to accept the name
|
||||
or not. a group name is always added. for unique names, further checks
|
||||
need to be carried out.
|
||||
|
||||
firstly, if the name in the database is one of samba's names, or if the
|
||||
name in the database is a group name, then it cannot be added as a unique
|
||||
name belonging to someone else. it is therefore rejected.
|
||||
|
||||
secondly, if the ip address of the name being registered does not match
|
||||
against the ip in the database, then the unique name may belong to
|
||||
someone else. a check needs to be carried out with the owner in case
|
||||
they still wish to keep this name. a detailed discussion of what action
|
||||
to take is in rfc1001.txt 15.2.2.2 and 15.2.2.3.
|
||||
|
||||
#if 0
|
||||
|
||||
samba currently implements non-secured WINS, whereupon the responsibility
|
||||
for checking the name is passed on to the host doing the registration.
|
||||
rfc1001.txt refers to this as an END-NODE CHALLENGE REGISTRATION RESPONSE.
|
||||
(samba itself cannot yet cope with receiving such responses if it
|
||||
registers its names with another WINS server).
|
||||
|
||||
#else
|
||||
|
||||
samba currently implements secured WINS, whereupon it is samba's
|
||||
responsibility to check the unique name before allowing it to be
|
||||
registered by the new owner.
|
||||
|
||||
as checking the unique name may take some time, samba must send a Wait
|
||||
Acknowledge packet to the host that wishes to claim the name. a
|
||||
NAME_REGISTER_CHALLENGE 'state' is then initiated, which will result
|
||||
in a name query being issued to the current owner.
|
||||
|
||||
if we receive a negative response or no response, the host wishing
|
||||
to claim the name is informed that they can have it. if we receive
|
||||
a positive response, this host is informed that it cannot have it.
|
||||
|
||||
#endif
|
||||
|
||||
having decided what kind of response to send (if any - acceptance of
|
||||
name registrations by broadcast is implicit), samba will send a
|
||||
positive or negative NAME REGISTRATION RESPONSE, or an END-NODE CHALLENGE
|
||||
REGISTRATION RESPONSE or a WAIT ACKNOWLEDGEMENT to the host that
|
||||
initially sent the registration.
|
||||
|
||||
|
||||
whew.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
send_name_response()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for sending out a positive or a negative
|
||||
registration response or release, or an end-node challenge registration
|
||||
response.
|
||||
|
||||
it is called from reply_name_release(), reply_name_reg(),
|
||||
dead_netbios_entry() and response_name_query_register().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
reply_name_release()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing a NetBIOS name from the
|
||||
database when a server sends a release packet.
|
||||
|
||||
samba looks for the appropriate subnet record that the release should
|
||||
be removed from, using find_req_subnet(). next, the name is searched
|
||||
for in the local database or the WINS database as appropriate.
|
||||
|
||||
if the name is found, it is removed from the database and a
|
||||
positive reply is sent confirming this. if the name is not
|
||||
found, a negative reply is sent.
|
||||
|
||||
a reply is _not_ sent if the release was done by broadcast: the
|
||||
release is implicit, and we should be grateful that they bothered
|
||||
to tell us. if the release was done by directed packet, then
|
||||
we deal with it as a WINS server and must reply (pos / neg).
|
||||
|
||||
at present, the criteria for removing a name have yet to be
|
||||
developed / experimented with. at present, the only flags that
|
||||
are checked are the NetBIOS flags.
|
||||
|
188
source3/nameservresp.doc
Normal file
188
source3/nameservresp.doc
Normal file
@ -0,0 +1,188 @@
|
||||
this module deals with the receipt of response packets. the
|
||||
response packets are expected to be received, and there is a
|
||||
record of this kept (see also: modules nameresp and namedbresp)
|
||||
|
||||
/*************************************************************************
|
||||
response_netbios_packet()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives netbios response packets. the samba server
|
||||
(or a rogue tcp/ip system, or nmblookup) will have sent out a packet
|
||||
requesting a response. a client (or a rogue tcp/ip system) responds
|
||||
to that request.
|
||||
|
||||
this function checks the validity of the packet it receives.
|
||||
the expected response records are searched for the transaction id,
|
||||
to see if it's a response expected by the samba server. if it isn't
|
||||
it's reported as such, and ignored.
|
||||
|
||||
if the response is found, then the subnet it was expected from will
|
||||
also have been found. the subnet it actually came in on can be
|
||||
checked against the subnet it was expected from and reported,
|
||||
otherwise this function just carries on.
|
||||
|
||||
the number of responses received is increased, and the number of
|
||||
retries left to be sent is set to zero.
|
||||
|
||||
after debug information is reported, and validation of the netbios
|
||||
packet (e.g only one response from one machine is expected for some
|
||||
functions) has occurred, the packet is processed. when the initial
|
||||
request was sent out, the expected response record was flagged with,
|
||||
for lack of a better word, a samba 'state' type. whenever a
|
||||
response is received, the appropriate function is called to carry on
|
||||
where the program control flow was interrupted while awaiting exactly
|
||||
such a response.
|
||||
|
||||
please note that _not_ receiving a response is dealt with in another
|
||||
area of code - expire_netbios_response_entries().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_query_sync()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_QUERY_SYNC and
|
||||
NAME_QUERY_CONFIRM.
|
||||
|
||||
NAME_QUERY_SYNC: name query a server before synchronising browse lists.
|
||||
NAME_QUERY_CONFIRM: name query a server to check that it's alive.
|
||||
|
||||
a NAME_QUERY_SYNC will be carried out in order to check that a server
|
||||
is alive before syncing browse lists. we don't want to delay the SMB
|
||||
NetServerEnum api just because the server has gone down: we have too
|
||||
much else to do.
|
||||
|
||||
a NAME_QUERY_CONFIRM is just a name query to see whether the server is
|
||||
alive. these queries are sent out by samba's WINS server side, to verify
|
||||
its netbios name database of all machines that have registered with it.
|
||||
|
||||
we don't normally expect a negative response from such a query, although
|
||||
we may do so if the query was sent to another WINS server. the registered
|
||||
entry should be removed if we receive a negative response.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_query_register()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states'
|
||||
NAME_REGISTER_CHALLENGE.
|
||||
|
||||
NAME_REGISTER_CHALLENGE: name query a server to establish whether to
|
||||
hand over a unique name to another server that asked for that name.
|
||||
|
||||
if a positive response is received to the name query, this indicates
|
||||
that the current owner still wants the name. we therefore refresh
|
||||
the name records indicating that the current owner still wants it,
|
||||
and we inform the potential owner (the other host) that they cannot
|
||||
have it.
|
||||
|
||||
if a negative response is received, this indicates that for some
|
||||
reason (for example, it may have just released the name or the
|
||||
WINS server may have had out-of-date records) the current owner
|
||||
does not want the name. in this instance, the name records are
|
||||
updated to give this unique name to the other host that wanted
|
||||
it, and the other host is informed that they can have it.
|
||||
|
||||
a failure to respond on the part of the current owner of the name
|
||||
is dealt with in dead_netbios_entry().
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_status_check()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_STATUS_CHECK
|
||||
and NAME_STATUS_MASTER_CHECK
|
||||
|
||||
NAME_STATUS_MASTER_CHECK: name status a primary domain controller,
|
||||
confirm its domain and then initiate syncing
|
||||
its browse list.
|
||||
|
||||
NAME_STATUS_CHECK: same as NAME_STATUS_MASTER_CHECK except the name status
|
||||
is issued to a master browser.
|
||||
|
||||
if we don't know what workgroup a server is responsible for, but we
|
||||
know that there is a master browser at a certain ip, we can issue a
|
||||
name status check. from the response received, there will be
|
||||
a master browser netbios entry. this will allow us to synchronise
|
||||
browse lists with that machine and then add the information to the
|
||||
correct part of samba's workgroup - server database.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_server_check()
|
||||
*************************************************************************/
|
||||
|
||||
this function receives responses to samba 'states' NAME_QUERY_MST_SRV_CHK,
|
||||
NAME_QUERY_SRV_CHK and NAME_QUERY_FIND_MST.
|
||||
|
||||
NAME_QUERY_FIND_MST: issued as a broadcast when we wish to find out all
|
||||
master browsers (i.e all servers that have registered
|
||||
the NetBIOS name ^1^2__MSBROWSE__^2(0x1), and then
|
||||
issue a NAME_STATUS_MASTER_CHECK on any servers that
|
||||
respond, which will initiate a sync browse lists.
|
||||
|
||||
NAME_QUERY_MST_SRV_CHK: same as a NAME_QUERY_FIND_MST except this is sent
|
||||
to a primary domain controller.
|
||||
|
||||
NAME_QUERY_SRV_CHK: same as a NAME_QUERY_MST_SRV_CHK except this is sent to
|
||||
a master browser.
|
||||
|
||||
the purpose of each of these states is to do a broadcast name query, or
|
||||
a name query directed at a WINS server, then to all hosts that respond,
|
||||
we issue a name status check, which will confirm for us the workgroup
|
||||
or domain name, and then initiate issuing a sync browse list call with
|
||||
that server.
|
||||
|
||||
a NAME_QUERY_SRV_CHK is sent when samba receives a list of backup
|
||||
browsers. it checks to see if that server is alive (by doing a
|
||||
name query on a server) and then syncs browse lists with it.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_reg()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for dealing with samba's registration
|
||||
attempts, by broadcast to a local subnet, or point-to-point with
|
||||
another WINS server.
|
||||
|
||||
please note that it cannot cope with END-NODE CHALLENGE REGISTRATION
|
||||
RESPONSEs at present.
|
||||
|
||||
when a response is received, samba determines if the response is a
|
||||
positive or a negative one. if it is a positive response, the name
|
||||
is added to samba's database.
|
||||
|
||||
when a negative response is received, samba will remove the name
|
||||
from its database. if, however, the name is a browser type (0x1b is
|
||||
a primary domain controller type name; or 0x1d, which is a master
|
||||
browser type name) then it must also stop being a primary domain
|
||||
controller or master browser respectively, depending on what kind
|
||||
of name was rejected.
|
||||
|
||||
(when no response is received, then expire_netbios_response_entries()
|
||||
is expected to deal with this. the only case that is dealt with here
|
||||
at present is when the registration was done by broadcast. if there
|
||||
is no challenge to the broadcast registration, it is implicitly
|
||||
assumed that claiming the name is acceptable).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
response_name_release()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for removing samba's NetBIOS name when
|
||||
samba contacts another WINS server with which it had registered the
|
||||
name.
|
||||
|
||||
only positive name releases are expected and dealt with. exactly what
|
||||
to do if a negative name release (i.e someone says 'oi! you have to
|
||||
keep that name!') is received is uncertain.
|
||||
|
||||
(when no response is received, then expire_netbios_response_entries()
|
||||
is expected to deal with this. if there is no challenge to the release
|
||||
of the name, the name is then removed from that subnet's NetBIOS
|
||||
name database).
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
NBT netbios routines and daemon - version 2
|
||||
Copyright (C) Andrew Tridgell 1994-1995
|
||||
Copyright (C) Andrew Tridgell 1994-1996
|
||||
|
||||
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
|
||||
@ -64,8 +64,6 @@ extern int updatecount;
|
||||
|
||||
extern time_t StartupTime;
|
||||
|
||||
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
tell a server to become a backup browser
|
||||
@ -385,7 +383,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
|
||||
{
|
||||
queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
|
||||
work->work_group,0x1d,0,0,
|
||||
False,False,back_ip);
|
||||
False,False,back_ip,back_ip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -812,49 +810,3 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
process udp 138 datagrams
|
||||
****************************************************************************/
|
||||
void process_dgram(struct packet_struct *p)
|
||||
{
|
||||
char *buf;
|
||||
char *buf2;
|
||||
int len;
|
||||
struct dgram_packet *dgram = &p->packet.dgram;
|
||||
|
||||
if (dgram->header.msg_type != 0x10 &&
|
||||
dgram->header.msg_type != 0x11 &&
|
||||
dgram->header.msg_type != 0x12) {
|
||||
/* don't process error packets etc yet */
|
||||
return;
|
||||
}
|
||||
|
||||
buf = &dgram->data[0];
|
||||
buf -= 4; /* XXXX for the pseudo tcp length -
|
||||
someday I need to get rid of this */
|
||||
|
||||
if (CVAL(buf,smb_com) != SMBtrans) return;
|
||||
|
||||
len = SVAL(buf,smb_vwv11);
|
||||
buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
|
||||
|
||||
DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
|
||||
namestr(&dgram->source_name),namestr(&dgram->dest_name),
|
||||
smb_buf(buf),CVAL(buf2,0),len));
|
||||
|
||||
|
||||
if (len <= 0) return;
|
||||
|
||||
/* datagram packet received for the browser mailslot */
|
||||
if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
|
||||
process_browse_packet(p,buf2,len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* datagram packet received for the domain log on mailslot */
|
||||
if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
|
||||
process_logon_packet(p,buf2,len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,26 +2,15 @@
|
||||
the module namework.c deals with NetBIOS datagram packets, primarily.
|
||||
it deals with nmbd's workgroup browser side and the domain log in
|
||||
side. none of the functionality here has specification documents available.
|
||||
empirical observation of packet traces has been the order of the day.
|
||||
empirical observation of packet traces has been the order of the day,
|
||||
along with some guess-work.
|
||||
|
||||
beware!
|
||||
|
||||
the receipt of datagram packets for workgroup browsing are dealt with here.
|
||||
some of the functions listed here will call others outside of this
|
||||
module, or will activate functionality dealt with by other modules.
|
||||
|
||||
these include: namedb.c, nameannounce.c, nameelect.c,
|
||||
namelogon.c, and namebrowse.c.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
process_dgram()
|
||||
*************************************************************************/
|
||||
|
||||
this function is responsible for identifying whether the datagram
|
||||
packet received is a browser packet or a domain logon packet. it
|
||||
also does some filtering of certain types of packets (e.g it
|
||||
filters out error packets).
|
||||
module, or will activate functionality dealt with by other modules
|
||||
(namedb, nameannounce, nameelect, namelogon, and namebrowse).
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@ -95,7 +84,8 @@ samba do not implement this latter option.
|
||||
this datagram is sent by a master browser to a primary domain
|
||||
controller. it is a way to ensure that master browsers are
|
||||
kept in sync with a primary domain controller across a wide
|
||||
area network.
|
||||
area network. on receipt of an ANN_MasterAnnouncement we
|
||||
should sync browse lists with the sender.
|
||||
|
||||
(i never got the hang of this one when i was experimenting.
|
||||
i forget exactly what it's for, and i never fully worked
|
||||
|
Loading…
Reference in New Issue
Block a user