• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/nbt_server/
1/*
2   Unix SMB/CIFS implementation.
3
4   NBT interface handling
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/util/dlinklist.h"
24#include "nbt_server/nbt_server.h"
25#include "smbd/service_task.h"
26#include "lib/socket/socket.h"
27#include "nbt_server/wins/winsserver.h"
28#include "nbt_server/dgram/proto.h"
29#include "system/network.h"
30#include "lib/socket/netif.h"
31#include "param/param.h"
32
33
34/*
35  receive an incoming request and dispatch it to the right place
36*/
37static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
38				 struct nbt_name_packet *packet,
39				 struct socket_address *src)
40{
41	struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
42						       struct nbtd_interface);
43	struct nbtd_server *nbtsrv = iface->nbtsrv;
44
45	nbtsrv->stats.total_received++;
46
47	/* see if its from one of our own interfaces - if so, then ignore it */
48	if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
49		DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
50		return;
51	}
52
53	switch (packet->operation & NBT_OPCODE) {
54	case NBT_OPCODE_QUERY:
55		nbtsrv->stats.query_count++;
56		nbtd_request_query(nbtsock, packet, src);
57		break;
58
59	case NBT_OPCODE_REGISTER:
60	case NBT_OPCODE_REFRESH:
61	case NBT_OPCODE_REFRESH2:
62		nbtsrv->stats.register_count++;
63		nbtd_request_defense(nbtsock, packet, src);
64		break;
65
66	case NBT_OPCODE_RELEASE:
67	case NBT_OPCODE_MULTI_HOME_REG:
68		nbtsrv->stats.release_count++;
69		nbtd_winsserver_request(nbtsock, packet, src);
70		break;
71
72	default:
73		nbtd_bad_packet(packet, src, "Unexpected opcode");
74		break;
75	}
76}
77
78static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
79				    struct nbt_name_packet *packet,
80				    struct socket_address *src)
81{
82	struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
83						       struct nbtd_interface);
84	struct nbtd_server *nbtsrv = iface->nbtsrv;
85	struct nbtd_interface *i;
86	struct nbt_name_request *req = NULL;
87
88	nbtsrv->stats.total_received++;
89
90	DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
91		src->addr, iface, iface->ip_address, iface->netmask));
92
93	/* try the broadcast interface */
94	if (nbtsrv->bcast_interface) {
95		i = nbtsrv->bcast_interface;
96		req = idr_find(i->nbtsock->idr, packet->name_trn_id);
97	}
98
99	/* try the wins server client interface */
100	if (!req && nbtsrv->wins_interface && nbtsrv->wins_interface->nbtsock) {
101		i = nbtsrv->wins_interface;
102		req = idr_find(i->nbtsock->idr, packet->name_trn_id);
103	}
104
105	/* try all other interfaces... */
106	if (!req) {
107		for (i = nbtsrv->interfaces; i; i = i->next) {
108			if (i == iface) {
109				continue;
110			}
111			req = idr_find(i->nbtsock->idr, packet->name_trn_id);
112			if (req) break;
113		}
114	}
115
116	if (!req) {
117		DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
118		return;
119	}
120
121	DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
122		src->addr, i, i->ip_address, i->netmask));
123
124	/*
125	 * redirect the incoming response to the socket
126	 * we sent the matching request
127	 */
128	nbt_name_socket_handle_response_packet(req, packet, src);
129}
130
131/*
132  find a registered name on an interface
133*/
134struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
135					struct nbt_name *name,
136					uint16_t nb_flags)
137{
138	struct nbtd_iface_name *iname;
139	for (iname=iface->names;iname;iname=iname->next) {
140		if (iname->name.type == name->type &&
141		    strcmp(name->name, iname->name.name) == 0 &&
142		    ((iname->nb_flags & nb_flags) == nb_flags)) {
143			return iname;
144		}
145	}
146	return NULL;
147}
148
149/*
150  start listening on the given address
151*/
152static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
153				struct loadparm_context *lp_ctx,
154				const char *bind_address,
155				const char *address,
156				const char *bcast,
157				const char *netmask)
158{
159	struct nbtd_interface *iface;
160	NTSTATUS status;
161	struct socket_address *bcast_address;
162	struct socket_address *unicast_address;
163
164	DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
165
166	/*
167	  we actually create two sockets. One listens on the broadcast address
168	  for the interface, and the other listens on our specific address. This
169	  allows us to run with "bind interfaces only" while still receiving
170	  broadcast addresses, and also simplifies matching incoming requests
171	  to interfaces
172	*/
173
174	iface = talloc(nbtsrv, struct nbtd_interface);
175	NT_STATUS_HAVE_NO_MEMORY(iface);
176
177	iface->nbtsrv        = nbtsrv;
178	iface->bcast_address = talloc_steal(iface, bcast);
179	iface->ip_address    = talloc_steal(iface, address);
180	iface->netmask       = talloc_steal(iface, netmask);
181	iface->names         = NULL;
182	iface->wack_queue    = NULL;
183
184	if (strcmp(netmask, "0.0.0.0") != 0) {
185		struct nbt_name_socket *bcast_nbtsock;
186
187		/* listen for broadcasts on port 137 */
188		bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx));
189		if (!bcast_nbtsock) {
190			talloc_free(iface);
191			return NT_STATUS_NO_MEMORY;
192		}
193
194		bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
195							    bcast, lp_nbt_port(lp_ctx));
196		if (!bcast_address) {
197			talloc_free(iface);
198			return NT_STATUS_NO_MEMORY;
199		}
200
201		status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
202		if (!NT_STATUS_IS_OK(status)) {
203			DEBUG(0,("Failed to bind to %s:%d - %s\n",
204				 bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
205			talloc_free(iface);
206			return status;
207		}
208		talloc_free(bcast_address);
209
210		nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
211	}
212
213	/* listen for unicasts on port 137 */
214	iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx,
215					      lp_iconv_convenience(nbtsrv->task->lp_ctx));
216	if (!iface->nbtsock) {
217		talloc_free(iface);
218		return NT_STATUS_NO_MEMORY;
219	}
220
221	unicast_address = socket_address_from_strings(iface->nbtsock,
222						      iface->nbtsock->sock->backend_name,
223						      bind_address, lp_nbt_port(lp_ctx));
224
225	status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
226	if (!NT_STATUS_IS_OK(status)) {
227		DEBUG(0,("Failed to bind to %s:%d - %s\n",
228			 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
229		talloc_free(iface);
230		return status;
231	}
232	talloc_free(unicast_address);
233
234	nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
235	nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface);
236
237	/* also setup the datagram listeners */
238	status = nbtd_dgram_setup(iface, bind_address);
239	if (!NT_STATUS_IS_OK(status)) {
240		DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
241			 bind_address, nt_errstr(status)));
242		talloc_free(iface);
243		return status;
244	}
245
246	if (strcmp(netmask, "0.0.0.0") == 0) {
247		DLIST_ADD(nbtsrv->bcast_interface, iface);
248	} else {
249		DLIST_ADD(nbtsrv->interfaces, iface);
250	}
251
252	return NT_STATUS_OK;
253}
254
255/*
256  setup a socket for talking to our WINS servers
257*/
258static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
259{
260	struct nbtd_interface *iface;
261
262	iface = talloc_zero(nbtsrv, struct nbtd_interface);
263	NT_STATUS_HAVE_NO_MEMORY(iface);
264
265	iface->nbtsrv        = nbtsrv;
266
267	DLIST_ADD(nbtsrv->wins_interface, iface);
268
269	return NT_STATUS_OK;
270}
271
272
273/*
274  setup our listening sockets on the configured network interfaces
275*/
276NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
277				 struct interface *ifaces)
278{
279	int num_interfaces = iface_count(ifaces);
280	int i;
281	TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
282	NTSTATUS status;
283
284	/* if we are allowing incoming packets from any address, then
285	   we also need to bind to the wildcard address */
286	if (!lp_bind_interfaces_only(lp_ctx)) {
287		const char *primary_address;
288
289		/* the primary address is the address we will return
290		   for non-WINS queries not made on a specific
291		   interface */
292		if (num_interfaces > 0) {
293			primary_address = iface_n_ip(ifaces, 0);
294		} else {
295			primary_address = inet_ntoa(interpret_addr2(
296							lp_netbios_name(lp_ctx)));
297		}
298		primary_address = talloc_strdup(tmp_ctx, primary_address);
299		NT_STATUS_HAVE_NO_MEMORY(primary_address);
300
301		status = nbtd_add_socket(nbtsrv,
302					 lp_ctx,
303					 "0.0.0.0",
304					 primary_address,
305					 talloc_strdup(tmp_ctx, "255.255.255.255"),
306					 talloc_strdup(tmp_ctx, "0.0.0.0"));
307		NT_STATUS_NOT_OK_RETURN(status);
308	}
309
310	for (i=0; i<num_interfaces; i++) {
311		const char *bcast = iface_n_bcast(ifaces, i);
312		const char *address, *netmask;
313
314		/* we can't assume every interface is broadcast capable */
315		if (bcast == NULL) continue;
316
317		address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
318		bcast   = talloc_strdup(tmp_ctx, bcast);
319		netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
320
321		status = nbtd_add_socket(nbtsrv, lp_ctx,
322					 address, address, bcast, netmask);
323		NT_STATUS_NOT_OK_RETURN(status);
324	}
325
326	if (lp_wins_server_list(lp_ctx)) {
327		status = nbtd_add_wins_socket(nbtsrv);
328		NT_STATUS_NOT_OK_RETURN(status);
329	}
330
331	talloc_free(tmp_ctx);
332
333	return NT_STATUS_OK;
334}
335
336
337/*
338  form a list of addresses that we should use in name query replies
339  we always place the IP in the given interface first
340*/
341const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
342{
343	struct nbtd_server *nbtsrv = iface->nbtsrv;
344	const char **ret = NULL;
345	struct nbtd_interface *iface2;
346	bool is_loopback = false;
347
348	if (iface->ip_address) {
349		is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
350		ret = str_list_add(ret, iface->ip_address);
351	}
352
353	for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
354		if (iface2 == iface) continue;
355
356		if (!iface2->ip_address) continue;
357
358		if (!is_loopback) {
359			if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
360				continue;
361			}
362		}
363
364		ret = str_list_add(ret, iface2->ip_address);
365	}
366
367	talloc_steal(mem_ctx, ret);
368
369	return ret;
370}
371
372
373/*
374  find the interface to use for sending a outgoing request
375*/
376struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
377					       const char *address, bool allow_bcast_iface)
378{
379	struct nbtd_interface *cur;
380
381	/* try to find a exact match */
382	for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
383		if (iface_same_net(address, cur->ip_address, cur->netmask)) {
384			DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
385				  address, cur->ip_address, cur->netmask, cur));
386			return cur;
387		}
388	}
389
390	/* no exact match, if we have the broadcast interface, use that */
391	if (allow_bcast_iface && nbtd_server->bcast_interface) {
392		cur = nbtd_server->bcast_interface;
393		DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
394			address, cur->ip_address, cur->netmask, cur));
395		return cur;
396	}
397
398	/* fallback to first interface */
399	cur = nbtd_server->interfaces;
400	DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
401		address, cur->ip_address, cur->netmask, cur));
402	return cur;
403}
404
405/*
406 * find the interface to use for sending a outgoing reply
407 */
408struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
409					     const char *address, bool allow_bcast_iface)
410{
411	struct nbtd_server *nbtd_server = iface->nbtsrv;
412
413	/* first try to use the given interfacel when it's not the broadcast one */
414	if (iface != nbtd_server->bcast_interface) {
415		return iface;
416	}
417
418	return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
419}
420