summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1997-10-17 23:08:07 +0000
committerJeremy Allison <jra@samba.org>1997-10-17 23:08:07 +0000
commitc336a2f08183f63031b0a08b2111669bc36a5f30 (patch)
treee6773bb1bbbde2c829a55ec608f270233f8a925f
parenta0a28db75365d974ee05aee9dd4fde1ffc3db72c (diff)
downloadsamba-c336a2f08183f63031b0a08b2111669bc36a5f30.tar.gz
samba-c336a2f08183f63031b0a08b2111669bc36a5f30.tar.bz2
samba-c336a2f08183f63031b0a08b2111669bc36a5f30.zip
.cvsignore: Added make_smbcodepage
interface.c: Added is_local_net(). locking.c: Added Fix for zero length share files from Gerald Werner <wernerg@mfldclin.edu> plus a race condition fix for the fix. nameannounce.c: Made function static. namedbresp.c: extern int ClientDGRAM removed - not used. namedbserver.c: extern int ClientDGRAM removed - not used. namedbsubnet.c: Added code to make sockets per subnet. namepacket.c: Added code to read from all sockets & filter. nameresp.c: extern int ClientDGRAM removed - not used. nameserv.c: Indentation tidyup :-). nameserv.h: Added sockets to struct subnet. nameservresp.c: Improved debug message. nmbd.c: Changed to terminte on listen_for_packets exiting. nmbsync.c: extern int ClientDGRAM & ClientNMB removed - not used. proto.h: The usual. util.c: Fixed debug message. Jeremy (jallison@whistle.com) (This used to be commit 6904c2de080b2a9702800e9e4126386ced20569d)
-rw-r--r--source3/.cvsignore1
-rw-r--r--source3/include/nameserv.h2
-rw-r--r--source3/include/proto.h17
-rw-r--r--source3/lib/interface.c12
-rw-r--r--source3/lib/util.c4
-rw-r--r--source3/locking/locking.c75
-rw-r--r--source3/nameannounce.c166
-rw-r--r--source3/namedbresp.c1
-rw-r--r--source3/namedbserver.c1
-rw-r--r--source3/namedbsubnet.c67
-rw-r--r--source3/namepacket.c238
-rw-r--r--source3/nameresp.c1
-rw-r--r--source3/nameserv.c70
-rw-r--r--source3/nameservresp.c3
-rw-r--r--source3/nmbd/nmbd.c29
-rw-r--r--source3/nmbsync.c3
16 files changed, 454 insertions, 236 deletions
diff --git a/source3/.cvsignore b/source3/.cvsignore
index 9b7ea034be..f6b77ee2f9 100644
--- a/source3/.cvsignore
+++ b/source3/.cvsignore
@@ -1,6 +1,7 @@
Makefile.RPM
makefile
makefile.sunos5
+make_smbcodepage
nmbd
nmblookup
smbclient
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index 81487e9ce9..ecd19b9563 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -291,6 +291,8 @@ struct subnet_record
struct in_addr bcast_ip;
struct in_addr mask_ip;
struct in_addr myip;
+ int nmb_sock; /* socket to listen for unicast 137. */
+ int dgram_sock; /* socket to listen for unicast 138. */
};
/* a resource record */
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 85ef094340..fa689d1c90 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -93,9 +93,9 @@ void CloseDir(void *p);
char *ReadDirName(void *p);
BOOL SeekDir(void *p,int pos);
int TellDir(void *p);
-void DirCacheAdd(char *path,char *name,char *dname,int snum);
-char *DirCacheCheck(char *path,char *name,int snum);
-void DirCacheFlush(int snum);
+void DirCacheAdd( char *path, char *name, char *dname, int snum );
+char *DirCacheCheck( char *path, char *name, int snum );
+void DirCacheFlush( int snum );
/*The following definitions come from fault.c */
@@ -111,6 +111,7 @@ void load_interfaces(void);
void iface_set_default(char *ip,char *bcast,char *nmask);
BOOL ismyip(struct in_addr ip);
BOOL ismybcast(struct in_addr bcast);
+BOOL is_local_net(struct in_addr from);
int iface_count(void);
struct in_addr *iface_n_ip(int n);
struct in_addr *iface_bcast(struct in_addr ip);
@@ -372,11 +373,6 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
int name_type,
struct subnet_record *d,
struct in_addr ip);
-void do_announce_host(int command,
- char *from_name, int from_type, struct in_addr from_ip,
- char *to_name , int to_type , struct in_addr to_ip,
- time_t announce_interval,
- char *server_name, int server_type, char *server_comment);
void announce_my_servers_removed(void);
void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type);
@@ -503,7 +499,7 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
char *data,int len);
void queue_packet(struct packet_struct *packet);
void run_packet_queue();
-void listen_for_packets(BOOL run_election);
+BOOL listen_for_packets(BOOL run_election);
BOOL send_mailslot_reply(BOOL unique, 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);
@@ -946,6 +942,9 @@ int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize);
int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize);
int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize);
+/*The following definitions come from ubi_dLinkList.c */
+
+
/*The following definitions come from ufc.c */
char *ufc_crypt(char *key,char *salt);
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 1dc605ff2f..c920cc0cfc 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -400,6 +400,18 @@ BOOL ismybcast(struct in_addr bcast)
}
/****************************************************************************
+ check if a packet is from a local (known) net
+ **************************************************************************/
+BOOL is_local_net(struct in_addr from)
+{
+ struct interface *i;
+ for (i=local_interfaces;i;i=i->next)
+ if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
+ return True;
+ return False;
+}
+
+/****************************************************************************
how many interfaces do we have
**************************************************************************/
int iface_count(void)
diff --git a/source3/lib/util.c b/source3/lib/util.c
index a82713a0d8..b69b30d20c 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -3284,8 +3284,8 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
{
if (port) {
if (port == SMB_PORT || port == NMB_PORT)
- DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
- port,socket_addr,strerror(errno)));
+ DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
+ port,inet_ntoa(sock.sin_addr),strerror(errno)));
close(res);
if (dlevel > 0 && port < 1000)
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 5071121bed..bbc0c0033f 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -716,6 +716,31 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
}
/*******************************************************************
+Force a share file to be deleted.
+********************************************************************/
+
+static int delete_share_file( int cnum, char *fname )
+{
+ /* the share file could be owned by anyone, so do this as root */
+ become_root(False);
+
+ if(unlink(fname) != 0)
+ {
+ DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
+ fname, strerror(errno)));
+ }
+ else
+ {
+ DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
+ }
+
+ /* return to our previous privilage level */
+ unbecome_root(False);
+
+ return 0;
+}
+
+/*******************************************************************
lock a share mode file.
******************************************************************/
BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
@@ -820,6 +845,31 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok
{
int fd = (int)token;
int ret = True;
+ struct stat sb;
+ pstring fname;
+
+ /* Fix for zero length share files from
+ Gerald Werner <wernerg@mfldclin.edu> */
+
+ share_name(cnum, dev, inode, fname);
+
+ /* get the share mode file size */
+ if(fstat((int)token, &sb) != 0)
+ {
+ DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
+ fname, strerror(errno)));
+ sb.st_size = 1;
+ ret = False;
+ }
+
+ /* If the file was zero length, we must delete before
+ doing the unlock to avoid a race condition (see
+ the code in lock_share_mode_entry for details.
+ */
+
+ /* remove the share file if zero length */
+ if(sb.st_size == 0)
+ delete_share_file(cnum, fname);
/* token is the fd of the open share mode file. */
/* Unlock the first byte. */
@@ -835,31 +885,6 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok
}
/*******************************************************************
-Force a share file to be deleted.
-********************************************************************/
-
-static int delete_share_file( int cnum, char *fname )
-{
- /* the share file could be owned by anyone, so do this as root */
- become_root(False);
-
- if(unlink(fname) != 0)
- {
- DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
- fname, strerror(errno)));
- }
- else
- {
- DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
- }
-
- /* return to our previous privilage level */
- unbecome_root(False);
-
- return 0;
-}
-
-/*******************************************************************
Read a share file into a buffer.
********************************************************************/
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index d69ee32ddf..b8dcb71fff 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -67,7 +67,7 @@ void announce_request(struct work_record *work, struct in_addr ip)
work->needannounce = True;
DEBUG(2,("sending announce request to %s for workgroup %s\n",
- inet_ntoa(ip),work->work_group));
+ inet_ntoa(ip),work->work_group));
bzero(outbuf,sizeof(outbuf));
p = outbuf;
@@ -84,9 +84,9 @@ void announce_request(struct work_record *work, struct in_addr ip)
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(False, BROWSE_MAILSLOT,ClientDGRAM,
- outbuf,PTR_DIFF(p,outbuf),
- myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
+ send_mailslot_reply(False, BROWSE_MAILSLOT, ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
}
@@ -106,15 +106,15 @@ void do_announce_request(char *info, char *to_name, int announce_type,
p++;
DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n",
- announce_type, info, inet_ntoa(dest_ip),to_name,to));
+ announce_type, info, inet_ntoa(dest_ip),to_name,to));
StrnCpy(p,info,16);
strupper(p);
p = skip_string(p,1);
- send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
- outbuf,PTR_DIFF(p,outbuf),
- myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
+ send_mailslot_reply(False,BROWSE_MAILSLOT, ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
}
@@ -144,48 +144,48 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
/****************************************************************************
send a host announcement packet
**************************************************************************/
-void do_announce_host(int command,
+static void do_announce_host(int command,
char *from_name, int from_type, struct in_addr from_ip,
char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval,
char *server_name, int server_type, char *server_comment)
{
- pstring outbuf;
- char *p;
+ pstring outbuf;
+ char *p;
- bzero(outbuf,sizeof(outbuf));
- p = outbuf+1;
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf+1;
- /* command type */
- CVAL(outbuf,0) = command;
+ /* command type */
+ CVAL(outbuf,0) = command;
- /* announcement parameters */
- CVAL(p,0) = updatecount;
- SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
+ /* announcement parameters */
+ CVAL(p,0) = updatecount;
+ SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
- StrnCpy(p+5,server_name,16);
- strupper(p+5);
+ StrnCpy(p+5,server_name,16);
+ strupper(p+5);
- CVAL(p,21) = lp_major_announce_version(); /* major version */
- CVAL(p,22) = lp_minor_announce_version(); /* minor version */
+ CVAL(p,21) = lp_major_announce_version(); /* major version */
+ CVAL(p,22) = lp_minor_announce_version(); /* minor version */
- SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
- /* browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT)*/
- SSVAL(p,27,BROWSER_ELECTION_VERSION);
- SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */
+ SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
+ /* browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT)*/
+ SSVAL(p,27,BROWSER_ELECTION_VERSION);
+ SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */
- pstrcpy(p+31,server_comment);
- p += 31;
- p = skip_string(p,1);
+ pstrcpy(p+31,server_comment);
+ p += 31;
+ p = skip_string(p,1);
- debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+ debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
- /* send the announcement */
- send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf,
- PTR_DIFF(p,outbuf),
- from_name, to_name,
- from_type, to_type,
- to_ip, from_ip);
+ /* send the announcement */
+ send_mailslot_reply(False,BROWSE_MAILSLOT, ClientDGRAM, outbuf,
+ PTR_DIFF(p,outbuf),
+ from_name, to_name,
+ from_type, to_type,
+ to_ip, from_ip);
}
@@ -217,58 +217,58 @@ void announce_my_servers_removed(void)
void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type)
{
- /* domain type cannot have anything in it that might confuse
- a client into thinking that the domain is in fact a server.
- (SV_TYPE_SERVER_UNIX, for example)
- */
- uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
- BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip);
-
- if(wins_iface)
- {
- DEBUG(0,("announce_server: error - announcement requested on WINS \
+ /* domain type cannot have anything in it that might confuse
+ a client into thinking that the domain is in fact a server.
+ (SV_TYPE_SERVER_UNIX, for example)
+ */
+ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
+ BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip);
+
+ if(wins_iface)
+ {
+ DEBUG(0,("announce_server: error - announcement requested on WINS \
interface for workgroup %s, name %s\n", work->work_group, name));
- return;
- }
+ return;
+ }
- /* Only do domain announcements if we are a master and it's
- our name we're being asked to announce. */
- if (AM_MASTER(work) && strequal(myname,name))
- {
- DEBUG(3,("sending local master announce to %s for %s(1e)\n",
- inet_ntoa(d->bcast_ip),work->work_group));
+ /* Only do domain announcements if we are a master and it's
+ our name we're being asked to announce. */
+ if (AM_MASTER(work) && strequal(myname,name))
+ {
+ DEBUG(3,("sending local master announce to %s for %s(1e)\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
- do_announce_host(ANN_LocalMasterAnnouncement,
- name , 0x00, d->myip,
- work->work_group, 0x1e, d->bcast_ip,
- ttl,
- name, server_type, comment);
+ do_announce_host(ANN_LocalMasterAnnouncement,
+ name , 0x00, d->myip,
+ work->work_group, 0x1e, d->bcast_ip,
+ ttl,
+ name, server_type, comment);
- DEBUG(3,("sending domain announce to %s for %s\n",
- inet_ntoa(d->bcast_ip),work->work_group));
+ DEBUG(3,("sending domain announce to %s for %s\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
- /* XXXX should we do a domain-announce-kill? */
- if (server_type != 0)
- {
- do_announce_host(ANN_DomainAnnouncement,
- name , 0x00, d->myip,
- MSBROWSE, 0x01, d->bcast_ip,
- ttl,
- work->work_group, server_type ? domain_type : 0,
- name);
- }
- }
- else
- {
- DEBUG(3,("sending host announce to %s for %s(1d)\n",
- inet_ntoa(d->bcast_ip),work->work_group));
-
- do_announce_host(ANN_HostAnnouncement,
- name , 0x00, d->myip,
- work->work_group, 0x1d, d->bcast_ip,
- ttl,
- name, server_type, comment);
- }
+ /* XXXX should we do a domain-announce-kill? */
+ if (server_type != 0)
+ {
+ do_announce_host(ANN_DomainAnnouncement,
+ name , 0x00, d->myip,
+ MSBROWSE, 0x01, d->bcast_ip,
+ ttl,
+ work->work_group, server_type ? domain_type : 0,
+ name);
+ }
+ }
+ else
+ {
+ DEBUG(3,("sending host announce to %s for %s(1d)\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
+
+ do_announce_host(ANN_HostAnnouncement,
+ name , 0x00, d->myip,
+ work->work_group, 0x1d, d->bcast_ip,
+ ttl,
+ name, server_type, comment);
+ }
}
/****************************************************************************
diff --git a/source3/namedbresp.c b/source3/namedbresp.c
index c8a31a6c79..e9fe39c3d7 100644
--- a/source3/namedbresp.c
+++ b/source3/namedbresp.c
@@ -25,7 +25,6 @@
#include "includes.h"
extern int ClientNMB;
-extern int ClientDGRAM;
extern struct subnet_record *subnetlist;
diff --git a/source3/namedbserver.c b/source3/namedbserver.c
index 9223cb6ce6..7440b42494 100644
--- a/source3/namedbserver.c
+++ b/source3/namedbserver.c
@@ -32,7 +32,6 @@
#include "smb.h"
extern int ClientNMB;
-extern int ClientDGRAM;
extern int DEBUGLEVEL;
diff --git a/source3/namedbsubnet.c b/source3/namedbsubnet.c
index c6663d71fd..3597c32387 100644
--- a/source3/namedbsubnet.c
+++ b/source3/namedbsubnet.c
@@ -33,6 +33,7 @@
extern int ClientNMB;
extern int ClientDGRAM;
+extern int global_nmb_port;
extern int DEBUGLEVEL;
@@ -130,14 +131,60 @@ struct subnet_record *find_subnet_all(struct in_addr bcast_ip)
}
/****************************************************************************
- create a domain entry
+ create a subnet entry
****************************************************************************/
-static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip, BOOL add)
+static struct subnet_record *make_subnet(struct in_addr myip, struct in_addr bcast_ip,
+ struct in_addr mask_ip, BOOL add)
{
- struct subnet_record *d;
+ struct subnet_record *d = NULL;
+ int nmb_sock, dgram_sock;
+
+ /* Check if we are creating the WINS subnet - if so don't create
+ sockets, use the ClientNMB and ClientDGRAM sockets instead.
+ */
+
+ if(ip_equal(bcast_ip, wins_ip))
+ {
+ nmb_sock = -1;
+ dgram_sock = -1;
+ }
+ else
+ {
+ /*
+ * Attempt to open the sockets on port 137/138 for this interface
+ * and bind them.
+ * Fail the subnet creation if this fails.
+ */
+
+ if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr)) == -1)
+ {
+ DEBUG(0,("make_subnet: Failed to open nmb socket on interface %s \
+for port %d. Error was %s\n", inet_ntoa(myip), global_nmb_port, strerror(errno)));
+ return NULL;
+ }
+
+ if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1)
+ {
+ DEBUG(0,("make_subnet: Failed to open dgram socket on interface %s \
+for port %d. Error was %s\n", inet_ntoa(myip), DGRAM_PORT, strerror(errno)));
+ return NULL;
+ }
+
+ /* Make sure we can broadcast from these sockets. */
+ set_socket_options(nmb_sock,"SO_BROADCAST");
+ set_socket_options(dgram_sock,"SO_BROADCAST");
+
+ }
+
d = (struct subnet_record *)malloc(sizeof(*d));
- if (!d) return(NULL);
+ if (!d)
+ {
+ DEBUG(0,("make_subnet: malloc fail !\n"));
+ close(nmb_sock);
+ close(dgram_sock);
+ return(NULL);
+ }
bzero((char *)d,sizeof(*d));
@@ -146,6 +193,9 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr
d->bcast_ip = bcast_ip;
d->mask_ip = mask_ip;
+ d->myip = myip;
+ d->nmb_sock = nmb_sock;
+ d->dgram_sock = dgram_sock;
d->workgrouplist = NULL;
if(add)
@@ -158,7 +208,8 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr
add a domain entry. creates a workgroup, if necessary, and adds the domain
to the named a workgroup.
****************************************************************************/
-static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
+static struct subnet_record *add_subnet_entry(struct in_addr myip,
+ struct in_addr bcast_ip,
struct in_addr mask_ip, char *name,
BOOL create_subnets, BOOL add)
{
@@ -175,7 +226,7 @@ static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
if(create_subnets == True)
{
/* Create new subnets. */
- if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL)
+ if((d = make_subnet(myip, bcast_ip, mask_ip, add)) == NULL)
{
DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n",
inet_ntoa(bcast_ip) ));
@@ -265,7 +316,7 @@ void add_my_subnets(char *group)
*/
for (i = local_interfaces; i; i = i->next)
{
- add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True);
+ add_subnet_entry(i->ip, i->bcast,i->nmask,group, create_subnets, True);
}
/* If we are using WINS, then we must add the workgroup to the WINS
@@ -278,7 +329,7 @@ void add_my_subnets(char *group)
if (lp_wins_support() || lp_wins_server())
{
struct in_addr wins_nmask = ipzero;
- wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False);
+ wins_subnet = add_subnet_entry(ipzero, wins_ip, wins_nmask, group, create_subnets, False);
}
/* Ensure we only create the subnets once. */
diff --git a/source3/namepacket.c b/source3/namepacket.c
index 4a9f586a76..55c850f254 100644
--- a/source3/namepacket.c
+++ b/source3/namepacket.c
@@ -504,71 +504,197 @@ void run_packet_queue()
}
/****************************************************************************
+ Create an fd_set containing all the sockets in the subnet structures,
+ plus the broadcast sockets.
+ ***************************************************************************/
+
+static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number)
+{
+ int *sock_array = NULL;
+ struct subnet_record *d = NULL;
+ int count = 0;
+ int num = 0;
+ fd_set *pset = (fd_set *)malloc(sizeof(fd_set));
+
+ if(pset == NULL)
+ {
+ DEBUG(0,("create_listen_fdset: malloc fail !\n"));
+ return True;
+ }
+
+ /* Check that we can add all the fd's we need. */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ count++;
+
+ if((count*2) + 2 > FD_SETSIZE)
+ {
+ DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
+only use %d.\n", (count*2) + 2, FD_SETSIZE));
+ return True;
+ }
+
+ if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL)
+ {
+ DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
+ return True;
+ }
+
+ FD_ZERO(pset);
+
+ /* Add in the broadcast socket on 137. */
+ FD_SET(ClientNMB,pset);
+ sock_array[num++] = ClientNMB;
+
+ /* Add in the 137 sockets on all the interfaces. */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ FD_SET(d->nmb_sock,pset);
+ sock_array[num++] = d->nmb_sock;
+ }
+
+ /* Add in the broadcast socket on 138. */
+ FD_SET(ClientDGRAM,pset);
+ sock_array[num++] = ClientDGRAM;
+
+ /* Add in the 138 sockets on all the interfaces. */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ FD_SET(d->dgram_sock,pset);
+ sock_array[num++] = d->dgram_sock;
+ }
+
+ *listen_number = (count*2) + 2;
+ *ppset = pset;
+ *psock_array = sock_array;
+
+ return False;
+}
+
+/****************************************************************************
listens for NMB or DGRAM packets, and queues them
***************************************************************************/
-void listen_for_packets(BOOL run_election)
+BOOL listen_for_packets(BOOL run_election)
{
- fd_set fds;
- int selrtn;
- struct timeval timeout;
+ static fd_set *listen_set = NULL;
+ static int listen_number = 0;
+ static int *sock_array = NULL;
- FD_ZERO(&fds);
- FD_SET(ClientNMB,&fds);
- FD_SET(ClientDGRAM,&fds);
+ fd_set fds;
+ int selrtn;
+ struct timeval timeout;
- /* during elections and when expecting a netbios response packet we
- need to send election packets at tighter intervals
+ if(listen_set == NULL)
+ {
+ if(create_listen_fdset(&listen_set, &sock_array, &listen_number))
+ {
+ DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
+ return True;
+ }
+ }
- ideally it needs to be the interval (in ms) between time now and
- the time we are expecting the next netbios packet */
+ memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
- timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
+ /* during elections and when expecting a netbios response packet we
+ need to send election packets at tighter intervals
- /* We can only take term signals when we are in the select. */
- BlockSignals(False, SIGTERM);
- selrtn = sys_select(&fds,&timeout);
- BlockSignals(True, SIGTERM);
+ ideally it needs to be the interval (in ms) between time now and
+ the time we are expecting the next netbios packet */
- if (FD_ISSET(ClientNMB,&fds))
- {
- struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
- if (packet)
- {
- if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) &&
- packet->port == NMB_PORT)
- {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else
- {
- queue_packet(packet);
- }
- }
- }
+ timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
+ timeout.tv_usec = 0;
- if (FD_ISSET(ClientDGRAM,&fds))
- {
- struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
- if (packet)
- {
- if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) &&
- packet->port == DGRAM_PORT)
- {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else
- {
- queue_packet(packet);
- }
- }
- }
+ /* We can only take term signals when we are in the select. */
+ BlockSignals(False, SIGTERM);
+ selrtn = sys_select(&fds,&timeout);
+ BlockSignals(True, SIGTERM);
+
+ if(selrtn > 0)
+ {
+ int i;
+
+ for(i = 0; i < listen_number; i++)
+ {
+ if(i < (listen_number/2))
+ {
+ /* Processing a 137 socket. */
+ if (FD_ISSET(sock_array[i],&fds))
+ {
+ struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
+ if (packet)
+ {
+
+ /*
+ * If we got a packet on the broadcast socket check it
+ * came from one of our local nets. We should only be
+ * receiving broadcasts from nets we have subnets for.
+ *
+ * Note that this filter precludes remote announces.
+ * If we need this to work we will have to add an
+ * 'allow local announce' parameter that gives a
+ * list of networks we will allow through the filter.
+ */
+ if((sock_array[i] == ClientNMB) && (!is_local_net(packet->ip)))
+ {
+ DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else if ((ip_equal(loopback_ip, packet->ip) ||
+ ismyip(packet->ip)) && packet->port == NMB_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Processing a 138 socket. */
+
+ if (FD_ISSET(sock_array[i],&fds))
+ {
+ struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
+ if (packet)
+ {
+ /*
+ * If we got a packet on the broadcast socket check it
+ * came from one of our local nets. We should only be
+ * receiving broadcasts from nets we have subnets for.
+ *
+ * Note that this filter precludes remote announces.
+ * If we need this to work we will have to add an
+ * 'allow local announce' parameter that gives a
+ * list of networks we will allow through the filter.
+ */
+ if((sock_array[i] == ClientDGRAM) && (!is_local_net(packet->ip)))
+ {
+ DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else if ((ip_equal(loopback_ip, packet->ip) ||
+ ismyip(packet->ip)) && packet->port == DGRAM_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
+ }
+ } /* end processing 138 socket. */
+ } /* end for */
+ } /* end if selret > 0 */
+ return False;
}
@@ -636,7 +762,7 @@ BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,ch
p.ip = dest_ip;
p.port = DGRAM_PORT;
- p.fd = ClientDGRAM;
+ p.fd = fd;
p.timestamp = time(NULL);
p.packet_type = DGRAM_PACKET;
diff --git a/source3/nameresp.c b/source3/nameresp.c
index 2e625735c4..81624fcaf1 100644
--- a/source3/nameresp.c
+++ b/source3/nameresp.c
@@ -25,7 +25,6 @@
#include "includes.h"
extern int ClientNMB;
-extern int ClientDGRAM;
extern struct subnet_record *subnetlist;
diff --git a/source3/nameserv.c b/source3/nameserv.c
index bc37d1c424..a90b41f834 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -168,7 +168,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
}
else
{
- /* broadcast the packet, but it comes from ipzero */
+ /* broadcast the packet */
queue_netbios_packet(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
@@ -214,45 +214,43 @@ void add_domain_logon_names(void)
****************************************************************************/
void add_domain_master_bcast(void)
{
- struct subnet_record *d;
-
- if (!lp_domain_master()) return;
-
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
- {
- struct work_record *work = find_workgroupstruct(d, myworkgroup, True);
-
- if (work && work->dom_state == DOMAIN_NONE)
- {
- struct nmb_name n;
- make_nmb_name(&n,myworkgroup,0x1b,scope);
+ struct subnet_record *d;
- if (!find_name(d->namelist, &n, FIND_SELF))
- {
- DEBUG(0,("%s add_domain_names: attempting to become domain \
-master browser on workgroup %s %s\n",
- timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
+ if (!lp_domain_master()) return;
- /* send out a query to establish whether there's a
- domain controller on the local subnet. if not,
- we can become a domain controller. it's only
- polite that we check, before claiming the
- NetBIOS name 0x1b.
- */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work = find_workgroupstruct(d, myworkgroup, True);
- DEBUG(0,("add_domain_names:querying subnet %s \
-for domain master on workgroup %s\n",
- inet_ntoa(d->bcast_ip), myworkgroup));
+ if (work && work->dom_state == DOMAIN_NONE)
+ {
+ struct nmb_name n;
+ make_nmb_name(&n,myworkgroup,0x1b,scope);
- queue_netbios_packet(d,ClientNMB,NMB_QUERY,
- NAME_QUERY_DOMAIN,
- myworkgroup, 0x1b,
- 0, 0,0,NULL,NULL,
- True, False,
- d->bcast_ip, d->bcast_ip, 0);
- }
- }
- }
+ if (!find_name(d->namelist, &n, FIND_SELF))
+ {
+ DEBUG(0,("%s add_domain_names: attempting to become domain \
+master browser on workgroup %s %s\n", timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
+
+ /* send out a query to establish whether there's a
+ domain controller on the local subnet. if not,
+ we can become a domain controller. it's only
+ polite that we check, before claiming the
+ NetBIOS name 0x1b.
+ */
+
+ DEBUG(0,("add_domain_names:querying subnet %s \
+for domain master on workgroup %s\n", inet_ntoa(d->bcast_ip), myworkgroup));
+
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,
+ NAME_QUERY_DOMAIN,
+ myworkgroup, 0x1b,
+ 0, 0,0,NULL,NULL,
+ True, False,
+ d->bcast_ip, d->bcast_ip, 0);
+ }
+ }
+ }
}
diff --git a/source3/nameservresp.c b/source3/nameservresp.c
index deb56c0850..61e4a835f4 100644
--- a/source3/nameservresp.c
+++ b/source3/nameservresp.c
@@ -806,7 +806,8 @@ void response_netbios_packet(struct packet_struct *p)
struct subnet_record *d = NULL;
if (!(n = find_response_record(&d,nmb->header.name_trn_id))) {
- DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
+ DEBUG(2,("unknown netbios response id %d (received late or from nmblookup?)\n",
+ nmb->header.name_trn_id));
return;
}
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index c7af54fa13..047284832f 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -34,8 +34,9 @@ pstring servicesf = CONFIGFILE;
extern pstring scope;
-int ClientNMB = -1;
-int ClientDGRAM = -1;
+int ClientNMB = -1;
+int ClientDGRAM = -1;
+int global_nmb_port = -1;
extern pstring myhostname;
static pstring host_file;
@@ -302,7 +303,8 @@ static void process(void)
{
time_t t = time(NULL);
run_election = check_elections();
- listen_for_packets(run_election);
+ if(listen_for_packets(run_election))
+ return;
run_packet_queue();
run_elections(t);
@@ -338,12 +340,19 @@ static BOOL open_sockets(BOOL isdaemon, int port)
return False;
}
+ /* The sockets opened here will be used to receive broadcast
+ packets *only*. Interface specific sockets are opened in
+ make_subnet() in namedbsubnet.c. Thus we bind to the
+ address "0.0.0.0". The parameter 'socket address' is
+ now deprecated.
+ */
+
if (isdaemon)
- ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
+ ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
else
ClientNMB = 0;
- ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
+ ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0);
if (ClientNMB == -1)
return(False);
@@ -353,7 +362,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)
set_socket_options(ClientNMB,"SO_BROADCAST");
set_socket_options(ClientDGRAM,"SO_BROADCAST");
- DEBUG(3,("Sockets opened.\n"));
+ DEBUG(3,("open_sockets: Broadcast sockets opened.\n"));
return True;
}
@@ -460,12 +469,12 @@ static void usage(char *pname)
**************************************************************************/
int main(int argc,char *argv[])
{
- int port = NMB_PORT;
int opt;
extern FILE *dbf;
extern char *optarg;
char pidFile[100] = { 0 };
+ global_nmb_port = NMB_PORT;
*host_file = 0;
StartupTime = time(NULL);
@@ -537,7 +546,7 @@ static void usage(char *pname)
DEBUGLEVEL = atoi(optarg);
break;
case 'p':
- port = atoi(optarg);
+ global_nmb_port = atoi(optarg);
break;
case 'h':
usage(argv[0]);
@@ -618,9 +627,9 @@ static void usage(char *pname)
}
- DEBUG(3,("Opening sockets %d\n", port));
+ DEBUG(3,("Opening sockets %d\n", global_nmb_port));
- if (!open_sockets(is_daemon,port)) return 1;
+ if (!open_sockets(is_daemon,global_nmb_port)) return 1;
load_interfaces();
add_my_subnets(myworkgroup);
diff --git a/source3/nmbsync.c b/source3/nmbsync.c
index de2f7aa00f..34d309d003 100644
--- a/source3/nmbsync.c
+++ b/source3/nmbsync.c
@@ -24,9 +24,6 @@
#define REPLACE_GETPASS
#include "includes.h"
-extern int ClientNMB;
-extern int ClientDGRAM;
-
extern int DEBUGLEVEL;
extern pstring myname;