Set num_validated_users to zero if Realloc fails.
[kai/samba.git] / source3 / nameresp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios library routines
5    Copyright (C) Andrew Tridgell 1994-1996
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 ipgrp;
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 = find_subnet(ipgrp);
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         default:
164         {
165           /* nothing to do but delete the dead expected-response structure */
166           /* this is normal. */
167           break;
168         }
169   }
170 }
171
172
173 /*******************************************************************
174   remove old name response entries
175
176   XXXX retry code needs to be added, including a retry wait period and a count
177        see name_query() and name_status() for suggested implementation.
178
179   ******************************************************************/
180 void expire_netbios_response_entries(time_t t)
181 {
182   struct subnet_record *d;
183
184   for (d = subnetlist; d; d = d->next)
185   {
186     struct response_record *n, *nextn;
187
188     for (n = d->responselist; n; n = nextn)
189     {
190           nextn = n->next;
191
192       if (n->repeat_time <= t)
193           {
194                   if (n->repeat_count > 0)
195                   {
196                         /* resend the entry */
197                         initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
198                                                 n->name.name, n->name.name_type,
199                                       n->nb_flags, n->bcast, n->recurse, n->send_ip);
200
201             n->repeat_time += n->repeat_interval; /* XXXX ms needed */
202             n->repeat_count--;
203
204                   }
205                   else
206                   {
207               DEBUG(4,("timeout response %d for %s %s\n",
208                                                 n->response_id, namestr(&n->name),
209                         inet_ntoa(n->send_ip)));
210
211                           dead_netbios_entry    (d,n); /* process the non-response */
212               remove_response_record(d,n); /* remove the non-response */
213
214                           continue;
215                    }
216           }
217     }
218   }
219 }
220
221
222 /****************************************************************************
223   wrapper function to override a broadcast message and send it to the WINS
224   name server instead, if it exists. if wins is false, and there has been no
225   WINS server specified, the packet will NOT be sent.
226   ****************************************************************************/
227 struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
228                                 int fd,int quest_type,enum state_type state,
229                             char *name,int name_type,int nb_flags, time_t ttl,
230                                 int server_type, char *my_name, char *my_comment,
231                             BOOL bcast,BOOL recurse,
232                                 struct in_addr send_ip, struct in_addr reply_to_ip)
233 {
234   /* XXXX note: please see rfc1001.txt section 10 for details on this
235      function: it is currently inappropriate to use this - it will do
236      for now - once there is a clarification of B, M and P nodes and
237      which one samba is supposed to be
238    */
239
240   if ((!lp_wins_support()) && (*lp_wins_server()))
241     {
242       /* samba is not a WINS server, and we are using a WINS server */
243       struct in_addr wins_ip;
244       wins_ip = *interpret_addr2(lp_wins_server());
245
246       if (!zero_ip(wins_ip))
247         {
248           bcast = False;
249           send_ip = wins_ip;
250         }
251       else
252         {
253           /* oops. smb.conf's wins server parameter MUST be a host_name 
254              or an ip_address. */
255           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
256         }
257     }
258
259   if (zero_ip(send_ip)) return NULL;
260
261   return queue_netbios_packet(d,fd, quest_type, state, 
262                        name, name_type, nb_flags, ttl,
263                server_type,my_name,my_comment,
264                        bcast, recurse, send_ip, reply_to_ip);
265 }
266
267
268 /****************************************************************************
269   initiate a netbios name query to find someone's or someones' IP
270   this is intended to be used (not exclusively) for broadcasting to
271   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
272   complete lists across a wide area network
273   ****************************************************************************/
274 struct response_record *queue_netbios_packet(struct subnet_record *d,
275                         int fd,int quest_type,enum state_type state,char *name,
276                         int name_type,int nb_flags, time_t ttl,
277                         int server_type, char *my_name, char *my_comment,
278                     BOOL bcast,BOOL recurse,
279                         struct in_addr send_ip, struct in_addr reply_to_ip)
280 {
281   struct in_addr wins_ip = ipgrp;
282   struct response_record *n;
283   uint16 id = 0xffff;
284
285   /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
286   if (ip_equal(wins_ip, send_ip)) return NULL;
287
288   initiate_netbios_packet(&id, fd, quest_type, name, name_type,
289                                       nb_flags, bcast, recurse, send_ip);
290
291   if (id == 0xffff) {
292     DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
293     return NULL;
294   }
295   
296   if ((n = make_response_queue_record(state,id,fd,
297                                                 quest_type,name,name_type,nb_flags,ttl,
298                                                 server_type,my_name, my_comment,
299                                                 bcast,recurse,send_ip,reply_to_ip)))
300     {
301       add_response_record(d,n);
302       return n;
303     }
304    return NULL;
305 }