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_responserecordsdb.c < prev    next >
C/C++ Source or Header  |  1998-01-29  |  8KB  |  264 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios library routines
  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 ClientNMB;
  28.  
  29. extern int DEBUGLEVEL;
  30.  
  31. extern pstring scope;
  32. extern pstring myname;
  33. extern struct in_addr ipzero;
  34.  
  35. int num_response_packets = 0;
  36.  
  37. /***************************************************************************
  38.   Add an expected response record into the list
  39.   **************************************************************************/
  40.  
  41. void add_response_record(struct subnet_record *subrec,
  42.                 struct response_record *rrec)
  43. {
  44.   struct response_record *rrec2;
  45.  
  46.   num_response_packets++; /* count of total number of packets still around */
  47.  
  48.   DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
  49.             rrec->response_id, subrec->subnet_name, num_response_packets));
  50.  
  51.   if (!subrec->responselist)
  52.   {
  53.     subrec->responselist = rrec;
  54.     rrec->prev = NULL;
  55.     rrec->next = NULL;
  56.     return;
  57.   }
  58.   
  59.   for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) 
  60.     ;
  61.   
  62.   rrec2->next = rrec;
  63.   rrec->next = NULL;
  64.   rrec->prev = rrec2;
  65. }
  66.  
  67. /***************************************************************************
  68.   Remove an expected response record from the list
  69.   **************************************************************************/
  70.  
  71. void remove_response_record(struct subnet_record *subrec,
  72.                 struct response_record *rrec)
  73. {
  74.   if (rrec->prev)
  75.     rrec->prev->next = rrec->next;
  76.   if (rrec->next)
  77.     rrec->next->prev = rrec->prev;
  78.  
  79.   if (subrec->responselist == rrec) 
  80.     subrec->responselist = rrec->next; 
  81.  
  82.   if(rrec->userdata)
  83.   {
  84.     if(rrec->userdata->free_fn)
  85.       (*rrec->userdata->free_fn)(rrec->userdata);
  86.     else
  87.       free((char *)rrec->userdata);
  88.   }
  89.  
  90.   /* Ensure we can delete. */
  91.   rrec->packet->locked = False;
  92.   free_packet(rrec->packet);
  93.  
  94.   free((char *)rrec);
  95.  
  96.   num_response_packets--; /* count of total number of packets still around */
  97. }
  98.  
  99. /****************************************************************************
  100.   Create a response record for an outgoing packet.
  101.   **************************************************************************/
  102.  
  103. struct response_record *make_response_record( struct subnet_record *subrec,
  104.                     struct packet_struct *p,
  105.                     response_function resp_fn,
  106.                     timeout_response_function timeout_fn,
  107.                     success_function success_fn,
  108.                     fail_function fail_fn,
  109.                     struct userdata_struct *userdata)
  110. {
  111.   struct response_record *rrec;
  112.   struct nmb_packet *nmb = &p->packet.nmb;
  113.  
  114.   if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) 
  115.   {
  116.     DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n"));
  117.     return NULL;
  118.   }
  119.  
  120.   bzero((char *)rrec, sizeof(*rrec));
  121.  
  122.   rrec->response_id = nmb->header.name_trn_id;
  123.  
  124.   rrec->resp_fn = resp_fn;
  125.   rrec->timeout_fn = timeout_fn;
  126.   rrec->success_fn = success_fn;
  127.   rrec->fail_fn = fail_fn;
  128.  
  129.   rrec->packet = p;
  130.  
  131.   if(userdata)
  132.   {
  133.     /* Intelligent userdata. */
  134.     if(userdata->copy_fn)
  135.     {
  136.       if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL)
  137.       {
  138.         DEBUG(0,("make_response_queue_record: copy fail for userdata.\n"));
  139.         free(rrec);
  140.         return NULL;
  141.       }
  142.     }
  143.     else
  144.     {
  145.       /* Primitive userdata, do a memcpy. */
  146.       if((rrec->userdata = (struct userdata_struct *)
  147.            malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL)
  148.       {
  149.         DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n"));
  150.         free(rrec);
  151.         return NULL;
  152.       }
  153.       rrec->userdata->copy_fn = userdata->copy_fn;
  154.       rrec->userdata->free_fn = userdata->free_fn;
  155.       rrec->userdata->userdata_len = userdata->userdata_len;
  156.       memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len);
  157.     }
  158.   }
  159.   else
  160.     rrec->userdata = NULL;
  161.  
  162.   rrec->num_msgs = 0;
  163.  
  164.   if(!nmb->header.nm_flags.bcast)
  165.     rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */
  166.   else
  167.     rrec->repeat_interval = 1; /* XXXX should be in ms */
  168.   rrec->repeat_count = 3; /* 3 retries */
  169.   rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */
  170.  
  171.   /* Lock the packet so we won't lose it while it's on the list. */
  172.   p->locked = True;
  173.  
  174.   add_response_record(subrec, rrec);
  175.  
  176.   return rrec;
  177. }
  178.  
  179. /****************************************************************************
  180.   Find a response in a subnet's name query response list. 
  181.   **************************************************************************/
  182.  
  183. static struct response_record *find_response_record_on_subnet(
  184.                                 struct subnet_record *subrec, uint16 id)
  185. {  
  186.   struct response_record *rrec = NULL;
  187.  
  188.   for (rrec = subrec->responselist; rrec; rrec = rrec->next)
  189.   {
  190.     if (rrec->response_id == id) 
  191.     {
  192.       DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n",
  193.                id, subrec->subnet_name));
  194.       break;
  195.     }
  196.   }
  197.   return rrec;
  198. }
  199.  
  200. /****************************************************************************
  201.   Find a response in any subnet's name query response list. 
  202.   **************************************************************************/
  203.  
  204. struct response_record *find_response_record(struct subnet_record **ppsubrec,
  205.                 uint16 id)
  206. {  
  207.   struct response_record *rrec = NULL;
  208.  
  209.   for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); 
  210.                   (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec))
  211.   {
  212.     if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL)
  213.       return rrec;
  214.   }
  215.  
  216.   /* There should never be response records on the remote_broadcast subnet.
  217.      Sanity check to ensure this is so. */
  218.   if(remote_broadcast_subnet->responselist != NULL)
  219.   {
  220.     DEBUG(0,("find_response_record: response record found on subnet %s. This should \
  221. never happen !\n", remote_broadcast_subnet->subnet_name));
  222.   }
  223.  
  224.   /* Now check the WINS server subnet if it exists. */
  225.   if(wins_server_subnet != NULL)
  226.   {
  227.     *ppsubrec = wins_server_subnet;
  228.     if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL)
  229.       return rrec;
  230.   }
  231.  
  232.   DEBUG(0,("find_response_record: response packet id %hu received with no \
  233. matching record.\n", id));
  234.  
  235.   *ppsubrec = NULL;
  236.  
  237.   return NULL;
  238. }
  239.  
  240. /****************************************************************************
  241.   Check if a refresh is queued for a particular name on a particular subnet.
  242.   **************************************************************************/
  243.    
  244. BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec)
  245. {  
  246.   struct response_record *rrec = NULL;
  247.    
  248.   for (rrec = subrec->responselist; rrec; rrec = rrec->next)
  249.   {
  250.     struct packet_struct *p = rrec->packet;
  251.     struct nmb_packet *nmb = &p->packet.nmb;
  252.  
  253.     if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
  254.        (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9))
  255.     {
  256.       /* Yes it's a queued refresh - check if the name is correct. */
  257.       if(nmb_name_equal(&nmb->question.question_name, &namerec->name))
  258.         return True;
  259.     }
  260.   }
  261.  
  262.   return False;
  263.