summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1996-08-20 15:45:16 +0000
committerAndrew Tridgell <tridge@samba.org>1996-08-20 15:45:16 +0000
commit748d65a4ac898708dc7d2fd6f2bdee41489fee86 (patch)
treeb54a4d77d71beba6e6422c366ecb17f57c172614
parent7f38abfbdb57b4ed33fa0aaacdfe7414d4c19a28 (diff)
downloadsamba-748d65a4ac898708dc7d2fd6f2bdee41489fee86.tar.gz
samba-748d65a4ac898708dc7d2fd6f2bdee41489fee86.tar.bz2
samba-748d65a4ac898708dc7d2fd6f2bdee41489fee86.zip
- fix a bug in NetServerEnum where counted and total were not counted
correctly if there were multiple instances of a name. This led to the infamous "not enough memory" error when browsing (but this isn't the only cause of that message) - fix a triple-chaining bug which affected OpenX following a TconX - fix a serious nmbd bug that meant nmdb would answer packets that it wasn't supposed to, causing havoc with browse lists. - never time out SELF packets. This is an interim fix until I find out why nmbd thought they should be timed out. (This used to be commit 2960c3908c2c3b01a1f2b77def60350018d298e1)
-rw-r--r--source3/include/includes.h2
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/namedbname.c24
-rw-r--r--source3/nameelect.c3
-rw-r--r--source3/namelogon.c5
-rw-r--r--source3/namepacket.c30
-rw-r--r--source3/namework.c80
-rw-r--r--source3/smbd/ipc.c14
-rw-r--r--source3/smbd/reply.c45
-rw-r--r--source3/smbd/server.c45
10 files changed, 101 insertions, 148 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h
index c7acbddc2b..5d5fd7fd55 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -227,11 +227,13 @@ Here come some platform specific sections
#endif
#endif
#ifdef SHADOW_PWD
+#if _LINUX_C_LIB_VERSION_MAJOR < 5
#ifndef crypt
#define crypt pw_encrypt
#endif
#endif
#endif
+#endif
#ifdef SUNOS4
#define SIGNAL_CAST (void (*)(int))
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 9ddf7cb1fd..f257ac0048 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -679,7 +679,6 @@ int reply_coreplus(char *outbuf);
int reply_lanman1(char *outbuf);
int reply_lanman2(char *outbuf);
int reply_nt1(char *outbuf);
-void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev);
void close_cnum(int cnum, int uid);
BOOL yield_connection(int cnum,char *name,int max_connections);
BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear);
diff --git a/source3/namedbname.c b/source3/namedbname.c
index 746353dd97..58b62bd0cb 100644
--- a/source3/namedbname.c
+++ b/source3/namedbname.c
@@ -238,9 +238,9 @@ void dump_names(void)
for (i = 0; i < n->num_ips; i++)
{
- DEBUG(3,("%15s NB=%2x ",
- inet_ntoa(n->ip_flgs[i].ip),
- n->ip_flgs[i].nb_flags));
+ DEBUG(3,("%15s NB=%2x source=%d",
+ inet_ntoa(n->ip_flgs[i].ip),
+ n->ip_flgs[i].nb_flags,n->source));
}
DEBUG(3,("\n"));
@@ -486,13 +486,17 @@ void expire_names(time_t t)
for (d = subnetlist; d; d = d->next)
{
for (n = d->namelist; n; n = next)
+ {
+ next = n->next;
+ if (n->death_time && n->death_time < t)
{
- if (n->death_time && n->death_time < t)
- {
+ if (n->source == SELF) {
+ DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name)));
+ n->death_time += 300;
+ continue;
+ }
DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
- next = n->next;
-
if (n->prev) n->prev->next = n->next;
if (n->next) n->next->prev = n->prev;
@@ -501,11 +505,7 @@ void expire_names(time_t t)
free(n->ip_flgs);
free(n);
}
- else
- {
- next = n->next;
- }
- }
+ }
}
}
diff --git a/source3/nameelect.c b/source3/nameelect.c
index 2edc484ba0..ef3935b1fd 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -564,8 +564,7 @@ void process_election(struct packet_struct *p,char *buf)
for (work = d->workgrouplist; work; work = work->next)
{
- if (listening_name(work, &dgram->dest_name) &&
- strequal(work->work_group, lp_workgroup()))
+ if (strequal(work->work_group, lp_workgroup()))
{
if (win_election(work, version,criterion,timeup,name))
{
diff --git a/source3/namelogon.c b/source3/namelogon.c
index c10049135c..aacf32c280 100644
--- a/source3/namelogon.c
+++ b/source3/namelogon.c
@@ -64,11 +64,6 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
DEBUG(3,("No domain logons\n"));
return;
}
- if (!listening_name(work, &dgram->dest_name))
- {
- DEBUG(4,("Not listening to that domain\n"));
- return;
- }
code = SVAL(buf,0);
switch (code) {
diff --git a/source3/namepacket.c b/source3/namepacket.c
index 4be5a95952..02f4958520 100644
--- a/source3/namepacket.c
+++ b/source3/namepacket.c
@@ -162,7 +162,10 @@ void initiate_netbios_packet(uint16 *id,
p.timestamp = time(NULL);
p.packet_type = NMB_PACKET;
- if (!send_packet(&p)) *id = 0xffff;
+ if (!send_packet(&p)) {
+ DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
+ *id = 0xffff;
+ }
return;
}
@@ -296,6 +299,26 @@ void queue_packet(struct packet_struct *packet)
packet->prev = p;
}
+/****************************************************************************
+ determine if a packet is for us. Note that to have any chance of
+ being efficient we need to drop as many packets as possible at this
+ stage as subsequent processing is expensive.
+
+ We also must make absolutely sure we don't tread on another machines
+ property by answering a packet that is not for us.
+ ****************************************************************************/
+static BOOL listening(struct packet_struct *p,struct nmb_name *n)
+{
+ struct subnet_record *d;
+ struct name_record *n1;
+
+ d = find_subnet(p->ip);
+
+ n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip);
+
+ return (n1 != NULL);
+}
+
/****************************************************************************
process udp 138 datagrams
@@ -307,6 +330,11 @@ static void process_dgram(struct packet_struct *p)
int len;
struct dgram_packet *dgram = &p->packet.dgram;
+ /* if we aren't listening to the destination name then ignore the packet */
+ if (!listening(p,&dgram->dest_name))
+ return;
+
+
if (dgram->header.msg_type != 0x10 &&
dgram->header.msg_type != 0x11 &&
dgram->header.msg_type != 0x12) {
diff --git a/source3/namework.c b/source3/namework.c
index 108048d500..90ab2fb1fb 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -166,22 +166,6 @@ BOOL same_context(struct dgram_packet *dgram)
/*******************************************************************
- am I listening on a name. XXXX check the type of name as well.
- ******************************************************************/
-BOOL listening_name(struct work_record *work, struct nmb_name *n)
-{
- if (strequal(n->name,myname) ||
- strequal(n->name,work->work_group) ||
- strequal(n->name,MSBROWSE))
- {
- return(True);
- }
-
- return(False);
-}
-
-
-/*******************************************************************
process a domain announcement frame
Announce frames come in 3 types. Servers send host announcements
@@ -667,70 +651,6 @@ static void process_announce_request(struct packet_struct *p,char *buf)
}
-/****************************************************************************
-depending on what announce has been made, we are only going to
-accept certain types of name announce. XXXX untested code
-
-check listening name type
-****************************************************************************/
-BOOL listening_type(struct packet_struct *p, int command)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int type = dgram->dest_name.name_type;
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- if (type != 0x0 || type != 0x20) return (False);
- break;
- }
-
- case ANN_AnnouncementRequest:
- {
- return (True);
- break;
- }
-
- case ANN_Election:
- {
- return (True);
- break;
- }
-
- case ANN_GetBackupListReq:
- {
- return (True);
- break;
- }
-
- case ANN_GetBackupListResp:
- {
- return (True);
- break;
- }
-
- case ANN_DomainAnnouncement:
- {
- if (type != 0x1b || type != 0x1c) return (False);
- break;
- }
-
- case ANN_MasterAnnouncement:
- {
- if (type != 0x1d) return (False);
- break;
- }
-
- case ANN_LocalMasterAnnouncement:
- {
- if (type != 0x1c || type != 0x1d) return (False);
- break;
- }
- }
- return (True); /* we're not dealing with unknown packet types */
-}
-
/****************************************************************************
process a browse frame
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 78a9807769..9da7c993dd 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -963,7 +963,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
int f_len, s_len;
struct srv_info_struct *servers=NULL;
int counted=0,total=0;
- int i;
+ int i,missed;
fstring domain;
BOOL domain_request;
BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
@@ -991,6 +991,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
total = get_server_info(servertype,&servers,domain);
data_len = fixed_len = string_len = 0;
+ missed = 0;
qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
@@ -1006,12 +1007,13 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
- if (data_len <= buf_len)
- {
+ if (data_len <= buf_len) {
counted++;
fixed_len += f_len;
string_len += s_len;
- }
+ } else {
+ missed++;
+ }
}
}
@@ -1044,12 +1046,12 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
SSVAL(*rparam,0,NERR_Success);
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,total);
+ SSVAL(*rparam,6,counted+missed);
if (servers) free(servers);
DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
- domain,uLevel,counted,total));
+ domain,uLevel,counted,counted+missed));
return(True);
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index a84a9af0c1..7241aadac0 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -130,6 +130,44 @@ static int connection_error(char *inbuf,char *outbuf,int connection_num)
}
+
+/****************************************************************************
+ parse a share descriptor string
+****************************************************************************/
+static void parse_connect(char *p,char *service,char *user,
+ char *password,int *pwlen,char *dev)
+{
+ char *p2;
+
+ DEBUG(4,("parsing connect string %s\n",p));
+
+ p2 = strrchr(p,'\\');
+ if (p2 == NULL)
+ strcpy(service,p);
+ else
+ strcpy(service,p2+1);
+
+ p += strlen(p) + 2;
+
+ strcpy(password,p);
+ *pwlen = strlen(password);
+
+ p += strlen(p) + 2;
+
+ strcpy(dev,p);
+
+ *user = 0;
+ p = strchr(service,'%');
+ if (p != NULL)
+ {
+ *p = 0;
+ strcpy(user,p+1);
+ }
+}
+
+
+
+
/****************************************************************************
reply to a tcon
****************************************************************************/
@@ -149,7 +187,7 @@ int reply_tcon(char *inbuf,char *outbuf)
vuid = valid_uid(uid);
- parse_connect(inbuf,service,user,password,&pwlen,dev);
+ parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
connection_num = make_connection(service,user,password,pwlen,dev,vuid);
@@ -1210,6 +1248,11 @@ int reply_unlink(char *inbuf,char *outbuf)
if (check_name(directory,cnum))
dirptr = OpenDir(directory);
+ /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
+ the pattern matches against the long name, otherwise the short name
+ We don't implement this yet XXXX
+ */
+
if (dirptr)
{
error = ERRbadfile;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 1fb6358794..683d63e7aa 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -2564,41 +2564,6 @@ static int reply_negprot(char *inbuf,char *outbuf)
/****************************************************************************
- parse a connect packet
-****************************************************************************/
-void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
-{
- char *p = smb_buf(buf) + 1;
- char *p2;
-
- DEBUG(4,("parsing connect string %s\n",p));
-
- p2 = strrchr(p,'\\');
- if (p2 == NULL)
- strcpy(service,p);
- else
- strcpy(service,p2+1);
-
- p += strlen(p) + 2;
-
- strcpy(password,p);
- *pwlen = strlen(password);
-
- p += strlen(p) + 2;
-
- strcpy(dev,p);
-
- *user = 0;
- p = strchr(service,'%');
- if (p != NULL)
- {
- *p = 0;
- strcpy(user,p+1);
- }
-}
-
-
-/****************************************************************************
close all open files for a connection
****************************************************************************/
static void close_open_files(int cnum)
@@ -3261,14 +3226,14 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
/* remember the original command type */
- smb_com1 = CVAL(orig_outbuf,smb_com);
+ smb_com1 = CVAL(orig_inbuf,smb_com);
/* save the data which will be overwritten by the new headers */
memcpy(inbuf_saved,inbuf2,smb_wct);
memcpy(outbuf_saved,outbuf2,smb_wct);
- /* give the new packet the same header as the first part of the SMB */
- memmove(inbuf2,orig_inbuf,smb_wct);
+ /* give the new packet the same header as the last part of the SMB */
+ memmove(inbuf2,inbuf,smb_wct);
/* create the in buffer */
CVAL(inbuf2,smb_com) = smb_com2;
@@ -3297,8 +3262,8 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
bufsize-chain_size);
- /* copy the new reply header over the old one, but preserve
- the smb_com field */
+ /* copy the new reply and request headers over the old ones, but
+ preserve the smb_com field */
memmove(orig_outbuf,outbuf2,smb_wct);
CVAL(orig_outbuf,smb_com) = smb_com1;