From c336a2f08183f63031b0a08b2111669bc36a5f30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Oct 1997 23:08:07 +0000 Subject: .cvsignore: Added make_smbcodepage interface.c: Added is_local_net(). locking.c: Added Fix for zero length share files from Gerald Werner 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) --- source3/.cvsignore | 1 + source3/include/nameserv.h | 2 + source3/include/proto.h | 17 ++-- source3/lib/interface.c | 12 +++ source3/lib/util.c | 4 +- source3/locking/locking.c | 75 +++++++++----- source3/nameannounce.c | 166 +++++++++++++++---------------- source3/namedbresp.c | 1 - source3/namedbserver.c | 1 - source3/namedbsubnet.c | 67 +++++++++++-- source3/namepacket.c | 238 ++++++++++++++++++++++++++++++++++----------- source3/nameresp.c | 1 - source3/nameserv.c | 70 +++++++------ source3/nameservresp.c | 3 +- source3/nmbd/nmbd.c | 29 ++++-- source3/nmbsync.c | 3 - 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 @@ -399,6 +399,18 @@ BOOL ismybcast(struct in_addr bcast) return False; } +/**************************************************************************** + 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 **************************************************************************/ 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 @@ -715,6 +715,31 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) return(True); } +/******************************************************************* +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. ******************************************************************/ @@ -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 */ + + 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. */ @@ -834,31 +884,6 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok return ret; } -/******************************************************************* -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 @@ -503,72 +503,198 @@ 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; -- cgit