tevent: Added a description for tevent queue.
[Samba/ekacnet.git] / source4 / nbt_server / interfaces.c
blob99c5886fd9d3b97eff5ee95b9b9807fee7de418b
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"
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 its 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));
51 return;
54 switch (packet->operation & NBT_OPCODE) {
55 case NBT_OPCODE_QUERY:
56 nbtsrv->stats.query_count++;
57 nbtd_request_query(nbtsock, packet, src);
58 break;
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);
65 break;
67 case NBT_OPCODE_RELEASE:
68 case NBT_OPCODE_MULTI_HOME_REG:
69 nbtsrv->stats.release_count++;
70 nbtd_winsserver_request(nbtsock, packet, src);
71 break;
73 default:
74 nbtd_bad_packet(packet, src, "Unexpected opcode");
75 break;
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... */
107 if (!req) {
108 for (i = nbtsrv->interfaces; i; i = i->next) {
109 if (i == iface) {
110 continue;
112 req = idr_find(i->nbtsock->idr, packet->name_trn_id);
113 if (req) break;
117 if (!req) {
118 DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
119 return;
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,
137 uint16_t nb_flags)
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)) {
144 return iname;
147 return NULL;
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,
156 const char *address,
157 const char *bcast,
158 const char *netmask)
160 struct nbtd_interface *iface;
161 NTSTATUS status;
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
172 to interfaces
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);
182 iface->names = NULL;
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, lp_iconv_convenience(nbtsrv->task->lp_ctx));
190 if (!bcast_nbtsock) {
191 talloc_free(iface);
192 return NT_STATUS_NO_MEMORY;
195 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
196 bcast, lp_nbt_port(lp_ctx));
197 if (!bcast_address) {
198 talloc_free(iface);
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, lp_nbt_port(lp_ctx), nt_errstr(status)));
206 talloc_free(iface);
207 return 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 lp_iconv_convenience(nbtsrv->task->lp_ctx));
217 if (!iface->nbtsock) {
218 talloc_free(iface);
219 return NT_STATUS_NO_MEMORY;
222 unicast_address = socket_address_from_strings(iface->nbtsock,
223 iface->nbtsock->sock->backend_name,
224 bind_address, lp_nbt_port(lp_ctx));
226 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
227 if (!NT_STATUS_IS_OK(status)) {
228 DEBUG(0,("Failed to bind to %s:%d - %s\n",
229 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
230 talloc_free(iface);
231 return status;
233 talloc_free(unicast_address);
235 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
236 nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface);
238 /* also setup the datagram listeners */
239 status = nbtd_dgram_setup(iface, bind_address);
240 if (!NT_STATUS_IS_OK(status)) {
241 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
242 bind_address, nt_errstr(status)));
243 talloc_free(iface);
244 return status;
247 if (strcmp(netmask, "0.0.0.0") == 0) {
248 DLIST_ADD(nbtsrv->bcast_interface, iface);
249 } else {
250 DLIST_ADD(nbtsrv->interfaces, iface);
253 return NT_STATUS_OK;
257 setup a socket for talking to our WINS servers
259 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
261 struct nbtd_interface *iface;
263 iface = talloc_zero(nbtsrv, struct nbtd_interface);
264 NT_STATUS_HAVE_NO_MEMORY(iface);
266 iface->nbtsrv = nbtsrv;
268 DLIST_ADD(nbtsrv->wins_interface, iface);
270 return NT_STATUS_OK;
275 setup our listening sockets on the configured network interfaces
277 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
278 struct interface *ifaces)
280 int num_interfaces = iface_count(ifaces);
281 int i;
282 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
283 NTSTATUS status;
285 /* if we are allowing incoming packets from any address, then
286 we also need to bind to the wildcard address */
287 if (!lp_bind_interfaces_only(lp_ctx)) {
288 const char *primary_address;
290 /* the primary address is the address we will return
291 for non-WINS queries not made on a specific
292 interface */
293 if (num_interfaces > 0) {
294 primary_address = iface_n_ip(ifaces, 0);
295 } else {
296 primary_address = inet_ntoa(interpret_addr2(
297 lp_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,
303 lp_ctx,
304 "0.0.0.0",
305 primary_address,
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++) {
312 const char *bcast = iface_n_bcast(ifaces, i);
313 const char *address, *netmask;
315 /* we can't assume every interface is broadcast capable */
316 if (bcast == NULL) continue;
318 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
319 bcast = talloc_strdup(tmp_ctx, bcast);
320 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
322 status = nbtd_add_socket(nbtsrv, lp_ctx,
323 address, address, bcast, netmask);
324 NT_STATUS_NOT_OK_RETURN(status);
327 if (lp_wins_server_list(lp_ctx)) {
328 status = nbtd_add_wins_socket(nbtsrv);
329 NT_STATUS_NOT_OK_RETURN(status);
332 talloc_free(tmp_ctx);
334 return NT_STATUS_OK;
339 form a list of addresses that we should use in name query replies
340 we always place the IP in the given interface first
342 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
344 struct nbtd_server *nbtsrv = iface->nbtsrv;
345 const char **ret = NULL;
346 struct nbtd_interface *iface2;
347 bool is_loopback = false;
349 if (iface->ip_address) {
350 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
351 ret = str_list_add(ret, iface->ip_address);
354 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
355 if (iface2 == iface) continue;
357 if (!iface2->ip_address) continue;
359 if (!is_loopback) {
360 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
361 continue;
365 ret = str_list_add(ret, iface2->ip_address);
368 talloc_steal(mem_ctx, ret);
370 return ret;
375 find the interface to use for sending a outgoing request
377 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
378 const char *address, bool allow_bcast_iface)
380 struct nbtd_interface *cur;
382 /* try to find a exact match */
383 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
384 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
385 DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
386 address, cur->ip_address, cur->netmask, cur));
387 return cur;
391 /* no exact match, if we have the broadcast interface, use that */
392 if (allow_bcast_iface && nbtd_server->bcast_interface) {
393 cur = nbtd_server->bcast_interface;
394 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
395 address, cur->ip_address, cur->netmask, cur));
396 return cur;
399 /* fallback to first interface */
400 cur = nbtd_server->interfaces;
401 DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
402 address, cur->ip_address, cur->netmask, cur));
403 return cur;
407 * find the interface to use for sending a outgoing reply
409 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
410 const char *address, bool allow_bcast_iface)
412 struct nbtd_server *nbtd_server = iface->nbtsrv;
414 /* first try to use the given interfacel when it's not the broadcast one */
415 if (iface != nbtd_server->bcast_interface) {
416 return iface;
419 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);