• 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.5.8/source4/nbt_server/
1/*
2   Unix SMB/CIFS implementation.
3
4   register our names
5
6   Copyright (C) Andrew Tridgell	2005
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 3 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, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "lib/events/events.h"
24#include "../lib/util/dlinklist.h"
25#include "nbt_server/nbt_server.h"
26#include "smbd/service_task.h"
27#include "libcli/composite/composite.h"
28#include "librpc/gen_ndr/ndr_samr.h"
29#include "nbt_server/wins/winsserver.h"
30#include "librpc/gen_ndr/ndr_nbt.h"
31#include "dsdb/samdb/samdb.h"
32#include "param/param.h"
33
34static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
35
36/*
37  a name refresh request has completed
38*/
39static void refresh_completion_handler(struct nbt_name_request *req)
40{
41	struct nbtd_iface_name *iname = talloc_get_type(req->async.private_data,
42							struct nbtd_iface_name);
43	NTSTATUS status;
44	struct nbt_name_refresh io;
45	TALLOC_CTX *tmp_ctx = talloc_new(iname);
46
47	status = nbt_name_refresh_recv(req, tmp_ctx, &io);
48	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
49		DEBUG(4,("Refreshed name %s with %s on interface %s\n",
50			 nbt_name_string(tmp_ctx, &iname->name),
51			 iname->iface->ip_address, iname->iface->bcast_address));
52		iname->registration_time = timeval_current();
53		nbtd_start_refresh_timer(iname);
54		talloc_free(tmp_ctx);
55		return;
56	}
57
58	iname->nb_flags |= NBT_NM_CONFLICT;
59	iname->nb_flags &= ~NBT_NM_ACTIVE;
60
61	if (NT_STATUS_IS_OK(status)) {
62		DEBUG(1,("Name conflict from %s refreshing name %s with %s on interface %s - %s\n",
63			 io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
64			 iname->iface->ip_address, iname->iface->bcast_address,
65			 nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
66	} else {
67		DEBUG(1,("Error refreshing name %s with %s on interface %s - %s\n",
68			 nbt_name_string(tmp_ctx, &iname->name),
69			 iname->iface->ip_address, iname->iface->bcast_address,
70			 nt_errstr(status)));
71	}
72
73	talloc_free(tmp_ctx);
74}
75
76
77/*
78  handle name refresh timer events
79*/
80static void name_refresh_handler(struct tevent_context *ev, struct tevent_timer *te,
81				 struct timeval t, void *private_data)
82{
83	struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
84	struct nbtd_interface *iface = iname->iface;
85	struct nbt_name_register io;
86	struct nbt_name_request *req;
87	struct nbtd_server *nbtsrv = iface->nbtsrv;
88
89	/* setup a single name register request. Notice that we don't
90	   use a name refresh request, as Windows and Samba3 do not
91	   defend against broadcast name refresh packets. So for this
92	   to be of any use at all, we need to refresh using name
93	   registration packets */
94	io.in.name            = iname->name;
95	io.in.dest_addr       = iface->bcast_address;
96	io.in.dest_port       = lp_nbt_port(iface->nbtsrv->task->lp_ctx);
97	io.in.address         = iface->ip_address;
98	io.in.nb_flags        = iname->nb_flags;
99	io.in.ttl             = iname->ttl;
100	io.in.register_demand = false;
101	io.in.broadcast       = true;
102	io.in.multi_homed     = false;
103	io.in.timeout         = 3;
104	io.in.retries         = 0;
105
106	nbtsrv->stats.total_sent++;
107	req = nbt_name_register_send(iface->nbtsock, &io);
108	if (req == NULL) return;
109
110	req->async.fn = refresh_completion_handler;
111	req->async.private_data = iname;
112}
113
114
115/*
116  start a timer to refresh this name
117*/
118static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
119{
120	uint32_t refresh_time;
121	uint32_t max_refresh_time = lp_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
122
123	refresh_time = MIN(max_refresh_time, iname->ttl/2);
124
125	event_add_timed(iname->iface->nbtsrv->task->event_ctx,
126			iname,
127			timeval_add(&iname->registration_time, refresh_time, 0),
128			name_refresh_handler, iname);
129}
130
131
132/*
133  a name registration has completed
134*/
135static void nbtd_register_handler(struct composite_context *creq)
136{
137	struct nbtd_iface_name *iname = talloc_get_type(creq->async.private_data,
138							struct nbtd_iface_name);
139	NTSTATUS status;
140	TALLOC_CTX *tmp_ctx = talloc_new(iname);
141
142	status = nbt_name_register_bcast_recv(creq);
143	if (NT_STATUS_IS_OK(status)) {
144		/* good - nobody complained about our registration */
145		iname->nb_flags |= NBT_NM_ACTIVE;
146		DEBUG(3,("Registered %s with %s on interface %s\n",
147			 nbt_name_string(tmp_ctx, &iname->name),
148			 iname->iface->ip_address, iname->iface->bcast_address));
149		iname->registration_time = timeval_current();
150		talloc_free(tmp_ctx);
151		nbtd_start_refresh_timer(iname);
152		return;
153	}
154
155	/* someone must have replied with an objection! */
156	iname->nb_flags |= NBT_NM_CONFLICT;
157
158	DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
159		 nbt_name_string(tmp_ctx, &iname->name),
160		 iname->iface->ip_address, iname->iface->bcast_address,
161		 nt_errstr(status)));
162	talloc_free(tmp_ctx);
163}
164
165
166/*
167  register a name on a network interface
168*/
169static void nbtd_register_name_iface(struct nbtd_interface *iface,
170				     const char *name, enum nbt_name_type type,
171				     uint16_t nb_flags)
172{
173	struct nbtd_iface_name *iname;
174	const char *scope = lp_netbios_scope(iface->nbtsrv->task->lp_ctx);
175	struct nbt_name_register_bcast io;
176	struct composite_context *creq;
177	struct nbtd_server *nbtsrv = iface->nbtsrv;
178
179	iname = talloc(iface, struct nbtd_iface_name);
180	if (!iname) return;
181
182	iname->iface     = iface;
183	iname->name.name = strupper_talloc(iname, name);
184	iname->name.type = type;
185	if (scope && *scope) {
186		iname->name.scope = strupper_talloc(iname, scope);
187	} else {
188		iname->name.scope = NULL;
189	}
190	iname->nb_flags          = nb_flags;
191	iname->ttl               = lp_parm_int(iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "bcast_ttl", 300000);
192	iname->registration_time = timeval_zero();
193	iname->wins_server       = NULL;
194
195	DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
196
197	if (nb_flags & NBT_NM_PERMANENT) {
198		/* permanent names are not announced and are immediately active */
199		iname->nb_flags |= NBT_NM_ACTIVE;
200		iname->ttl       = 0;
201		return;
202	}
203
204	/* if this is the wins interface, then we need to do a special
205	   wins name registration */
206	if (iface == iface->nbtsrv->wins_interface) {
207		nbtd_winsclient_register(iname);
208		return;
209	}
210
211	/* setup a broadcast name registration request */
212	io.in.name            = iname->name;
213	io.in.dest_addr       = iface->bcast_address;
214	io.in.dest_port       = lp_nbt_port(iface->nbtsrv->task->lp_ctx);
215	io.in.address         = iface->ip_address;
216	io.in.nb_flags        = nb_flags;
217	io.in.ttl             = iname->ttl;
218
219	nbtsrv->stats.total_sent++;
220	creq = nbt_name_register_bcast_send(iface->nbtsock, &io);
221	if (creq == NULL) return;
222
223	creq->async.fn = nbtd_register_handler;
224	creq->async.private_data = iname;
225}
226
227
228/*
229  register one name on all our interfaces
230*/
231void nbtd_register_name(struct nbtd_server *nbtsrv,
232			const char *name, enum nbt_name_type type,
233			uint16_t nb_flags)
234{
235	struct nbtd_interface *iface;
236
237	/* register with all the local interfaces */
238	for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
239		nbtd_register_name_iface(iface, name, type, nb_flags);
240	}
241
242	/* register on our general broadcast interface as a permanent name */
243	if (nbtsrv->bcast_interface) {
244		nbtd_register_name_iface(nbtsrv->bcast_interface, name, type,
245					 nb_flags | NBT_NM_PERMANENT);
246	}
247
248	/* register with our WINS servers */
249	if (nbtsrv->wins_interface) {
250		nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
251	}
252}
253
254
255/*
256  register our names on all interfaces
257*/
258void nbtd_register_names(struct nbtd_server *nbtsrv)
259{
260	uint16_t nb_flags = NBT_NODE_M;
261	const char **aliases;
262
263	/* note that we don't initially mark the names "ACTIVE". They are
264	   marked active once registration is successful */
265	nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
266	nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_USER,   nb_flags);
267	nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_SERVER, nb_flags);
268
269	aliases = lp_netbios_aliases(nbtsrv->task->lp_ctx);
270	while (aliases && aliases[0]) {
271		nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
272		nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
273		aliases++;
274	}
275
276	if (lp_server_role(nbtsrv->task->lp_ctx) == ROLE_DOMAIN_CONTROLLER)	{
277		bool is_pdc = samdb_is_pdc(nbtsrv->sam_ctx);
278		if (is_pdc) {
279			nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx),
280					   NBT_NAME_PDC, nb_flags);
281		}
282		nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx),
283				   NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
284	}
285
286	nb_flags |= NBT_NM_GROUP;
287	nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
288
289	nb_flags |= NBT_NM_PERMANENT;
290	nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_CLIENT, nb_flags);
291	nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_SERVER, nb_flags);
292	nbtd_register_name(nbtsrv, "*",               NBT_NAME_CLIENT, nb_flags);
293}
294