Fix bug 9519 - Samba returns unexpected error on SMB posix open.
[Samba/bjacke.git] / source3 / nmbd / nmbd_nameregister.c
blob71c4751d7c1d0cf27dcc2e37b5c58fd532a325cc
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"
24 #include "nmbd/nmbd.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 if (!ip_equal_v4(rrec->packet->ip, p->ip)) {
109 DEBUG(5,("register_name_response: Ignoring WINS server response "
110 "from IP %s, for name %s. We sent to IP %s\n",
111 inet_ntoa(p->ip),
112 nmb_namestr(answer_name),
113 inet_ntoa(rrec->packet->ip)));
114 return;
116 /* Unicast - check to see if the response allows us to have the name. */
117 if (nmb->header.opcode == NMB_WACK_OPCODE) {
118 /* WINS server is telling us to wait. Pretend we didn't get
119 the response but don't send out any more register requests. */
121 DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
122 inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
124 rrec->repeat_count = 0;
125 /* How long we should wait for. */
126 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
127 rrec->num_msgs--;
128 return;
129 } else if (nmb->header.rcode != 0) {
130 /* Error code - we didn't get the name. */
131 success = False;
133 DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
134 subrec==unicast_subnet?"WINS ":"",
135 inet_ntoa(p->ip),
136 nmb_namestr(answer_name),
137 reg_name,
138 nmb->header.rcode));
139 } else {
140 success = True;
141 /* Get the data we need to pass to the success function. */
142 nb_flags = get_nb_flags(nmb->answers->rdata);
143 ttl = nmb->answers->ttl;
145 /* send off a registration for the next IP, if any */
146 wins_next_registration(rrec);
150 DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
151 success ? "success" : "failure",
152 subrec==unicast_subnet?"WINS ":"",
153 nmb_namestr(answer_name),
154 reg_name,
155 inet_ntoa(rrec->packet->ip)));
157 if(success) {
158 /* Enter the registered name into the subnet name database before calling
159 the success function. */
160 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
161 if( rrec->success_fn)
162 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
163 } else {
164 struct nmb_name qname = *question_name;
165 if( rrec->fail_fn)
166 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
167 /* Remove the name. */
168 standard_fail_register( subrec, &qname);
171 /* Ensure we don't retry. */
172 remove_response_record(subrec, rrec);
175 /****************************************************************************
176 Deal with a timeout of a WINS registration request
177 ****************************************************************************/
179 static void wins_registration_timeout(struct subnet_record *subrec,
180 struct response_record *rrec)
182 struct userdata_struct *userdata = rrec->userdata;
183 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
184 struct nmb_name *nmbname = &sent_nmb->question.question_name;
185 struct in_addr register_ip;
186 fstring src_addr;
188 putip(&register_ip,&sent_nmb->additional->rdata[2]);
190 fstrcpy(src_addr, inet_ntoa(register_ip));
192 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
193 inet_ntoa(rrec->packet->ip), src_addr));
195 /* mark it temporarily dead for this source address */
196 wins_srv_died(rrec->packet->ip, register_ip);
198 /* if we have some userdata then use that to work out what
199 wins server to try next */
200 if (userdata) {
201 const char *tag = (const char *)userdata->data;
203 /* try the next wins server in our failover list for
204 this tag */
205 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
208 /* if we have run out of wins servers for this tag then they
209 must all have timed out. We treat this as *success*, not
210 failure, and go into our standard name refresh mode. This
211 copes with all the wins servers being down */
212 if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
213 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
214 int ttl = sent_nmb->additional->ttl;
216 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
217 if(rrec->success_fn) {
218 (*(register_name_success_function)rrec->success_fn)(subrec,
219 rrec->userdata,
220 nmbname,
221 nb_flags,
222 ttl,
223 register_ip);
226 /* send off a registration for the next IP, if any */
227 wins_next_registration(rrec);
229 /* don't need to send this packet any more */
230 remove_response_record(subrec, rrec);
231 return;
234 /* we will be moving to the next WINS server for this group,
235 send it immediately */
236 rrec->repeat_count = 2;
237 rrec->repeat_time = time(NULL) + 1;
238 rrec->in_expiration_processing = False;
240 DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
241 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
243 /* notice that we don't remove the response record. This keeps
244 us trying to register with each of our failover wins servers */
247 /****************************************************************************
248 Deal with a timeout when registering one of our names.
249 ****************************************************************************/
251 static void register_name_timeout_response(struct subnet_record *subrec,
252 struct response_record *rrec)
255 * If we are registering unicast, then NOT getting a response is an
256 * error - we do not have the name. If we are registering broadcast,
257 * then we don't expect to get a response.
260 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
261 bool bcast = sent_nmb->header.nm_flags.bcast;
262 bool success = False;
263 struct nmb_name *question_name = &sent_nmb->question.question_name;
264 uint16 nb_flags = 0;
265 int ttl = 0;
266 struct in_addr registered_ip;
268 if (bcast) {
269 if(rrec->num_msgs == 0) {
270 /* Not receiving a message is success for broadcast registration. */
271 success = True;
273 /* Pull the success values from the original request packet. */
274 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
275 ttl = sent_nmb->additional->ttl;
276 putip(&registered_ip,&sent_nmb->additional->rdata[2]);
278 } else {
279 /* wins timeouts are special */
280 wins_registration_timeout(subrec, rrec);
281 return;
284 DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
285 success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
286 if(success) {
287 /* Enter the registered name into the subnet name database before calling
288 the success function. */
289 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
290 if( rrec->success_fn)
291 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
292 } else {
293 struct nmb_name qname = *question_name;
294 if( rrec->fail_fn)
295 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
296 /* Remove the name. */
297 standard_fail_register( subrec, &qname);
300 /* Ensure we don't retry. */
301 remove_response_record(subrec, rrec);
304 /****************************************************************************
305 Initiate one multi-homed name registration packet.
306 ****************************************************************************/
308 static void multihomed_register_one(struct nmb_name *nmbname,
309 uint16 nb_flags,
310 register_name_success_function success_fn,
311 register_name_fail_function fail_fn,
312 struct in_addr ip,
313 const char *tag)
315 struct userdata_struct *userdata;
316 struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
317 fstring ip_str;
319 userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
320 if (!userdata) {
321 DEBUG(0,("Failed to allocate userdata structure!\n"));
322 return;
324 ZERO_STRUCTP(userdata);
325 userdata->userdata_len = strlen(tag) + 1;
326 strlcpy(userdata->data, tag, userdata->userdata_len);
328 fstrcpy(ip_str, inet_ntoa(ip));
330 DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
331 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
333 if (queue_register_multihomed_name(unicast_subnet,
334 register_name_response,
335 register_name_timeout_response,
336 success_fn,
337 fail_fn,
338 userdata,
339 nmbname,
340 nb_flags,
342 wins_ip) == NULL) {
343 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
344 nmb_namestr(nmbname), inet_ntoa(ip)));
347 free(userdata);
350 /****************************************************************************
351 We have finished the registration of one IP and need to see if we have
352 any more IPs left to register with this group of wins server for this name.
353 ****************************************************************************/
355 static void wins_next_registration(struct response_record *rrec)
357 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
358 struct nmb_name *nmbname = &sent_nmb->question.question_name;
359 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
360 struct userdata_struct *userdata = rrec->userdata;
361 const char *tag;
362 struct in_addr last_ip;
363 struct subnet_record *subrec;
365 putip(&last_ip,&sent_nmb->additional->rdata[2]);
367 if (!userdata) {
368 /* it wasn't multi-homed */
369 return;
372 tag = (const char *)userdata->data;
374 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
375 if (ip_equal_v4(last_ip, subrec->myip)) {
376 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
377 break;
381 if (!subrec) {
382 /* no more to do! */
383 return;
386 switch (sent_nmb->header.opcode) {
387 case NMB_NAME_MULTIHOMED_REG_OPCODE:
388 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
389 break;
390 case NMB_NAME_REFRESH_OPCODE_8:
391 queue_wins_refresh(nmbname,
392 register_name_response,
393 register_name_timeout_response,
394 nb_flags, subrec->myip, tag);
395 break;
399 /****************************************************************************
400 Try and register one of our names on the unicast subnet - multihomed.
401 ****************************************************************************/
403 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
404 register_name_success_function success_fn,
405 register_name_fail_function fail_fn)
408 If we are adding a group name, we just send multiple
409 register name packets to the WINS server (this is an
410 internet group name.
412 If we are adding a unique name, We need first to add
413 our names to the unicast subnet namelist. This is
414 because when a WINS server receives a multihomed
415 registration request, the first thing it does is to
416 send a name query to the registering machine, to see
417 if it has put the name in it's local namelist.
418 We need the name there so the query response code in
419 nmbd_incomingrequests.c will find it.
421 We are adding this name prematurely (we don't really
422 have it yet), but as this is on the unicast subnet
423 only we will get away with this (only the WINS server
424 will ever query names from us on this subnet).
426 int num_ips=0;
427 int i, t;
428 struct subnet_record *subrec;
429 char **wins_tags;
430 struct in_addr *ip_list;
431 unstring name;
433 for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
434 num_ips++;
436 if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
437 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
438 return;
441 for (subrec = FIRST_SUBNET, i = 0;
442 subrec;
443 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
444 ip_list[i] = subrec->myip;
447 pull_ascii_nstring(name, sizeof(name), nmbname->name);
448 add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
449 nb_flags, lp_max_ttl(), SELF_NAME,
450 num_ips, ip_list);
452 /* get the list of wins tags - we try to register for each of them */
453 wins_tags = wins_srv_tags();
455 /* Now try and register the name for each wins tag. Note that
456 at this point we only register our first IP with each wins
457 group. We will register the rest from
458 wins_next_registration() when we get the reply for this
459 one. That follows the way W2K does things (tridge)
461 for (t=0; wins_tags && wins_tags[t]; t++) {
462 multihomed_register_one(nmbname, nb_flags,
463 success_fn, fail_fn,
464 ip_list[0],
465 wins_tags[t]);
468 wins_srv_tags_free(wins_tags);
470 SAFE_FREE(ip_list);
473 /****************************************************************************
474 Try and register one of our names.
475 ****************************************************************************/
477 void register_name(struct subnet_record *subrec,
478 const char *name, int type, uint16 nb_flags,
479 register_name_success_function success_fn,
480 register_name_fail_function fail_fn,
481 struct userdata_struct *userdata)
483 struct nmb_name nmbname;
484 nstring nname;
486 errno = 0;
487 push_ascii_nstring(nname, name);
488 if (errno == E2BIG) {
489 unstring tname;
490 pull_ascii_nstring(tname, sizeof(tname), nname);
491 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
492 name, tname));
493 make_nmb_name(&nmbname, tname, type);
494 } else {
495 make_nmb_name(&nmbname, name, type);
498 /* Always set the NB_ACTIVE flag on the name we are
499 registering. Doesn't make sense without it.
502 nb_flags |= NB_ACTIVE;
504 if (subrec == unicast_subnet) {
505 /* we now always do multi-homed registration if we are
506 registering to a WINS server. This copes much
507 better with complex WINS setups */
508 multihomed_register_name(&nmbname, nb_flags,
509 success_fn, fail_fn);
510 return;
513 if (queue_register_name(subrec,
514 register_name_response,
515 register_name_timeout_response,
516 success_fn,
517 fail_fn,
518 userdata,
519 &nmbname,
520 nb_flags) == NULL) {
521 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
522 nmb_namestr(&nmbname)));
526 /****************************************************************************
527 Try and refresh one of our names. This is *only* called for WINS refresh
528 ****************************************************************************/
530 void wins_refresh_name(struct name_record *namerec)
532 int t;
533 char **wins_tags;
535 /* get the list of wins tags - we try to refresh for each of them */
536 wins_tags = wins_srv_tags();
538 for (t=0; wins_tags && wins_tags[t]; t++) {
539 queue_wins_refresh(&namerec->name,
540 register_name_response,
541 register_name_timeout_response,
542 namerec->data.nb_flags,
543 namerec->data.ip[0], wins_tags[t]);
546 wins_srv_tags_free(wins_tags);