s4:provision - Added LDBBackend and ExistingBackend.
[ira/wip.git] / source4 / nbt_server / interfaces.c
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 */
37 static 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
78 static 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 */
134 struct 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 */
152 static 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 */
258 static 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 */
276 NTSTATUS 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 */
341 const 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 */
376 struct 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  */
408 struct 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 }