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