- fix a bug in NetServerEnum where counted and total were not counted
authorAndrew Tridgell <tridge@samba.org>
Tue, 20 Aug 1996 15:45:16 +0000 (15:45 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 20 Aug 1996 15:45:16 +0000 (15:45 +0000)
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.

source/include/includes.h
source/include/proto.h
source/namedbname.c
source/nameelect.c
source/namelogon.c
source/namepacket.c
source/namework.c
source/smbd/ipc.c
source/smbd/reply.c
source/smbd/server.c

index c7acbddc2b3d9f80c550fde7f5d30e966dfdf914..5d5fd7fd55c9a08e416479c043439bf31c1cb7b4 100644 (file)
@@ -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))
index 9ddf7cb1fd89a88ba17ffbfac91f47268c614279..f257ac0048f3e79c72f37a81e6984f9c83478f7a 100644 (file)
@@ -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);
index 746353dd97648a820cd5932e1056d8a37055cc0d..58b62bd0cbc7ba3ad54332180a5fbf259ab877f5 100644 (file)
@@ -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;
-               }
-               }
+           }
        }
 }
 
index 2edc484ba0c2263bd80589efdb282e6aadea6756..ef3935b1fdf3433ca3c51d57a1c74dadf80e2cd2 100644 (file)
@@ -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))
            {
index c10049135c42e1cf502af8b91c5b552ae89664e7..aacf32c2804ab64b32185143c3d97f3d4100f255 100644 (file)
@@ -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) {
index 4be5a959526c513a4393002816fff8781cfb36d0..02f4958520c09ca66db2194b147ef80be3a56a89 100644 (file)
@@ -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) {
index 108048d5001de7d011ef28f0286c42662085aefe..90ab2fb1fb63f16abb6eafef6294c0a678979993 100644 (file)
@@ -165,22 +165,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
 
@@ -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
index 78a98077694b1b8853f0b1b0ae06879f06461958..9da7c993dd1da1150a94fb907e1cd3e920f0db47 100644 (file)
@@ -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);
 }
index a84a9af0c17c7d768c7d0b05c087a85b9d56f1a4..7241aadac08e94c7812a099b44e475e5600db766 100644 (file)
@@ -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;
index 1fb6358794aae7fa41ecdcd84b8e74760dbbab4e..683d63e7aaa65723f5e362b88974013ca6ef9c65 100644 (file)
@@ -2563,41 +2563,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
 ****************************************************************************/
@@ -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;