home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / namedbsubnet.c < prev    next >
C/C++ Source or Header  |  1997-07-31  |  11KB  |  364 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios routines and daemon - version 2
  5.    Copyright (C) Andrew Tridgell 1994-1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.    
  21.    Revision History:
  22.  
  23.    14 jan 96: lkcl@pires.co.uk
  24.    added multiple workgroup domain master support
  25.  
  26.    04 jul 96: lkcl@pires.co.uk
  27.    created module namedbsubnet containing subnet database functions
  28.  
  29. */
  30.  
  31. #include "includes.h"
  32. #include "smb.h"
  33.  
  34. extern int ClientNMB;
  35. extern int ClientDGRAM;
  36.  
  37. extern int DEBUGLEVEL;
  38.  
  39. extern struct in_addr wins_ip;
  40. extern struct in_addr ipzero;
  41.  
  42. extern pstring myname;
  43. extern fstring myworkgroup;
  44. extern char **my_netbios_names;
  45.  
  46. BOOL updatedlists = True;
  47. int updatecount = 0;
  48.  
  49. /* local interfaces structure */
  50. extern struct interface *local_interfaces;
  51.  
  52. /* this is our domain/workgroup/server database */
  53. struct subnet_record *subnetlist = NULL;
  54.  
  55. /* WINS subnet - keep this separate so enumeration code doesn't
  56.    run onto it by mistake. */
  57. struct subnet_record *wins_subnet = NULL;
  58.  
  59. extern uint16 nb_type; /* samba's NetBIOS name type */
  60.  
  61. /****************************************************************************
  62.   add a domain into the list
  63.   **************************************************************************/
  64. static void add_subnet(struct subnet_record *d)
  65. {
  66.   struct subnet_record *d2;
  67.  
  68.   if (!subnetlist)
  69.   {
  70.     subnetlist = d;
  71.     d->prev = NULL;
  72.     d->next = NULL;
  73.     return;
  74.   }
  75.  
  76.   for (d2 = subnetlist; d2->next; d2 = d2->next);
  77.  
  78.   d2->next = d;
  79.   d->next = NULL;
  80.   d->prev = d2;
  81. }
  82.  
  83.  
  84. /****************************************************************************
  85.   find a subnet in the subnetlist - not including WINS.
  86.   **************************************************************************/
  87. struct subnet_record *find_subnet(struct in_addr bcast_ip)
  88. {   
  89.   struct subnet_record *d;
  90.   
  91.   /* search through subnet list for broadcast/netmask that matches
  92.      the source ip address. */
  93.   
  94.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
  95.     {
  96.       if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
  97.         return d;
  98.     }
  99.   
  100.   return (NULL);
  101. }
  102.  
  103.  
  104. /****************************************************************************
  105.   finds the appropriate subnet structure. directed packets (non-bcast) are
  106.   assumed to come from a point-to-point (P or M node), and so the subnet we
  107.   return in this instance is the WINS 'pseudo-subnet' with ip 255.255.255.255
  108.   ****************************************************************************/
  109. struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast)
  110. {
  111.   if (bcast)
  112.   {
  113.     /* identify the subnet the broadcast request came from */
  114.     return find_subnet(*iface_bcast(ip));
  115.   }
  116.   /* Return the subnet with the pseudo-ip of 255.255.255.255 */
  117.   return wins_subnet;
  118. }
  119.  
  120. /****************************************************************************
  121.   find a subnet in the subnetlist - if the subnet is not found
  122.   then return the WINS subnet.
  123.   **************************************************************************/
  124. struct subnet_record *find_subnet_all(struct in_addr bcast_ip)
  125. {
  126.   struct subnet_record *d = find_subnet(bcast_ip);
  127.   if(!d)
  128.     return wins_subnet;
  129.   return d;
  130. }
  131.  
  132. /****************************************************************************
  133.   create a domain entry
  134.   ****************************************************************************/
  135. static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip, BOOL add)
  136. {
  137.   struct subnet_record *d;
  138.   d = (struct subnet_record *)malloc(sizeof(*d));
  139.   
  140.   if (!d) return(NULL);
  141.   
  142.   bzero((char *)d,sizeof(*d));
  143.   
  144.   DEBUG(4, ("making subnet %s ", inet_ntoa(bcast_ip)));
  145.   DEBUG(4, ("%s\n", inet_ntoa(mask_ip)));
  146.   
  147.   d->bcast_ip = bcast_ip;
  148.   d->mask_ip  = mask_ip;
  149.   d->workgrouplist = NULL;
  150.   
  151.   if(add)
  152.     add_subnet(d);
  153.   
  154.   return d;
  155. }
  156.  
  157. /****************************************************************************
  158.   add a domain entry. creates a workgroup, if necessary, and adds the domain
  159.   to the named a workgroup.
  160.   ****************************************************************************/
  161. static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, 
  162.                        struct in_addr mask_ip, char *name, 
  163.                                        BOOL create_subnets, BOOL add)
  164. {
  165.   struct subnet_record *d = NULL;
  166.  
  167.   if (zero_ip(bcast_ip)) 
  168.     bcast_ip = *iface_bcast(bcast_ip);
  169.   
  170.   /* Note that we should also add into the WINS subnet as add_subnet_entry
  171.     should be called to add NetBIOS names and server entries on all
  172.     interfaces, including the WINS interface
  173.    */
  174.  
  175.   if(create_subnets == True)
  176.   {
  177.     /* Create new subnets. */
  178.     if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL)
  179.     {
  180.       DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n",
  181.                inet_ntoa(bcast_ip) ));
  182.       return NULL;
  183.     }
  184.     return d;
  185.   }
  186.   if(ip_equal(bcast_ip, wins_ip))
  187.     return wins_subnet;
  188.   return find_subnet(bcast_ip);
  189. }
  190.  
  191. /****************************************************************************
  192.  Add a workgroup into a subnet, and if it's our primary workgroup,
  193.  add the required names to it.
  194. **************************************************************************/
  195.  
  196. void add_workgroup_to_subnet( struct subnet_record *d, char *group)
  197. {
  198.   struct work_record *w = NULL;
  199.  
  200.   DEBUG(5,("add_workgroup_to_subnet: Adding workgroup %s to subnet %s\n",
  201.             group, inet_ntoa(d->bcast_ip)));
  202.  
  203.   /* This next statement creates the workgroup struct if it doesn't
  204.      already exist. 
  205.    */
  206.   if((w = find_workgroupstruct(d, group, True)) == NULL)
  207.   {
  208.     DEBUG(0,("add_workgroup_to_subnet: Unable to add workgroup %s to subnet %s\n",
  209.               group, inet_ntoa(d->bcast_ip) ));
  210.     return;
  211.   }
  212.  
  213.   /* add WORKGROUP(00) entries into name database
  214.      or register with WINS server, if it's our workgroup.
  215.    */
  216.   if (strequal(myworkgroup, group))
  217.   {
  218.     int n;
  219.  
  220.     add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
  221.     add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
  222.  
  223.     /* Add all our server names to the workgroup list. We remove any
  224.        browser or logon server flags from all but the primary name.
  225.      */
  226.     for( n = 0; my_netbios_names[n]; n++)
  227.     {    
  228.       char *name = my_netbios_names[n];
  229.       int stype = w->ServerType;
  230.  
  231.       if(!strequal(myname, name))
  232.           stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
  233.                      SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
  234.  
  235.       add_server_entry(d,w,name,stype|SV_TYPE_LOCAL_LIST_ONLY,0,
  236.         lp_serverstring(),True);
  237.       DEBUG(3,("add_workgroup_to_subnet: Added server name entry %s \
  238. to subnet %s\n", name, inet_ntoa(d->bcast_ip)));
  239.     }
  240.   }
  241. }
  242.  
  243. /****************************************************************************
  244.   create subnet / workgroup / server entries
  245.      
  246.   - add or create the subnet lists
  247.   - add or create the workgroup entries in each subnet entry
  248.   - register appropriate NetBIOS names for the workgroup entries
  249.      
  250. **************************************************************************/
  251. void add_my_subnets(char *group)
  252. {    
  253.   static BOOL create_subnets = True;
  254.   struct subnet_record *d = NULL;
  255.   struct interface *i = NULL;
  256.  
  257.   if (*group == '*') return;
  258.  
  259.   /* Create subnets from all the local interfaces and thread them onto
  260.      the linked list. 
  261.    */
  262.   for (i = local_interfaces; i; i = i->next)
  263.   {
  264.     add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True);
  265.   }
  266.  
  267.   /* If we are using WINS, then we must add the workgroup to the WINS
  268.      subnet. This is used as a place to keep collated server lists.
  269.    */
  270.  
  271.   /* Create the WINS subnet if we are using WINS - but don't thread it
  272.      onto the linked subnet list. 
  273.    */    
  274.   if (lp_wins_support() || lp_wins_server())
  275.   {
  276.     struct in_addr wins_nmask = ipzero;
  277.     wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False);
  278.   }
  279.  
  280.   /* Ensure we only create the subnets once. */
  281.   create_subnets = False;
  282.  
  283.   /* Now we have created all the subnets - we can add the names
  284.      that make us a client member in the workgroup.
  285.    */
  286.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
  287.     add_workgroup_to_subnet(d, group);
  288. }
  289.  
  290. /*******************************************************************
  291.   write out browse.dat
  292.   ******************************************************************/
  293. void write_browse_list(time_t t)
  294. {
  295.   struct subnet_record *d;
  296.   pstring fname,fnamenew;
  297.   FILE *f;
  298.  
  299.   static time_t lasttime = 0;
  300.  
  301.   if (!lasttime) lasttime = t;
  302.   if (!updatedlists || t - lasttime < 5) return;
  303.   
  304.   lasttime = t;
  305.   updatedlists = False;
  306.   updatecount++;
  307.   
  308.   dump_names();
  309.   dump_workgroups();
  310.   
  311.   strcpy(fname,lp_lockdir());
  312.   trim_string(fname,NULL,"/");
  313.   strcat(fname,"/");
  314.   strcat(fname,SERVER_LIST);
  315.   strcpy(fnamenew,fname);
  316.   strcat(fnamenew,".");
  317.   
  318.   f = fopen(fnamenew,"w");
  319.   
  320.   if (!f)
  321.     {
  322.       DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
  323.       return;
  324.     }
  325.   
  326.   for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d))
  327.     {
  328.       struct work_record *work;
  329.       for (work = d->workgrouplist; work ; work = work->next)
  330.     {
  331.       struct server_record *s;
  332.       for (s = work->serverlist; s ; s = s->next)
  333.         {
  334.           fstring tmp;
  335.           
  336.           /* don't list domains I don't have a master for */
  337.           if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0])
  338.         {
  339.           continue;
  340.         }
  341.           
  342.           /* output server details, plus what workgroup/domain
  343.          they're in. without the domain information, the
  344.          combined list of all servers in all workgroups gets
  345.          sent to anyone asking about any workgroup! */
  346.           
  347.           sprintf(tmp, "\"%s\"", s->serv.name);
  348.           fprintf(f, "%-25s ", tmp);
  349.           fprintf(f, "%08x ", s->serv.type);
  350.           sprintf(tmp, "\"%s\" ", s->serv.comment);
  351.           fprintf(f, "%-30s", tmp);
  352.           fprintf(f, "\"%s\"\n", work->work_group);
  353.         }
  354.     }
  355.     }
  356.   
  357.   fclose(f);
  358.   unlink(fname);
  359.   chmod(fnamenew,0644);
  360.   rename(fnamenew,fname);   
  361.   DEBUG(3,("Wrote browse list %s\n",fname));
  362. }
  363.  
  364.