f5ac49255a9a0221b3f9962f0fc7a2fff92979c0
[metze/samba/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
79 /*
80   find a registered name on an interface
81 */
82 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface, 
83                                         struct nbt_name *name, 
84                                         uint16_t nb_flags)
85 {
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;
92                 }
93         }
94         return NULL;
95 }
96
97 /*
98   start listening on the given address
99 */
100 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv, 
101                                 struct loadparm_context *lp_ctx,
102                                 const char *bind_address, 
103                                 const char *address, 
104                                 const char *bcast, 
105                                 const char *netmask)
106 {
107         struct nbtd_interface *iface;
108         NTSTATUS status;
109         struct socket_address *bcast_address;
110         struct socket_address *unicast_address;
111
112         DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
113
114         /*
115           we actually create two sockets. One listens on the broadcast address
116           for the interface, and the other listens on our specific address. This
117           allows us to run with "bind interfaces only" while still receiving 
118           broadcast addresses, and also simplifies matching incoming requests 
119           to interfaces
120         */
121
122         iface = talloc(nbtsrv, struct nbtd_interface);
123         NT_STATUS_HAVE_NO_MEMORY(iface);
124
125         iface->nbtsrv        = nbtsrv;
126         iface->bcast_address = talloc_steal(iface, bcast);
127         iface->ip_address    = talloc_steal(iface, address);
128         iface->netmask       = talloc_steal(iface, netmask);
129         iface->names         = NULL;
130         iface->wack_queue    = NULL;
131
132         if (strcmp(netmask, "0.0.0.0") != 0) {
133                 struct nbt_name_socket *bcast_nbtsock;
134
135                 /* listen for broadcasts on port 137 */
136                 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx));
137                 if (!bcast_nbtsock) {
138                         talloc_free(iface);
139                         return NT_STATUS_NO_MEMORY;
140                 }
141
142                 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name, 
143                                                             bcast, lp_nbt_port(lp_ctx));
144                 if (!bcast_address) {
145                         talloc_free(iface);
146                         return NT_STATUS_NO_MEMORY;
147                 }
148
149                 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
150                 if (!NT_STATUS_IS_OK(status)) {
151                         DEBUG(0,("Failed to bind to %s:%d - %s\n", 
152                                  bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
153                         talloc_free(iface);
154                         return status;
155                 }
156                 talloc_free(bcast_address);
157
158                 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
159         }
160
161         /* listen for unicasts on port 137 */
162         iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, 
163                                               lp_iconv_convenience(nbtsrv->task->lp_ctx));
164         if (!iface->nbtsock) {
165                 talloc_free(iface);
166                 return NT_STATUS_NO_MEMORY;
167         }
168
169         unicast_address = socket_address_from_strings(iface->nbtsock, 
170                                                       iface->nbtsock->sock->backend_name, 
171                                                       bind_address, lp_nbt_port(lp_ctx));
172
173         status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
174         if (!NT_STATUS_IS_OK(status)) {
175                 DEBUG(0,("Failed to bind to %s:%d - %s\n", 
176                          bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
177                 talloc_free(iface);
178                 return status;
179         }
180         talloc_free(unicast_address);
181
182         nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
183
184         /* also setup the datagram listeners */
185         status = nbtd_dgram_setup(iface, bind_address);
186         if (!NT_STATUS_IS_OK(status)) {
187                 DEBUG(0,("Failed to setup dgram listen on %s - %s\n", 
188                          bind_address, nt_errstr(status)));
189                 talloc_free(iface);
190                 return status;
191         }
192         
193         if (strcmp(netmask, "0.0.0.0") == 0) {
194                 DLIST_ADD(nbtsrv->bcast_interface, iface);
195         } else {
196                 DLIST_ADD(nbtsrv->interfaces, iface);
197         }
198
199         return NT_STATUS_OK;
200 }
201
202 /*
203   setup a socket for talking to our WINS servers
204 */
205 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
206 {
207         struct nbtd_interface *iface;
208
209         iface = talloc_zero(nbtsrv, struct nbtd_interface);
210         NT_STATUS_HAVE_NO_MEMORY(iface);
211
212         iface->nbtsrv        = nbtsrv;
213
214         DLIST_ADD(nbtsrv->wins_interface, iface);
215
216         return NT_STATUS_OK;
217 }
218
219
220 /*
221   setup our listening sockets on the configured network interfaces
222 */
223 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
224                                  struct interface *ifaces)
225 {
226         int num_interfaces = iface_count(ifaces);
227         int i;
228         TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
229         NTSTATUS status;
230
231         /* if we are allowing incoming packets from any address, then
232            we also need to bind to the wildcard address */
233         if (!lp_bind_interfaces_only(lp_ctx)) {
234                 const char *primary_address;
235
236                 /* the primary address is the address we will return
237                    for non-WINS queries not made on a specific
238                    interface */
239                 if (num_interfaces > 0) {
240                         primary_address = iface_n_ip(ifaces, 0);
241                 } else {
242                         primary_address = inet_ntoa(interpret_addr2(
243                                                         lp_netbios_name(lp_ctx)));
244                 }
245                 primary_address = talloc_strdup(tmp_ctx, primary_address);
246                 NT_STATUS_HAVE_NO_MEMORY(primary_address);
247
248                 status = nbtd_add_socket(nbtsrv, 
249                                          lp_ctx,
250                                          "0.0.0.0",
251                                          primary_address,
252                                          talloc_strdup(tmp_ctx, "255.255.255.255"),
253                                          talloc_strdup(tmp_ctx, "0.0.0.0"));
254                 NT_STATUS_NOT_OK_RETURN(status);
255         }
256
257         for (i=0; i<num_interfaces; i++) {
258                 const char *bcast = iface_n_bcast(ifaces, i);
259                 const char *address, *netmask;
260
261                 /* we can't assume every interface is broadcast capable */
262                 if (bcast == NULL) continue;
263
264                 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
265                 bcast   = talloc_strdup(tmp_ctx, bcast);
266                 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
267
268                 status = nbtd_add_socket(nbtsrv, lp_ctx, 
269                                          address, address, bcast, netmask);
270                 NT_STATUS_NOT_OK_RETURN(status);
271         }
272
273         if (lp_wins_server_list(lp_ctx)) {
274                 status = nbtd_add_wins_socket(nbtsrv);
275                 NT_STATUS_NOT_OK_RETURN(status);
276         }
277
278         talloc_free(tmp_ctx);
279
280         return NT_STATUS_OK;
281 }
282
283
284 /*
285   form a list of addresses that we should use in name query replies
286   we always place the IP in the given interface first
287 */
288 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
289 {
290         struct nbtd_server *nbtsrv = iface->nbtsrv;
291         const char **ret = NULL;
292         struct nbtd_interface *iface2;
293         bool is_loopback = false;
294
295         if (iface->ip_address) {
296                 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
297                 ret = str_list_add(ret, iface->ip_address);
298         }
299
300         for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
301                 if (iface2 == iface) continue;
302
303                 if (!iface2->ip_address) continue;
304
305                 if (!is_loopback) {
306                         if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
307                                 continue;
308                         }
309                 }
310
311                 ret = str_list_add(ret, iface2->ip_address);
312         }
313
314         talloc_steal(mem_ctx, ret);
315
316         return ret;
317 }
318
319
320 /*
321   find the interface to use for sending a outgoing request
322 */
323 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
324                                                const char *address, bool allow_bcast_iface)
325 {
326         struct nbtd_interface *cur;
327
328         /* try to find a exact match */
329         for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
330                 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
331                         DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
332                                   address, cur->ip_address, cur->netmask, cur));
333                         return cur;
334                 }
335         }
336
337         /* no exact match, if we have the broadcast interface, use that */
338         if (allow_bcast_iface && nbtd_server->bcast_interface) {
339                 cur = nbtd_server->bcast_interface;
340                 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
341                         address, cur->ip_address, cur->netmask, cur));
342                 return cur;
343         }
344
345         /* fallback to first interface */
346         cur = nbtd_server->interfaces;
347         DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
348                 address, cur->ip_address, cur->netmask, cur));
349         return cur;
350 }
351
352 /*
353  * find the interface to use for sending a outgoing reply
354  */
355 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
356                                              const char *address, bool allow_bcast_iface)
357 {
358         struct nbtd_server *nbtd_server = iface->nbtsrv;
359
360         /* first try to use the given interfacel when it's not the broadcast one */
361         if (iface != nbtd_server->bcast_interface) {
362                 return iface;
363         }
364
365         return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
366 }