summaryrefslogtreecommitdiff
path: root/source3/namework.c
diff options
context:
space:
mode:
authorSamba Release Account <samba-bugs@samba.org>1996-07-02 15:31:33 +0000
committerSamba Release Account <samba-bugs@samba.org>1996-07-02 15:31:33 +0000
commit7ca58ce114b4eafb2bb05d9e9699fe9effd8d9ec (patch)
tree867dd58fa56063c6afc6e4a8035dd1df27f71d54 /source3/namework.c
parentee1db519411a969413e60a875812f9909f71d525 (diff)
downloadsamba-7ca58ce114b4eafb2bb05d9e9699fe9effd8d9ec.tar.gz
samba-7ca58ce114b4eafb2bb05d9e9699fe9effd8d9ec.tar.bz2
samba-7ca58ce114b4eafb2bb05d9e9699fe9effd8d9ec.zip
as a result of the writing of namework.doc, namework.c has been tidied up,
some bugs fixed / documented and some discrepancies noted down (in namework.c as well as namework.doc) namebrowse.c and namelogon.c contain functions that were inappropriately placed in namework.c. namebrowse.c contains browse sync queue management functions that were inappropriately placed in namedb.c the 'cmd_type' member of response_record has been renamed to 'state' because that more accurately reflects it purpose (not entirely. sigh). fixed a bug in nameserv.c that meant the previous version wouldn't compile. there's probably a bit more... lkcl (This used to be commit a66417ebe871a1c1366c395ea4c7099852975e65)
Diffstat (limited to 'source3/namework.c')
-rw-r--r--source3/namework.c516
1 files changed, 189 insertions, 327 deletions
diff --git a/source3/namework.c b/source3/namework.c
index f0fca0071e..7307ddce04 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -45,12 +45,6 @@ extern struct in_addr ipzero;
extern int workgroup_count; /* total number of workgroups we know about */
-/* this is our browse cache database */
-extern struct browse_cache_record *browserlist;
-
-/* this is our domain/workgroup/server database */
-extern struct interface *local_interfaces;
-
/* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist;
@@ -70,8 +64,6 @@ extern int updatecount;
extern time_t StartupTime;
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
-
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
@@ -106,6 +98,11 @@ tell a server to become a backup browser
**************************************************************************/
void tell_become_backup(void)
{
+ /* XXXX note: this function is currently unsuitable for use, as it
+ does not properly check that a server is in a fit state to become
+ a backup browser before asking it to be one.
+ */
+
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{
@@ -155,234 +152,6 @@ void tell_become_backup(void)
}
}
-/****************************************************************************
-find a server responsible for a workgroup, and sync browse lists
-**************************************************************************/
-static void start_sync_browse_entry(struct browse_cache_record *b)
-{
- struct subnet_record *d;
- struct work_record *work;
-
- if (!(d = find_subnet(b->ip))) return;
-
- /* only sync if we are the master */
- if (AM_MASTER(work)) {
-
- /* first check whether the group we intend to sync with exists. if it
- doesn't, the server must have died. o dear. */
-
- /* see response_netbios_packet() or expire_netbios_response_entries() */
- queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SYNC,
- b->group,0x20,0,0,
- False,False,b->ip);
- }
-
- b->synced = True;
-}
-
-
-/****************************************************************************
-search through browser list for an entry to sync with
-**************************************************************************/
-void do_browser_lists(void)
-{
- struct browse_cache_record *b;
- static time_t last = 0;
- time_t t = time(NULL);
-
- if (t-last < 20) return; /* don't do too many of these at once! */
- /* XXXX equally this period should not be too long
- the server may die in the intervening gap */
-
- last = t;
-
- /* pick any entry in the list, preferably one whose time is up */
- for (b = browserlist; b && b->next; b = b->next)
- {
- if (b->sync_time < t && b->synced == False) break;
- }
-
- if (b && !b->synced)
- {
- /* sync with the selected entry then remove some dead entries */
- start_sync_browse_entry(b);
- expire_browse_cache(t - 60);
- }
-
-}
-
-
-/****************************************************************************
-find a server responsible for a workgroup, and sync browse lists
-control ends up back here via response_name_query.
-**************************************************************************/
-void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
- int name_type,
- struct in_addr ip)
-{
- add_browser_entry(serv_name, name_type, work_name, 0, ip);
-
- if (cmd == NAME_QUERY_MST_SRV_CHK)
- {
- /* announce ourselves as a master browser to serv_name */
- do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
- 0x20, 0, ip);
- }
-}
-
-
-/****************************************************************************
- add the default workgroup into my domain
- **************************************************************************/
-void add_my_subnets(char *group)
-{
- struct interface *i;
-
- /* add or find domain on our local subnet, in the default workgroup */
-
- if (*group == '*') return;
-
- /* the coding choice is up to you, andrew: i can see why you don't want
- global access to the local_interfaces structure: so it can't get
- messed up! */
- for (i = local_interfaces; i; i = i->next)
- {
- add_subnet_entry(i->bcast,i->nmask,group, True, False);
- }
-}
-
-
-/****************************************************************************
- send a backup list response.
- **************************************************************************/
-static void send_backup_list(char *work_name, struct nmb_name *src_name,
- int info_count, int token, int info,
- int name_type, struct in_addr ip)
-{
- struct subnet_record *d;
- char outbuf[1024];
- char *p, *countptr, *nameptr;
- int count = 0;
- int i, j;
- char *theirname = src_name->name;
-
- DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
- work_name, inet_ntoa(ip),
- myname,0x20,theirname,0x0));
-
- if (name_type == 0x1d)
- {
- DEBUG(4,("master browsers: "));
- }
- else if (name_type == 0x1b)
- {
- DEBUG(4,("domain controllers: "));
- }
- else
- {
- DEBUG(0,("backup request for unknown type %0x\n", name_type));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
-
- CVAL(p,0) = 10; /* backup list response */
- p++;
-
- countptr = p; /* count pointer */
-
- SSVAL(p,1,token); /* sender's workgroup index representation */
- SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
- p += 5;
-
- nameptr = p;
-
- for (d = subnetlist; d; d = d->next)
- {
- struct work_record *work;
-
- for (work = d->workgrouplist; work; work = work->next)
- {
- struct server_record *s;
-
- if (!strequal(work->work_group, work_name)) continue;
-
- for (s = work->serverlist; s; s = s->next)
- {
- BOOL found = False;
- char *n;
-
- if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
-
- for (n = nameptr; n < p; n = skip_string(n, 1))
- {
- if (strequal(n, s->serv.name)) found = True;
- }
-
- if (found) continue; /* exclude names already added */
-
- /* workgroup request: include all backup browsers in the list */
- /* domain request: include all domain members in the list */
-
- if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
- (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
- {
- DEBUG(4, ("%s ", s->serv.name));
-
- count++;
- strcpy(p,s->serv.name);
- strupper(p);
- p = skip_string(p,1);
- }
- }
- }
- }
-
- if (count == 0)
- {
- DEBUG(4, ("none\n"));
- return;
- }
- else
- {
- DEBUG(4, (" - count %d\n", count));
- }
-
- CVAL(countptr,0) = count; /* total number of backup browsers found */
-
- {
- int len = PTR_DIFF(p, outbuf);
-
- for (i = 0; i < len; i+= 16)
- {
- DEBUG(4, ("%3x char ", i));
-
- for (j = 0; j < 16; j++)
- {
- unsigned char x = outbuf[i+j];
- if (x < 32 || x > 127) x = '.';
-
- if (i+j >= len) break;
- DEBUG(4, ("%c", x));
- }
-
- DEBUG(4, (" hex ", i));
-
- for (j = 0; j < 16; j++)
- {
- if (i+j >= len) break;
- DEBUG(4, (" %02x", outbuf[i+j]));
- }
-
- DEBUG(4, ("\n"));
- }
-
- }
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- myname,theirname,0x20,0,ip,*iface_ip(ip));
-}
-
/*******************************************************************
same context: scope. should check name_type as well, and makes sure
@@ -471,7 +240,16 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
if (same_context(dgram)) return;
- if (command == ANN_DomainAnnouncement) {
+ if (command == ANN_DomainAnnouncement) {
+ /* XXXX if we are a master browser for the workgroup work_name,
+ then there is a local subnet configuration problem. only
+ we should be sending out such domain announcements, because
+ as the master browser, that is our job.
+
+ stop being a master browser, and force an election. this will
+ sort out the network problem. hopefully.
+ */
+
work_name = name;
} else {
work_name = dgram->dest_name.name;
@@ -501,6 +279,14 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
tell_become_backup();
#endif
+ /* XXXX over-kill: i don't think we should really be doing this,
+ but it doesn't do much harm other than to add extra network
+ traffic. to be more precise, we should (possibly) only
+ sync browse lists with a host that sends an
+ ANN_LocalMasterAnnouncement or an ANN_DomainAnnouncement.
+ possibly.
+ */
+
/* get their browse list from them and add it to ours. */
add_browser_entry(serv_name,dgram->dest_name.name_type,
work->work_group,30,ip);
@@ -543,6 +329,12 @@ static void process_master_announce(struct packet_struct *p,char *buf)
we receive a list of servers, and we attempt to locate them all on
our local subnet, and sync browse lists with them on the workgroup
they are said to be in.
+
+ XXXX NOTE: this function is in overdrive. it should not really do
+ half of what it actually does (it should pick _one_ name from the
+ list received and sync with it at regular intervals, rather than
+ sync with them all only once!)
+
******************************************************************/
static void process_rcv_backup_list(struct packet_struct *p,char *buf)
{
@@ -570,7 +362,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
buf1, inet_ntoa(ip)));
/* XXXX assume name is a DNS name NOT a netbios name. a more complete
- approach is to use reply_name_query functionality to find the name */
+ approach is to use reply_name_query functionality to find the name */
back_ip = *interpret_addr2(buf1);
if (zero_ip(back_ip))
@@ -602,10 +394,143 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
}
}
+
+/****************************************************************************
+ send a backup list response.
+ **************************************************************************/
+static void send_backup_list(char *work_name, struct nmb_name *src_name,
+ int info_count, int token, int info,
+ int name_type, struct in_addr ip)
+{
+ struct subnet_record *d;
+ char outbuf[1024];
+ char *p, *countptr, *nameptr;
+ int count = 0;
+ int i, j;
+ char *theirname = src_name->name;
+
+ DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
+ work_name, inet_ntoa(ip),
+ myname,0x20,theirname,0x0));
+
+ if (name_type == 0x1d)
+ {
+ DEBUG(4,("master browsers: "));
+ }
+ else if (name_type == 0x1b)
+ {
+ DEBUG(4,("domain controllers: "));
+ }
+ else
+ {
+ DEBUG(0,("backup request for unknown type %0x\n", name_type));
+ return;
+ }
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+
+ CVAL(p,0) = ANN_GetBackupListResp; /* backup list response */
+ p++;
+
+ countptr = p; /* count pointer */
+
+ SSVAL(p,1,token); /* sender's workgroup index representation */
+ SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
+ p += 5;
+
+ nameptr = p;
+
+ for (d = subnetlist; d; d = d->next)
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ struct server_record *s;
+
+ if (!strequal(work->work_group, work_name)) continue;
+
+ for (s = work->serverlist; s; s = s->next)
+ {
+ BOOL found = False;
+ char *n;
+
+ if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
+
+ for (n = nameptr; n < p; n = skip_string(n, 1))
+ {
+ if (strequal(n, s->serv.name)) found = True;
+ }
+
+ if (found) continue; /* exclude names already added */
+
+ /* workgroup request: include all backup browsers in the list */
+ /* domain request: include all domain members in the list */
+
+ if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
+ (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
+ {
+ DEBUG(4, ("%s ", s->serv.name));
+
+ count++;
+ strcpy(p,s->serv.name);
+ strupper(p);
+ p = skip_string(p,1);
+ }
+ }
+ }
+ }
+
+ if (count == 0)
+ {
+ DEBUG(4, ("none\n"));
+ return;
+ }
+ else
+ {
+ DEBUG(4, (" - count %d\n", count));
+ }
+
+ CVAL(countptr,0) = count; /* total number of backup browsers found */
+
+ {
+ int len = PTR_DIFF(p, outbuf);
+
+ for (i = 0; i < len; i+= 16)
+ {
+ DEBUG(4, ("%3x char ", i));
+
+ for (j = 0; j < 16; j++)
+ {
+ unsigned char x = outbuf[i+j];
+ if (x < 32 || x > 127) x = '.';
+
+ if (i+j >= len) break;
+ DEBUG(4, ("%c", x));
+ }
+
+ DEBUG(4, (" hex ", i));
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i+j >= len) break;
+ DEBUG(4, (" %02x", outbuf[i+j]));
+ }
+
+ DEBUG(4, ("\n"));
+ }
+
+ }
+ send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ myname,theirname,0x20,0x0,ip,*iface_ip(ip));
+}
+
+
/*******************************************************************
process a send backup list request
- A client send a backup list request to ask for a list of servers on
+ A client sends a backup list request to ask for a list of servers on
the net that maintain server lists for a domain. A server is then
chosen from this list to send NetServerEnum commands to to list
available servers.
@@ -618,7 +543,7 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d;
+ struct subnet_record *d;
struct work_record *work;
int count = CVAL(buf,0);
@@ -658,7 +583,7 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
process a reset browser state
diagnostic packet:
- 0x1 - stop being a master browser
+ 0x1 - stop being a master browser and become a backup browser.
0x2 - discard browse lists, stop being a master browser, try again.
0x4 - stop being a master browser forever. no way. ain't gonna.
@@ -688,6 +613,10 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
}
}
+ /* XXXX documentation inconsistency: the above description does not
+ exactly tally with what is implemented for state & 0x2
+ */
+
/* totally delete all servers and start afresh */
if (state & 0x2)
{
@@ -730,12 +659,23 @@ static void process_announce_request(struct packet_struct *p,char *buf)
if (strequal(dgram->source_name.name,myname)) return;
+ /* XXXX BUG or FEATURE?: need to ensure that we are a member of
+ this workgroup before announcing, particularly as we only
+ respond on local interfaces anyway.
+
+ if (strequal(dgram->dest_name, lp_workgroup()) return; ???
+ */
+
if (!d) return;
if (!d->my_interface) return;
for (work = d->workgrouplist; work; work = work->next)
{
+ /* XXXX BUG: the destination name type should also be checked,
+ not just the name. e.g if the name is WORKGROUP(0x1d) then
+ we should only respond if we own that name */
+
if (strequal(dgram->dest_name.name,work->work_group))
{
work->needannounce = True;
@@ -745,89 +685,6 @@ static void process_announce_request(struct packet_struct *p,char *buf)
/****************************************************************************
- process a domain logon packet
- **************************************************************************/
-void process_logon_packet(struct packet_struct *p,char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d = find_subnet(ip);
- char *logname,*q;
- char *reply_name;
- BOOL add_slashes = False;
- pstring outbuf;
- int code,reply_code;
- struct work_record *work;
-
- if (!d) return;
-
- if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
- return;
-
- if (!lp_domain_logons()) {
- DEBUG(3,("No domain logons\n"));
- return;
- }
- if (!listening_name(work, &dgram->dest_name))
- {
- DEBUG(4,("Not listening to that domain\n"));
- return;
- }
-
- code = SVAL(buf,0);
- switch (code) {
- case 0:
- {
- char *machine = buf+2;
- char *user = skip_string(machine,1);
- logname = skip_string(user,1);
- reply_code = 6;
- reply_name = myname;
- add_slashes = True;
- DEBUG(3,("Domain login request from %s(%s) user=%s\n",
- machine,inet_ntoa(p->ip),user));
- }
- break;
- case 7:
- {
- char *machine = buf+2;
- logname = skip_string(machine,1);
- reply_code = 7;
- reply_name = lp_domain_controller();
- if (!*reply_name) {
- DEBUG(3,("No domain controller configured\n"));
- return;
- }
- DEBUG(3,("GETDC request from %s(%s)\n",
- machine,inet_ntoa(p->ip)));
- }
- break;
- default:
- DEBUG(3,("Unknown domain request %d\n",code));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- q = outbuf;
- SSVAL(q,0,reply_code);
- q += 2;
- if (add_slashes) {
- strcpy(q,"\\\\");
- q += 2;
- }
- StrnCpy(q,reply_name,16);
- strupper(q);
- q = skip_string(q,1);
- SSVAL(q,0,0xFFFF);
- q += 2;
-
- send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
- myname,&dgram->source_name.name[0],0x20,0,p->ip,
- *iface_ip(p->ip));
-}
-
-
-/****************************************************************************
depending on what announce has been made, we are only going to
accept certain types of name announce. XXXX untested code
@@ -988,11 +845,16 @@ void process_dgram(struct packet_struct *p)
if (len <= 0) return;
- if (strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
- {
+ /* datagram packet received for the browser mailslot */
+ if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
process_browse_packet(p,buf2,len);
- } else if (strequal(smb_buf(buf),"\\MAILSLOT\\NET\\NETLOGON")) {
+ 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;
}
}