Revert "pidl: Use non-existent function dissect_ndr_int64()"
[Samba.git] / source4 / nbt_server / interfaces.c
blob0888c1b54a65195485f74701e233dfe254f107be
1 /*
2 Unix SMB/CIFS implementation.
4 NBT interface handling
6 Copyright (C) Andrew Tridgell 2005
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/>.
22 #include "includes.h"
23 #include "../lib/util/dlinklist.h"
24 #include "nbt_server/nbt_server.h"
25 #include "samba/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 #include "lib/util/util_net.h"
33 #include "lib/util/idtree.h"
34 #include "../source3/include/fstring.h"
35 #include "../source3/libsmb/nmblib.h"
36 #include "../source3/libsmb/unexpected.h"
39 receive an incoming request and dispatch it to the right place
41 static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
42 struct nbt_name_packet *packet,
43 struct socket_address *src)
45 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
46 struct nbtd_interface);
47 struct nbtd_server *nbtsrv = iface->nbtsrv;
49 nbtsrv->stats.total_received++;
51 /* see if it's from one of our own interfaces - if so, then ignore it */
52 if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
53 DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
54 return;
57 switch (packet->operation & NBT_OPCODE) {
58 case NBT_OPCODE_QUERY:
59 nbtsrv->stats.query_count++;
60 nbtd_request_query(nbtsock, packet, src);
61 break;
63 case NBT_OPCODE_REGISTER:
64 case NBT_OPCODE_REFRESH:
65 case NBT_OPCODE_REFRESH2:
66 nbtsrv->stats.register_count++;
67 nbtd_request_defense(nbtsock, packet, src);
68 break;
70 case NBT_OPCODE_RELEASE:
71 case NBT_OPCODE_MULTI_HOME_REG:
72 nbtsrv->stats.release_count++;
73 nbtd_winsserver_request(nbtsock, packet, src);
74 break;
76 default:
77 nbtd_bad_packet(packet, src, "Unexpected opcode");
78 break;
82 static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
83 struct nbt_name_packet *packet,
84 struct socket_address *src)
86 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
87 struct nbtd_interface);
88 struct nbtd_server *nbtsrv = iface->nbtsrv;
89 struct nbtd_interface *i;
90 struct nbt_name_request *req = NULL;
92 nbtsrv->stats.total_received++;
94 DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
95 src->addr, iface, iface->ip_address, iface->netmask));
97 /* try the broadcast interface */
98 if (nbtsrv->bcast_interface) {
99 i = nbtsrv->bcast_interface;
100 req = idr_find(i->nbtsock->idr, packet->name_trn_id);
103 /* try the wins server client interface */
104 if (!req && nbtsrv->wins_interface && nbtsrv->wins_interface->nbtsock) {
105 i = nbtsrv->wins_interface;
106 req = idr_find(i->nbtsock->idr, packet->name_trn_id);
109 /* try all other interfaces... */
110 if (!req) {
111 for (i = nbtsrv->interfaces; i; i = i->next) {
112 if (i == iface) {
113 continue;
115 req = idr_find(i->nbtsock->idr, packet->name_trn_id);
116 if (req) break;
120 if (!req) {
121 struct packet_struct *pstruct = NULL;
122 DATA_BLOB blob = { .length = 0, };
123 enum ndr_err_code ndr_err;
126 * Here we have NBT_FLAG_REPLY
128 DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
130 ndr_err = ndr_push_struct_blob(&blob, packet, packet,
131 (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
132 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
133 DBG_ERR("ndr_push_nbt_name_packet - %s\n",
134 ndr_errstr(ndr_err));
135 return;
138 pstruct = parse_packet((char *)blob.data,
139 blob.length,
140 NMB_PACKET,
141 interpret_addr2(src->addr),
142 src->port);
143 if (pstruct != NULL) {
144 nb_packet_dispatch(nbtsrv->unexpected_server, pstruct);
145 free_packet(pstruct);
148 return;
151 DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
152 src->addr, i, i->ip_address, i->netmask));
155 * redirect the incoming response to the socket
156 * we sent the matching request
158 nbt_name_socket_handle_response_packet(req, packet, src);
162 find a registered name on an interface
164 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
165 struct nbt_name *name,
166 uint16_t nb_flags)
168 struct nbtd_iface_name *iname;
169 for (iname=iface->names;iname;iname=iname->next) {
170 if (iname->name.type == name->type &&
171 strcmp(name->name, iname->name.name) == 0 &&
172 ((iname->nb_flags & nb_flags) == nb_flags)) {
173 return iname;
176 return NULL;
180 start listening on the given address
182 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
183 struct loadparm_context *lp_ctx,
184 const char *bind_address,
185 const char *address,
186 const char *bcast,
187 const char *netmask)
189 struct nbtd_interface *iface;
190 NTSTATUS status;
191 struct socket_address *bcast_address;
192 struct socket_address *unicast_address;
194 DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
197 we actually create two sockets. One listens on the broadcast address
198 for the interface, and the other listens on our specific address. This
199 allows us to run with "bind interfaces only" while still receiving
200 broadcast addresses, and also simplifies matching incoming requests
201 to interfaces
204 iface = talloc(nbtsrv, struct nbtd_interface);
205 NT_STATUS_HAVE_NO_MEMORY(iface);
207 iface->nbtsrv = nbtsrv;
208 iface->bcast_address = talloc_steal(iface, bcast);
209 iface->ip_address = talloc_steal(iface, address);
210 iface->netmask = talloc_steal(iface, netmask);
211 iface->names = NULL;
212 iface->wack_queue = NULL;
214 if (strcmp(netmask, "0.0.0.0") != 0) {
215 struct nbt_name_socket *bcast_nbtsock;
217 /* listen for broadcasts on port 137 */
218 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
219 if (!bcast_nbtsock) {
220 talloc_free(iface);
221 return NT_STATUS_NO_MEMORY;
224 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
225 bcast, lpcfg_nbt_port(lp_ctx));
226 if (!bcast_address) {
227 talloc_free(iface);
228 return NT_STATUS_NO_MEMORY;
231 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0,("Failed to bind to %s:%d - %s\n",
234 bcast, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
235 talloc_free(iface);
236 return status;
238 talloc_free(bcast_address);
240 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
243 /* listen for unicasts on port 137 */
244 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
245 if (!iface->nbtsock) {
246 talloc_free(iface);
247 return NT_STATUS_NO_MEMORY;
250 unicast_address = socket_address_from_strings(iface->nbtsock,
251 iface->nbtsock->sock->backend_name,
252 bind_address, lpcfg_nbt_port(lp_ctx));
254 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
255 if (!NT_STATUS_IS_OK(status)) {
256 DEBUG(0,("Failed to bind to %s:%d - %s\n",
257 bind_address, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
258 talloc_free(iface);
259 return status;
261 talloc_free(unicast_address);
263 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
264 nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface);
266 /* also setup the datagram listeners */
267 status = nbtd_dgram_setup(iface, bind_address);
268 if (!NT_STATUS_IS_OK(status)) {
269 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
270 bind_address, nt_errstr(status)));
271 talloc_free(iface);
272 return status;
275 if (strcmp(netmask, "0.0.0.0") == 0) {
276 DLIST_ADD(nbtsrv->bcast_interface, iface);
277 } else {
278 DLIST_ADD(nbtsrv->interfaces, iface);
281 return NT_STATUS_OK;
285 setup a socket for talking to our WINS servers
287 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
289 struct nbtd_interface *iface;
291 iface = talloc_zero(nbtsrv, struct nbtd_interface);
292 NT_STATUS_HAVE_NO_MEMORY(iface);
294 iface->nbtsrv = nbtsrv;
296 DLIST_ADD(nbtsrv->wins_interface, iface);
298 return NT_STATUS_OK;
303 setup our listening sockets on the configured network interfaces
305 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
306 struct interface *ifaces)
308 int num_interfaces = iface_list_count(ifaces);
309 int i;
310 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
311 NTSTATUS status;
313 /* if we are allowing incoming packets from any address, then
314 we also need to bind to the wildcard address */
315 if (!lpcfg_bind_interfaces_only(lp_ctx)) {
316 const char *primary_address;
318 primary_address = iface_list_first_v4(ifaces);
320 /* the primary address is the address we will return
321 for non-WINS queries not made on a specific
322 interface */
323 if (primary_address == NULL) {
324 primary_address = inet_ntoa(interpret_addr2(
325 lpcfg_netbios_name(lp_ctx)));
328 primary_address = talloc_strdup(tmp_ctx, primary_address);
329 NT_STATUS_HAVE_NO_MEMORY(primary_address);
331 status = nbtd_add_socket(nbtsrv,
332 lp_ctx,
333 "0.0.0.0",
334 primary_address,
335 talloc_strdup(tmp_ctx, "255.255.255.255"),
336 talloc_strdup(tmp_ctx, "0.0.0.0"));
337 NT_STATUS_NOT_OK_RETURN(status);
340 for (i=0; i<num_interfaces; i++) {
341 const char *bcast;
342 const char *address, *netmask;
344 if (!iface_list_n_is_v4(ifaces, i)) {
345 /* v4 only for NBT protocol */
346 continue;
349 bcast = iface_list_n_bcast(ifaces, i);
350 /* we can't assume every interface is broadcast capable */
351 if (bcast == NULL) continue;
353 address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
354 bcast = talloc_strdup(tmp_ctx, bcast);
355 netmask = talloc_strdup(tmp_ctx, iface_list_n_netmask(ifaces, i));
357 status = nbtd_add_socket(nbtsrv, lp_ctx,
358 address, address, bcast, netmask);
359 NT_STATUS_NOT_OK_RETURN(status);
362 if (lpcfg_wins_server_list(lp_ctx)) {
363 status = nbtd_add_wins_socket(nbtsrv);
364 NT_STATUS_NOT_OK_RETURN(status);
367 talloc_free(tmp_ctx);
369 return NT_STATUS_OK;
374 form a list of addresses that we should use in name query replies
375 we always place the IP in the given interface first
377 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
379 struct nbtd_server *nbtsrv = iface->nbtsrv;
380 const char **ret = NULL;
381 struct nbtd_interface *iface2;
382 bool is_loopback = false;
384 if (iface->ip_address) {
385 is_loopback = iface_list_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
386 ret = str_list_add(ret, iface->ip_address);
389 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
390 if (iface2 == iface) continue;
392 if (!iface2->ip_address) continue;
394 if (!is_loopback) {
395 if (iface_list_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
396 continue;
400 ret = str_list_add(ret, iface2->ip_address);
403 talloc_steal(mem_ctx, ret);
405 return ret;
410 find the interface to use for sending a outgoing request
412 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
413 const char *address, bool allow_bcast_iface)
415 struct nbtd_interface *cur;
417 /* try to find a exact match */
418 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
419 if (iface_list_same_net(address, cur->ip_address, cur->netmask)) {
420 DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
421 address, cur->ip_address, cur->netmask, cur));
422 return cur;
426 /* no exact match, if we have the broadcast interface, use that */
427 if (allow_bcast_iface && nbtd_server->bcast_interface) {
428 cur = nbtd_server->bcast_interface;
429 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
430 address, cur->ip_address, cur->netmask, cur));
431 return cur;
434 /* fallback to first interface */
435 cur = nbtd_server->interfaces;
436 DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
437 address, cur->ip_address, cur->netmask, cur));
438 return cur;
442 * find the interface to use for sending a outgoing reply
444 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
445 const char *address, bool allow_bcast_iface)
447 struct nbtd_server *nbtd_server = iface->nbtsrv;
449 /* first try to use the given interfacel when it's not the broadcast one */
450 if (iface != nbtd_server->bcast_interface) {
451 return iface;
454 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);