WHATSNEW: Update changes.
[Samba.git] / source / nmbd / nmbd_nameregister.c
blob98f129aa892d872774ddbd528cd57eef7b6041b0
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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 /* forward declarations */
26 static void wins_next_registration(struct response_record *rrec);
29 /****************************************************************************
30 Deal with a response packet when registering one of our names.
31 ****************************************************************************/
33 static void register_name_response(struct subnet_record *subrec,
34 struct response_record *rrec, struct packet_struct *p)
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.
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;
53 putip(&register_ip,&sent_nmb->additional->rdata[2]);
54 fstrcpy(reg_name, inet_ntoa(register_ip));
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);
61 /* Sanity check. Ensure that the answer name in the incoming packet is the
62 same as the requested name in the outgoing packet. */
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;
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;
76 if(bcast) {
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.
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--;
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;
98 #endif /* OLD_SAMBA_SERVER_HACK */
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. */
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));
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;
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;
136 /* send off a registration for the next IP, if any */
137 wins_next_registration(rrec);
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)));
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);
162 /* Ensure we don't retry. */
163 remove_response_record(subrec, rrec);
166 /****************************************************************************
167 Deal with a timeout of a WINS registration request
168 ****************************************************************************/
170 static void wins_registration_timeout(struct subnet_record *subrec,
171 struct response_record *rrec)
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;
179 putip(&register_ip,&sent_nmb->additional->rdata[2]);
181 fstrcpy(src_addr, inet_ntoa(register_ip));
183 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
184 inet_ntoa(rrec->packet->ip), src_addr));
186 /* mark it temporarily dead for this source address */
187 wins_srv_died(rrec->packet->ip, register_ip);
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;
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);
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;
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);
217 /* send off a registration for the next IP, if any */
218 wins_next_registration(rrec);
220 /* don't need to send this packet any more */
221 remove_response_record(subrec, rrec);
222 return;
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;
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)));
234 /* notice that we don't remove the response record. This keeps
235 us trying to register with each of our failover wins servers */
238 /****************************************************************************
239 Deal with a timeout when registering one of our names.
240 ****************************************************************************/
242 static void register_name_timeout_response(struct subnet_record *subrec,
243 struct response_record *rrec)
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.
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;
259 if (bcast) {
260 if(rrec->num_msgs == 0) {
261 /* Not receiving a message is success for broadcast registration. */
262 success = True;
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]);
269 } else {
270 /* wins timeouts are special */
271 wins_registration_timeout(subrec, rrec);
272 return;
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);
291 /* Ensure we don't retry. */
292 remove_response_record(subrec, rrec);
295 /****************************************************************************
296 Initiate one multi-homed name registration packet.
297 ****************************************************************************/
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)
306 struct userdata_struct *userdata;
307 struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
308 fstring ip_str;
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;
315 ZERO_STRUCTP(userdata);
316 userdata->userdata_len = strlen(tag) + 1;
317 strlcpy(userdata->data, tag, userdata->userdata_len);
319 fstrcpy(ip_str, inet_ntoa(ip));
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));
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,
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)));
338 free(userdata);
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 ****************************************************************************/
346 static void wins_next_registration(struct response_record *rrec)
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;
356 putip(&last_ip,&sent_nmb->additional->rdata[2]);
358 if (!userdata) {
359 /* it wasn't multi-homed */
360 return;
363 tag = (const char *)userdata->data;
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;
372 if (!subrec) {
373 /* no more to do! */
374 return;
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;
390 /****************************************************************************
391 Try and register one of our names on the unicast subnet - multihomed.
392 ****************************************************************************/
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)
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.
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.
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).
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;
424 for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
425 num_ips++;
427 if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
428 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
429 return;
432 for (subrec = FIRST_SUBNET, i = 0;
433 subrec;
434 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
435 ip_list[i] = subrec->myip;
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);
443 /* get the list of wins tags - we try to register for each of them */
444 wins_tags = wins_srv_tags();
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)
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]);
459 wins_srv_tags_free(wins_tags);
461 SAFE_FREE(ip_list);
464 /****************************************************************************
465 Try and register one of our names.
466 ****************************************************************************/
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)
474 struct nmb_name nmbname;
475 nstring nname;
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);
489 /* Always set the NB_ACTIVE flag on the name we are
490 registering. Doesn't make sense without it.
493 nb_flags |= NB_ACTIVE;
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;
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)));
517 /****************************************************************************
518 Try and refresh one of our names. This is *only* called for WINS refresh
519 ****************************************************************************/
521 void wins_refresh_name(struct name_record *namerec)
523 int t;
524 char **wins_tags;
526 /* get the list of wins tags - we try to refresh for each of them */
527 wins_tags = wins_srv_tags();
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]);
537 wins_srv_tags_free(wins_tags);