s4-netlogon: implement dcesrv_netr_DsRAddressToSitenamesExW
[Samba/aatanasov.git] / source3 / nmbd / nmbd_nameregister.c
blobd4359aab37d44153881e836231be3dbe2f4e8fc0
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 if (!ip_equal_v4(rrec->packet->ip, p->ip)) {
108 DEBUG(5,("register_name_response: Ignoring WINS server response "
109 "from IP %s, for name %s. We sent to IP %s\n",
110 inet_ntoa(p->ip),
111 nmb_namestr(answer_name),
112 inet_ntoa(rrec->packet->ip)));
113 return;
115 /* Unicast - check to see if the response allows us to have the name. */
116 if (nmb->header.opcode == NMB_WACK_OPCODE) {
117 /* WINS server is telling us to wait. Pretend we didn't get
118 the response but don't send out any more register requests. */
120 DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
121 inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
123 rrec->repeat_count = 0;
124 /* How long we should wait for. */
125 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
126 rrec->num_msgs--;
127 return;
128 } else if (nmb->header.rcode != 0) {
129 /* Error code - we didn't get the name. */
130 success = False;
132 DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
133 subrec==unicast_subnet?"WINS ":"",
134 inet_ntoa(p->ip),
135 nmb_namestr(answer_name),
136 reg_name,
137 nmb->header.rcode));
138 } else {
139 success = True;
140 /* Get the data we need to pass to the success function. */
141 nb_flags = get_nb_flags(nmb->answers->rdata);
142 ttl = nmb->answers->ttl;
144 /* send off a registration for the next IP, if any */
145 wins_next_registration(rrec);
149 DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
150 success ? "success" : "failure",
151 subrec==unicast_subnet?"WINS ":"",
152 nmb_namestr(answer_name),
153 reg_name,
154 inet_ntoa(rrec->packet->ip)));
156 if(success) {
157 /* Enter the registered name into the subnet name database before calling
158 the success function. */
159 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
160 if( rrec->success_fn)
161 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
162 } else {
163 struct nmb_name qname = *question_name;
164 if( rrec->fail_fn)
165 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
166 /* Remove the name. */
167 standard_fail_register( subrec, &qname);
170 /* Ensure we don't retry. */
171 remove_response_record(subrec, rrec);
174 /****************************************************************************
175 Deal with a timeout of a WINS registration request
176 ****************************************************************************/
178 static void wins_registration_timeout(struct subnet_record *subrec,
179 struct response_record *rrec)
181 struct userdata_struct *userdata = rrec->userdata;
182 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
183 struct nmb_name *nmbname = &sent_nmb->question.question_name;
184 struct in_addr register_ip;
185 fstring src_addr;
187 putip(&register_ip,&sent_nmb->additional->rdata[2]);
189 fstrcpy(src_addr, inet_ntoa(register_ip));
191 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
192 inet_ntoa(rrec->packet->ip), src_addr));
194 /* mark it temporarily dead for this source address */
195 wins_srv_died(rrec->packet->ip, register_ip);
197 /* if we have some userdata then use that to work out what
198 wins server to try next */
199 if (userdata) {
200 const char *tag = (const char *)userdata->data;
202 /* try the next wins server in our failover list for
203 this tag */
204 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
207 /* if we have run out of wins servers for this tag then they
208 must all have timed out. We treat this as *success*, not
209 failure, and go into our standard name refresh mode. This
210 copes with all the wins servers being down */
211 if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
212 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
213 int ttl = sent_nmb->additional->ttl;
215 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
216 if(rrec->success_fn) {
217 (*(register_name_success_function)rrec->success_fn)(subrec,
218 rrec->userdata,
219 nmbname,
220 nb_flags,
221 ttl,
222 register_ip);
225 /* send off a registration for the next IP, if any */
226 wins_next_registration(rrec);
228 /* don't need to send this packet any more */
229 remove_response_record(subrec, rrec);
230 return;
233 /* we will be moving to the next WINS server for this group,
234 send it immediately */
235 rrec->repeat_count = 2;
236 rrec->repeat_time = time(NULL) + 1;
237 rrec->in_expiration_processing = False;
239 DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
240 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
242 /* notice that we don't remove the response record. This keeps
243 us trying to register with each of our failover wins servers */
246 /****************************************************************************
247 Deal with a timeout when registering one of our names.
248 ****************************************************************************/
250 static void register_name_timeout_response(struct subnet_record *subrec,
251 struct response_record *rrec)
254 * If we are registering unicast, then NOT getting a response is an
255 * error - we do not have the name. If we are registering broadcast,
256 * then we don't expect to get a response.
259 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
260 bool bcast = sent_nmb->header.nm_flags.bcast;
261 bool success = False;
262 struct nmb_name *question_name = &sent_nmb->question.question_name;
263 uint16 nb_flags = 0;
264 int ttl = 0;
265 struct in_addr registered_ip;
267 if (bcast) {
268 if(rrec->num_msgs == 0) {
269 /* Not receiving a message is success for broadcast registration. */
270 success = True;
272 /* Pull the success values from the original request packet. */
273 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
274 ttl = sent_nmb->additional->ttl;
275 putip(&registered_ip,&sent_nmb->additional->rdata[2]);
277 } else {
278 /* wins timeouts are special */
279 wins_registration_timeout(subrec, rrec);
280 return;
283 DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
284 success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
285 if(success) {
286 /* Enter the registered name into the subnet name database before calling
287 the success function. */
288 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
289 if( rrec->success_fn)
290 (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
291 } else {
292 struct nmb_name qname = *question_name;
293 if( rrec->fail_fn)
294 (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
295 /* Remove the name. */
296 standard_fail_register( subrec, &qname);
299 /* Ensure we don't retry. */
300 remove_response_record(subrec, rrec);
303 /****************************************************************************
304 Initiate one multi-homed name registration packet.
305 ****************************************************************************/
307 static void multihomed_register_one(struct nmb_name *nmbname,
308 uint16 nb_flags,
309 register_name_success_function success_fn,
310 register_name_fail_function fail_fn,
311 struct in_addr ip,
312 const char *tag)
314 struct userdata_struct *userdata;
315 struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
316 fstring ip_str;
318 userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
319 if (!userdata) {
320 DEBUG(0,("Failed to allocate userdata structure!\n"));
321 return;
323 ZERO_STRUCTP(userdata);
324 userdata->userdata_len = strlen(tag) + 1;
325 strlcpy(userdata->data, tag, userdata->userdata_len);
327 fstrcpy(ip_str, inet_ntoa(ip));
329 DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
330 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
332 if (queue_register_multihomed_name(unicast_subnet,
333 register_name_response,
334 register_name_timeout_response,
335 success_fn,
336 fail_fn,
337 userdata,
338 nmbname,
339 nb_flags,
341 wins_ip) == NULL) {
342 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
343 nmb_namestr(nmbname), inet_ntoa(ip)));
346 free(userdata);
349 /****************************************************************************
350 We have finished the registration of one IP and need to see if we have
351 any more IPs left to register with this group of wins server for this name.
352 ****************************************************************************/
354 static void wins_next_registration(struct response_record *rrec)
356 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
357 struct nmb_name *nmbname = &sent_nmb->question.question_name;
358 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
359 struct userdata_struct *userdata = rrec->userdata;
360 const char *tag;
361 struct in_addr last_ip;
362 struct subnet_record *subrec;
364 putip(&last_ip,&sent_nmb->additional->rdata[2]);
366 if (!userdata) {
367 /* it wasn't multi-homed */
368 return;
371 tag = (const char *)userdata->data;
373 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
374 if (ip_equal_v4(last_ip, subrec->myip)) {
375 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
376 break;
380 if (!subrec) {
381 /* no more to do! */
382 return;
385 switch (sent_nmb->header.opcode) {
386 case NMB_NAME_MULTIHOMED_REG_OPCODE:
387 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
388 break;
389 case NMB_NAME_REFRESH_OPCODE_8:
390 queue_wins_refresh(nmbname,
391 register_name_response,
392 register_name_timeout_response,
393 nb_flags, subrec->myip, tag);
394 break;
398 /****************************************************************************
399 Try and register one of our names on the unicast subnet - multihomed.
400 ****************************************************************************/
402 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
403 register_name_success_function success_fn,
404 register_name_fail_function fail_fn)
407 If we are adding a group name, we just send multiple
408 register name packets to the WINS server (this is an
409 internet group name.
411 If we are adding a unique name, We need first to add
412 our names to the unicast subnet namelist. This is
413 because when a WINS server receives a multihomed
414 registration request, the first thing it does is to
415 send a name query to the registering machine, to see
416 if it has put the name in it's local namelist.
417 We need the name there so the query response code in
418 nmbd_incomingrequests.c will find it.
420 We are adding this name prematurely (we don't really
421 have it yet), but as this is on the unicast subnet
422 only we will get away with this (only the WINS server
423 will ever query names from us on this subnet).
425 int num_ips=0;
426 int i, t;
427 struct subnet_record *subrec;
428 char **wins_tags;
429 struct in_addr *ip_list;
430 unstring name;
432 for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
433 num_ips++;
435 if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
436 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
437 return;
440 for (subrec = FIRST_SUBNET, i = 0;
441 subrec;
442 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
443 ip_list[i] = subrec->myip;
446 pull_ascii_nstring(name, sizeof(name), nmbname->name);
447 add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
448 nb_flags, lp_max_ttl(), SELF_NAME,
449 num_ips, ip_list);
451 /* get the list of wins tags - we try to register for each of them */
452 wins_tags = wins_srv_tags();
454 /* Now try and register the name for each wins tag. Note that
455 at this point we only register our first IP with each wins
456 group. We will register the rest from
457 wins_next_registration() when we get the reply for this
458 one. That follows the way W2K does things (tridge)
460 for (t=0; wins_tags && wins_tags[t]; t++) {
461 multihomed_register_one(nmbname, nb_flags,
462 success_fn, fail_fn,
463 ip_list[0],
464 wins_tags[t]);
467 wins_srv_tags_free(wins_tags);
469 SAFE_FREE(ip_list);
472 /****************************************************************************
473 Try and register one of our names.
474 ****************************************************************************/
476 void register_name(struct subnet_record *subrec,
477 const char *name, int type, uint16 nb_flags,
478 register_name_success_function success_fn,
479 register_name_fail_function fail_fn,
480 struct userdata_struct *userdata)
482 struct nmb_name nmbname;
483 nstring nname;
485 errno = 0;
486 push_ascii_nstring(nname, name);
487 if (errno == E2BIG) {
488 unstring tname;
489 pull_ascii_nstring(tname, sizeof(tname), nname);
490 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
491 name, tname));
492 make_nmb_name(&nmbname, tname, type);
493 } else {
494 make_nmb_name(&nmbname, name, type);
497 /* Always set the NB_ACTIVE flag on the name we are
498 registering. Doesn't make sense without it.
501 nb_flags |= NB_ACTIVE;
503 if (subrec == unicast_subnet) {
504 /* we now always do multi-homed registration if we are
505 registering to a WINS server. This copes much
506 better with complex WINS setups */
507 multihomed_register_name(&nmbname, nb_flags,
508 success_fn, fail_fn);
509 return;
512 if (queue_register_name(subrec,
513 register_name_response,
514 register_name_timeout_response,
515 success_fn,
516 fail_fn,
517 userdata,
518 &nmbname,
519 nb_flags) == NULL) {
520 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
521 nmb_namestr(&nmbname)));
525 /****************************************************************************
526 Try and refresh one of our names. This is *only* called for WINS refresh
527 ****************************************************************************/
529 void wins_refresh_name(struct name_record *namerec)
531 int t;
532 char **wins_tags;
534 /* get the list of wins tags - we try to refresh for each of them */
535 wins_tags = wins_srv_tags();
537 for (t=0; wins_tags && wins_tags[t]; t++) {
538 queue_wins_refresh(&namerec->name,
539 register_name_response,
540 register_name_timeout_response,
541 namerec->data.nb_flags,
542 namerec->data.ip[0], wins_tags[t]);
545 wins_srv_tags_free(wins_tags);