• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.0.25b/source/nmbd/
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 2 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, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22*/
23
24#include "includes.h"
25
26/* forward declarations */
27static void wins_next_registration(struct response_record *rrec);
28
29
30/****************************************************************************
31 Deal with a response packet when registering one of our names.
32****************************************************************************/
33
34static void register_name_response(struct subnet_record *subrec,
35                       struct response_record *rrec, struct packet_struct *p)
36{
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.
41	 */
42
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;
53
54	putip(&register_ip,&sent_nmb->additional->rdata[2]);
55	fstrcpy(reg_name, inet_ntoa(register_ip));
56
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);
60	}
61
62	/* Sanity check. Ensure that the answer name in the incoming packet is the
63	   same as the requested name in the outgoing packet. */
64
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;
69	}
70
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;
75	}
76
77	if(bcast) {
78		/*
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.
85		 */
86
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--;
94
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;
98		}
99#endif /* OLD_SAMBA_SERVER_HACK */
100
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. */
112
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));
115
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;
124
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;
136
137			/* send off a registration for the next IP, if any */
138			wins_next_registration(rrec);
139		}
140	}
141
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)));
148
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		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, rrec, question_name);
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
170static 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
242static 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		if( rrec->fail_fn)
285			(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
286		/* Remove the name. */
287		standard_fail_register( subrec, rrec, question_name);
288	}
289
290	/* Ensure we don't retry. */
291	remove_response_record(subrec, rrec);
292}
293
294/****************************************************************************
295 Initiate one multi-homed name registration packet.
296****************************************************************************/
297
298static void multihomed_register_one(struct nmb_name *nmbname,
299				    uint16 nb_flags,
300				    register_name_success_function success_fn,
301				    register_name_fail_function fail_fn,
302				    struct in_addr ip,
303				    const char *tag)
304{
305	struct userdata_struct *userdata;
306	struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
307	fstring ip_str;
308
309	userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
310	if (!userdata) {
311		DEBUG(0,("Failed to allocate userdata structure!\n"));
312		return;
313	}
314	ZERO_STRUCTP(userdata);
315	userdata->userdata_len = strlen(tag) + 1;
316	strlcpy(userdata->data, tag, userdata->userdata_len);
317
318	fstrcpy(ip_str, inet_ntoa(ip));
319
320	DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
321		 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
322
323	if (queue_register_multihomed_name(unicast_subnet,
324					   register_name_response,
325					   register_name_timeout_response,
326					   success_fn,
327					   fail_fn,
328					   userdata,
329					   nmbname,
330					   nb_flags,
331					   ip,
332					   wins_ip) == NULL) {
333		DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
334			 nmb_namestr(nmbname), inet_ntoa(ip)));
335	}
336
337	free(userdata);
338}
339
340/****************************************************************************
341 We have finished the registration of one IP and need to see if we have
342 any more IPs left to register with this group of wins server for this name.
343****************************************************************************/
344
345static void wins_next_registration(struct response_record *rrec)
346{
347	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
348	struct nmb_name *nmbname = &sent_nmb->question.question_name;
349	uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
350	struct userdata_struct *userdata = rrec->userdata;
351	const char *tag;
352	struct in_addr last_ip;
353	struct subnet_record *subrec;
354
355	putip(&last_ip,&sent_nmb->additional->rdata[2]);
356
357	if (!userdata) {
358		/* it wasn't multi-homed */
359		return;
360	}
361
362	tag = (const char *)userdata->data;
363
364	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
365		if (ip_equal(last_ip, subrec->myip)) {
366			subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
367			break;
368		}
369	}
370
371	if (!subrec) {
372		/* no more to do! */
373		return;
374	}
375
376	switch (sent_nmb->header.opcode) {
377	case NMB_NAME_MULTIHOMED_REG_OPCODE:
378		multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
379		break;
380	case NMB_NAME_REFRESH_OPCODE_8:
381		queue_wins_refresh(nmbname,
382				   register_name_response,
383				   register_name_timeout_response,
384				   nb_flags, subrec->myip, tag);
385		break;
386	}
387}
388
389/****************************************************************************
390 Try and register one of our names on the unicast subnet - multihomed.
391****************************************************************************/
392
393static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
394				     register_name_success_function success_fn,
395				     register_name_fail_function fail_fn)
396{
397	/*
398	  If we are adding a group name, we just send multiple
399	  register name packets to the WINS server (this is an
400	  internet group name.
401
402	  If we are adding a unique name, We need first to add
403	  our names to the unicast subnet namelist. This is
404	  because when a WINS server receives a multihomed
405	  registration request, the first thing it does is to
406	  send a name query to the registering machine, to see
407	  if it has put the name in it's local namelist.
408	  We need the name there so the query response code in
409	  nmbd_incomingrequests.c will find it.
410
411	  We are adding this name prematurely (we don't really
412	  have it yet), but as this is on the unicast subnet
413	  only we will get away with this (only the WINS server
414	  will ever query names from us on this subnet).
415	*/
416	int num_ips=0;
417	int i, t;
418	struct subnet_record *subrec;
419	char **wins_tags;
420	struct in_addr *ip_list;
421	unstring name;
422
423	for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
424		num_ips++;
425
426	if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
427		DEBUG(0,("multihomed_register_name: malloc fail !\n"));
428		return;
429	}
430
431	for (subrec = FIRST_SUBNET, i = 0;
432	     subrec;
433	     subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
434		ip_list[i] = subrec->myip;
435	}
436
437	pull_ascii_nstring(name, sizeof(name), nmbname->name);
438	add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
439			   nb_flags, lp_max_ttl(), SELF_NAME,
440			   num_ips, ip_list);
441
442	/* get the list of wins tags - we try to register for each of them */
443	wins_tags = wins_srv_tags();
444
445	/* Now try and register the name for each wins tag.  Note that
446	   at this point we only register our first IP with each wins
447	   group. We will register the rest from
448	   wins_next_registration() when we get the reply for this
449	   one. That follows the way W2K does things (tridge)
450	*/
451	for (t=0; wins_tags && wins_tags[t]; t++) {
452		multihomed_register_one(nmbname, nb_flags,
453					success_fn, fail_fn,
454					ip_list[0],
455					wins_tags[t]);
456	}
457
458	wins_srv_tags_free(wins_tags);
459
460	SAFE_FREE(ip_list);
461}
462
463/****************************************************************************
464 Try and register one of our names.
465****************************************************************************/
466
467void register_name(struct subnet_record *subrec,
468                   const char *name, int type, uint16 nb_flags,
469                   register_name_success_function success_fn,
470                   register_name_fail_function fail_fn,
471                   struct userdata_struct *userdata)
472{
473	struct nmb_name nmbname;
474	nstring nname;
475
476	errno = 0;
477	push_ascii_nstring(nname, name);
478        if (errno == E2BIG) {
479		unstring tname;
480		pull_ascii_nstring(tname, sizeof(tname), nname);
481		DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
482			name, tname));
483		make_nmb_name(&nmbname, tname, type);
484	} else {
485		make_nmb_name(&nmbname, name, type);
486	}
487
488	/* Always set the NB_ACTIVE flag on the name we are
489	   registering. Doesn't make sense without it.
490	*/
491
492	nb_flags |= NB_ACTIVE;
493
494	if (subrec == unicast_subnet) {
495		/* we now always do multi-homed registration if we are
496		   registering to a WINS server. This copes much
497		   better with complex WINS setups */
498		multihomed_register_name(&nmbname, nb_flags,
499					 success_fn, fail_fn);
500		return;
501	}
502
503	if (queue_register_name(subrec,
504				register_name_response,
505				register_name_timeout_response,
506				success_fn,
507				fail_fn,
508				userdata,
509				&nmbname,
510				nb_flags) == NULL) {
511		DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
512			 nmb_namestr(&nmbname)));
513	}
514}
515
516/****************************************************************************
517 Try and refresh one of our names. This is *only* called for WINS refresh
518****************************************************************************/
519
520void wins_refresh_name(struct name_record *namerec)
521{
522	int t;
523	char **wins_tags;
524
525	/* get the list of wins tags - we try to refresh for each of them */
526	wins_tags = wins_srv_tags();
527
528	for (t=0; wins_tags && wins_tags[t]; t++) {
529		queue_wins_refresh(&namerec->name,
530				   register_name_response,
531				   register_name_timeout_response,
532				   namerec->data.nb_flags,
533				   namerec->data.ip[0], wins_tags[t]);
534	}
535
536	wins_srv_tags_free(wins_tags);
537}
538