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 / nameresp.c < prev    next >
C/C++ Source or Header  |  1997-08-12  |  10KB  |  327 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios library routines
  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.    Module name: nameresp.c
  22.  
  23. */
  24.  
  25. #include "includes.h"
  26.  
  27. extern int ClientNMB;
  28. extern int ClientDGRAM;
  29.  
  30. extern struct subnet_record *subnetlist;
  31.  
  32. extern int DEBUGLEVEL;
  33.  
  34. extern pstring scope;
  35. extern struct in_addr ipzero;
  36. extern struct in_addr wins_ip;
  37.  
  38.  
  39. /***************************************************************************
  40.   deals with an entry before it dies
  41.   **************************************************************************/
  42. static void dead_netbios_entry(struct subnet_record *d,
  43.                 struct response_record *n)
  44. {
  45.   DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
  46.        inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
  47.  
  48.   debug_state_type(n->state);
  49.  
  50.   switch (n->state)
  51.   {
  52.     case NAME_QUERY_CONFIRM:
  53.     {
  54.       if (!lp_wins_support()) return; /* only if we're a WINS server */
  55.       
  56.       if (n->num_msgs == 0)
  57.         {
  58.       /* oops. name query had no response. check that the name is
  59.          unique and then remove it from our WINS database */
  60.       
  61.       /* IMPORTANT: see query_refresh_names() */
  62.       
  63.       if ((!NAME_GROUP(n->nb_flags)))
  64.         {
  65.           struct subnet_record *d1 = wins_subnet;
  66.           if (d1)
  67.         {
  68.           /* remove the name that had been registered with us,
  69.              and we're now getting no response when challenging.
  70.              see rfc1001.txt 15.5.2
  71.              */
  72.           remove_netbios_name(d1, n->name.name, n->name.name_type,
  73.                       REGISTER, n->send_ip);
  74.         }
  75.         }
  76.     }
  77.       break;
  78.     }
  79.     
  80.   case NAME_QUERY_MST_CHK:
  81.     {
  82.       /* if no response received, the master browser must have gone
  83.      down on that subnet, without telling anyone. */
  84.       
  85.       /* IMPORTANT: see response_netbios_packet() */
  86.       
  87.       if (n->num_msgs == 0)
  88.     browser_gone(n->name.name, n->send_ip);
  89.       break;
  90.     }
  91.   
  92.   case NAME_RELEASE:
  93.     {
  94.       /* if no response received, it must be OK for us to release the
  95.      name. nobody objected (including a potentially dead or deaf
  96.      WINS server) */
  97.       
  98.       /* IMPORTANT: see response_name_release() */
  99.       
  100.       if (ismyip(n->send_ip))
  101.     {
  102.       name_unregister_work(d,n->name.name,n->name.name_type);
  103.     }
  104.       if (!n->bcast && n->num_msgs == 0)
  105.     {
  106.       DEBUG(0,("WINS server did not respond to name release!\n"));
  107.       /* XXXX whoops. we have problems. must deal with this */
  108.     }
  109.       break;
  110.     }
  111.   
  112.   case NAME_REGISTER_CHALLENGE:
  113.     {
  114.       /* name challenge: no reply. we can reply to the person that
  115.      wanted the unique name and tell them that they can have it
  116.      */
  117.       
  118.       add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name,
  119.                n->nb_flags, GET_TTL(0),
  120.                n->reply_to_ip, False, n->reply_to_ip);
  121.       
  122.       if (!n->bcast && n->num_msgs == 0)
  123.     {
  124.       DEBUG(1,("WINS server did not respond to name registration!\n"));
  125.       /* XXXX whoops. we have problems. must deal with this */
  126.     }
  127.       break;
  128.     }
  129.   
  130.   case NAME_REGISTER:
  131.     {
  132.       /* if no response received, and we are using a broadcast registration
  133.      method, it must be OK for us to register the name: nobody objected 
  134.      on that subnet. if we are using a WINS server, then the WINS
  135.      server must be dead or deaf.
  136.      */
  137.       if (n->num_msgs == 0)
  138.     {
  139.       if (n->bcast)
  140.         {
  141.           /* broadcast method: implicit acceptance of the name registration
  142.          by not receiving any objections. */
  143.           
  144.           /* IMPORTANT: see response_name_reg() */
  145.           
  146.           name_register_work(d,n->name.name,n->name.name_type,
  147.                  n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
  148.         }
  149.       else
  150.         {
  151.           /* received no response. rfc1001.txt states that after retrying,
  152.          we should assume the WINS server is dead, and fall back to
  153.          broadcasting (see bits about M nodes: can't find any right
  154.          now) */
  155.           
  156.           DEBUG(1,("WINS server did not respond to name registration!\n"));
  157.           /* XXXX whoops. we have problems. must deal with this */
  158.         }
  159.     }
  160.       break;
  161.     }
  162.   
  163.   case NAME_QUERY_DOMAIN:
  164.     {
  165.       /* if no response was received, there is no domain controller for
  166.          this DOMAIN registered within WINS.  it's ok for us to register
  167.          the DOMAIN<1b> name.
  168.      */
  169.       
  170.       if (n->num_msgs == 0)
  171.     {
  172.       struct work_record *work = find_workgroupstruct(d,n->name.name,False);
  173.       if (work && d)
  174.         {
  175.           become_domain_master(d,work);
  176.         }
  177.     }
  178.       else
  179.         {
  180.           DEBUG(1, ("nmbd configured as domain master and one already exists\n"));
  181.         }
  182.       break;
  183.     }
  184.  
  185.   default:
  186.     {
  187.       /* nothing to do but delete the dead expected-response structure */
  188.       /* this is normal. */
  189.       break;
  190.     }
  191.   }
  192. }
  193.  
  194.  
  195. /*******************************************************************
  196.   remove old name response entries
  197.  
  198.   XXXX retry code needs to be added, including a retry wait period and a count
  199.        see name_query() and name_status() for suggested implementation.
  200.  
  201.   ******************************************************************/
  202. void expire_netbios_response_entries(time_t t)
  203. {
  204.   struct subnet_record *d;
  205.  
  206.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
  207.   {
  208.     struct response_record *n, *nextn;
  209.  
  210.     for (n = d->responselist; n; n = nextn)
  211.     {
  212.       nextn = n->next;
  213.  
  214.       if (n->repeat_time <= t)
  215.       {
  216.         if (n->repeat_count > 0)
  217.         {
  218.           /* resend the entry */
  219.           initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
  220.                          n->name.name, n->name.name_type,
  221.                          n->nb_flags, n->bcast, n->recurse, n->send_ip);
  222.  
  223.           n->repeat_time += n->repeat_interval; /* XXXX ms needed */
  224.           n->repeat_count--;
  225.  
  226.         }
  227.         else
  228.         {
  229.           DEBUG(4,("timeout response %d for %s %s\n",
  230.                    n->response_id, namestr(&n->name),
  231.                    inet_ntoa(n->send_ip)));
  232.  
  233.           dead_netbios_entry(d,n); /* process the non-response */
  234.           remove_response_record(d,n); /* remove the non-response */
  235.  
  236.           continue;
  237.         }
  238.       }
  239.     }
  240.   }
  241. }
  242.  
  243.  
  244. /****************************************************************************
  245.   wrapper function to override a broadcast message and send it to the WINS
  246.   name server instead, if it exists. if wins is false, and there has been no
  247.   WINS server specified, the packet will NOT be sent.
  248.   ****************************************************************************/
  249. struct response_record *queue_netbios_pkt_wins(
  250.                 int fd,int quest_type,enum state_type state,
  251.                 char *name,int name_type,int nb_flags, time_t ttl,
  252.                 int server_type, char *my_name, char *my_comment,
  253.                 BOOL bcast,BOOL recurse,
  254.                 struct in_addr send_ip, struct in_addr reply_to_ip)
  255. {
  256.   /* XXXX note: please see rfc1001.txt section 10 for details on this
  257.      function: it is currently inappropriate to use this - it will do
  258.      for now - once there is a clarification of B, M and P nodes and
  259.      which one samba is supposed to be
  260.    */
  261.  
  262.   if ((!lp_wins_support()) && (*lp_wins_server()))
  263.     {
  264.       /* samba is not a WINS server, and we are using a WINS server */
  265.       struct in_addr real_wins_ip;
  266.       real_wins_ip = *interpret_addr2(lp_wins_server());
  267.  
  268.       if (!zero_ip(real_wins_ip))
  269.     {
  270.       bcast = False;
  271.       send_ip = real_wins_ip;
  272.     }
  273.       else
  274.     {
  275.       /* oops. smb.conf's wins server parameter MUST be a host_name 
  276.          or an ip_address. */
  277.       DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
  278.     }
  279.     }
  280.  
  281.   if (zero_ip(send_ip)) return NULL;
  282.  
  283.   return queue_netbios_packet(wins_subnet,fd, quest_type, state, 
  284.                name, name_type, nb_flags, ttl,
  285.                server_type,my_name,my_comment,
  286.                bcast, recurse, send_ip, reply_to_ip);
  287. }
  288.  
  289.  
  290. /****************************************************************************
  291.   initiate a netbios name query to find someone's or someones' IP
  292.   this is intended to be used (not exclusively) for broadcasting to
  293.   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
  294.   complete lists across a wide area network
  295.   ****************************************************************************/
  296. struct response_record *queue_netbios_packet(struct subnet_record *d,
  297.             int fd,int quest_type,enum state_type state,char *name,
  298.             int name_type,int nb_flags, time_t ttl,
  299.             int server_type, char *my_name, char *my_comment,
  300.             BOOL bcast,BOOL recurse,
  301.             struct in_addr send_ip, struct in_addr reply_to_ip)
  302. {
  303.   struct response_record *n;
  304.   uint16 id = 0xffff;
  305.  
  306.   /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
  307.   if (ip_equal(wins_ip, send_ip)) return NULL;
  308.  
  309.   initiate_netbios_packet(&id, fd, quest_type, name, name_type,
  310.               nb_flags, bcast, recurse, send_ip);
  311.  
  312.   if (id == 0xffff) {
  313.     DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
  314.     return NULL;
  315.   }
  316.   
  317.   if ((n = make_response_queue_record(state,id,fd,
  318.                       quest_type,name,name_type,nb_flags,ttl,
  319.                       server_type,my_name, my_comment,
  320.                       bcast,recurse,send_ip,reply_to_ip)))
  321.     {
  322.       add_response_record(d,n);
  323.       return n;
  324.     }
  325.    return NULL;
  326. }
  327.