Finish removal of iconv_convenience in public API's.
[sfrench/samba-autobuild/.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 #include "lib/util/util_net.h"
33
34
35 /*
36   receive an incoming request and dispatch it to the right place
37 */
38 static void nbtd_request_handler(struct nbt_name_socket *nbtsock, 
39                                  struct nbt_name_packet *packet, 
40                                  struct socket_address *src)
41 {
42         struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
43                                                        struct nbtd_interface);
44         struct nbtd_server *nbtsrv = iface->nbtsrv;
45
46         nbtsrv->stats.total_received++;
47
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;
52         }
53
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;
59
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;
66
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;
72
73         default:
74                 nbtd_bad_packet(packet, src, "Unexpected opcode");
75                 break;
76         }
77 }
78
79 static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
80                                     struct nbt_name_packet *packet,
81                                     struct socket_address *src)
82 {
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;
88
89         nbtsrv->stats.total_received++;
90
91         DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
92                 src->addr, iface, iface->ip_address, iface->netmask));
93
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);
98         }
99
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);
104         }
105
106         /* try all other interfaces... */
107         if (!req) {
108                 for (i = nbtsrv->interfaces; i; i = i->next) {
109                         if (i == iface) {
110                                 continue;
111                         }
112                         req = idr_find(i->nbtsock->idr, packet->name_trn_id);
113                         if (req) break;
114                 }
115         }
116
117         if (!req) {
118                 DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
119                 return;
120         }
121
122         DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
123                 src->addr, i, i->ip_address, i->netmask));
124
125         /*
126          * redirect the incoming response to the socket
127          * we sent the matching request
128          */
129         nbt_name_socket_handle_response_packet(req, packet, src);
130 }
131
132 /*
133   find a registered name on an interface
134 */
135 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface, 
136                                         struct nbt_name *name, 
137                                         uint16_t nb_flags)
138 {
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;
145                 }
146         }
147         return NULL;
148 }
149
150 /*
151   start listening on the given address
152 */
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)
159 {
160         struct nbtd_interface *iface;
161         NTSTATUS status;
162         struct socket_address *bcast_address;
163         struct socket_address *unicast_address;
164
165         DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
166
167         /*
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
173         */
174
175         iface = talloc(nbtsrv, struct nbtd_interface);
176         NT_STATUS_HAVE_NO_MEMORY(iface);
177
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;
184
185         if (strcmp(netmask, "0.0.0.0") != 0) {
186                 struct nbt_name_socket *bcast_nbtsock;
187
188                 /* listen for broadcasts on port 137 */
189                 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
190                 if (!bcast_nbtsock) {
191                         talloc_free(iface);
192                         return NT_STATUS_NO_MEMORY;
193                 }
194
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;
200                 }
201
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;
208                 }
209                 talloc_free(bcast_address);
210
211                 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
212         }
213
214         /* listen for unicasts on port 137 */
215         iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_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 }