JHT ===> Update only.
[samba.git] / source / namework.c
index 108048d5001de7d011ef28f0286c42662085aefe..3e1ac220058bd20b3578d745a46fc9fa7b61c99f 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    NBT netbios routines and daemon - version 2
-   Copyright (C) Andrew Tridgell 1994-1996
+   Copyright (C) Andrew Tridgell 1994-1997
    
    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
@@ -37,6 +37,7 @@ extern pstring scope;
 extern BOOL CanRecurse;
 
 extern pstring myname;
+extern fstring myworkgroup;
 
 extern int ClientNMB;
 extern int ClientDGRAM;
@@ -48,16 +49,8 @@ extern int workgroup_count; /* total number of workgroups we know about */
 /* this is our domain/workgroup/server database */
 extern struct subnet_record *subnetlist;
 
-/* machine comment for host announcements */
-extern  pstring ServerComment;
-
 extern int  updatecount;
 
-/* what server type are we currently */
-#define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \
-               SV_TYPE_TIME_SOURCE | SV_TYPE_SERVER_UNIX |\
-               SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER)
-
 /* backup request types: which servers are to be included */
 #define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
 #define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL   )
@@ -87,7 +80,8 @@ void reset_server(char *name, int state, struct in_addr ip)
   DEBUG(2,("sending reset to %s %s of state %d\n",
           name,inet_ntoa(ip),state));
 
-  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+  send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+              outbuf,PTR_DIFF(p,outbuf),
                      myname,name,0x20,0x1d,ip,*iface_ip(ip));
 }
 
@@ -103,7 +97,7 @@ void tell_become_backup(void)
    */
 
   struct subnet_record *d;
-  for (d = subnetlist; d; d = d->next)
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
     {
       struct work_record *work;
       for (work = d->workgrouplist; work; work = work->next)
@@ -118,7 +112,7 @@ void tell_become_backup(void)
              
              num_servers++;
              
-             if (strequal(myname, s->serv.name)) continue;
+             if (is_myname(s->serv.name)) continue;
              
              if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
                num_backups++;
@@ -159,23 +153,7 @@ void tell_become_backup(void)
 BOOL same_context(struct dgram_packet *dgram)
 {
   if (!strequal(dgram->dest_name  .scope,scope )) return(True);
-  if ( strequal(dgram->source_name.name ,myname)) return(True);
-  
-  return(False);
-}
-
-
-/*******************************************************************
-  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);
-    }
+  if ( is_myname(dgram->source_name.name)) return(True);
   
   return(False);
 }
@@ -196,11 +174,10 @@ BOOL listening_name(struct work_record *work, struct nmb_name *n)
   resources. We just have to pass it to smbd (via browser.dat) and let
   the client choose using bit masks.
   ******************************************************************/
-static void process_announce(struct packet_struct *p,uint16 command,char *buf)
+static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
-  struct in_addr ip = dgram->header.source_ip;
-  struct subnet_record *d = find_subnet(ip); 
+  struct subnet_record *d = find_subnet(p->ip);  /* Explicitly exclude WINS - local nets only */
   int update_count = CVAL(buf,0);
 
   int ttl = IVAL(buf,1)/1000;
@@ -237,7 +214,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
        dgram->dest_name.name_type != 0x1))
     {
       DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
-               command, inet_ntoa(ip), namestr(&dgram->dest_name)));
+               command, inet_ntoa(p->ip), namestr(&dgram->dest_name)));
       return;
     }
   
@@ -267,6 +244,9 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
        dgram->dest_name.name_type == 0x1e))
     add = True;
   
+  DEBUG(4,("search for workgroup: %s (add? %s)\n",
+            work_name, BOOLSTR(add)));
+
   if (!(work = find_workgroupstruct(d, work_name,add)))
     return;
   
@@ -275,7 +255,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
   ttl = GET_TTL(ttl);
   
   /* add them to our browse list, and update the browse.dat file */
-  add_server_entry(d,work,name,servertype,ttl,comment,True);
+  add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
   updatedlists = True;
 
 #if 0
@@ -283,43 +263,43 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
      disabling it */
   tell_become_backup();
 #endif
