r25546: Convert to standard bool type.
[Samba.git] / source / nbt_server / interfaces.c
blobf2a875142a8ae5fc2f8214c8ac4a839d429dbb9d
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 "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"
35 receive an incoming request and dispatch it to the right place
37 static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
38 struct nbt_name_packet *packet,
39 struct socket_address *src)
41 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
42 struct nbtd_interface);
43 struct nbtd_server *nbtsrv = iface->nbtsrv;
45 nbtsrv->stats.total_received++;
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;
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;
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;
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;
72 default:
73 nbtd_bad_packet(packet, src, "Unexpected opcode");
74 break;
80 find a registered name on an interface
82 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
83 struct nbt_name *name,
84 uint16_t nb_flags)
86 struct nbtd_iface_name *iname;
87 for (iname=iface->names;iname;iname=iname->next) {
88 if (iname->name.type == name->type &&
89 strcmp(name->name, iname->name.name) == 0 &&
90 ((iname->nb_flags & nb_flags) == nb_flags)) {
91 return iname;
94 return NULL;
98 start listening on the given address
100 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
101 const char *bind_address,
102 const char *address,
103 const char *bcast,
104 const char *netmask)
106 struct nbtd_interface *iface;
107 NTSTATUS status;
108 struct socket_address *bcast_address;
109 struct socket_address *unicast_address;
112 we actually create two sockets. One listens on the broadcast address
113 for the interface, and the other listens on our specific address. This
114 allows us to run with "bind interfaces only" while still receiving
115 broadcast addresses, and also simplifies matching incoming requests
116 to interfaces
119 iface = talloc(nbtsrv, struct nbtd_interface);
120 NT_STATUS_HAVE_NO_MEMORY(iface);
122 iface->nbtsrv = nbtsrv;
123 iface->bcast_address = talloc_steal(iface, bcast);
124 iface->ip_address = talloc_steal(iface, address);
125 iface->netmask = talloc_steal(iface, netmask);
126 iface->names = NULL;
128 if (strcmp(netmask, "0.0.0.0") != 0) {
129 struct nbt_name_socket *bcast_nbtsock;
131 /* listen for broadcasts on port 137 */
132 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
133 if (!bcast_nbtsock) {
134 talloc_free(iface);
135 return NT_STATUS_NO_MEMORY;
138 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
139 bcast, lp_nbt_port(global_loadparm));
140 if (!bcast_address) {
141 talloc_free(iface);
142 return NT_STATUS_NO_MEMORY;
145 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
146 if (!NT_STATUS_IS_OK(status)) {
147 DEBUG(0,("Failed to bind to %s:%d - %s\n",
148 bcast, lp_nbt_port(global_loadparm), nt_errstr(status)));
149 talloc_free(iface);
150 return status;
152 talloc_free(bcast_address);
154 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
157 /* listen for unicasts on port 137 */
158 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
159 if (!iface->nbtsock) {
160 talloc_free(iface);
161 return NT_STATUS_NO_MEMORY;
164 unicast_address = socket_address_from_strings(iface->nbtsock,
165 iface->nbtsock->sock->backend_name,
166 bind_address, lp_nbt_port(global_loadparm));
168 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
169 if (!NT_STATUS_IS_OK(status)) {
170 DEBUG(0,("Failed to bind to %s:%d - %s\n",
171 bind_address, lp_nbt_port(global_loadparm), nt_errstr(status)));
172 talloc_free(iface);
173 return status;
175 talloc_free(unicast_address);
177 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
179 /* also setup the datagram listeners */
180 status = nbtd_dgram_setup(iface, bind_address);
181 if (!NT_STATUS_IS_OK(status)) {
182 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
183 bind_address, nt_errstr(status)));
184 talloc_free(iface);
185 return status;
188 if (strcmp(netmask, "0.0.0.0") == 0) {
189 DLIST_ADD(nbtsrv->bcast_interface, iface);
190 } else {
191 DLIST_ADD(nbtsrv->interfaces, iface);
194 return NT_STATUS_OK;
198 setup a socket for talking to our WINS servers
200 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
202 struct nbtd_interface *iface;
204 iface = talloc_zero(nbtsrv, struct nbtd_interface);
205 NT_STATUS_HAVE_NO_MEMORY(iface);
207 iface->nbtsrv = nbtsrv;
209 DLIST_ADD(nbtsrv->wins_interface, iface);
211 return NT_STATUS_OK;
216 setup our listening sockets on the configured network interfaces
218 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
220 int num_interfaces = iface_count();
221 int i;
222 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
223 NTSTATUS status;
225 /* if we are allowing incoming packets from any address, then
226 we also need to bind to the wildcard address */
227 if (!lp_bind_interfaces_only(global_loadparm)) {
228 const char *primary_address;
230 /* the primary address is the address we will return
231 for non-WINS queries not made on a specific
232 interface */
233 if (num_interfaces > 0) {
234 primary_address = iface_n_ip(0);
235 } else {
236 primary_address = sys_inet_ntoa(interpret_addr2(
237 lp_netbios_name(global_loadparm)));
239 primary_address = talloc_strdup(tmp_ctx, primary_address);
240 NT_STATUS_HAVE_NO_MEMORY(primary_address);
242 status = nbtd_add_socket(nbtsrv,
243 "0.0.0.0",
244 primary_address,
245 talloc_strdup(tmp_ctx, "255.255.255.255"),
246 talloc_strdup(tmp_ctx, "0.0.0.0"));
247 NT_STATUS_NOT_OK_RETURN(status);
250 for (i=0; i<num_interfaces; i++) {
251 const char *bcast = iface_n_bcast(i);
252 const char *address, *netmask;
254 /* we can't assume every interface is broadcast capable */
255 if (bcast == NULL) continue;
257 address = talloc_strdup(tmp_ctx, iface_n_ip(i));
258 bcast = talloc_strdup(tmp_ctx, bcast);
259 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
261 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
262 NT_STATUS_NOT_OK_RETURN(status);
265 if (lp_wins_server_list(global_loadparm)) {
266 status = nbtd_add_wins_socket(nbtsrv);
267 NT_STATUS_NOT_OK_RETURN(status);
270 talloc_free(tmp_ctx);
272 return NT_STATUS_OK;
277 form a list of addresses that we should use in name query replies
278 we always place the IP in the given interface first
280 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
282 struct nbtd_server *nbtsrv = iface->nbtsrv;
283 const char **ret = NULL;
284 struct nbtd_interface *iface2;
285 bool is_loopback = false;
287 if (iface->ip_address) {
288 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
289 ret = str_list_add(ret, iface->ip_address);
292 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
293 if (iface2 == iface) continue;
295 if (!iface2->ip_address) continue;
297 if (!is_loopback) {
298 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
299 continue;
303 ret = str_list_add(ret, iface2->ip_address);
306 talloc_steal(mem_ctx, ret);
308 return ret;
313 find the interface to use for sending a outgoing request
315 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
316 const char *address, bool allow_bcast_iface)
318 struct nbtd_interface *cur;
320 /* try to find a exact match */
321 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
322 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
323 return cur;
327 /* no exact match, if we have the broadcast interface, use that */
328 if (allow_bcast_iface && nbtd_server->bcast_interface) {
329 return nbtd_server->bcast_interface;
332 /* fallback to first interface */
333 return nbtd_server->interfaces;
337 * find the interface to use for sending a outgoing reply
339 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
340 const char *address, bool allow_bcast_iface)
342 struct nbtd_server *nbtd_server = iface->nbtsrv;
344 /* first try to use the given interfacel when it's not the broadcast one */
345 if (iface != nbtd_server->bcast_interface) {
346 return iface;
349 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);