Unix SMB/Netbios implementation.
Version 1.9.
NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1996
+ Copyright (C) Andrew Tridgell 1994-1997
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
extern BOOL CanRecurse;
extern pstring myname;
+extern fstring myworkgroup;
extern int ClientNMB;
extern int ClientDGRAM;
/* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist;
-/* machine comment for host announcements */
-extern pstring ServerComment;
-
extern int updatecount;
-/* what server type are we currently */
-#define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \
- SV_TYPE_TIME_SOURCE | SV_TYPE_SERVER_UNIX |\
- SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER)
-
/* backup request types: which servers are to be included */
#define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
#define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL )
DEBUG(2,("sending reset to %s %s of state %d\n",
name,inet_ntoa(ip),state));
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,name,0x20,0x1d,ip,*iface_ip(ip));
}
*/
struct subnet_record *d;
- for (d = subnetlist; d; d = d->next)
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
num_servers++;
- if (strequal(myname, s->serv.name)) continue;
+ if (is_myname(s->serv.name)) continue;
if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
num_backups++;
BOOL same_context(struct dgram_packet *dgram)
{
if (!strequal(dgram->dest_name .scope,scope )) return(True);
- if ( strequal(dgram->source_name.name ,myname)) return(True);
-
- return(False);
-}
-
-
-/*******************************************************************
- am I listening on a name. XXXX check the type of name as well.
- ******************************************************************/
-BOOL listening_name(struct work_record *work, struct nmb_name *n)
-{
- if (strequal(n->name,myname) ||
- strequal(n->name,work->work_group) ||
- strequal(n->name,MSBROWSE))
- {
- return(True);
- }
+ if ( is_myname(dgram->source_name.name)) return(True);
return(False);
}
resources. We just have to pass it to smbd (via browser.dat) and let
the client choose using bit masks.
******************************************************************/
-static void process_announce(struct packet_struct *p,uint16 command,char *buf)
+static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
- struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d = find_subnet(ip);
+ struct subnet_record *d = find_subnet(p->ip); /* Explicitly exclude WINS - local nets only */
int update_count = CVAL(buf,0);
int ttl = IVAL(buf,1)/1000;
dgram->dest_name.name_type != 0x1))
{
DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
- command, inet_ntoa(ip), namestr(&dgram->dest_name)));
+ command, inet_ntoa(p->ip), namestr(&dgram->dest_name)));
return;
}
dgram->dest_name.name_type == 0x1e))
add = True;
+ DEBUG(4,("search for workgroup: %s (add? %s)\n",
+ work_name, BOOLSTR(add)));
+
if (!(work = find_workgroupstruct(d, work_name,add)))
return;
ttl = GET_TTL(ttl);
/* add them to our browse list, and update the browse.dat file */
- add_server_entry(d,work,name,servertype,ttl,comment,True);
+ add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
updatedlists = True;
#if 0
disabling it */
tell_become_backup();
#endif
-
- /* get the local_only browse list from the local master and add it
- to ours. */
- if (command == ANN_LocalMasterAnnouncement)
- {
- add_browser_entry(serv_name,dgram->dest_name.name_type,
- work->work_group,30,ip,True);
- }
}
/*******************************************************************
process a master announcement frame
+ Domain master browsers recieve these from local masters. The Domain
+ master should then issue a sync with the local master, asking for
+ that machines local server list.
******************************************************************/
static void process_master_announce(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 = find_subnet(ip);
- struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
char *name = buf;
struct work_record *work;
name[15] = 0;
- DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
+ DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
if (same_context(dgram)) return;
- if (!d || !mydomain) return;
+ if (!wins_subnet)
+ {
+ DEBUG(3,("process_master_announce: No wins subnet !\n"));
+ return;
+ }
- if (!lp_domain_master()) return;
+ if (!lp_domain_master())
+ {
+ DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n"));
+ return;
+ }
- for (work = mydomain->workgrouplist; work; work = work->next)
+ for (work = wins_subnet->workgrouplist; work; work = work->next)
{
- if (AM_MASTER(work))
+ if (AM_MASTER(work) || AM_DOMMST(work))
{
/* merge browse lists with them */
- add_browser_entry(name,0x1b, work->work_group,30,ip,True);
+ add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True);
}
}
}
static void process_rcv_backup_list(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
- struct in_addr ip = dgram->header.source_ip;
int count = CVAL(buf,0);
uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
char *buf1;
DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
- namestr(&dgram->dest_name), inet_ntoa(ip),
+ namestr(&dgram->dest_name), inet_ntoa(p->ip),
count, info));
if (same_context(dgram)) return;
for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
{
struct in_addr back_ip;
- struct subnet_record *d;
+ /* struct subnet_record *d; */
DEBUG(4,("Searching for backup browser %s at %s...\n",
- buf1, inet_ntoa(ip)));
+ buf1, inet_ntoa(p->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 */
DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
+#if 0
/* XXXX function needs work */
- continue;
+ continue;
if ((d = find_subnet(back_ip)))
{
}
}
}
+#endif
}
}
#if 0
- for (d = subnetlist; d; d = d->next)
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
{
struct work_record *work;
int len = PTR_DIFF(p, outbuf);
debug_browse_data(outbuf, len);
}
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,theirname,0x0,0x0,ip,*iface_ip(ip));
}
if (state & 0x1)
{
struct subnet_record *d;
- for (d = subnetlist; d; d = d->next)
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{
if (AM_MASTER(work))
{
- become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
+ unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
}
}
}
if (state & 0x2)
{
struct subnet_record *d;
- for (d = subnetlist; d; d = d->next)
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
{
struct work_record *work;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
}
- add_my_subnets(lp_workgroup());
+ add_my_subnets(myworkgroup);
}
/* stop browsing altogether. i don't think this is a good idea! */
struct dgram_packet *dgram = &p->packet.dgram;
struct work_record *work;
struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d = find_subnet(ip);
+ struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */
int token = CVAL(buf,0);
char *name = buf+1;
name[15] = 0;
- DEBUG(3,("Announce request from %s to %s token=0x%X\n",
+ DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n",
name,namestr(&dgram->dest_name), token));
- if (strequal(dgram->source_name.name,myname)) return;
+ if (is_myname(dgram->source_name.name)) 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 (strequal(dgram->dest_name, myworkgroup) return; ???
*/
- if (!d) return;
-
+ if (!d)
+ {
+ DEBUG(3,("process_announce_request: No local interface to announce to %s\n",
+ name));
+ return;
+ }
+
for (work = d->workgrouplist; work; work = work->next)
{
/* XXXX BUG: the destination name type should also be checked,
}
-/****************************************************************************
-depending on what announce has been made, we are only going to
-accept certain types of name announce. XXXX untested code
-
-check listening name type
-****************************************************************************/
-BOOL listening_type(struct packet_struct *p, int command)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int type = dgram->dest_name.name_type;
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- if (type != 0x0 || type != 0x20) return (False);
- break;
- }
-
- case ANN_AnnouncementRequest:
- {
- return (True);
- break;
- }
-
- case ANN_Election:
- {
- return (True);
- break;
- }
-
- case ANN_GetBackupListReq:
- {
- return (True);
- break;
- }
-
- case ANN_GetBackupListResp:
- {
- return (True);
- break;
- }
-
- case ANN_DomainAnnouncement:
- {
- if (type != 0x1b || type != 0x1c) return (False);
- break;
- }
-
- case ANN_MasterAnnouncement:
- {
- if (type != 0x1d) return (False);
- break;
- }
-
- case ANN_LocalMasterAnnouncement:
- {
- if (type != 0x1c || type != 0x1d) return (False);
- break;
- }
- }
- return (True); /* we're not dealing with unknown packet types */
-}
-
/****************************************************************************
process a browse frame
case ANN_LocalMasterAnnouncement:
{
debug_browse_data(buf, len);
- process_announce(p,command,buf+1);
+ process_localnet_announce(p,command,buf+1);
break;
}