JHT ==> Just tidying up for Release.
[samba.git] / source3 / namedbname.c
index 5c514c263ffe1248d06ce4afe1c72d69216467b9..c91541cc8157e30b499a21be90a63469defdf08b 100644 (file)
@@ -36,6 +36,7 @@ extern int DEBUGLEVEL;
 extern pstring scope;
 extern struct in_addr ipzero;
 extern struct in_addr wins_ip;
+extern BOOL updatedlists;
 
 extern struct subnet_record *subnetlist;
 
@@ -52,14 +53,14 @@ uint16 nb_type = 0; /* samba's NetBIOS name type */
   ****************************************************************************/
 void set_samba_nb_type(void)
 {
-       if (lp_wins_support() || (*lp_wins_server()))
-       {
-               nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
-       }
-       else
-       {
-               nb_type = NB_BFLAG; /* samba is broadcast-only node type */
-       }
+  if (lp_wins_support() || (*lp_wins_server()))
+  {
+    nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
+  }
+  else
+  {
+    nb_type = NB_BFLAG; /* samba is broadcast-only node type */
+  }
 }
 
 
@@ -111,6 +112,9 @@ static void add_name(struct subnet_record *d, struct name_record *n)
   n2->next = n;
   n->next = NULL;
   n->prev = n2;
+
+  if((d == wins_subnet) && lp_wins_support())
+    updatedlists = True;
 }
 
 
@@ -131,8 +135,17 @@ void remove_name(struct subnet_record *d, struct name_record *n)
   {
     if (nlist->next) nlist->next->prev = nlist->prev;
     if (nlist->prev) nlist->prev->next = nlist->next;
+
+    if(nlist == d->namelist)
+      d->namelist = nlist->next;
+
+    if(nlist->ip_flgs != NULL)
+      free(nlist->ip_flgs);
     free(nlist);
   }
+
+  if((d == wins_subnet) && lp_wins_support())
+    updatedlists = True;
 }
 
 
@@ -142,23 +155,25 @@ void remove_name(struct subnet_record *d, struct name_record *n)
 struct name_record *find_name(struct name_record *n,
                        struct nmb_name *name, int search)
 {
-       struct name_record *ret;
+  struct name_record *ret;
   
-       for (ret = n; ret; ret = ret->next)
-       {
-               if (name_equal(&ret->name,name))
-               {
-                       /* self search: self names only */
-                       if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
-                       {
-                               continue;
-                       }
-                       DEBUG(9,("find_name: found name %s\n", name->name));
-                       return ret;
-               }
-       }
-    DEBUG(9,("find_name: name %s NOT FOUND\n", name->name));
-    return NULL;
+  for (ret = n; ret; ret = ret->next)
+  {
+    if (name_equal(&ret->name,name))
+    {
+      /* self search: self names only */
+      if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
+      {
+        continue;
+      }
+      DEBUG(9,("find_name: found name %s(%02x)\n", 
+                name->name, name->name_type));
+      return ret;
+    }
+  }
+  DEBUG(9,("find_name: name %s(%02x) NOT FOUND\n", name->name, 
+            name->name_type));
+  return NULL;
 }
 
 
@@ -247,7 +262,7 @@ void dump_names(void)
       }
      DEBUG(4,("\n"));
 
-     if (f && n->source == REGISTER)
+     if (f && ((n->source == REGISTER) || (n->source == SELF)))
       {
       /* XXXX i have little imagination as to how to output nb_flags as
          anything other than as a hexadecimal number :-) */
@@ -258,11 +273,11 @@ void dump_names(void)
 
         for (i = 0; i < n->num_ips; i++)
         {
-           fprintf(f, "%s %2x ",
-                                               inet_ntoa(n->ip_flgs[i].ip),
-                                               n->ip_flgs[i].nb_flags);
+           fprintf(f, "%s %2x%c ",
+                inet_ntoa(n->ip_flgs[i].ip),
+                n->ip_flgs[i].nb_flags, (n->source == REGISTER ? 'R' : 'S'));
         }
-               fprintf(f, "\n");
+        fprintf(f, "\n");
       }
 
   }
@@ -339,6 +354,17 @@ void load_netbios_names(void)
          continue;
        }
 
+      /* Deal with SELF or REGISTER name encoding. Default is REGISTER 
+         for compatibility with old nmbds. */
+      if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
+      {
+        DEBUG(5,("Ignoring SELF name %s\n", line));
+        continue;
+      }
+
+      if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
+        nb_flags_str[strlen(nb_flags_str)-1] = '\0';
+
       /* netbios name. # divides the name from the type (hex): netbios#xx */
       strcpy(name,name_str);
 
