dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba3 / source / nmbd / nmbd_nameregister.c
blob541d594d82a525072e772e480a459129f4b401e3
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
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.
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.
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.
24 #include "includes.h"
26 /* forward declarations */
27 static void wins_next_registration(struct response_record *rrec);
30 /****************************************************************************
31 Deal with a response packet when registering one of our names.
32 ****************************************************************************/
34 static void register_name_response(struct subnet_record *subrec,
35 struct response_record *rrec, struct packet_struct *p)
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.
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;
54 putip(&register_ip,&sent_nmb->additional->rdata[2]);
55 fstrcpy(reg_name, inet_ntoa(register_ip));
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);
62 /* Sanity check. Ensure that the answer name in the incoming packet is the
63 same as the requested name in the outgoing packet. */
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;
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;
77 if(bcast) {
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.
87 #if 1 /* OLD_SAMBA_SERVER_HACK */
88 unstring ans_name;
89 pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
90 if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
91 (answer_name->name_type == 0x1b)) {
92 /* Pretend we did not get this. */
93 rrec->num_msgs--;
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;
99 #endif /* OLD_SAMBA_SERVER_HACK */
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. */
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));
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;
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;
137 /* send off a registration for the next IP, if any */
138 wins_next_registration(rrec);
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)));
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 struct nmb_name qname = *question_name;
157 if( rrec->fail_fn)
158 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
159 /* Remove the name. */
160 standard_fail_register( subrec, &qname);
163 /* Ensure we don't retry. */
164 remove_response_record(subrec, rrec);
167 /****************************************************************************
168 Deal with a timeout of a WINS registration request
169 ****************************************************************************/
171 static void wins_registration_timeout(struct subnet_record *subrec,
172 struct response_record *rrec)
174 struct userdata_struct *userdata = rrec->userdata;
175 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
176 struct nmb_name *nmbname = &sent_nmb->question.question_name;
177 struct in_addr register_ip;
178 fstring src_addr;
180 putip(&register_ip,&sent_nmb->additional->rdata[2]);
182 fstrcpy(src_addr, inet_ntoa(register_ip));
184 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
185 inet_ntoa(rrec->packet->ip), src_addr));
187 /* mark it temporarily dead for this source address */
188 wins_srv_died(rrec->packet->ip, register_ip);
190 /* if we have some userdata then use that to work out what
191 wins server to try next */
192 if (userdata) {
193 const char *tag = (const char *)userdata->data;
195 /* try the next wins server in our failover list for
196 this tag */
197 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
200 /* if we have run out of wins servers for this tag then they
201 must all have timed out. We treat this as *success*, not
202 failure, and go into our standard name refresh mode. This
203 copes with all the wins servers being down */
204 if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
205 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
206 int ttl = sent_nmb->additional->ttl;
208 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
209 if(rrec->success_fn) {
210 (*(register_name_success_function)rrec->success_fn)(subrec,
211 rrec->userdata,
212 nmbname,
213 nb_flags,
214 ttl,
215 register_ip);
218 /* send off a registration for the next IP, if any */
219 wins_next_registration(rrec);
221 /* don't need to send this packet any more */
222 remove_response_record(subrec, rrec);
223 return;
226 /* we will be moving to the next WINS server for this group,
227 send it immediately */
228 rrec->repeat_count = 2;
229 rrec->repeat_time = time(NULL) + 1;
230 rrec->in_expiration_processing = False;
232 DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
233 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
235 /* notice that we don't remove the response record. This keeps
236 us trying to register with each of our failover wins servers */
239 /****************************************************************************
240 Deal with a timeout when registering one of our names.
241 ****************************************************************************/
243 static void register_name_timeout_response(struct subnet_record *subrec,
244 struct response_record *rrec)
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.
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;
260 if (bcast) {
261 if(rrec->num_msgs == 0) {
262 /* Not receiving a message is success for broadcast registration. */
263 success = True;
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]);
270 } else {
271 /* wins timeouts are special */
272 wins_registration_timeout(subrec, rrec);
273 return;
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 struct nmb_name qname = *question_name;
286 if( rrec->fail_fn)
287 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
288 /* Remove the name. */
289 standard_fail_register( subrec, &qname);
292 /* Ensure we don't retry. */
293 remove_response_record(subrec, rrec);
296 /****************************************************************************
297 Initiate one multi-homed name registration packet.
298 ****************************************************************************/
300 static void multihomed_register_one(struct nmb_name *nmbname,
301 uint16 nb_flags,
302 register_name_success_function success_fn,
303 register_name_fail_function fail_fn,
304 struct in_addr ip,
305 const char *tag)
307 struct userdata_struct *userdata;
308 struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
309 fstring ip_str;
311 userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
312 if (!userdata) {
313 DEBUG(0,("Failed to allocate userdata structure!\n"));
314 return;
316 ZERO_STRUCTP(userdata);
317 userdata->userdata_len = strlen(tag) + 1;
318 strlcpy(userdata->data, tag, userdata->userdata_len);
320 fstrcpy(ip_str, inet_ntoa(ip));
322 DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
323 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
325 if (queue_register_multihomed_name(unicast_subnet,
326 register_name_response,
327 register_name_timeout_response,
328 success_fn,
329 fail_fn,
330 userdata,
331 nmbname,
332 nb_flags,
334 wins_ip) == NULL) {
335 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
336 nmb_namestr(nmbname), inet_ntoa(ip)));
339 free(userdata);
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 ****************************************************************************/
347 static void wins_next_registration(struct response_record *rrec)
349 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
350 struct nmb_name *nmbname = &sent_nmb->question.question_name;
351 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
352 struct userdata_struct *userdata = rrec->userdata;
353 const char *tag;
354 struct in_addr last_ip;
355 struct subnet_record *subrec;
357 putip(&last_ip,&sent_nmb->additional->rdata[2]);
359 if (!userdata) {
360 /* it wasn't multi-homed */
361 return;
364 tag = (const char *)userdata->data;
366 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
367 if (ip_equal(last_ip, subrec->myip)) {
368 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
369 break;
373 if (!subrec) {
374 /* no more to do! */
375 return;
378 switch (sent_nmb->header.opcode) {
379 case NMB_NAME_MULTIHOMED_REG_OPCODE:
380 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
381 break;
382 case NMB_NAME_REFRESH_OPCODE_8:
383 queue_wins_refresh(nmbname,
384 register_name_response,
385 register_name_timeout_response,
386 nb_flags, subrec->myip, tag);
387 break;
391 /****************************************************************************
392 Try and register one of our names on the unicast subnet - multihomed.
393 ****************************************************************************/
395 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
396 register_name_success_function success_fn,
397 register_name_fail_function fail_fn)
400 If we are adding a group name, we just send multiple
401 register name packets to the WINS server (this is an
402 internet group name.
404 If we are adding a unique name, We need first to add
405 our names to the unicast subnet namelist. This is
406 because when a WINS server receives a multihomed
407 registration request, the first thing it does is to
408 send a name query to the registering machine, to see
409 if it has put the name in it's local namelist.
410 We need the name there so the query response code in
411 nmbd_incomingrequests.c will find it.
413 We are adding this name prematurely (we don't really
414 have it yet), but as this is on the unicast subnet
415 only we will get away with this (only the WINS server
416 will ever query names from us on this subnet).
418 int num_ips=0;
419 int i, t;
420 struct subnet_record *subrec;
421 char **wins_tags;
422 struct in_addr *ip_list;
423 unstring name;
425 for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
426 num_ips++;
428 if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
429 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
430 return;
433 for (subrec = FIRST_SUBNET, i = 0;
434 subrec;
435 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
436 ip_list[i] = subrec->myip;
439 pull_ascii_nstring(name, sizeof(name), nmbname->name);
440 add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
441 nb_flags, lp_max_ttl(), SELF_NAME,
442 num_ips, ip_list);
444 /* get the list of wins tags - we try to register for each of them */
445 wins_tags = wins_srv_tags();
447 /* Now try and register the name for each wins tag. Note that
448 at this point we only register our first IP with each wins
449 group. We will register the rest from
450 wins_next_registration() when we get the reply for this
451 one. That follows the way W2K does things (tridge)
453 for (t=0; wins_tags && wins_tags[t]; t++) {
454 multihomed_register_one(nmbname, nb_flags,
455 success_fn, fail_fn,
456 ip_list[0],
457 wins_tags[t]);
460 wins_srv_tags_free(wins_tags);
462 SAFE_FREE(ip_list);
465 /****************************************************************************
466 Try and register one of our names.
467 ****************************************************************************/
469 void register_name(struct subnet_record *subrec,
470 const char *name, int type, uint16 nb_flags,
471 register_name_success_function success_fn,
472 register_name_fail_function fail_fn,
473 struct userdata_struct *userdata)
475 struct nmb_name nmbname;
476 nstring nname;
478 errno = 0;
479 push_ascii_nstring(nname, name);
480 if (errno == E2BIG) {
481 unstring tname;
482 pull_ascii_nstring(tname, sizeof(tname), nname);
483 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
484 name, tname));
485 make_nmb_name(&nmbname, tname, type);
486 } else {
487 make_nmb_name(&nmbname, name, type);
490 /* Always set the NB_ACTIVE flag on the name we are
491 registering. Doesn't make sense without it.
494 nb_flags |= NB_ACTIVE;
496 if (subrec == unicast_subnet) {
497 /* we now always do multi-homed registration if we are
498 registering to a WINS server. This copes much
499 better with complex WINS setups */
500 multihomed_register_name(&nmbname, nb_flags,
501 success_fn, fail_fn);
502 return;
505 if (queue_register_name(subrec,
506 register_name_response,
507 register_name_timeout_response,
508 success_fn,
509 fail_fn,
510 userdata,
511 &nmbname,
512 nb_flags) == NULL) {
513 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
514 nmb_namestr(&nmbname)));
518 /****************************************************************************
519 Try and refresh one of our names. This is *only* called for WINS refresh
520 ****************************************************************************/
522 void wins_refresh_name(struct name_record *namerec)
524 int t;
525 char **wins_tags;
527 /* get the list of wins tags - we try to refresh for each of them */
528 wins_tags = wins_srv_tags();
530 for (t=0; wins_tags && wins_tags[t]; t++) {
531 queue_wins_refresh(&namerec->name,
532 register_name_response,
533 register_name_timeout_response,
534 namerec->data.nb_flags,
535 namerec->data.ip[0], wins_tags[t]);
538 wins_srv_tags_free(wins_tags);