2 Unix SMB/CIFS implementation.
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/>.
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 #include "lib/util/util_net.h"
36 receive an incoming request and dispatch it to the right place
38 static void nbtd_request_handler(struct nbt_name_socket
*nbtsock
,
39 struct nbt_name_packet
*packet
,
40 struct socket_address
*src
)
42 struct nbtd_interface
*iface
= talloc_get_type(nbtsock
->incoming
.private_data
,
43 struct nbtd_interface
);
44 struct nbtd_server
*nbtsrv
= iface
->nbtsrv
;
46 nbtsrv
->stats
.total_received
++;
48 /* see if it's from one of our own interfaces - if so, then ignore it */
49 if (nbtd_self_packet_and_bcast(nbtsock
, packet
, src
)) {
50 DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src
->addr
, src
->port
));
54 switch (packet
->operation
& NBT_OPCODE
) {
55 case NBT_OPCODE_QUERY
:
56 nbtsrv
->stats
.query_count
++;
57 nbtd_request_query(nbtsock
, packet
, src
);
60 case NBT_OPCODE_REGISTER
:
61 case NBT_OPCODE_REFRESH
:
62 case NBT_OPCODE_REFRESH2
:
63 nbtsrv
->stats
.register_count
++;
64 nbtd_request_defense(nbtsock
, packet
, src
);
67 case NBT_OPCODE_RELEASE
:
68 case NBT_OPCODE_MULTI_HOME_REG
:
69 nbtsrv
->stats
.release_count
++;
70 nbtd_winsserver_request(nbtsock
, packet
, src
);
74 nbtd_bad_packet(packet
, src
, "Unexpected opcode");
79 static void nbtd_unexpected_handler(struct nbt_name_socket
*nbtsock
,
80 struct nbt_name_packet
*packet
,
81 struct socket_address
*src
)
83 struct nbtd_interface
*iface
= talloc_get_type(nbtsock
->incoming
.private_data
,
84 struct nbtd_interface
);
85 struct nbtd_server
*nbtsrv
= iface
->nbtsrv
;
86 struct nbtd_interface
*i
;
87 struct nbt_name_request
*req
= NULL
;
89 nbtsrv
->stats
.total_received
++;
91 DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
92 src
->addr
, iface
, iface
->ip_address
, iface
->netmask
));
94 /* try the broadcast interface */
95 if (nbtsrv
->bcast_interface
) {
96 i
= nbtsrv
->bcast_interface
;
97 req
= idr_find(i
->nbtsock
->idr
, packet
->name_trn_id
);
100 /* try the wins server client interface */
101 if (!req
&& nbtsrv
->wins_interface
&& nbtsrv
->wins_interface
->nbtsock
) {
102 i
= nbtsrv
->wins_interface
;
103 req
= idr_find(i
->nbtsock
->idr
, packet
->name_trn_id
);
106 /* try all other interfaces... */
108 for (i
= nbtsrv
->interfaces
; i
; i
= i
->next
) {
112 req
= idr_find(i
->nbtsock
->idr
, packet
->name_trn_id
);
118 DEBUG(10,("unexpected from src[%s] unable to redirected\n", src
->addr
));
122 DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
123 src
->addr
, i
, i
->ip_address
, i
->netmask
));
126 * redirect the incoming response to the socket
127 * we sent the matching request
129 nbt_name_socket_handle_response_packet(req
, packet
, src
);
133 find a registered name on an interface
135 struct nbtd_iface_name
*nbtd_find_iname(struct nbtd_interface
*iface
,
136 struct nbt_name
*name
,
139 struct nbtd_iface_name
*iname
;
140 for (iname
=iface
->names
;iname
;iname
=iname
->next
) {
141 if (iname
->name
.type
== name
->type
&&
142 strcmp(name
->name
, iname
->name
.name
) == 0 &&
143 ((iname
->nb_flags
& nb_flags
) == nb_flags
)) {
151 start listening on the given address
153 static NTSTATUS
nbtd_add_socket(struct nbtd_server
*nbtsrv
,
154 struct loadparm_context
*lp_ctx
,
155 const char *bind_address
,
160 struct nbtd_interface
*iface
;
162 struct socket_address
*bcast_address
;
163 struct socket_address
*unicast_address
;
165 DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address
, address
, bcast
, netmask
));
168 we actually create two sockets. One listens on the broadcast address
169 for the interface, and the other listens on our specific address. This
170 allows us to run with "bind interfaces only" while still receiving
171 broadcast addresses, and also simplifies matching incoming requests
175 iface
= talloc(nbtsrv
, struct nbtd_interface
);
176 NT_STATUS_HAVE_NO_MEMORY(iface
);
178 iface
->nbtsrv
= nbtsrv
;
179 iface
->bcast_address
= talloc_steal(iface
, bcast
);
180 iface
->ip_address
= talloc_steal(iface
, address
);
181 iface
->netmask
= talloc_steal(iface
, netmask
);
183 iface
->wack_queue
= NULL
;
185 if (strcmp(netmask
, "0.0.0.0") != 0) {
186 struct nbt_name_socket
*bcast_nbtsock
;
188 /* listen for broadcasts on port 137 */
189 bcast_nbtsock
= nbt_name_socket_init(iface
, nbtsrv
->task
->event_ctx
);
190 if (!bcast_nbtsock
) {
192 return NT_STATUS_NO_MEMORY
;
195 bcast_address
= socket_address_from_strings(bcast_nbtsock
, bcast_nbtsock
->sock
->backend_name
,
196 bcast
, lpcfg_nbt_port(lp_ctx
));
197 if (!bcast_address
) {
199 return NT_STATUS_NO_MEMORY
;
202 status
= socket_listen(bcast_nbtsock
->sock
, bcast_address
, 0, 0);
203 if (!NT_STATUS_IS_OK(status
)) {
204 DEBUG(0,("Failed to bind to %s:%d - %s\n",
205 bcast
, lpcfg_nbt_port(lp_ctx
), nt_errstr(status
)));
209 talloc_free(bcast_address
);
211 nbt_set_incoming_handler(bcast_nbtsock
, nbtd_request_handler
, iface
);
214 /* listen for unicasts on port 137 */
215 iface
->nbtsock
= nbt_name_socket_init(iface
, nbtsrv
->task
->event_ctx
);
216 if (!iface
->nbtsock
) {
218 return NT_STATUS_NO_MEMORY
;
221 unicast_address
= socket_address_from_strings(iface
->nbtsock
,
222 iface
->nbtsock
->sock
->backend_name
,
223 bind_address
, lpcfg_nbt_port(lp_ctx
));
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
, lpcfg_nbt_port(lp_ctx
), nt_errstr(status
)));
232 talloc_free(unicast_address
);
234 nbt_set_incoming_handler(iface
->nbtsock
, nbtd_request_handler
, iface
);
235 nbt_set_unexpected_handler(iface
->nbtsock
, nbtd_unexpected_handler
, iface
);
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
)));
246 if (strcmp(netmask
, "0.0.0.0") == 0) {
247 DLIST_ADD(nbtsrv
->bcast_interface
, iface
);
249 DLIST_ADD(nbtsrv
->interfaces
, iface
);
256 setup a socket for talking to our WINS servers
258 static NTSTATUS
nbtd_add_wins_socket(struct nbtd_server
*nbtsrv
)
260 struct nbtd_interface
*iface
;
262 iface
= talloc_zero(nbtsrv
, struct nbtd_interface
);
263 NT_STATUS_HAVE_NO_MEMORY(iface
);
265 iface
->nbtsrv
= nbtsrv
;
267 DLIST_ADD(nbtsrv
->wins_interface
, iface
);
274 setup our listening sockets on the configured network interfaces
276 NTSTATUS
nbtd_startup_interfaces(struct nbtd_server
*nbtsrv
, struct loadparm_context
*lp_ctx
,
277 struct interface
*ifaces
)
279 int num_interfaces
= iface_list_count(ifaces
);
281 TALLOC_CTX
*tmp_ctx
= talloc_new(nbtsrv
);
284 /* if we are allowing incoming packets from any address, then
285 we also need to bind to the wildcard address */
286 if (!lpcfg_bind_interfaces_only(lp_ctx
)) {
287 const char *primary_address
;
289 primary_address
= iface_list_first_v4(ifaces
);
291 /* the primary address is the address we will return
292 for non-WINS queries not made on a specific
294 if (primary_address
== NULL
) {
295 primary_address
= inet_ntoa(interpret_addr2(
296 lpcfg_netbios_name(lp_ctx
)));
299 primary_address
= talloc_strdup(tmp_ctx
, primary_address
);
300 NT_STATUS_HAVE_NO_MEMORY(primary_address
);
302 status
= nbtd_add_socket(nbtsrv
,
306 talloc_strdup(tmp_ctx
, "255.255.255.255"),
307 talloc_strdup(tmp_ctx
, "0.0.0.0"));
308 NT_STATUS_NOT_OK_RETURN(status
);
311 for (i
=0; i
<num_interfaces
; i
++) {
313 const char *address
, *netmask
;
315 if (!iface_list_n_is_v4(ifaces
, i
)) {
316 /* v4 only for NBT protocol */
320 bcast
= iface_list_n_bcast(ifaces
, i
);
321 /* we can't assume every interface is broadcast capable */
322 if (bcast
== NULL
) continue;
324 address
= talloc_strdup(tmp_ctx
, iface_list_n_ip(ifaces
, i
));
325 bcast
= talloc_strdup(tmp_ctx
, bcast
);
326 netmask
= talloc_strdup(tmp_ctx
, iface_list_n_netmask(ifaces
, i
));
328 status
= nbtd_add_socket(nbtsrv
, lp_ctx
,
329 address
, address
, bcast
, netmask
);
330 NT_STATUS_NOT_OK_RETURN(status
);
333 if (lpcfg_wins_server_list(lp_ctx
)) {
334 status
= nbtd_add_wins_socket(nbtsrv
);
335 NT_STATUS_NOT_OK_RETURN(status
);
338 talloc_free(tmp_ctx
);
345 form a list of addresses that we should use in name query replies
346 we always place the IP in the given interface first
348 const char **nbtd_address_list(struct nbtd_interface
*iface
, TALLOC_CTX
*mem_ctx
)
350 struct nbtd_server
*nbtsrv
= iface
->nbtsrv
;
351 const char **ret
= NULL
;
352 struct nbtd_interface
*iface2
;
353 bool is_loopback
= false;
355 if (iface
->ip_address
) {
356 is_loopback
= iface_list_same_net(iface
->ip_address
, "127.0.0.1", "255.0.0.0");
357 ret
= str_list_add(ret
, iface
->ip_address
);
360 for (iface2
=nbtsrv
->interfaces
;iface2
;iface2
=iface2
->next
) {
361 if (iface2
== iface
) continue;
363 if (!iface2
->ip_address
) continue;
366 if (iface_list_same_net(iface2
->ip_address
, "127.0.0.1", "255.0.0.0")) {
371 ret
= str_list_add(ret
, iface2
->ip_address
);
374 talloc_steal(mem_ctx
, ret
);
381 find the interface to use for sending a outgoing request
383 struct nbtd_interface
*nbtd_find_request_iface(struct nbtd_server
*nbtd_server
,
384 const char *address
, bool allow_bcast_iface
)
386 struct nbtd_interface
*cur
;
388 /* try to find a exact match */
389 for (cur
=nbtd_server
->interfaces
;cur
;cur
=cur
->next
) {
390 if (iface_list_same_net(address
, cur
->ip_address
, cur
->netmask
)) {
391 DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
392 address
, cur
->ip_address
, cur
->netmask
, cur
));
397 /* no exact match, if we have the broadcast interface, use that */
398 if (allow_bcast_iface
&& nbtd_server
->bcast_interface
) {
399 cur
= nbtd_server
->bcast_interface
;
400 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
401 address
, cur
->ip_address
, cur
->netmask
, cur
));
405 /* fallback to first interface */
406 cur
= nbtd_server
->interfaces
;
407 DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
408 address
, cur
->ip_address
, cur
->netmask
, cur
));
413 * find the interface to use for sending a outgoing reply
415 struct nbtd_interface
*nbtd_find_reply_iface(struct nbtd_interface
*iface
,
416 const char *address
, bool allow_bcast_iface
)
418 struct nbtd_server
*nbtd_server
= iface
->nbtsrv
;
420 /* first try to use the given interfacel when it's not the broadcast one */
421 if (iface
!= nbtd_server
->bcast_interface
) {
425 return nbtd_find_request_iface(nbtd_server
, address
, allow_bcast_iface
);