sync 3.0 branch with head
[kai/samba-autobuild/.git] / source3 / nmbd / nmbd_nameregister.c
1 /* 
2    Unix SMB/CIFS implementation.
3    NBT netbios routines and daemon - version 2
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6    Copyright (C) Jeremy Allison 1994-1998
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21    
22 */
23
24 #include "includes.h"
25
26 extern fstring global_myworkgroup;
27
28 /* forward declarations */
29 static void wins_next_registration(struct response_record *rrec);
30
31
32 /****************************************************************************
33  Deal with a response packet when registering one of our names.
34 ****************************************************************************/
35
36 static void register_name_response(struct subnet_record *subrec,
37                        struct response_record *rrec, struct packet_struct *p)
38 {
39         /* 
40          * If we are registering broadcast, then getting a response is an
41          * error - we do not have the name. If we are registering unicast,
42          * then we expect to get a response.
43          */
44
45         struct nmb_packet *nmb = &p->packet.nmb;
46         BOOL bcast = nmb->header.nm_flags.bcast;
47         BOOL success = True;
48         struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
49         struct nmb_name *answer_name = &nmb->answers->rr_name;
50         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
51         int ttl = 0;
52         uint16 nb_flags = 0;
53         struct in_addr register_ip;
54         fstring reg_name;
55         
56         putip(&register_ip,&sent_nmb->additional->rdata[2]);
57         fstrcpy(reg_name, inet_ntoa(register_ip));
58         
59         if (subrec == unicast_subnet) {
60                 /* we know that this wins server is definately alive - for the moment! */
61                 wins_srv_alive(rrec->packet->ip, register_ip);
62         }
63
64         /* Sanity check. Ensure that the answer name in the incoming packet is the
65            same as the requested name in the outgoing packet. */
66
67         if(!question_name || !answer_name) {
68                 DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
69                          question_name ? "question_name" : "answer_name" ));
70                 return;
71         }
72
73         if(!nmb_name_equal(question_name, answer_name)) {
74                 DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", 
75                          nmb_namestr(answer_name), nmb_namestr(question_name)));
76                 return;
77         }
78
79         if(bcast) {
80                 /*
81                  * Special hack to cope with old Samba nmbd's.
82                  * Earlier versions of Samba (up to 1.9.16p11) respond 
83                  * to a broadcast name registration of WORKGROUP<1b> when 
84                  * they should not. Hence, until these versions are gone, 
85                  * we should treat such errors as success for this particular
86                  * case only. jallison@whistle.com.
87                  */
88                 
89 #if 1 /* OLD_SAMBA_SERVER_HACK */
90                 if((nmb->header.rcode == ACT_ERR) && strequal(global_myworkgroup, answer_name->name) &&
91                    (answer_name->name_type == 0x1b)) {
92                         /* Pretend we did not get this. */
93                         rrec->num_msgs--;
94
95                         DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", 
96                                  nmb_namestr(answer_name)));
97                         return;
98                 }
99 #endif /* OLD_SAMBA_SERVER_HACK */
100
101                 /* Someone else has the name. Log the problem. */
102                 DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", 
103                          nmb_namestr(answer_name), 
104                          reg_name,
105                          subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
106                 success = False;
107         } else {
108                 /* Unicast - check to see if the response allows us to have the name. */
109                 if (nmb->header.opcode == NMB_WACK_OPCODE) {
110                         /* WINS server is telling us to wait. Pretend we didn't get
111                            the response but don't send out any more register requests. */
112
113                         DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", 
114                                  inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
115
116                         rrec->repeat_count = 0;
117                         /* How long we should wait for. */
118                         rrec->repeat_time = p->timestamp + nmb->answers->ttl;
119                         rrec->num_msgs--;
120                         return;
121                 } else if (nmb->header.rcode != 0) {
122                         /* Error code - we didn't get the name. */
123                         success = False;
124
125                         DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", 
126                                  subrec==unicast_subnet?"WINS ":"",
127                                  inet_ntoa(p->ip), 
128                                  nmb_namestr(answer_name), 
129                                  reg_name,
130                                  nmb->header.rcode));
131                 } else {
132                         success = True;
133                         /* Get the data we need to pass to the success function. */
134                         nb_flags = get_nb_flags(nmb->answers->rdata);
135                         ttl = nmb->answers->ttl;
136
137                         /* send off a registration for the next IP, if any */
138                         wins_next_registration(rrec);
139                 }
140         } 
141
142         DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
143                  success ? "success" : "failure", 
144                  subrec==unicast_subnet?"WINS ":"",
145                  nmb_namestr(answer_name), 
146                  reg_name,
147                  inet_ntoa(rrec->packet->ip)));
148
149         if(success) {
150                 /* Enter the registered name into the subnet name database before calling
151                    the success function. */
152                 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
153                 if( rrec->success_fn)
154                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
155         } else {
156                 if( rrec->fail_fn)
157                         (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
158                 /* Remove the name. */
159                 standard_fail_register( subrec, rrec, question_name);
160         }
161
162         /* Ensure we don't retry. */
163         remove_response_record(subrec, rrec);
164 }
165
166
167 /****************************************************************************
168  Deal with a timeout of a WINS registration request
169 ****************************************************************************/
170 static void wins_registration_timeout(struct subnet_record *subrec,
171                                       struct response_record *rrec)
172 {
173         struct userdata_struct *userdata = rrec->userdata;
174         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
175         struct nmb_name *nmbname = &sent_nmb->question.question_name;
176         struct in_addr register_ip;
177         fstring src_addr;
178
179         putip(&register_ip,&sent_nmb->additional->rdata[2]);
180
181         fstrcpy(src_addr, inet_ntoa(register_ip));
182
183         DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", 
184                  inet_ntoa(rrec->packet->ip), src_addr));
185
186         /* mark it temporarily dead for this source address */
187         wins_srv_died(rrec->packet->ip, register_ip);
188
189         /* if we have some userdata then use that to work out what
190            wins server to try next */
191         if (userdata) {
192                 const char *tag = (const char *)userdata->data;
193
194                 /* try the next wins server in our failover list for
195                    this tag */
196                 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
197         }
198
199         /* if we have run out of wins servers for this tag then they
200            must all have timed out. We treat this as *success*, not
201            failure, and go into our standard name refresh mode. This
202            copes with all the wins servers being down */
203         if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
204                 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
205                 int ttl = sent_nmb->additional->ttl;
206
207                 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
208                 if(rrec->success_fn) {
209                         (*(register_name_success_function)rrec->success_fn)(subrec, 
210                                                                             rrec->userdata, 
211                                                                             nmbname, 
212                                                                             nb_flags, 
213                                                                             ttl, 
214                                                                             register_ip);
215                 }
216
217                 /* send off a registration for the next IP, if any */
218                 wins_next_registration(rrec);
219
220                 /* don't need to send this packet any more */
221                 remove_response_record(subrec, rrec);
222                 return;
223         }
224         
225         /* we will be moving to the next WINS server for this group,
226            send it immediately */
227         rrec->repeat_count = 2;
228         rrec->repeat_time = time(NULL) + 1;
229         rrec->in_expiration_processing = False;
230
231         DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
232                  nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
233
234         /* notice that we don't remove the response record. This keeps
235            us trying to register with each of our failover wins servers */
236 }
237
238
239 /****************************************************************************
240  Deal with a timeout when registering one of our names.
241 ****************************************************************************/
242
243 static void register_name_timeout_response(struct subnet_record *subrec,
244                                            struct response_record *rrec)
245 {
246         /*
247          * If we are registering unicast, then NOT getting a response is an
248          * error - we do not have the name. If we are registering broadcast,
249          * then we don't expect to get a response.
250          */
251
252         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
253         BOOL bcast = sent_nmb->header.nm_flags.bcast;
254         BOOL success = False;
255         struct nmb_name *question_name = &sent_nmb->question.question_name;
256         uint16 nb_flags = 0;
257         int ttl = 0;
258         struct in_addr registered_ip;
259         
260         if (bcast) {
261                 if(rrec->num_msgs == 0) {
262                         /* Not receiving a message is success for broadcast registration. */
263                         success = True; 
264
265                         /* Pull the success values from the original request packet. */
266                         nb_flags = get_nb_flags(sent_nmb->additional->rdata);
267                         ttl = sent_nmb->additional->ttl;
268                         putip(&registered_ip,&sent_nmb->additional->rdata[2]);
269                 }
270         } else {
271                 /* wins timeouts are special */
272                 wins_registration_timeout(subrec, rrec);
273                 return;
274         }
275
276         DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
277                  success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
278         if(success) {
279                 /* Enter the registered name into the subnet name database before calling
280                    the success function. */
281                 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
282                 if( rrec->success_fn)
283                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
284         } else {
285                 if( rrec->fail_fn)
286                         (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
287                 /* Remove the name. */
288                 standard_fail_register( subrec, rrec, question_name);
289         }
290
291         /* Ensure we don't retry. */
292         remove_response_record(subrec, rrec);
293 }
294
295
296 /****************************************************************************
297 initiate one multi-homed name registration packet
298 ****************************************************************************/
299 static void multihomed_register_one(struct nmb_name *nmbname,
300                                     uint16 nb_flags,
301                                     register_name_success_function success_fn,
302                                     register_name_fail_function fail_fn,
303                                     struct in_addr ip,
304                                     const char *tag)
305 {
306         struct userdata_struct *userdata;
307         struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
308         fstring ip_str;
309
310         userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1);
311         if (!userdata) {
312                 DEBUG(0,("Failed to allocate userdata structure!\n"));
313                 return;
314         }
315         ZERO_STRUCTP(userdata);
316         userdata->userdata_len = strlen(tag) + 1;
317         strlcpy(userdata->data, tag, userdata->userdata_len);   
318
319         fstrcpy(ip_str, inet_ntoa(ip));
320
321         DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
322                  nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
323
324         if (queue_register_multihomed_name(unicast_subnet,
325                                            register_name_response,
326                                            register_name_timeout_response,
327                                            success_fn,
328                                            fail_fn,
329                                            userdata,
330                                            nmbname,
331                                            nb_flags,
332                                            ip,
333                                            wins_ip) == NULL) {
334                 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n", 
335                          nmb_namestr(nmbname), inet_ntoa(ip)));         
336         }
337
338         free(userdata);
339 }
340
341
342 /****************************************************************************
343 we have finished the registration of one IP and need to see if we have
344 any more IPs left to register with this group of wins server for this name
345 ****************************************************************************/
346 static void wins_next_registration(struct response_record *rrec)
347 {
348         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
349         struct nmb_name *nmbname = &sent_nmb->question.question_name;
350         uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
351         struct userdata_struct *userdata = rrec->userdata;
352         const char *tag;
353         struct in_addr last_ip;
354         struct subnet_record *subrec;
355
356         putip(&last_ip,&sent_nmb->additional->rdata[2]);
357
358         if (!userdata) {
359                 /* it wasn't multi-homed */
360                 return;
361         }
362
363         tag = (const char *)userdata->data;
364
365         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
366                 if (ip_equal(last_ip, subrec->myip)) {
367                         subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
368                         break;
369                 }
370         }
371
372         if (!subrec) {
373                 /* no more to do! */
374                 return;
375         }
376
377         switch (sent_nmb->header.opcode) {
378         case NMB_NAME_MULTIHOMED_REG_OPCODE:
379                 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
380                 break;
381         case NMB_NAME_REFRESH_OPCODE_8:
382                 queue_wins_refresh(nmbname, 
383                                    register_name_response,
384                                    register_name_timeout_response,
385                                    nb_flags, subrec->myip, tag);
386                 break;
387         }
388 }
389
390 /****************************************************************************
391  Try and register one of our names on the unicast subnet - multihomed.
392 ****************************************************************************/
393 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
394                                      register_name_success_function success_fn,
395                                      register_name_fail_function fail_fn)
396 {
397         /*
398           If we are adding a group name, we just send multiple
399           register name packets to the WINS server (this is an
400           internet group name.
401
402           If we are adding a unique name, We need first to add 
403           our names to the unicast subnet namelist. This is 
404           because when a WINS server receives a multihomed 
405           registration request, the first thing it does is to 
406           send a name query to the registering machine, to see 
407           if it has put the name in it's local namelist.
408           We need the name there so the query response code in
409           nmbd_incomingrequests.c will find it.
410
411           We are adding this name prematurely (we don't really
412           have it yet), but as this is on the unicast subnet
413           only we will get away with this (only the WINS server
414           will ever query names from us on this subnet).
415         */
416         int num_ips=0;
417         int i, t;
418         struct subnet_record *subrec;
419         char **wins_tags;
420         struct in_addr *ip_list;
421
422         for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
423                 num_ips++;
424         
425         if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL) {
426                 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
427                 return;
428         }
429
430         for (subrec = FIRST_SUBNET, i = 0; 
431              subrec;
432              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
433                 ip_list[i] = subrec->myip;
434         }
435
436         add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
437                            nb_flags, lp_max_ttl(), SELF_NAME,
438                            num_ips, ip_list);
439
440         /* get the list of wins tags - we try to register for each of them */
441         wins_tags = wins_srv_tags();
442
443         /* Now try and register the name for each wins tag.  Note that
444            at this point we only register our first IP with each wins
445            group. We will register the rest from
446            wins_next_registration() when we get the reply for this
447            one. That follows the way W2K does things (tridge)
448         */
449         for (t=0; wins_tags && wins_tags[t]; t++) {
450                 multihomed_register_one(nmbname, nb_flags,
451                                         success_fn, fail_fn,
452                                         ip_list[0],
453                                         wins_tags[t]);
454         }
455
456         wins_srv_tags_free(wins_tags);
457         
458         SAFE_FREE(ip_list);
459 }
460
461
462 /****************************************************************************
463  Try and register one of our names.
464 ****************************************************************************/
465 void register_name(struct subnet_record *subrec,
466                    char *name, int type, uint16 nb_flags,
467                    register_name_success_function success_fn,
468                    register_name_fail_function fail_fn,
469                    struct userdata_struct *userdata)
470 {
471         struct nmb_name nmbname;
472         
473         make_nmb_name(&nmbname, name, type);
474
475         /* Always set the NB_ACTIVE flag on the name we are
476            registering. Doesn't make sense without it.
477         */
478         
479         nb_flags |= NB_ACTIVE;
480         
481         if (subrec == unicast_subnet) {
482                 /* we now always do multi-homed registration if we are
483                    registering to a WINS server. This copes much
484                    better with complex WINS setups */
485                 multihomed_register_name(&nmbname, nb_flags,
486                                          success_fn, fail_fn);
487                 return;
488         }
489         
490         if (queue_register_name(subrec,
491                                 register_name_response,
492                                 register_name_timeout_response,
493                                 success_fn,
494                                 fail_fn,
495                                 userdata,
496                                 &nmbname,
497                                 nb_flags) == NULL) {
498                 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
499                          nmb_namestr(&nmbname)));
500         }
501 }
502
503
504 /****************************************************************************
505  Try and refresh one of our names. This is *only* called for WINS refresh
506 ****************************************************************************/
507 void wins_refresh_name(struct name_record *namerec)
508 {
509         int t;
510         char **wins_tags;
511
512         /* get the list of wins tags - we try to refresh for each of them */
513         wins_tags = wins_srv_tags();
514
515         for (t=0; wins_tags && wins_tags[t]; t++) {
516                 queue_wins_refresh(&namerec->name, 
517                                    register_name_response,
518                                    register_name_timeout_response,
519                                    namerec->data.nb_flags,
520                                    namerec->data.ip[0], wins_tags[t]);
521         }
522
523         wins_srv_tags_free(wins_tags);
524 }