98f129aa892d872774ddbd528cd57eef7b6041b0
[ira/wip.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-2003
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 3 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, see <http://www.gnu.org/licenses/>.
20    
21 */
22
23 #include "includes.h"
24
25 /* forward declarations */
26 static void wins_next_registration(struct response_record *rrec);
27
28
29 /****************************************************************************
30  Deal with a response packet when registering one of our names.
31 ****************************************************************************/
32
33 static void register_name_response(struct subnet_record *subrec,
34                        struct response_record *rrec, struct packet_struct *p)
35 {
36         /* 
37          * If we are registering broadcast, then getting a response is an
38          * error - we do not have the name. If we are registering unicast,
39          * then we expect to get a response.
40          */
41
42         struct nmb_packet *nmb = &p->packet.nmb;
43         bool bcast = nmb->header.nm_flags.bcast;
44         bool success = True;
45         struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
46         struct nmb_name *answer_name = &nmb->answers->rr_name;
47         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
48         int ttl = 0;
49         uint16 nb_flags = 0;
50         struct in_addr register_ip;
51         fstring reg_name;
52         
53         putip(&register_ip,&sent_nmb->additional->rdata[2]);
54         fstrcpy(reg_name, inet_ntoa(register_ip));
55         
56         if (subrec == unicast_subnet) {
57                 /* we know that this wins server is definately alive - for the moment! */
58                 wins_srv_alive(rrec->packet->ip, register_ip);
59         }
60
61         /* Sanity check. Ensure that the answer name in the incoming packet is the
62            same as the requested name in the outgoing packet. */
63
64         if(!question_name || !answer_name) {
65                 DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
66                          question_name ? "question_name" : "answer_name" ));
67                 return;
68         }
69
70         if(!nmb_name_equal(question_name, answer_name)) {
71                 DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", 
72                          nmb_namestr(answer_name), nmb_namestr(question_name)));
73                 return;
74         }
75
76         if(bcast) {
77                 /*
78                  * Special hack to cope with old Samba nmbd's.
79                  * Earlier versions of Samba (up to 1.9.16p11) respond 
80                  * to a broadcast name registration of WORKGROUP<1b> when 
81                  * they should not. Hence, until these versions are gone, 
82                  * we should treat such errors as success for this particular
83                  * case only. jallison@whistle.com.
84                  */
85                 
86 #if 1 /* OLD_SAMBA_SERVER_HACK */
87                 unstring ans_name;
88                 pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
89                 if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
90                    (answer_name->name_type == 0x1b)) {
91                         /* Pretend we did not get this. */
92                         rrec->num_msgs--;
93
94                         DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", 
95                                  nmb_namestr(answer_name)));
96                         return;
97                 }
98 #endif /* OLD_SAMBA_SERVER_HACK */
99
100                 /* Someone else has the name. Log the problem. */
101                 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", 
102                          nmb_namestr(answer_name), 
103                          reg_name,
104                          subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
105                 success = False;
106         } else {
107                 /* Unicast - check to see if the response allows us to have the name. */
108                 if (nmb->header.opcode == NMB_WACK_OPCODE) {
109                         /* WINS server is telling us to wait. Pretend we didn't get
110                            the response but don't send out any more register requests. */
111
112                         DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", 
113                                  inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
114
115                         rrec->repeat_count = 0;
116                         /* How long we should wait for. */
117                         rrec->repeat_time = p->timestamp + nmb->answers->ttl;
118                         rrec->num_msgs--;
119                         return;
120                 } else if (nmb->header.rcode != 0) {
121                         /* Error code - we didn't get the name. */
122                         success = False;
123
124                         DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", 
125                                  subrec==unicast_subnet?"WINS ":"",
126                                  inet_ntoa(p->ip), 
127                                  nmb_namestr(answer_name), 
128                                  reg_name,
129                                  nmb->header.rcode));
130                 } else {
131                         success = True;
132                         /* Get the data we need to pass to the success function. */
133                         nb_flags = get_nb_flags(nmb->answers->rdata);
134                         ttl = nmb->answers->ttl;
135
136                         /* send off a registration for the next IP, if any */
137                         wins_next_registration(rrec);
138                 }
139         } 
140
141         DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
142                  success ? "success" : "failure", 
143                  subrec==unicast_subnet?"WINS ":"",
144                  nmb_namestr(answer_name), 
145                  reg_name,
146                  inet_ntoa(rrec->packet->ip)));
147
148         if(success) {
149                 /* Enter the registered name into the subnet name database before calling
150                    the success function. */
151                 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
152                 if( rrec->success_fn)
153                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
154         } else {
155                 struct nmb_name qname = *question_name;
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, &qname);
160         }
161
162         /* Ensure we don't retry. */
163         remove_response_record(subrec, rrec);
164 }
165
166 /****************************************************************************
167  Deal with a timeout of a WINS registration request
168 ****************************************************************************/
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  Deal with a timeout when registering one of our names.
240 ****************************************************************************/
241
242 static void register_name_timeout_response(struct subnet_record *subrec,
243                                            struct response_record *rrec)
244 {
245         /*
246          * If we are registering unicast, then NOT getting a response is an
247          * error - we do not have the name. If we are registering broadcast,
248          * then we don't expect to get a response.
249          */
250
251         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
252         bool bcast = sent_nmb->header.nm_flags.bcast;
253         bool success = False;
254         struct nmb_name *question_name = &sent_nmb->question.question_name;
255         uint16 nb_flags = 0;
256         int ttl = 0;
257         struct in_addr registered_ip;
258         
259         if (bcast) {
260                 if(rrec->num_msgs == 0) {
261                         /* Not receiving a message is success for broadcast registration. */
262                         success = True; 
263
264                         /* Pull the success values from the original request packet. */
265                         nb_flags = get_nb_flags(sent_nmb->additional->rdata);
266                         ttl = sent_nmb->additional->ttl;
267                         putip(&registered_ip,&sent_nmb->additional->rdata[2]);
268                 }
269         } else {
270                 /* wins timeouts are special */
271                 wins_registration_timeout(subrec, rrec);
272                 return;
273         }
274
275         DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
276                  success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
277         if(success) {
278                 /* Enter the registered name into the subnet name database before calling
279                    the success function. */
280                 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
281                 if( rrec->success_fn)
282                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
283         } else {
284                 struct nmb_name qname = *question_name;
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, &qname);
289         }
290
291         /* Ensure we don't retry. */
292         remove_response_record(subrec, rrec);
293 }
294
295 /****************************************************************************
296  Initiate one multi-homed name registration packet.
297 ****************************************************************************/
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 *)SMB_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  We have finished the registration of one IP and need to see if we have
343  any more IPs left to register with this group of wins server for this name.
344 ****************************************************************************/
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_v4(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
394 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
395                                      register_name_success_function success_fn,
396                                      register_name_fail_function fail_fn)
397 {
398         /*
399           If we are adding a group name, we just send multiple
400           register name packets to the WINS server (this is an
401           internet group name.
402
403           If we are adding a unique name, We need first to add 
404           our names to the unicast subnet namelist. This is 
405           because when a WINS server receives a multihomed 
406           registration request, the first thing it does is to 
407           send a name query to the registering machine, to see 
408           if it has put the name in it's local namelist.
409           We need the name there so the query response code in
410           nmbd_incomingrequests.c will find it.
411
412           We are adding this name prematurely (we don't really
413           have it yet), but as this is on the unicast subnet
414           only we will get away with this (only the WINS server
415           will ever query names from us on this subnet).
416         */
417         int num_ips=0;
418         int i, t;
419         struct subnet_record *subrec;
420         char **wins_tags;
421         struct in_addr *ip_list;
422         unstring name;
423
424         for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
425                 num_ips++;
426         
427         if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
428                 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
429                 return;
430         }
431
432         for (subrec = FIRST_SUBNET, i = 0; 
433              subrec;
434              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
435                 ip_list[i] = subrec->myip;
436         }
437
438         pull_ascii_nstring(name, sizeof(name), nmbname->name);
439         add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
440                            nb_flags, lp_max_ttl(), SELF_NAME,
441                            num_ips, ip_list);
442
443         /* get the list of wins tags - we try to register for each of them */
444         wins_tags = wins_srv_tags();
445
446         /* Now try and register the name for each wins tag.  Note that
447            at this point we only register our first IP with each wins
448            group. We will register the rest from
449            wins_next_registration() when we get the reply for this
450            one. That follows the way W2K does things (tridge)
451         */
452         for (t=0; wins_tags && wins_tags[t]; t++) {
453                 multihomed_register_one(nmbname, nb_flags,
454                                         success_fn, fail_fn,
455                                         ip_list[0],
456                                         wins_tags[t]);
457         }
458
459         wins_srv_tags_free(wins_tags);
460         
461         SAFE_FREE(ip_list);
462 }
463
464 /****************************************************************************
465  Try and register one of our names.
466 ****************************************************************************/
467
468 void register_name(struct subnet_record *subrec,
469                    const char *name, int type, uint16 nb_flags,
470                    register_name_success_function success_fn,
471                    register_name_fail_function fail_fn,
472                    struct userdata_struct *userdata)
473 {
474         struct nmb_name nmbname;
475         nstring nname;
476
477         errno = 0;
478         push_ascii_nstring(nname, name);
479         if (errno == E2BIG) {
480                 unstring tname;
481                 pull_ascii_nstring(tname, sizeof(tname), nname);
482                 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
483                         name, tname));
484                 make_nmb_name(&nmbname, tname, type);
485         } else {
486                 make_nmb_name(&nmbname, name, type);
487         }
488
489         /* Always set the NB_ACTIVE flag on the name we are
490            registering. Doesn't make sense without it.
491         */
492         
493         nb_flags |= NB_ACTIVE;
494         
495         if (subrec == unicast_subnet) {
496                 /* we now always do multi-homed registration if we are
497                    registering to a WINS server. This copes much
498                    better with complex WINS setups */
499                 multihomed_register_name(&nmbname, nb_flags,
500                                          success_fn, fail_fn);
501                 return;
502         }
503         
504         if (queue_register_name(subrec,
505                                 register_name_response,
506                                 register_name_timeout_response,
507                                 success_fn,
508                                 fail_fn,
509                                 userdata,
510                                 &nmbname,
511                                 nb_flags) == NULL) {
512                 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
513                          nmb_namestr(&nmbname)));
514         }
515 }
516
517 /****************************************************************************
518  Try and refresh one of our names. This is *only* called for WINS refresh
519 ****************************************************************************/
520
521 void wins_refresh_name(struct name_record *namerec)
522 {
523         int t;
524         char **wins_tags;
525
526         /* get the list of wins tags - we try to refresh for each of them */
527         wins_tags = wins_srv_tags();
528
529         for (t=0; wins_tags && wins_tags[t]; t++) {
530                 queue_wins_refresh(&namerec->name, 
531                                    register_name_response,
532                                    register_name_timeout_response,
533                                    namerec->data.nb_flags,
534                                    namerec->data.ip[0], wins_tags[t]);
535         }
536
537         wins_srv_tags_free(wins_tags);
538 }