-
-  /* get the local_only browse list from the local master and add it 
-     to ours. */
-  if (command == ANN_LocalMasterAnnouncement)
-  {
-    add_browser_entry(serv_name,dgram->dest_name.name_type,
-                     work->work_group,30,ip,True);
-  }
 }
 
 /*******************************************************************
   process a master announcement frame
+  Domain master browsers recieve these from local masters. The Domain
+  master should then issue a sync with the local master, asking for
+  that machines local server list.
   ******************************************************************/
 static void process_master_announce(struct packet_struct *p,char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
-  struct in_addr ip = dgram->header.source_ip;
-  struct subnet_record *d = find_subnet(ip);
-  struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
   char *name = buf;
   struct work_record *work;
   name[15] = 0;
   
-  DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
+  DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
   
   if (same_context(dgram)) return;
   
-  if (!d || !mydomain) return;
+  if (!wins_subnet) 
+    {
+      DEBUG(3,("process_master_announce: No wins subnet !\n"));
+      return;
+    }
   
-  if (!lp_domain_master()) return;
+  if (!lp_domain_master()) 
+    {
+      DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n"));
+      return;
+    }
   
-  for (work = mydomain->workgrouplist; work; work = work->next)
+  for (work = wins_subnet->workgrouplist; work; work = work->next)
   {
-    if (AM_MASTER(work))
+    if (AM_MASTER(work) || AM_DOMMST(work))
     {
          /* merge browse lists with them */
-         add_browser_entry(name,0x1b, work->work_group,30,ip,True);
+         add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True);
     }
   }
 }
@@ -340,13 +320,12 @@ static void process_master_announce(struct packet_struct *p,char *buf)
 static void process_rcv_backup_list(struct packet_struct *p,char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
-  struct in_addr ip = dgram->header.source_ip;
   int count = CVAL(buf,0);
   uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
   char *buf1;
   
   DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
-          namestr(&dgram->dest_name), inet_ntoa(ip),
+          namestr(&dgram->dest_name), inet_ntoa(p->ip),
           count, info));
   
   if (same_context(dgram)) return;
@@ -357,10 +336,10 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
   for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
   {
     struct in_addr back_ip;
-    struct subnet_record *d;
+    /* struct subnet_record *d; */
       
     DEBUG(4,("Searching for backup browser %s at %s...\n",
-              buf1, inet_ntoa(ip)));
+              buf1, inet_ntoa(p->ip)));
       
     /* XXXX assume name is a DNS name NOT a netbios name. a more complete
           approach is to use reply_name_query functionality to find the name */
@@ -376,8 +355,9 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
       DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
       DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
       
+#if 0
       /* XXXX function needs work */
-         continue;
+      continue;
 
     if ((d = find_subnet(back_ip)))
        {
@@ -398,6 +378,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
                }
          }
        }
+#endif
   }
 }
 
@@ -448,7 +429,7 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
 
 #if 0
 
-  for (d = subnetlist; d; d = d->next)
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
   {
       struct work_record *work;
       
@@ -511,7 +492,8 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
     int len = PTR_DIFF(p, outbuf);
     debug_browse_data(outbuf, len);
   }
-  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+  send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+              outbuf,PTR_DIFF(p,outbuf),
                      myname,theirname,0x0,0x0,ip,*iface_ip(ip));
 }
 
@@ -586,14 +568,14 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
   if (state & 0x1)
     {
       struct subnet_record *d;
-      for (d = subnetlist; d; d = d->next)
+      for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
        {
          struct work_record *work;
          for (work = d->workgrouplist; work; work = work->next)
            {
              if (AM_MASTER(work))
                {
-                 become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
+                 unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
                }
            }
        }
@@ -607,12 +589,12 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
   if (state & 0x2)
     {
       struct subnet_record *d;
-      for (d = subnetlist; d; d = d->next)
+      for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
        {
          struct work_record *work;
          for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
        }
-      add_my_subnets(lp_workgroup());
+      add_my_subnets(myworkgroup);
     }
   
   /* stop browsing altogether. i don't think this is a good idea! */
@@ -633,26 +615,31 @@ static void process_announce_request(struct packet_struct *p,char *buf)
   struct dgram_packet *dgram = &p->packet.dgram;
   struct work_record *work;
   struct in_addr ip = dgram->header.source_ip;
-  struct subnet_record *d = find_subnet(ip);
+  struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */
   int token = CVAL(buf,0);
   char *name = buf+1;
   
   name[15] = 0;
   
-  DEBUG(3,("Announce request from %s to %s token=0x%X\n",
+  DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n",
           name,namestr(&dgram->dest_name), token));
   
-  if (strequal(dgram->source_name.name,myname)) return;
+  if (is_myname(dgram->source_name.name)) return;
   
   /* XXXX BUG or FEATURE?: need to ensure that we are a member of
      this workgroup before announcing, particularly as we only
      respond on local interfaces anyway.
 
-     if (strequal(dgram->dest_name, lp_workgroup()) return; ???
+     if (strequal(dgram->dest_name, myworkgroup) return; ???
    */
 
-  if (!d) return;
-  
+  if (!d) 
+    {
+      DEBUG(3,("process_announce_request: No local interface to announce to %s\n",
+                name));
+      return;
+    }
   for (work = d->workgrouplist; work; work = work->next)
     {
      /* XXXX BUG: the destination name type should also be checked,
@@ -667,70 +654,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
@@ -745,7 +668,7 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
     case ANN_LocalMasterAnnouncement:
       {
         debug_browse_data(buf, len);
-       process_announce(p,command,buf+1);
+       process_localnet_announce(p,command,buf+1);
        break;
       }