home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / nmbd_namelistdb.c < prev    next >
C/C++ Source or Header  |  1998-05-12  |  19KB  |  587 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-1998
  6.    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
  7.    Copyright (C) Jeremy Allison 1994-1998
  8.    
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2 of the License, or
  12.    (at your option) any later version.
  13.    
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.    
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.    
  23. */
  24.  
  25. #include "includes.h"
  26.  
  27. extern int DEBUGLEVEL;
  28.  
  29. extern pstring scope;
  30. extern char **my_netbios_names;
  31.  
  32. uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
  33.  
  34.  
  35. /****************************************************************************
  36.   Set Samba's NetBIOS name type.
  37.   ****************************************************************************/
  38.  
  39. void set_samba_nb_type(void)
  40. {
  41.   if (lp_wins_support() || (*lp_wins_server()))
  42.     samba_nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
  43.   else
  44.     samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type */
  45. }
  46.  
  47. /****************************************************************************
  48.   Returns True if the netbios name is ^1^2__MSBROWSE__^2^1.
  49.  
  50.   Note: This name is registered if as a master browser or backup browser
  51.   you are responsible for a workgroup (when you announce a domain by
  52.   broadcasting on your local subnet, you announce it as coming from this
  53.   name: see announce_host()).
  54.  
  55.   **************************************************************************/
  56.  
  57. BOOL ms_browser_name(char *name, int type)
  58. {
  59.   return (strequal(name,MSBROWSE) && (type == 0x01));
  60. }
  61.  
  62. /****************************************************************************
  63.   Add a netbios name into a namelist.
  64.   **************************************************************************/
  65.  
  66. static void add_name_to_namelist(struct subnet_record *subrec, 
  67.                                  struct name_record *namerec)
  68. {
  69.   struct name_record *namerec2;
  70.  
  71.   if (!subrec->namelist)
  72.   {
  73.     subrec->namelist = namerec;
  74.     namerec->prev = NULL;
  75.     namerec->next = NULL;
  76.     return;
  77.   }
  78.  
  79.   for (namerec2 = subrec->namelist; namerec2->next; namerec2 = namerec2->next) 
  80.     ;
  81.  
  82.   namerec2->next = namerec;
  83.   namerec->next = NULL;
  84.   namerec->prev = namerec2;
  85.   namerec->subnet = subrec;
  86.  
  87.   subrec->namelist_changed = True;
  88. }
  89.  
  90. /****************************************************************************
  91.   Remove a name from the namelist.
  92.   **************************************************************************/
  93.  
  94. void remove_name_from_namelist(struct subnet_record *subrec, 
  95.                                struct name_record *namerec)
  96. {
  97.   if (namerec->next)
  98.     namerec->next->prev = namerec->prev;
  99.   if (namerec->prev)
  100.     namerec->prev->next = namerec->next;
  101.  
  102.   if(namerec == subrec->namelist)
  103.     subrec->namelist = namerec->next;
  104.  
  105.   if(namerec->ip != NULL)
  106.     free((char *)namerec->ip);
  107.   free((char *)namerec);
  108.  
  109.   subrec->namelist_changed = True;
  110. }
  111.  
  112.  
  113. /****************************************************************************
  114.   Find a name in a subnet.
  115.   **************************************************************************/
  116.  
  117. struct name_record *find_name_on_subnet(struct subnet_record *subrec,
  118.                                       struct nmb_name *nmbname, BOOL self_only)
  119. {
  120.   struct name_record *namerec = subrec->namelist;
  121.   struct name_record *name_ret;
  122.   
  123.   for (name_ret = namerec; name_ret; name_ret = name_ret->next)
  124.   {
  125.     if (nmb_name_equal(&name_ret->name, nmbname))
  126.     {
  127.       /* Self names only - these include permanent names. */
  128.       if (self_only && (name_ret->source != SELF_NAME) && 
  129.               (name_ret->source != PERMANENT_NAME) )
  130.       {
  131.         continue;
  132.       }
  133.       DEBUG(9,("find_name_on_subnet: on subnet %s - found name %s source=%d\n", 
  134.                 subrec->subnet_name, namestr(nmbname), name_ret->source));
  135.       return name_ret;
  136.     }
  137.   }
  138.   DEBUG(9,("find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", 
  139.             subrec->subnet_name, namestr(nmbname)));
  140.   return NULL;
  141. }
  142.  
  143. /****************************************************************************
  144.   Find a name over all known broadcast subnets.
  145. **************************************************************************/
  146.  
  147. struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname, 
  148.                                                            BOOL self_only)
  149. {
  150.   struct subnet_record *subrec;
  151.   struct name_record *namerec = NULL;
  152.  
  153.   for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
  154.   {
  155.     if((namerec = find_name_on_subnet(subrec, nmbname, self_only))!= NULL)
  156.       break;
  157.   }
  158.  
  159.   return namerec;
  160. }    
  161.   
  162. /****************************************************************************
  163.   Update the ttl of an entry in a subnet name list.
  164.   ****************************************************************************/
  165.  
  166. void update_name_ttl(struct name_record *namerec, int ttl)
  167. {
  168.   time_t time_now = time(NULL);
  169.  
  170.   if(namerec->death_time != PERMANENT_TTL)
  171.     namerec->death_time = time_now + ttl;
  172.  
  173.   namerec->refresh_time = time_now + (ttl/2);
  174.  
  175.   namerec->subnet->namelist_changed = True;
  176.  
  177. /****************************************************************************
  178.   Add an entry to a subnet name list.
  179.   ****************************************************************************/
  180.  
  181. struct name_record *add_name_to_subnet(struct subnet_record *subrec,
  182.         char *name, int type, uint16 nb_flags, int ttl, 
  183.                 enum name_source source, int num_ips, struct in_addr *iplist)
  184. {
  185.   struct name_record *namerec;
  186.   time_t time_now = time(NULL);
  187.  
  188.   if((namerec = (struct name_record *)malloc(sizeof(*namerec))) == NULL)
  189.   {
  190.     DEBUG(0,("add_name_to_subnet: malloc fail.\n"));
  191.     return NULL;
  192.   }
  193.  
  194.   bzero((char *)namerec,sizeof(*namerec));
  195.  
  196.   namerec->subnet = subrec;
  197.  
  198.   namerec->num_ips = num_ips;
  199.   namerec->ip = (struct in_addr *)malloc(sizeof(struct in_addr) * namerec->num_ips);
  200.   if (!namerec->ip)
  201.   {
  202.      DEBUG(0,("add_name_to_subnet: malloc fail when creating ip_flgs.\n"));
  203.      free((char *)namerec);
  204.      return NULL;
  205.   }
  206.  
  207.   bzero((char *)namerec->ip, sizeof(struct in_addr) * namerec->num_ips);
  208.  
  209.   memcpy(&namerec->ip[0], iplist, num_ips * sizeof(struct in_addr));
  210.  
  211.   make_nmb_name(&namerec->name,name,type,scope);
  212.  
  213.   /* Setup the death_time and refresh_time. */
  214.   if(ttl == PERMANENT_TTL)
  215.     namerec->death_time = PERMANENT_TTL;
  216.   else
  217.     namerec->death_time = time_now + ttl;
  218.  
  219.   namerec->refresh_time = time_now + (ttl/2);
  220.  
  221.   /* Enter the name as active. */
  222.   namerec->nb_flags = nb_flags | NB_ACTIVE;
  223.  
  224.   /* If it's our primary name, flag it as so. */
  225.   if(strequal(my_netbios_names[0],name))
  226.     namerec->nb_flags |= NB_PERM;
  227.  
  228.   namerec->source = source;
  229.   
  230.   add_name_to_namelist(subrec,namerec);
  231.  
  232.   DEBUG(3,("add_name_to_subnet: Added netbios name %s with first IP %s ttl=%d nb_flags=%2x to subnet %s\n",
  233.        namestr(&namerec->name),inet_ntoa(*iplist),ttl,(unsigned int)nb_flags,
  234.        subrec->subnet_name));
  235.  
  236.   subrec->namelist_changed = True;
  237.  
  238.   return(namerec);
  239. }
  240.  
  241. /*******************************************************************
  242.  Utility function automatically called when a name refresh or register 
  243.  succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
  244.  it).
  245.  ******************************************************************/
  246.  
  247. void standard_success_register(struct subnet_record *subrec, 
  248.                              struct userdata_struct *userdata,
  249.                              struct nmb_name *nmbname, uint16 nb_flags, int ttl,
  250.                              struct in_addr registered_ip)
  251. {
  252.   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
  253.  
  254.   if(namerec == NULL)
  255.     add_name_to_subnet(subrec, nmbname->name, nmbname->name_type,
  256.                      nb_flags, ttl, SELF_NAME, 1, ®istered_ip);
  257.   else
  258.     update_name_ttl(namerec, ttl);
  259. }
  260.  
  261. /*******************************************************************
  262.  Utility function automatically called when a name refresh or register 
  263.  fails.
  264.  ******************************************************************/
  265.  
  266. void standard_fail_register(struct subnet_record *subrec, 
  267.                              struct response_record *rrec, struct nmb_name *nmbname)
  268. {
  269.   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
  270.  
  271.   DEBUG(0,("standard_fail_register: Failed to register/refresh name %s on subnet %s\n",
  272.            namestr(nmbname), subrec->subnet_name));
  273.  
  274.   /* Remove the name from the subnet. */
  275.   if(namerec)
  276.     remove_name_from_namelist(subrec, namerec);
  277. }
  278.  
  279. /*******************************************************************
  280.  Utility function to remove an IP address from a name record.
  281.  ******************************************************************/
  282.  
  283. static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
  284. {
  285.   if(ind != namerec->num_ips)
  286.     memmove( (char *)(&namerec->ip[ind]), (char *)(&namerec->ip[ind+1]), 
  287.               ( namerec->num_ips - ind - 1) * sizeof(struct in_addr));
  288.  
  289.   namerec->num_ips--;
  290.   namerec->subnet->namelist_changed = True;
  291. }
  292.  
  293. /*******************************************************************
  294.  Utility function to check if an IP address exists in a name record.
  295.  ******************************************************************/
  296.  
  297. BOOL find_ip_in_name_record(struct name_record *namerec, struct in_addr ip)
  298. {
  299.   int i;
  300.  
  301.   for(i = 0; i < namerec->num_ips; i++)
  302.     if(ip_equal( namerec->ip[i], ip))
  303.       return True;
  304.  
  305.   return False;
  306. }
  307.  
  308. /*******************************************************************
  309.  Utility function to add an IP address to a name record.
  310.  ******************************************************************/
  311.  
  312. void add_ip_to_name_record(struct name_record *namerec, struct in_addr new_ip)
  313. {
  314.   struct in_addr *new_list;
  315.  
  316.   /* Don't add one we already have. */
  317.   if(find_ip_in_name_record( namerec, new_ip))
  318.     return;
  319.   
  320.   if((new_list = (struct in_addr *)malloc( (namerec->num_ips + 1)*sizeof(struct in_addr)) )== NULL)
  321.   {
  322.     DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
  323.     return;
  324.   }
  325.  
  326.   memcpy((char *)new_list, (char *)namerec->ip, namerec->num_ips *sizeof(struct in_addr));
  327.   new_list[namerec->num_ips] = new_ip;
  328.  
  329.   free((char *)namerec->ip);
  330.   namerec->ip = new_list;
  331.   namerec->num_ips += 1;
  332.  
  333.   namerec->subnet->namelist_changed = True;
  334. }
  335.  
  336. /*******************************************************************
  337.  Utility function to remove an IP address from a name record.
  338.  ******************************************************************/
  339.  
  340. void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip)
  341. {
  342.   /* Try and find the requested ip address - remove it. */
  343.   int i;
  344.   int orig_num = namerec->num_ips;
  345.  
  346.   for(i = 0; i < orig_num; i++)
  347.     if( ip_equal( remove_ip, namerec->ip[i]) )
  348.     {
  349.       remove_nth_ip_in_record( namerec, i);
  350.       break;
  351.     }
  352. }
  353.  
  354. /*******************************************************************
  355.  Utility function that release_name callers can plug into as the
  356.  success function when a name release is successful. Used to save
  357.  duplication of success_function code.
  358.  ******************************************************************/
  359.  
  360. void standard_success_release(struct subnet_record *subrec, 
  361.                              struct userdata_struct *userdata,
  362.                              struct nmb_name *nmbname, struct in_addr released_ip)
  363. {
  364.   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME);
  365.  
  366.   if(namerec == NULL)
  367.   {
  368.     DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. Name \
  369. was not found on subnet.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name));
  370.     return;
  371.   }
  372.   else
  373.   {
  374.     int orig_num = namerec->num_ips;
  375.  
  376.     remove_ip_from_name_record( namerec, released_ip);
  377.  
  378.     if(namerec->num_ips == orig_num)
  379.       DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. This ip \
  380. is not known for this name.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ));
  381.   }
  382.  
  383.   if (namerec->num_ips == 0)
  384.     remove_name_from_namelist(subrec, namerec);
  385. }
  386.  
  387. /*******************************************************************
  388.   Expires old names in a subnet namelist.
  389.   ******************************************************************/
  390.  
  391. void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
  392. {
  393.   struct name_record *namerec;
  394.   struct name_record *next_namerec;
  395.  
  396.   for (namerec = subrec->namelist; namerec; namerec = next_namerec)
  397.   {
  398.     next_namerec = namerec->next;
  399.     if ((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < t))
  400.     {
  401.       if (namerec->source == SELF_NAME)
  402.       {
  403.         DEBUG(3,("expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", 
  404.              subrec->subnet_name, namestr(&namerec->name)));
  405.         namerec->death_time += 300;
  406.         namerec->subnet->namelist_changed = True;
  407.         continue;
  408.       }
  409.       DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", 
  410.                  subrec->subnet_name, namestr(&namerec->name)));
  411.   
  412.       remove_name_from_namelist(subrec, namerec);
  413.     }
  414.   }
  415. }
  416.  
  417. /*******************************************************************
  418.   Expires old names in all subnet namelists.
  419.   ******************************************************************/
  420.  
  421. void expire_names(time_t t)
  422. {
  423.   struct subnet_record *subrec;
  424.  
  425.   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
  426.   {
  427.     expire_names_on_subnet(subrec, t);
  428.   }
  429. }
  430.  
  431. /****************************************************************************
  432.   Add the magic samba names, useful for finding samba servers.
  433.   These go directly into the name list for a particular subnet,
  434.   without going through the normal registration process.
  435.   When adding them to the unicast subnet, add them as a list of
  436.   all broadcast subnet IP addresses.
  437. **************************************************************************/
  438.  
  439. void add_samba_names_to_subnet(struct subnet_record *subrec)
  440. {
  441.   struct in_addr *iplist = &subrec->myip;
  442.   int num_ips = 1;
  443.  
  444.   /* These names are added permanently (ttl of zero) and will NOT be
  445.      refreshed.  */
  446.  
  447.   if((subrec == unicast_subnet) || (subrec == wins_server_subnet))
  448.   {
  449.     struct subnet_record *bcast_subrecs;
  450.     int i;
  451.     /* Create an IP list containing all our known subnets. */
  452.  
  453.     num_ips = iface_count();
  454.     if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
  455.     {
  456.       DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
  457.       return;
  458.     }
  459.  
  460.     for(bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs; 
  461.                  bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++)
  462.       iplist[i] = bcast_subrecs->myip;
  463.  
  464.   }
  465.  
  466.   add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
  467.                      PERMANENT_NAME, num_ips, iplist);
  468.   add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
  469.                      PERMANENT_NAME, num_ips, iplist);
  470.   add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
  471.                    PERMANENT_NAME, num_ips, iplist);
  472.   add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
  473.                    PERMANENT_NAME, num_ips, iplist);
  474.  
  475.   if(iplist != &subrec->myip)
  476.     free((char *)iplist);
  477. }
  478.  
  479. /****************************************************************************
  480.  Dump the contents of the namelists on all the subnets (including unicast)
  481.  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
  482. **************************************************************************/
  483.  
  484. static void dump_subnet_namelist( struct subnet_record *subrec, FILE *fp)
  485. {
  486.   struct name_record *namerec;
  487.   char *src_type;
  488.   struct tm *tm;
  489.   int i;
  490.  
  491.   fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
  492.   for (namerec = subrec->namelist; namerec; namerec = namerec->next)
  493.   {
  494.     fprintf(fp,"\tName = %s\t", namestr(&namerec->name));
  495.     switch(namerec->source)
  496.     {
  497.       case LMHOSTS_NAME:
  498.         src_type = "LMHOSTS_NAME";
  499.         break;
  500.       case WINS_PROXY_NAME:
  501.         src_type = "WINS_PROXY_NAME";
  502.         break;
  503.       case REGISTER_NAME:
  504.         src_type = "REGISTER_NAME";
  505.         break;
  506.       case SELF_NAME:
  507.         src_type = "SELF_NAME";
  508.         break;
  509.       case DNS_NAME:
  510.         src_type = "DNS_NAME";
  511.         break;
  512.       case DNSFAIL_NAME:
  513.         src_type = "DNSFAIL_NAME";
  514.         break;
  515.       case PERMANENT_NAME:
  516.         src_type = "PERMANENT_NAME";
  517.         break;
  518.       default:
  519.         src_type = "unknown!";
  520.         break;
  521.     }
  522.     fprintf(fp, "Source = %s\nb_flags = %x\t", src_type, namerec->nb_flags);
  523.  
  524.     if(namerec->death_time != PERMANENT_TTL)
  525.     {
  526.       tm = LocalTime(&namerec->death_time);
  527.       fprintf(fp, "death_time = %s\t", asctime(tm));
  528.     }
  529.     else
  530.       fprintf(fp, "death_time = PERMANENT\t");
  531.  
  532.     if(namerec->refresh_time != PERMANENT_TTL)
  533.     {
  534.       tm = LocalTime(&namerec->refresh_time);
  535.       fprintf(fp, "refresh_time = %s\n", asctime(tm));
  536.     }
  537.     else
  538.       fprintf(fp, "refresh_time = PERMANENT\n");
  539.  
  540.     fprintf(fp, "\t\tnumber of IPS = %d", namerec->num_ips);
  541.     for(i = 0; i < namerec->num_ips; i++)
  542.       fprintf(fp, "\t%s", inet_ntoa(namerec->ip[i]));
  543.  
  544.     fprintf(fp, "\n\n");
  545.   }
  546. }
  547.  
  548. /****************************************************************************
  549.  Dump the contents of the namelists on all the subnets (including unicast)
  550.  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
  551. **************************************************************************/
  552.  
  553. void dump_all_namelists(void)
  554. {
  555.   pstring fname;
  556.   FILE *fp; 
  557.   struct subnet_record *subrec;
  558.  
  559.   pstrcpy(fname,lp_lockdir());
  560.   trim_string(fname,NULL,"/");
  561.   pstrcat(fname,"/"); 
  562.   pstrcat(fname,"namelist.debug");
  563.  
  564.   fp = fopen(fname,"w");
  565.      
  566.   if (!fp)
  567.   { 
  568.     DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
  569.               fname,strerror(errno)));
  570.     return;
  571.   }
  572.       
  573.   for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
  574.     dump_subnet_namelist( subrec, fp);
  575.  
  576.   if(!we_are_a_wins_client())
  577.     dump_subnet_namelist(unicast_subnet, fp);
  578.  
  579.   if(remote_broadcast_subnet->namelist != NULL)
  580.     dump_subnet_namelist(remote_broadcast_subnet, fp);
  581.  
  582.   if(wins_server_subnet != NULL)
  583.     dump_subnet_namelist( wins_server_subnet, fp);
  584.   fclose(fp);
  585. }
  586.