diff --git a/source/include/proto.h b/source/include/proto.h index 2c7cb8a1269..77c7129b2ad 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -67,6 +67,8 @@ 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); +int iface_count(void); +struct in_addr *iface_n_ip(int n); struct in_addr *iface_bcast(struct in_addr ip); struct in_addr *iface_nmask(struct in_addr ip); struct in_addr *iface_ip(struct in_addr ip); @@ -197,7 +199,7 @@ void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, int name_type, struct in_addr ip); void update_from_reg(char *name, int type, struct in_addr ip); -void add_my_domains(void); +void add_my_domains(char *group); BOOL same_context(struct dgram_packet *dgram); BOOL listening_name(struct work_record *work, struct nmb_name *n); void process_logon_packet(struct packet_struct *p,char *buf,int len); @@ -239,6 +241,9 @@ BOOL server_cryptkey(char *buf); BOOL server_validate(char *buf); BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname); void pcap_printer_fn(void (*fn)()); +int read_predict(int fd,int offset,char *buf,char **ptr,int num); +void do_read_prediction(); +void invalidate_read_prediction(int fd); void lpq_reset(int snum); void print_file(int fnum); int get_printqueue(int snum,int cnum,print_queue_struct **queue, @@ -457,9 +462,6 @@ int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew); BOOL send_keepalive(int client); int read_data(int fd,char *buffer,int N); int write_data(int fd,char *buffer,int N); -int read_predict(int fd,int offset,char *buf,char **ptr,int num); -void do_read_prediction(); -void invalidate_read_prediction(int fd); int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align); int read_smb_length(int fd,char *inbuf,int timeout); BOOL receive_smb(int fd,char *buffer,int timeout); diff --git a/source/lib/interface.c b/source/lib/interface.c index a47ef6e47e7..f2a535d80cd 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -388,6 +388,33 @@ BOOL ismybcast(struct in_addr bcast) return False; } +/**************************************************************************** + how many interfaces do we have + **************************************************************************/ +int iface_count(void) +{ + int ret = 0; + struct interface *i; + + for (i=interfaces;i;i=i->next) + ret++; + return ret; +} + +/**************************************************************************** + return IP of the Nth interface + **************************************************************************/ +struct in_addr *iface_n_ip(int n) +{ + struct interface *i; + + for (i=interfaces;i && n;i=i->next) + n--; + + if (i) return &i->ip; + return NULL; +} + static struct interface *iface_find(struct in_addr ip) { struct interface *i; diff --git a/source/lib/util.c b/source/lib/util.c index 6cc9a7e1722..cfe8ea05b09 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -56,10 +56,6 @@ int trans_num = 0; */ int case_default = CASE_LOWER; - -/* size of reads during a direct file to file transfer */ -int ReadSize = 16*1024; - pstring debugf = "/tmp/log.samba"; int syslog_level; @@ -1951,7 +1947,6 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL /* Check if error */ if(selrtn == -1) { - errno = EBADF; return -1; } @@ -1974,7 +1969,6 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL /* force a particular error number for portability */ DEBUG(5,("read gave error %s\n",strerror(errno))); - errno = EBADF; return -1; } @@ -2068,10 +2062,6 @@ int read_data(int fd,char *buffer,int N) { ret = read(fd,buffer + total,N - total); - /* this is for portability */ - if (ret < 0) - errno = EBADF; - if (ret <= 0) return total; total += ret; @@ -2101,142 +2091,28 @@ int write_data(int fd,char *buffer,int N) } -/* variables used by the read prediction module */ -int rp_fd = -1; -int rp_offset = 0; -int rp_length = 0; -int rp_alloced = 0; -int rp_predict_fd = -1; -int rp_predict_offset = 0; -int rp_predict_length = 0; -int rp_timeout = 5; -time_t rp_time = 0; -char *rp_buffer = NULL; -BOOL predict_skip=False; -time_t smb_last_time=(time_t)0; - -/**************************************************************************** -handle read prediction on a file -****************************************************************************/ -int read_predict(int fd,int offset,char *buf,char **ptr,int num) -{ - int ret = 0; - int possible = rp_length - (offset - rp_offset); - - possible = MIN(possible,num); - - /* give data if possible */ - if (fd == rp_fd && - offset >= rp_offset && - possible>0 && - smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } - - if (ret == num) { - predict_skip = True; - } else { - predict_skip = False; - - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; - } - - if (ret < 0) ret = 0; - - return(ret); -} - -/**************************************************************************** -pre-read some data -****************************************************************************/ -void do_read_prediction() -{ - if (predict_skip) return; - - if (rp_predict_fd == -1) - return; - - rp_fd = rp_predict_fd; - rp_offset = rp_predict_offset; - rp_length = 0; - - rp_predict_fd = -1; - - rp_predict_length = MIN(rp_predict_length,2*ReadSize); - rp_predict_length = MAX(rp_predict_length,1024); - rp_offset = (rp_offset/1024)*1024; - rp_predict_length = (rp_predict_length/1024)*1024; - - if (rp_predict_length > rp_alloced) - { - rp_buffer = Realloc(rp_buffer,rp_predict_length); - rp_alloced = rp_predict_length; - if (!rp_buffer) - { - DEBUG(0,("can't allocate read-prediction buffer\n")); - rp_predict_fd = -1; - rp_fd = -1; - rp_alloced = 0; - return; - } - } - - if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { - rp_fd = -1; - rp_predict_fd = -1; - return; - } - - rp_length = read(rp_fd,rp_buffer,rp_predict_length); - rp_time = time(NULL); - if (rp_length < 0) - rp_length = 0; -} - -/**************************************************************************** -invalidate read-prediction on a fd -****************************************************************************/ -void invalidate_read_prediction(int fd) -{ - if (rp_fd == fd) - rp_fd = -1; - if (rp_predict_fd == fd) - rp_predict_fd = -1; -} - - /**************************************************************************** transfer some data between two fd's ****************************************************************************/ int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align) { static char *buf=NULL; + static int size=0; char *buf1,*abuf; - static int size = 0; int total = 0; DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen)); - if ((size < ReadSize) && buf) { - free(buf); - buf = NULL; + if (size == 0) { + size = lp_readsize(); + size = MAX(size,1024); } - size = MAX(ReadSize,1024); - while (!buf && size>0) { buf = (char *)Realloc(buf,size+8); if (!buf) size /= 2; } + if (!buf) { DEBUG(0,("Can't allocate transfer buffer!\n")); exit(1); diff --git a/source/loadparm.h b/source/loadparm.h index 0e39537c9e5..780ed633cad 100644 --- a/source/loadparm.h +++ b/source/loadparm.h @@ -93,6 +93,7 @@ extern int lp_maxdisksize(void); extern int lp_lpqcachetime(void); extern int lp_syslog(void); extern int lp_deadtime(void); +extern int lp_readsize(void); extern int lp_debuglevel(void); extern int lp_maxprotocol(void); extern int lp_maxpacket(void); diff --git a/source/namedb.c b/source/namedb.c index 2e942587be8..2868d54ac4f 100644 --- a/source/namedb.c +++ b/source/namedb.c @@ -460,6 +460,8 @@ struct domain_record *add_domain_entry(struct in_addr source_ip, { struct work_record *w = find_workgroupstruct(d, name, add); + 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)) @@ -586,7 +588,8 @@ struct server_record *add_server_entry(struct domain_record *d, if (ismybcast(d->bcast_ip) && strequal(lp_workgroup(),work->work_group)) { - servertype |= SV_TYPE_LOCAL_LIST_ONLY; + if (servertype) + servertype |= SV_TYPE_LOCAL_LIST_ONLY; } else { @@ -599,6 +602,9 @@ struct server_record *add_server_entry(struct domain_record *d, strupper(s->serv.name); s->serv.type = servertype; s->death_time = ttl?time(NULL)+ttl*3:0; + + if (servertype == 0) + s->death_time = time(NULL)-1; /* for a domain entry, the comment field refers to the server name */ diff --git a/source/nameelect.c b/source/nameelect.c index a78c8483c5d..765791b80f2 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -178,8 +178,6 @@ static void become_master(struct domain_record *d, struct work_record *work) /* add domain master and domain member names or register with WINS */ add_name_entry(work->work_group,0x1b,NB_ACTIVE ); - add_name_entry(work->work_group,0x1c,NB_ACTIVE|NB_GROUP); - work->ServerType |= SV_TYPE_DOMAIN_MASTER; if (lp_domain_logons()) @@ -215,7 +213,6 @@ void become_nonmaster(struct domain_record *d, struct work_record *work) work->ElectionCriterion &= ~0x4; remove_name_entry(work->work_group,0x1b); - remove_name_entry(work->work_group,0x1c); remove_name_entry(work->work_group,0x1d); remove_name_entry(MSBROWSE ,0x01); } diff --git a/source/nameserv.c b/source/nameserv.c index ba61dd34173..69be6b0131d 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -267,6 +267,11 @@ void add_my_names(void) add_netbios_entry("*",0x0,NB_ACTIVE,0,SELF,ip,False); add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False); add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False); + + if (lp_wins_support()) { + /* the 0x1c name gets added by any WINS server it seems */ + add_name_entry(my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP); + } } /******************************************************************* diff --git a/source/namework.c b/source/namework.c index cbf65a955fc..5e61ecefb44 100644 --- a/source/namework.c +++ b/source/namework.c @@ -270,16 +270,19 @@ void update_from_reg(char *name, int type, struct in_addr ip) /**************************************************************************** add the default workgroup into my domain **************************************************************************/ -void add_my_domains(void) +void add_my_domains(char *group) { - /* add or find domain on our local subnet, in the default workgroup */ - - if (*lp_workgroup() != '*') - { - add_domain_entry(*iface_bcast(ipzero), - *iface_nmask(ipzero), - lp_workgroup(), True); - } + int n,i; + struct in_addr *ip; + + if (*group == '*') return; + + n = iface_count(); + for (i=0;iworkgrouplist;work;work=remove_workgroup(d,work)); } - add_my_domains(); + add_my_domains(lp_workgroup()); } /* stop browsing altogether. i don't think this is a good idea! */ diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index b93ac2d580b..cd2ebb0521f 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -492,7 +492,7 @@ static void usage(char *pname) return(-1); if (*group) - add_domain_entry(*iface_bcast(ipzero),*iface_nmask(ipzero),group, True); + add_my_domains(group); if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); @@ -519,7 +519,7 @@ static void usage(char *pname) string_sub(ServerComment,"%h",myhostname); add_my_names(); - add_my_domains(); + add_my_domains(lp_workgroup()); DEBUG(3,("Checked names\n")); diff --git a/source/nmbsync.c b/source/nmbsync.c index e86e8d53eb7..c9e0dfc4628 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -103,7 +103,6 @@ static BOOL add_info(struct domain_record *d, struct work_record *work, int serv uint32 stype = IVAL(p,18); int comment_offset = IVAL(p,22) & 0xFFFF; char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - struct work_record *w = work; DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); @@ -111,16 +110,17 @@ static BOOL add_info(struct domain_record *d, struct work_record *work, int serv if (stype & SV_TYPE_DOMAIN_ENUM) { /* creates workgroup on remote subnet */ - if ((w = find_workgroupstruct(d,sname, False))) + if ((w = find_workgroupstruct(d,sname, True))) { if (ismybcast(d->bcast_ip)) { announce_request(w, d->bcast_ip); } } - } + } - add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); + if (w) + add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); } } } diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 876385ab18b..fcd70b4b75e 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -56,7 +56,6 @@ BOOL bLoaded = False; extern int DEBUGLEVEL; -extern int ReadSize; extern pstring user_socket_options; #ifndef GLOBAL_NAME @@ -149,6 +148,7 @@ typedef struct int syslog; int os_level; int max_ttl; + int ReadSize; BOOL bWINSsupport; BOOL bWINSproxy; BOOL bPreferredMaster; @@ -409,7 +409,7 @@ struct parm_struct {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL}, {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL}, {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL}, - {"read size", P_INTEGER, P_GLOBAL, &ReadSize, NULL}, + {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL}, #ifdef KANJI {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system}, #endif /* KANJI */ @@ -582,6 +582,7 @@ static void init_globals(void) Globals.bBrowseList = True; Globals.bWINSsupport = True; Globals.bWINSproxy = False; + Globals.ReadSize = 16*1024; #ifdef KANJI coding_system = interpret_coding_system (KANJI, SJIS_CODE); @@ -735,6 +736,7 @@ FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux) FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet) FN_GLOBAL_INTEGER(lp_keepalive,&keepalive) FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel) +FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize) FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime) FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol) FN_GLOBAL_INTEGER(lp_security,&Globals.security) diff --git a/source/smbd/predict.c b/source/smbd/predict.c new file mode 100644 index 00000000000..8df381b367a --- /dev/null +++ b/source/smbd/predict.c @@ -0,0 +1,146 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + file read prediction routines + Copyright (C) Andrew Tridgell 1992-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. +*/ + +#include "includes.h" +#include "loadparm.h" + +extern int DEBUGLEVEL; + + +/* variables used by the read prediction module */ +static int rp_fd = -1; +static int rp_offset = 0; +static int rp_length = 0; +static int rp_alloced = 0; +static int rp_predict_fd = -1; +static int rp_predict_offset = 0; +static int rp_predict_length = 0; +static int rp_timeout = 5; +static time_t rp_time = 0; +static char *rp_buffer = NULL; +static BOOL predict_skip=False; +time_t smb_last_time=(time_t)0; + +/**************************************************************************** +handle read prediction on a file +****************************************************************************/ +int read_predict(int fd,int offset,char *buf,char **ptr,int num) +{ + int ret = 0; + int possible = rp_length - (offset - rp_offset); + + possible = MIN(possible,num); + + /* give data if possible */ + if (fd == rp_fd && + offset >= rp_offset && + possible>0 && + smb_last_time-rp_time < rp_timeout) + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } + + if (ret == num) { + predict_skip = True; + } else { + predict_skip = False; + + /* prepare the next prediction */ + rp_predict_fd = fd; + rp_predict_offset = offset + num; + rp_predict_length = num; + } + + if (ret < 0) ret = 0; + + return(ret); +} + +/**************************************************************************** +pre-read some data +****************************************************************************/ +void do_read_prediction() +{ + static int readsize = 0; + + if (predict_skip) return; + + if (rp_predict_fd == -1) + return; + + rp_fd = rp_predict_fd; + rp_offset = rp_predict_offset; + rp_length = 0; + + rp_predict_fd = -1; + + if (readsize == 0) { + readsize = lp_readsize(); + readsize = MAX(readsize,1024); + } + + rp_predict_length = MIN(rp_predict_length,2*readsize); + rp_predict_length = MAX(rp_predict_length,1024); + rp_offset = (rp_offset/1024)*1024; + rp_predict_length = (rp_predict_length/1024)*1024; + + if (rp_predict_length > rp_alloced) + { + rp_buffer = Realloc(rp_buffer,rp_predict_length); + rp_alloced = rp_predict_length; + if (!rp_buffer) + { + DEBUG(0,("can't allocate read-prediction buffer\n")); + rp_predict_fd = -1; + rp_fd = -1; + rp_alloced = 0; + return; + } + } + + if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { + rp_fd = -1; + rp_predict_fd = -1; + return; + } + + rp_length = read(rp_fd,rp_buffer,rp_predict_length); + rp_time = time(NULL); + if (rp_length < 0) + rp_length = 0; +} + +/**************************************************************************** +invalidate read-prediction on a fd +****************************************************************************/ +void invalidate_read_prediction(int fd) +{ + if (rp_fd == fd) + rp_fd = -1; + if (rp_predict_fd == fd) + rp_predict_fd = -1; +} +