summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h8
-rw-r--r--source3/namedb.c707
-rw-r--r--source3/namedbresp.doc2
-rw-r--r--source3/namedbsubnet.c9
-rw-r--r--source3/nameelect.c23
-rw-r--r--source3/nameelect.doc15
-rw-r--r--source3/nameresp.c28
-rw-r--r--source3/nameserv.c4
-rw-r--r--source3/nameserv.doc50
-rw-r--r--source3/nameservreply.c155
-rw-r--r--source3/nameservreply.doc79
-rw-r--r--source3/nameservresp.c70
-rw-r--r--source3/nameservresp.doc30
-rw-r--r--source3/smbd/ipc.c2
14 files changed, 241 insertions, 941 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index af5ed8bf41..2286b93a6d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -357,16 +357,18 @@ void add_my_names(void);
void remove_my_names();
void refresh_my_names(time_t t);
void query_refresh_names(void);
-void reply_name_release(struct packet_struct *p);
+void add_name_respond(struct subnet_record *d, int fd, uint16 response_id,
+ struct nmb_name *name,
+ int nb_flags, int ttl, struct in_addr register_ip,
+ BOOL new_owner, struct in_addr reply_to_ip);
void send_name_response(int fd,
int name_trn_id, int opcode, BOOL success, BOOL recurse,
struct nmb_name *reply_name, int nb_flags, int ttl,
struct in_addr ip);
+void reply_name_release(struct packet_struct *p);
void reply_name_reg(struct packet_struct *p);
void reply_name_status(struct packet_struct *p);
void reply_name_query(struct packet_struct *p);
-void response_name_release(struct subnet_record *d, struct packet_struct *p);
-void response_name_reg(struct subnet_record *d, struct packet_struct *p);
void response_netbios_packet(struct packet_struct *p);
void reset_server(char *name, int state, struct in_addr ip);
void tell_become_backup(void);
diff --git a/source3/namedb.c b/source3/namedb.c
deleted file mode 100644
index 96f64393c7..0000000000
--- a/source3/namedb.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1995
-
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- 14 jan 96: lkcl@pires.co.uk
- added multiple workgroup domain master support
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-
-extern int DEBUGLEVEL;
-
-extern time_t StartupTime;
-extern pstring myname;
-extern pstring scope;
-
-extern struct in_addr ipgrp;
-extern struct in_addr ipzero;
-
-/* local interfaces structure */
-extern struct interface *local_interfaces;
-
-/* remote interfaces structure */
-extern struct interface *remote_interfaces;
-
-/* this is our domain/workgroup/server database */
-struct subnet_record *subnetlist = NULL;
-
-static BOOL updatedlists = True;
-int updatecount=0;
-
-int workgroup_count = 0; /* unique index key: one for each workgroup */
-
-/* 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)
-
-
-/****************************************************************************
- add a workgroup into the domain list
- **************************************************************************/
-static void add_workgroup(struct work_record *work, struct subnet_record *d)
-{
- struct work_record *w2;
-
- if (!work || !d) return;
-
- if (!d->workgrouplist)
- {
- d->workgrouplist = work;
- work->prev = NULL;
- work->next = NULL;
- return;
- }
-
- for (w2 = d->workgrouplist; w2->next; w2 = w2->next);
-
- w2->next = work;
- work->next = NULL;
- work->prev = w2;
-}
-
-
-/****************************************************************************
- create a blank workgroup
- **************************************************************************/
-static struct work_record *make_workgroup(char *name)
-{
- struct work_record *work;
- struct subnet_record *d;
- int t = -1;
-
- if (!name || !name[0]) return NULL;
-
- work = (struct work_record *)malloc(sizeof(*work));
- if (!work) return(NULL);
-
- StrnCpy(work->work_group,name,sizeof(work->work_group)-1);
- work->serverlist = NULL;
-
- work->ServerType = DFLT_SERVER_TYPE;
- work->RunningElection = False;
- work->ElectionCount = 0;
- work->needelection = False;
- work->needannounce = True;
- work->state = MST_NONE;
-
- /* make sure all token representations of workgroups are unique */
-
- for (d = subnetlist; d && t == -1; d = d->next)
- {
- struct work_record *w;
- for (w = d->workgrouplist; w && t == -1; w = w->next)
- {
- if (strequal(w->work_group, work->work_group)) t = w->token;
- }
- }
-
- if (t == -1)
- {
- work->token = ++workgroup_count;
- }
- else
- {
- work->token = t;
- }
-
-
- /* WfWg uses 01040b01 */
- /* Win95 uses 01041501 */
- /* NTAS uses ???????? */
- work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
- work->ElectionCriterion |= (lp_os_level() << 24);
- if (lp_domain_master()) {
- work->ElectionCriterion |= 0x80;
- }
-
- return work;
-}
-
-
-/*******************************************************************
- expire old servers in the serverlist
- time of -1 indicates everybody dies
- ******************************************************************/
-void remove_old_servers(struct work_record *work, time_t t)
-{
- struct server_record *s;
- struct server_record *nexts;
-
- /* expire old entries in the serverlist */
- for (s = work->serverlist; s; s = nexts)
- {
- if (t == -1 || (s->death_time && s->death_time < t))
- {
- DEBUG(3,("Removing dead server %s\n",s->serv.name));
- updatedlists = True;
- nexts = s->next;
-
- if (s->prev) s->prev->next = s->next;
- if (s->next) s->next->prev = s->prev;
-
- if (work->serverlist == s)
- work->serverlist = s->next;
-
- free(s);
- }
- else
- {
- nexts = s->next;
- }
- }
-}
-
-
-/*******************************************************************
- remove workgroups
- ******************************************************************/
-struct work_record *remove_workgroup(struct subnet_record *d,
- struct work_record *work)
-{
- struct work_record *ret_work = NULL;
-
- if (!d || !work) return NULL;
-
- DEBUG(3,("Removing old workgroup %s\n", work->work_group));
-
- remove_old_servers(work, -1);
-
- ret_work = work->next;
-
- if (work->prev) work->prev->next = work->next;
- if (work->next) work->next->prev = work->prev;
-
- if (d->workgrouplist == work) d->workgrouplist = work->next;
-
- free(work);
-
- return ret_work;
-}
-
-
-/****************************************************************************
- add a domain into the list
- **************************************************************************/
-static void add_subnet(struct subnet_record *d)
-{
- struct subnet_record *d2;
-
- if (!subnetlist)
- {
- subnetlist = d;
- d->prev = NULL;
- d->next = NULL;
- return;
- }
-
- for (d2 = subnetlist; d2->next; d2 = d2->next);
-
- d2->next = d;
- d->next = NULL;
- d->prev = d2;
-}
-
-/***************************************************************************
- add a server into the list
- **************************************************************************/
-static void add_server(struct work_record *work,struct server_record *s)
-{
- struct server_record *s2;
-
- if (!work->serverlist) {
- work->serverlist = s;
- s->prev = NULL;
- s->next = NULL;
- return;
- }
-
- for (s2 = work->serverlist; s2->next; s2 = s2->next) ;
-
- s2->next = s;
- s->next = NULL;
- s->prev = s2;
-}
-
-
-/****************************************************************************
- find a workgroup in the workgrouplist
- only create it if the domain allows it, or the parameter 'add' insists
- that it get created/added anyway. this allows us to force entries in
- lmhosts file to be added.
- **************************************************************************/
-struct work_record *find_workgroupstruct(struct subnet_record *d,
- fstring name, BOOL add)
-{
- struct work_record *ret, *work;
-
- if (!d) return NULL;
-
- DEBUG(4, ("workgroup search for %s: ", name));
-
- if (strequal(name, "*"))
- {
- DEBUG(2,("add any workgroups: initiating browser search on %s\n",
- inet_ntoa(d->bcast_ip)));
- queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
- MSBROWSE,0x1,0,0,
- True,False, d->bcast_ip, d->bcast_ip);
- return NULL;
- }
-
- for (ret = d->workgrouplist; ret; ret = ret->next) {
- if (!strcmp(ret->work_group,name)) {
- DEBUG(4, ("found\n"));
- return(ret);
- }
- }
-
- if (!add) {
- DEBUG(4, ("not found\n"));
- return NULL;
- }
-
- DEBUG(4,("not found: creating\n"));
-
- if ((work = make_workgroup(name)))
- {
- if (lp_preferred_master() &&
- strequal(lp_workgroup(), name) &&
- d->my_interface)
- {
- DEBUG(3, ("preferred master startup for %s\n", work->work_group));
- work->needelection = True;
- work->ElectionCriterion |= (1<<3);
- }
- if (!d->my_interface)
- {
- work->needelection = False;
- }
- add_workgroup(work, d);
- return(work);
- }
- return NULL;
-}
-
-/****************************************************************************
- find a subnet in the subnetlist
- **************************************************************************/
-struct subnet_record *find_subnet(struct in_addr bcast_ip)
-{
- struct subnet_record *d;
- struct in_addr wins_ip = ipgrp;
-
- /* search through subnet list for broadcast/netmask that matches
- the source ip address. a subnet 255.255.255.255 represents the
- WINS list. */
-
- for (d = subnetlist; d; d = d->next)
- {
- if (ip_equal(bcast_ip, wins_ip))
- {
- if (ip_equal(bcast_ip, d->bcast_ip))
- {
- return d;
- }
- }
- else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
- {
- return(d);
- }
- }
-
- return (NULL);
-}
-
-
-/****************************************************************************
- dump a copy of the workgroup/domain database
- **************************************************************************/
-void dump_workgroups(void)
-{
- struct subnet_record *d;
-
- for (d = subnetlist; d; d = d->next)
- {
- if (d->workgrouplist)
- {
- struct work_record *work;
-
- DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip)));
- DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip)));
-
- for (work = d->workgrouplist; work; work = work->next)
- {
- DEBUG(4,("\t%s(%d)\n", work->work_group, work->token));
- if (work->serverlist)
- {
- struct server_record *s;
- for (s = work->serverlist; s; s = s->next)
- {
- DEBUG(4,("\t\t%s %8x (%s)\n",
- s->serv.name, s->serv.type, s->serv.comment));
- }
- }
- }
- }
- }
-}
-
-/****************************************************************************
- create a domain entry
- ****************************************************************************/
-static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip)
-{
- struct subnet_record *d;
- d = (struct subnet_record *)malloc(sizeof(*d));
-
- if (!d) return(NULL);
-
- bzero((char *)d,sizeof(*d));
-
- DEBUG(4, ("making domain %s ", inet_ntoa(bcast_ip)));
- DEBUG(4, ("%s\n", inet_ntoa(mask_ip)));
-
- d->bcast_ip = bcast_ip;
- d->mask_ip = mask_ip;
- d->workgrouplist = NULL;
- d->my_interface = False; /* True iff the interface is on the samba host */
-
- add_subnet(d);
-
- return d;
-}
-
-
-/****************************************************************************
- add the remote interfaces from lp_remote_interfaces() and lp_interfaces()
- to the netbios subnet database.
- ****************************************************************************/
-void add_subnet_interfaces(void)
-{
- struct interface *i;
-
- /* loop on all local interfaces */
- for (i = local_interfaces; i; i = i->next)
- {
- /* add the interface into our subnet database */
- if (!find_subnet(i->bcast))
- {
- struct subnet_record *d = make_subnet(i->bcast,i->nmask);
- if (d)
- {
- /* short-cut method to identifying local interfaces */
- d->my_interface = True;
- }
- }
- }
-
- /* loop on all remote interfaces */
- for (i = remote_interfaces; i; i = i->next)
- {
- /* add the interface into our subnet database */
- if (!find_subnet(i->bcast))
- {
- make_subnet(i->bcast,i->nmask);
- }
- }
-
- /* add the pseudo-ip interface for WINS: 255.255.255.255 */
- if (lp_wins_support())
- {
- struct in_addr wins_bcast = ipgrp;
- struct in_addr wins_nmask = ipzero;
- make_subnet(wins_bcast, wins_nmask);
- }
-}
-
-
-/****************************************************************************
- add a domain entry. creates a workgroup, if necessary, and adds the domain
- to the named a workgroup.
- ****************************************************************************/
-struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
- struct in_addr mask_ip,
- char *name, BOOL add, BOOL lmhosts)
-{
- struct subnet_record *d;
-
- /* XXXX andrew: struct in_addr ip appears not to be referenced at all except
- in the DEBUG comment. i assume that the DEBUG comment below actually
- intends to refer to bcast_ip? i don't know.
-
- struct in_addr ip = ipgrp;
-
- */
-
- if (zero_ip(bcast_ip))
- bcast_ip = *iface_bcast(bcast_ip);
-
- /* add the domain into our domain database */
- if ((d = find_subnet(bcast_ip)) ||
- (d = make_subnet(bcast_ip, mask_ip)))
- {
- struct work_record *w = find_workgroupstruct(d, name, add);
- extern pstring ServerComment;
-
- if (!w) return NULL;
-
- /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database
- or register with WINS server, if it's our workgroup */
- if (strequal(lp_workgroup(), name) && d->my_interface)
- {
- add_my_name_entry(d,name,0x1e,NB_ACTIVE|NB_GROUP);
- add_my_name_entry(d,name,0x0 ,NB_ACTIVE|NB_GROUP);
- }
- /* add samba server name to workgroup list */
- if ((strequal(lp_workgroup(), name) && d->my_interface) || lmhosts)
- {
- add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True);
- }
-
- DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(bcast_ip)));
- return d;
- }
- return NULL;
-}
-
-/****************************************************************************
- 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);
- }
- }
- }
-}
-
-
-/****************************************************************************
- add a server entry
- ****************************************************************************/
-struct server_record *add_server_entry(struct subnet_record *d,
- struct work_record *work,
- char *name,int servertype,
- int ttl,char *comment,
- BOOL replace)
-{
- BOOL newentry=False;
- struct server_record *s;
-
- if (name[0] == '*')
- {
- return (NULL);
- }
-
- for (s = work->serverlist; s; s = s->next)
- {
- if (strequal(name,s->serv.name)) break;
- }
-
- if (s && !replace)
- {
- DEBUG(4,("Not replacing %s\n",name));
- return(s);
- }
-
- if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
- updatedlists=True;
-
- if (!s)
- {
- newentry = True;
- s = (struct server_record *)malloc(sizeof(*s));
-
- if (!s) return(NULL);
-
- bzero((char *)s,sizeof(*s));
- }
-
-
- if (d->my_interface && strequal(lp_workgroup(),work->work_group))
- {
- if (servertype)
- servertype |= SV_TYPE_LOCAL_LIST_ONLY;
- }
- else
- {
- servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
- }
-
- /* update the entry */
- StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
- StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
- strupper(s->serv.name);
- s->serv.type = servertype;
- s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
-
- /* for a domain entry, the comment field refers to the server name */
-
- if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
-
- if (newentry)
- {
- add_server(work, s);
-
- DEBUG(3,("Added "));
- }
- else
- {
- DEBUG(3,("Updated "));
- }
-
- DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
- name,servertype,comment,
- work->work_group,inet_ntoa(d->bcast_ip)));
-
- return(s);
-}
-
-
-/****************************************************************************
- 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);
- }
-}
-
-
-/*******************************************************************
- write out browse.dat
- ******************************************************************/
-void write_browse_list(void)
-{
- struct subnet_record *d;
-
- pstring fname,fnamenew;
- FILE *f;
-
- if (!updatedlists) return;
-
- dump_names();
- dump_workgroups();
-
- updatedlists = False;
- updatecount++;
-
- strcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,SERVER_LIST);
- strcpy(fnamenew,fname);
- strcat(fnamenew,".");
-
- f = fopen(fnamenew,"w");
-
- if (!f)
- {
- DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
- return;
- }
-
- 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)
- {
- fstring tmp;
-
- /* don't list domains I don't have a master for */
- if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0])
- {
- continue;
- }
-
- /* output server details, plus what workgroup/domain
- they're in. without the domain information, the
- combined list of all servers in all workgroups gets
- sent to anyone asking about any workgroup! */
-
- sprintf(tmp, "\"%s\"", s->serv.name);
- fprintf(f, "%-25s ", tmp);
- fprintf(f, "%08x ", s->serv.type);
- sprintf(tmp, "\"%s\" ", s->serv.comment);
- fprintf(f, "%-30s", tmp);
- fprintf(f, "\"%s\"\n", work->work_group);
- }
- }
- }
-
- fclose(f);
- unlink(fname);
- chmod(fnamenew,0644);
- rename(fnamenew,fname);
- DEBUG(3,("Wrote browse list %s\n",fname));
-}
-
-
-/*******************************************************************
- expire old servers in the serverlist
- ******************************************************************/
-void expire_servers(time_t t)
-{
- struct subnet_record *d;
-
- for (d = subnetlist ; d ; d = d->next)
- {
- struct work_record *work;
-
- for (work = d->workgrouplist; work; work = work->next)
- {
- remove_old_servers(work, t);
- }
- }
-}
-
diff --git a/source3/namedbresp.doc b/source3/namedbresp.doc
index 68db43aec2..66f5a22124 100644
--- a/source3/namedbresp.doc
+++ b/source3/namedbresp.doc
@@ -22,7 +22,7 @@ the response to come from.
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.
+the number of retries is set to 3, 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.
diff --git a/source3/namedbsubnet.c b/source3/namedbsubnet.c
index 6b187b21bb..dd26592e66 100644
--- a/source3/namedbsubnet.c
+++ b/source3/namedbsubnet.c
@@ -253,13 +253,16 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
add_my_name_entry(d,name,0x1e,NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,name,0x0 ,NB_ACTIVE|NB_GROUP);
}
- /* add samba server name to workgroup list */
- if ((strequal(lp_workgroup(), name) && d->my_interface) || lmhosts)
+ /* add samba server name to workgroup list. don't add
+ lmhosts server entries to local interfaces */
+ if ((strequal(lp_workgroup(), name) && d->my_interface) ||
+ (lmhosts && !d->my_interface))
{
add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True);
+ DEBUG(3,("Added server name entry %s at %s\n",
+ name,inet_ntoa(bcast_ip)));
}
- DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(bcast_ip)));
return d;
}
return NULL;
diff --git a/source3/nameelect.c b/source3/nameelect.c
index e115b0d881..ba66f41a91 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -255,6 +255,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
{
case MST_NONE: /* while we were nothing but a server... */
{
+ DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
work->state = MST_WON; /* ... an election win was successful */
work->ElectionCriterion |= 0x5;
@@ -263,29 +264,29 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
- DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
-
/* add special browser name */
add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
- break;
+ /* DON'T do anything else after calling add_my_name_entry() */
+ return;
}
case MST_WON: /* while nothing had happened except we won an election... */
{
+ DEBUG(3,("go to second stage: register as master browser\n"));
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);
- DEBUG(3,("go to second stage: register as master browser\n"));
-
/* add master name */
add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
- break;
+ /* DON'T do anything else after calling add_my_name_entry() */
+ return;
}
case MST_MSB: /* while we were still only registered MSBROWSE state... */
{
+ DEBUG(3,("2nd stage complete: registered as master browser\n"));
work->state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
/* update our server status */
@@ -301,8 +302,12 @@ void become_master(struct subnet_record *d, struct work_record *work)
if (lp_domain_master())
{
DEBUG(3,("third stage: register as domain master\n"));
+
/* add domain master name */
add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ return;
}
else
{
@@ -313,11 +318,12 @@ void become_master(struct subnet_record *d, struct work_record *work)
}
case MST_BROWSER: /* while we were still a master browser... */
{
- work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */
-
/* update our server status */
if (lp_domain_master())
{
+ DEBUG(3,("fourth stage: samba is now a domain master.\n"));
+ work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */
+
work->ServerType |= SV_TYPE_DOMAIN_MASTER;
if (lp_domain_logons())
@@ -325,7 +331,6 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->ServerType |= SV_TYPE_DOMAIN_CTRL;
work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
}
- DEBUG(3,("fourth stage: samba is now a domain master.\n"));
add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
}
diff --git a/source3/nameelect.doc b/source3/nameelect.doc
index b8e6b56ad9..c03f044541 100644
--- a/source3/nameelect.doc
+++ b/source3/nameelect.doc
@@ -180,10 +180,17 @@ 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.
+if it's a local subnet and not one of samba's workgroups, then
+samba will force an election (which it is not obliged to do).
+remove_workgroup() will be expected to remove all references
+to this workgroup and the servers in it from the database.
+
+if it's a remote subnet and not one of samba's workgroups then
+no election is forced, and remove_workgroup() will be expected
+to remove all server entries from this workgroup _except_ those
+added from the lmhosts file. if there are entries added from
+the lmhosts file, then the workgroup entry will remain,
+otherwise it too will be removed.
/*************************************************************************
diff --git a/source3/nameresp.c b/source3/nameresp.c
index 3a9d46bf9d..f87088dffa 100644
--- a/source3/nameresp.c
+++ b/source3/nameresp.c
@@ -113,15 +113,18 @@ static void dead_netbios_entry(struct subnet_record *d,
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);
+ add_name_respond(d,n->fd, n->response_id ,&n->name,
+ n->nb_flags, GET_TTL(0),
+ n->reply_to_ip, False, n->reply_to_ip);
- 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;
+ if (!n->bcast)
+ {
+ DEBUG(1,("WINS server did not respond to name registration!\n"));
+ /* XXXX whoops. we have problems. must deal with this */
+ }
+ break;
}
+
case NAME_REGISTER:
{
/* if no response received, and we are using a broadcast registration
@@ -141,14 +144,13 @@ static void dead_netbios_entry(struct subnet_record *d,
}
else
{
- /* XXXX oops. this is where i wish this code could retry DGRAM
- packets. we directed a name registration at a WINS server, and
- received no response. rfc1001.txt states that after retrying,
+ /* received no response. rfc1001.txt states that after retrying,
we should assume the WINS server is dead, and fall back to
- broadcasting. */
+ broadcasting (see bits about M nodes: can't find any right
+ now) */
- DEBUG(1,("WINS server did not respond to name registration!\n"));
- /* XXXX whoops. we have problems. must deal with this */
+ DEBUG(1,("WINS server did not respond to name registration!\n"));
+ /* XXXX whoops. we have problems. must deal with this */
}
break;
}
diff --git a/source3/nameserv.c b/source3/nameserv.c
index 9fc578d009..371f12e011 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -141,8 +141,8 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
actually be true
*/
- add_netbios_entry(d,name,type,nb_flags,0,
- SELF,ipzero,False,lp_wins_support());
+ /* this will call add_netbios_entry() */
+ name_register_work(d, name, type, nb_flags,0, ipzero, False);
}
else
{
diff --git a/source3/nameserv.doc b/source3/nameserv.doc
index 8cb2bbc53d..71e5c980c6 100644
--- a/source3/nameserv.doc
+++ b/source3/nameserv.doc
@@ -62,12 +62,33 @@ if samba is using one.
if the name is already in samba's database, then it is re-registered,
otherwise it is simply registered.
-if samba registers its name with another WINS server, then the function
-response_name_reg() is responsible for updating samba's name database
-to reflect the claim or otherwise of the name.
+if the name is being registered in a WINS capacity (the subnet to which
+the name should be added is the WINS pseudo-subnet) then we add the entry
+immediately if samba is a WINS server. it uses name_register_work()
+because if the name is being added as part of becoming a master browser,
+we want to carry on that process. if the name is registered with another
+WINS server, we must wait for an answer from that WINS server. either
+name_register_work() or name_unregister_work() will be called as a result.
-expire_netbios_response_entries() is responsible for taking further action
-if no response to the registration is received.
+if the name is being registered on a local subnet, then it is
+broadcast. an explicit rejection from another host will result
+in name_unregister_work() being called. no response will, after
+retrying, result in name_register_work() being called.
+
+what ever method is used, the name will either be registered
+or rejected, and what ever process was taking place (becoming
+a master browser for example) will carry on.
+
+expire_netbios_response_entries() is responsible for taking further
+action if no response to the registration is received.
+
+note that there may be a large number of function calls on the
+stack if become_master() is called and samba is configured as
+a WINS server. the loop will be:
+
+become_master(), add_my_name_entry(), name_register_work() and
+back to become_master() with the new value of the workgroup
+'state'.
/*************************************************************************
@@ -78,9 +99,22 @@ this function is responsible for removing a NetBIOS name. if the name
being removed is registered on a local subnet, a name release should be
broadcast on the local subnet.
-if samba has registered the name with a WINS server, it must send a
-name release to the WINS server it is using. once it receives a reply,
-it can proceed (see response_name_rel())
+if the name is being released in a WINS capacity (the subnet to
+which the name should be added is the WINS pseudo-subnet) then we
+remove the entry immediately if samba is a WINS server. it uses
+name_unregister_work() because if the name is being added as part of
+becoming a master browser, we want to terminate that process. if the
+name is released from another WINS server, we must wait for an
+answer from that WINS server. name_unregister_work() will
+definitely be called as a result, because at present we ignore
+negative responses for a name release from a WINS server.
+
+if the name is being releasedd on a local subnet, then it is
+broadcast. name_unregister_work() will definitely be called
+because we ignore negative name releases at present.
+
+what ever method is used, the name will be released. (NOT TRUE!
+see response_name_release())
expire_netbios_response_entries() is responsible for taking further action
if no response to the name release is received.
diff --git a/source3/nameservreply.c b/source3/nameservreply.c
index cd26be5a8b..6501bded68 100644
--- a/source3/nameservreply.c
+++ b/source3/nameservreply.c
@@ -40,56 +40,23 @@ extern struct in_addr ipgrp;
/****************************************************************************
-reply to a name release
-****************************************************************************/
-void reply_name_release(struct packet_struct *p)
+ add a netbios entry. respond to the (possibly new) owner.
+ **************************************************************************/
+void add_name_respond(struct subnet_record *d, int fd, uint16 response_id,
+ struct nmb_name *name,
+ int nb_flags, int ttl, struct in_addr register_ip,
+ BOOL new_owner, struct in_addr reply_to_ip)
{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct in_addr ip;
- int nb_flags = nmb->additional->rdata[0];
- BOOL bcast = nmb->header.nm_flags.bcast;
- struct name_record *n;
- struct subnet_record *d = NULL;
- int search = 0;
-
- putip((char *)&ip,&nmb->additional->rdata[2]);
-
- DEBUG(3,("Name release on name %s\n",
- namestr(&nmb->question.question_name)));
-
- if (!(d = find_req_subnet(p->ip, bcast)))
- {
- DEBUG(3,("response packet: bcast %s not known\n",
- inet_ntoa(p->ip)));
- return;
- }
-
- if (bcast)
- search &= FIND_LOCAL;
- else
- search &= FIND_WINS;
-
- n = find_name_search(&d, &nmb->question.question_name,
- search, ip);
-
- /* XXXX under what conditions should we reject the removal?? */
- if (n && n->nb_flags == nb_flags)
- {
- /* success = True; */
-
- remove_name(d,n);
- n = NULL;
- }
-
- if (bcast) return;
-
- /* Send a NAME RELEASE RESPONSE */
- send_name_response(p->fd, nmb->header.name_trn_id, NMB_REL,
- True, False,
- &nmb->question.question_name, nb_flags, 0, ip);
+ /* register the old or the new owners' ip */
+ add_netbios_entry(d,name->name,name->name_type,
+ nb_flags,ttl,REGISTER,register_ip,False,True);
+
+ /* reply yes or no to the host that requested the name */
+ send_name_response(fd, response_id, NMB_REG,
+ new_owner, True,
+ name, nb_flags, ttl, reply_to_ip);
}
-
/****************************************************************************
send a registration / release response: pos/neg
**************************************************************************/
@@ -133,6 +100,58 @@ void send_name_response(int fd,
/****************************************************************************
+reply to a name release
+****************************************************************************/
+void reply_name_release(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct in_addr ip;
+ int nb_flags = nmb->additional->rdata[0];
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ struct name_record *n;
+ struct subnet_record *d = NULL;
+ int search = 0;
+ BOOL success = False;
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ DEBUG(3,("Name release on name %s\n",
+ namestr(&nmb->question.question_name)));
+
+ if (!(d = find_req_subnet(p->ip, bcast)))
+ {
+ DEBUG(3,("response packet: bcast %s not known\n",
+ inet_ntoa(p->ip)));
+ return;
+ }
+
+ if (bcast)
+ search &= FIND_LOCAL;
+ else
+ search &= FIND_WINS;
+
+ n = find_name_search(&d, &nmb->question.question_name,
+ search, ip);
+
+ /* XXXX under what conditions should we reject the removal?? */
+ if (n && n->nb_flags == nb_flags)
+ {
+ success = True;
+
+ remove_name(d,n);
+ n = NULL;
+ }
+
+ if (bcast) return;
+
+ /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
+ send_name_response(p->fd, nmb->header.name_trn_id, NMB_REL,
+ success, False,
+ &nmb->question.question_name, nb_flags, 0, ip);
+}
+
+
+/****************************************************************************
reply to a reg request
**************************************************************************/
void reply_name_reg(struct packet_struct *p)
@@ -156,10 +175,6 @@ void reply_name_reg(struct packet_struct *p)
BOOL success = True;
BOOL secured_redirect = False;
- BOOL recurse = True; /* true if samba replies yes/no: false if caller
- must challenge the current owner of the unique
- name: applies to non-secured WINS server only
- */
struct in_addr ip, from_ip;
int search = 0;
@@ -205,38 +220,6 @@ void reply_name_reg(struct packet_struct *p)
}
else if(!ip_equal(ip, n->ip))
{
-#if 0
- /* hm. this unique name doesn't belong to them. */
-
- /* XXXX rfc1001.txt says:
- * if we are doing non-secured WINS (which is much simpler) then
- * we send a message to the person wanting the name saying 'he
- * owns this name: i don't want to hear from you ever again
- * until you've checked with him if you can have it!'. we then
- * abandon the registration. once the person wanting the name
- * has checked with the current owner, they will repeat the
- * registration packet if the current owner is dead or doesn't
- * want the name.
- */
-
- /* non-secured WINS implementation: caller is responsible
- for checking with current owner of name, then getting back
- to us... IF current owner no longer owns the unique name */
-
- /* XXXX please note also that samba cannot cope with
- _receiving_ such redirecting, non-secured registration
- packets. code to do this needs to be added.
- */
-
- secured_redirect = False;
- success = False;
- recurse = False;
-
- /* we inform on the current owner to the caller (which is
- why it's non-secure */
-
- reply_name = &n->name;
-#else
/* XXXX rfc1001.txt says:
* if we are doing secured WINS, we must send a Wait-Acknowledge
* packet (WACK) to the person who wants the name, then do a
@@ -246,12 +229,8 @@ void reply_name_reg(struct packet_struct *p)
*/
secured_redirect = True;
- recurse = False;
reply_name = &n->name;
-
-#endif /* 0 */
-
}
else
{
@@ -324,7 +303,7 @@ void reply_name_reg(struct packet_struct *p)
*/
send_name_response(p->fd, nmb->header.name_trn_id, NMB_REG,
- success, recurse,
+ success, True,
reply_name, nb_flags, ttl, ip);
}
}
diff --git a/source3/nameservreply.doc b/source3/nameservreply.doc
index aeb3d29f17..56a5d160f6 100644
--- a/source3/nameservreply.doc
+++ b/source3/nameservreply.doc
@@ -26,13 +26,15 @@ 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.
+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 packet
-received is a point-to-point (unicast), then the WINS database
-is included in the search.
+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 search is not in the WINS database, then we need to find the
+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.
@@ -100,7 +102,8 @@ 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.
+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
@@ -116,54 +119,21 @@ 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
+name registrations by broadcast is implicit), samba will send either 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.
-
+REGISTRATION RESPONSE 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()
*************************************************************************/
@@ -187,3 +157,30 @@ 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.
+
+/*************************************************************************
+ send_name_response()
+ *************************************************************************/
+
+this function is a wrap around reply_netbios_packet(). it sends
+a response to a name registration or release packet, minimising
+the function parameters needed to do this.
+
+if the function is called with the parameter 'success' set to
+True, then a positive response (to the registration or release)
+is made (see rfc1002.txt 4.2.5 and 4.2.10). if this parameter
+is False, then a negative response is issued (see rfc1002.txt
+4.2.6 and 4.2.11)
+
+if the function is called with a registration code, and the
+parameter 'recurse' is False, then an End-Node Challenge
+Registration response is issued (see rfc1002.txt 4.2.7)
+
+note: this function could also easily be used for name conflict
+demand (see rfc1002.txt 4.2.8).
+
+note: End-Node Challenge Registration response is only sent in
+non-secured NetBIOS Name Server implementations. samba now
+implements secured NetBIOS Name Server functionality (see
+rfc1001.txt 15.1.6).
+
diff --git a/source3/nameservresp.c b/source3/nameservresp.c
index dc7cc63c5a..e47afc55b3 100644
--- a/source3/nameservresp.c
+++ b/source3/nameservresp.c
@@ -46,7 +46,8 @@ extern struct in_addr ipzero;
response for a reg release received. samba has asked a WINS server if it
could release a name.
**************************************************************************/
-void response_name_release(struct subnet_record *d, struct packet_struct *p)
+static void response_name_release(struct subnet_record *d,
+ struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
char *name = nmb->question.question_name.name;
@@ -55,33 +56,42 @@ void response_name_release(struct subnet_record *d, struct packet_struct *p)
DEBUG(4,("response name release received\n"));
if (nmb->header.rcode == 0 && nmb->answers->rdata)
- {
- /* IMPORTANT: see expire_netbios_response_entries() */
+ {
+ /* IMPORTANT: see expire_netbios_response_entries() */
- struct in_addr found_ip;
- putip((char*)&found_ip,&nmb->answers->rdata[2]);
+ struct in_addr found_ip;
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
- if (ismyip(found_ip))
- {
- remove_netbios_name(d,name,type,SELF,found_ip);
- }
+ /* NOTE: we only release our own names at present */
+ if (ismyip(found_ip))
+ {
+ name_unregister_work(d,name,type);
}
- else
+ else
{
- DEBUG(2,("name release for %s rejected!\n",
+ DEBUG(2,("name release for different ip! %s %s\n",
+ inet_ntoa(found_ip),
+ namestr(&nmb->question.question_name)));
+ }
+ }
+ else
+ {
+ DEBUG(2,("name release for %s rejected!\n",
namestr(&nmb->question.question_name)));
- /* XXXX do we honestly care if our name release was rejected?
- only if samba is issuing the release on behalf of some out-of-sync
- server. if it's one of samba's SELF names, we don't care. */
- }
+ /* XXXX PANIC! what to do if it's one of samba's own names? */
+
+ /* XXXX do we honestly care if our name release was rejected?
+ only if samba is issuing the release on behalf of some out-of-sync
+ server. if it's one of samba's SELF names, we don't care. */
+ }
}
/****************************************************************************
response for a reg request received
**************************************************************************/
-void response_name_reg(struct subnet_record *d, struct packet_struct *p)
+static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
char *name = nmb->question.question_name.name;
@@ -92,25 +102,22 @@ void response_name_reg(struct subnet_record *d, struct packet_struct *p)
if (nmb->header.rcode == 0 && nmb->answers->rdata)
{
- /* IMPORTANT: see expire_netbios_response_entries() */
+ /* IMPORTANT: see expire_netbios_response_entries() */
- int nb_flags = nmb->answers->rdata[0];
- int ttl = nmb->answers->ttl;
- struct in_addr found_ip;
+ int nb_flags = nmb->answers->rdata[0];
+ int ttl = nmb->answers->ttl;
+ struct in_addr found_ip;
- putip((char*)&found_ip,&nmb->answers->rdata[2]);
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
- name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
+ name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
}
else
{
DEBUG(1,("name registration for %s rejected!\n",
namestr(&nmb->question.question_name)));
- /* XXXX oh dear. we have problems. must deal with our name having
- been rejected: e.g if it was our GROUP(1d) name, we must unbecome
- a master browser. */
-
+ /* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work(d,name,type);
}
}
@@ -332,14 +339,9 @@ static void response_name_query_register(struct nmb_packet *nmb,
}
/* register the old or the new owners' ip */
- add_netbios_entry(d, ans_name->name, ans_name->name_type,
- n->nb_flags,GET_TTL(0),REGISTER,
- register_ip,False,True);
-
- /* reply yes or no to the host that requested the name */
- send_name_response(n->fd, n->response_id, NMB_REG,
- new_owner, True,
- &n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip);
+ add_name_respond(d, n->fd, n->response_id,&n->name,n->nb_flags,
+ GET_TTL(0), register_ip,
+ new_owner, n->reply_to_ip);
}
diff --git a/source3/nameservresp.doc b/source3/nameservresp.doc
index 2f0d1912c8..f50f3a7c4f 100644
--- a/source3/nameservresp.doc
+++ b/source3/nameservresp.doc
@@ -2,6 +2,9 @@ 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)
+point of interest to design purists: every function in this
+module is static except response_netbios_packet().
+
/*************************************************************************
response_netbios_packet()
*************************************************************************/
@@ -62,33 +65,6 @@ 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()
*************************************************************************/
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 415c939bf3..0f00e3ec21 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -1013,7 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
int counted=0,total=0;
int i;
fstring domain;
- BOOL domains;
+ BOOL domains = False;
BOOL domain_request;
BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;