@@ -417,21 +443,34 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
   struct name_record *n2=NULL;
   struct subnet_record *found_subnet = 0;
   int search = 0;
-  BOOL self = source == SELF;
+  BOOL self = (source == SELF);
 
   /* add the name to the WINS list if the name comes from a directed query */
   search |= wins ? FIND_WINS : FIND_LOCAL;
+
+  /* If it's a local search then we need to set the subnet
+     we are looking at. */
+  if(search & FIND_LOCAL)
+    found_subnet = d;
+
   /* search for SELF names only */
   search |= self ? FIND_SELF : 0;
 
   if (!self)
   {
-    if (!wins && type != 0x1b)
+    if (!wins && (type != 0x1b))
     {
        /* the only broadcast (non-WINS) names we are adding are ours
           (SELF) and Domain Master type names */
        return NULL;
     }
+    if(wins && (type == 0x1d))
+    {
+      /* Do not allow any 0x1d names to be registered in a WINS,
+         database although we return success for them.
+       */
+      return NULL;
+    }
   }
 
   n = (struct name_record *)malloc(sizeof(*n));
@@ -483,35 +522,37 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
   ******************************************************************/
 void expire_names(time_t t)
 {
-       struct name_record *n;
-       struct name_record *next;
-       struct subnet_record *d;
-
-       /* expire old names */
-       for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
-       {
-         for (n = d->namelist; n; n = next)
-           {
-             next = n->next;
-             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)));
+  struct name_record *n;
+  struct name_record *next;
+  struct subnet_record *d;
+
+  /* expire old names */
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+  {
+    for (n = d->namelist; n; n = next)
+    {
+      next = n->next;
+      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)));
                  
-                 if (n->prev) n->prev->next = n->next;
-                 if (n->next) n->next->prev = n->prev;
+        if (n->prev) n->prev->next = n->next;
+        if (n->next) n->next->prev = n->prev;
                  
-                 if (d->namelist == n) d->namelist = n->next; 
+        if (d->namelist == n) d->namelist = n->next; 
                  
-                 free(n->ip_flgs);
-                 free(n);
-               }
-           }
-       }
+        if(n->ip_flgs != NULL)
+          free(n->ip_flgs);
+        free(n);
+      }
+    }
+  }
 }
 
 
@@ -520,40 +561,39 @@ void expire_names(time_t t)
   ****************************************************************************/
 struct name_record *dns_name_search(struct nmb_name *question, int Time)
 {
-       int name_type = question->name_type;
-       char *qname = question->name;
-       char *r;
-       BOOL dns_type = (name_type == 0x20 || name_type == 0);
-       struct in_addr dns_ip;
-
-       if (wins_subnet == NULL) 
-          return NULL;
-
-       DEBUG(3,("Search for %s - ", namestr(question)));
-
-       /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
-       if (!dns_type)
-       {
-               DEBUG(3,("types 0x20 0x0 only: name not found\n"));
-               return NULL;
-       }
+  int name_type = question->name_type;
+  char *qname = question->name;
+  BOOL dns_type = (name_type == 0x20 || name_type == 0);
+  struct in_addr dns_ip;
 
-       /* look it up with DNS */      
-       dns_ip.s_addr = interpret_addr(qname);
-
-       if (!dns_ip.s_addr)
-       {
-               /* no luck with DNS. We could possibly recurse here XXXX */
-               DEBUG(3,("not found. no recursion.\n"));
-               /* add the fail to WINS cache of names. give it 1 hour in the cache */
-               add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,
-                                 True, True);
-               return NULL;
-       }
+  if (wins_subnet == NULL) 
+    return NULL;
+
+  DEBUG(3,("Search for %s - ", namestr(question)));
+
+  /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
+  if (!dns_type)
+  {
+    DEBUG(3,("types 0x20 0x0 only: name not found\n"));
+    return NULL;
+  }
+
+  /* look it up with DNS */      
+  dns_ip.s_addr = interpret_addr(qname);
+
+  if (!dns_ip.s_addr)
+  {
+    /* no luck with DNS. We could possibly recurse here XXXX */
+    DEBUG(3,("not found. no recursion.\n"));
+    /* add the fail to WINS cache of names. give it 1 hour in the cache */
+    add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,
+                  True, True);
+    return NULL;
+  }
 
-       DEBUG(3,("found with DNS: %s\n", inet_ntoa(dns_ip)));
+  DEBUG(3,("found with DNS: %s\n", inet_ntoa(dns_ip)));
 
-       /* add it to our WINS cache of names. give it 2 hours in the cache */
-       return add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
-                                True,True);
+  /* add it to our WINS cache of names. give it 2 hours in the cache */
+  return add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
+                         True,True);
 }