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