- bit a bit manipulation bug in find_name_search()
authorAndrew Tridgell <tridge@samba.org>
Wed, 21 Aug 1996 08:30:29 +0000 (08:30 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 21 Aug 1996 08:30:29 +0000 (08:30 +0000)
- add the * and __SAMBA__ names to all subnets

- sort the name status reply list and remove duplicate entries.

source/namedbname.c
source/nameserv.c
source/nameservreply.c

index 58b62bd0cbc7ba3ad54332180a5fbf259ab877f5..1f16553b0f416e848041300dd20b0ae8dbd8468f 100644 (file)
@@ -173,27 +173,25 @@ struct name_record *find_name_search(struct subnet_record **d,
 {
        if (d == NULL) return NULL; /* bad error! */
        
-    if ((search & FIND_LOCAL) == FIND_LOCAL)
-       {
-               if (*d != NULL)
-        {
-                       struct name_record *n = find_name((*d)->namelist, name, search);
-                       DEBUG(4,("find_name on local: %s %s search %x\n",
-                                               namestr(name),inet_ntoa(ip), search));
-                       if (n) return n;
-               }
-       }
-
-       if ((search & FIND_WINS) != FIND_WINS) return NULL;
-
-       /* find WINS subnet record. */
-       *d = find_subnet(ipgrp);
+    if (search & FIND_LOCAL) {
+      if (*d != NULL) {
+       struct name_record *n = find_name((*d)->namelist, name, search);
+       DEBUG(4,("find_name on local: %s %s search %x\n",
+                namestr(name),inet_ntoa(ip), search));
+       if (n) return n;
+      }
+    }
 
-       if (*d == NULL) return NULL;
+    if (!(search & FIND_WINS)) return NULL;
 
-       DEBUG(4,("find_name on WINS: %s %s search %x\n",
-                                               namestr(name),inet_ntoa(ip), search));
-       return find_name((*d)->namelist, name, search);
+    /* find WINS subnet record. */
+    *d = find_subnet(ipgrp);
+    
+    if (*d == NULL) return NULL;
+    
+    DEBUG(4,("find_name on WINS: %s %s search %x\n",
+            namestr(name),inet_ntoa(ip), search));
+    return find_name((*d)->namelist, name, search);
 }
 
 
index 26c2f330dacb1296a3630530a7aa9a665d0979e8..c8bbb52811636540adf78bde5eb0d82a9accda47 100644 (file)
@@ -160,11 +160,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
   **************************************************************************/
 void add_my_names(void)
 {
-  BOOL wins = lp_wins_support();
   struct subnet_record *d;
-
-  struct in_addr ip = ipzero;
-
   /* each subnet entry, including WINS pseudo-subnet, has SELF names */
 
   /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
@@ -173,20 +169,23 @@ void add_my_names(void)
 
   for (d = subnetlist; d; d = d->next)
   {
-       add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
-       add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
-       add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
-       add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
+    BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp);
 
+    add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
+    add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
+    add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
+    add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
+    
     /* these names are added permanently (ttl of zero) and will NOT be
        refreshed with the WINS server  */
-       add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
-       add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
-       add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,ip,False,wins);
-
+    add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+    add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+    add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+    add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+    
     if (lp_domain_logons()) {
-       /* XXXX the 0x1c is apparently something to do with domain logons */
-         add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+      /* XXXX the 0x1c is apparently something to do with domain logons */
+      add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
     }
   }
   if (lp_domain_master() && (d = find_subnet(ipgrp)))
index b77f9958b8147905bd42f59afc15f0a76fcd7069..b01c2c25b4cc51ec43fe18b57fbd2857230d0ecd 100644 (file)
@@ -310,6 +310,29 @@ void reply_name_reg(struct packet_struct *p)
   }
 }
 
+/* this is used to sort names for a name status into a sensible order
+   we put our own names first, then in alphabetical order */
+static int status_compare(char *n1,char *n2)
+{
+  extern pstring myname;
+  int l1,l2,l3;
+
+  /* its a bit tricky because the names are space padded */
+  for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
+  for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
+  l3 = strlen(myname);
+
+  if ((l1==l3) && strncmp(n1,myname,l3) == 0 && 
+      (l2!=l3 || strncmp(n2,myname,l3) != 0))
+    return -1;
+
+  if ((l2==l3) && strncmp(n2,myname,l3) == 0 && 
+      (l1!=l3 || strncmp(n1,myname,l3) != 0))
+    return 1;
+
+  return memcmp(n1,n2,18);
+}
+
 
 /****************************************************************************
   reply to a name status query
@@ -323,15 +346,14 @@ void reply_name_status(struct packet_struct *p)
   char *qname   = nmb->question.question_name.name;
   int ques_type = nmb->question.question_name.name_type;
   char rdata[MAX_DGRAM_SIZE];
-  char *countptr, *buf, *bufend;
-  int names_added;
+  char *countptr, *buf, *bufend, *buf0;
+  int names_added,i;
   struct name_record *n;
   struct subnet_record *d = NULL;
-  int search = FIND_SELF | FIND_WINS;
+  int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
 
-  BOOL bcast = nmb->header.nm_flags.bcast;
-  
-  if (!(d = find_req_subnet(p->ip, bcast)))
+  /* NOTE: we always treat a name status lookup as a bcast */ 
+  if (!(d = find_req_subnet(p->ip, True)))
   {
     DEBUG(3,("Name status req: bcast %s not known\n",
                        inet_ntoa(p->ip)));
@@ -339,10 +361,8 @@ void reply_name_status(struct packet_struct *p)
   }
 
   DEBUG(3,("Name status for name %s %s\n",
-          namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
-  
-  if (bcast)
-    search |= FIND_LOCAL;
+          namestr(&nmb->question.question_name), 
+          inet_ntoa(p->ip)));
 
   n = find_name_search(&d, &nmb->question.question_name,
                                search, p->ip);
@@ -353,7 +373,8 @@ void reply_name_status(struct packet_struct *p)
   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
   countptr = buf = rdata;
   buf += 1;
-  
+  buf0 = buf;
+
   names_added = 0;
 
   n = d->namelist;
@@ -368,9 +389,11 @@ void reply_name_status(struct packet_struct *p)
             from the response. if we don't exclude them, windows clients
             get confused and will respond with an error for NET VIEW */
       
-      if (name_type < 0x1b || name_type > 0x20 || 
-          ques_type < 0x1b || ques_type > 0x20 ||
-          strequal(qname, n->name.name))
+      if (!strequal(n->name.name,"*") &&
+         !strequal(n->name.name,"__SAMBA__") &&
+         (name_type < 0x1b || name_type > 0x20 || 
+          ques_type < 0x1b || ques_type > 0x20 ||
+          strequal(qname, n->name.name)))
       {
         /* start with first bit of putting info in buffer: the name */
         bzero(buf,18);
@@ -387,6 +410,20 @@ void reply_name_status(struct packet_struct *p)
       }
     }
 
+    /* remove duplicate names */
+    qsort(buf0,names_added,18,QSORT_CAST status_compare);
+
+    for (i=1;i<names_added;i++) {
+      if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
+       names_added--;
+       if (names_added == i) break;
+       memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
+       i--;
+      }
+    }
+
+    buf = buf0 + 18*names_added;
+
     n = n->next;
 
     if (!n)