Merge commit 'release-4-0-0alpha1' into v4-0-test
[amitay/samba.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, 
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                                 const char *bind_address, 
102                                 const char *address, 
103                                 const char *bcast, 
104                                 const char *netmask)
105 {
106         struct nbtd_interface *iface;
107         NTSTATUS status;
108         struct socket_address *bcast_address;
109         struct socket_address *unicast_address;
110
111         /*
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
117         */
118
119         iface = talloc(nbtsrv, struct nbtd_interface);
120         NT_STATUS_HAVE_NO_MEMORY(iface);
121
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;
127
128         if (strcmp(netmask, "0.0.0.0") != 0) {
129                 struct nbt_name_socket *bcast_nbtsock;
130
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;
136                 }
137
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;
143                 }
144
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;
151                 }
152                 talloc_free(bcast_address);
153
154                 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
155         }
156
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;
162         }
163
164         unicast_address = socket_address_from_strings(iface->nbtsock, 
165                                                       iface->nbtsock->sock->backend_name, 
166                                                       bind_address, lp_nbt_port(global_loadparm));
167
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;
174         }
175         talloc_free(unicast_address);
176
177         nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
178
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;
186         }
187         
188         if (strcmp(netmask, "0.0.0.0") == 0) {
189                 DLIST_ADD(nbtsrv->bcast_interface, iface);
190         } else {
191                 DLIST_ADD(nbtsrv->interfaces, iface);
192         }
193
194         return NT_STATUS_OK;
195 }
196
197 /*
198   setup a socket for talking to our WINS servers
199 */
200 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
201 {
202         struct nbtd_interface *iface;
203
204         iface = talloc_zero(nbtsrv, struct nbtd_interface);
205         NT_STATUS_HAVE_NO_MEMORY(iface);
206
207         iface->nbtsrv        = nbtsrv;
208
209         DLIST_ADD(nbtsrv->wins_interface, iface);
210
211         return NT_STATUS_OK;
212 }
213
214
215 /*
216   setup our listening sockets on the configured network interfaces
217 */
218 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
219 {
220         int num_interfaces = iface_count();
221         int i;
222         TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
223         NTSTATUS status;
224
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;
229
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)));
238                 }
239                 primary_address = talloc_strdup(tmp_ctx, primary_address);
240                 NT_STATUS_HAVE_NO_MEMORY(primary_address);
241
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);
248         }
249
250         for (i=0; i<num_interfaces; i++) {
251                 const char *bcast = iface_n_bcast(i);
252                 const char *address, *netmask;
253
254                 /* we can't assume every interface is broadcast capable */
255                 if (bcast == NULL) continue;
256
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));
260
261                 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
262                 NT_STATUS_NOT_OK_RETURN(status);
263         }
264
265         if (lp_wins_server_list(global_loadparm)) {
266                 status = nbtd_add_wins_socket(nbtsrv);
267                 NT_STATUS_NOT_OK_RETURN(status);
268         }
269
270         talloc_free(tmp_ctx);
271
272         return NT_STATUS_OK;
273 }
274
275
276 /*
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
279 */
280 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
281 {
282         struct nbtd_server *nbtsrv = iface->nbtsrv;
283         const char **ret = NULL;
284         struct nbtd_interface *iface2;
285         bool is_loopback = false;
286
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);
290         }
291
292         for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
293                 if (iface2 == iface) continue;
294
295                 if (!iface2->ip_address) continue;
296
297                 if (!is_loopback) {
298                         if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
299                                 continue;
300                         }
301                 }
302
303                 ret = str_list_add(ret, iface2->ip_address);
304         }
305
306         talloc_steal(mem_ctx, ret);
307
308         return ret;
309 }
310
311
312 /*
313   find the interface to use for sending a outgoing request
314 */
315 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
316                                                const char *address, bool allow_bcast_iface)
317 {
318         struct nbtd_interface *cur;
319
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;
324                 }
325         }
326
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;
330         }
331
332         /* fallback to first interface */
333         return nbtd_server->interfaces;
334 }
335
336 /*
337  * find the interface to use for sending a outgoing reply
338  */
339 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
340                                              const char *address, bool allow_bcast_iface)
341 {
342         struct nbtd_server *nbtd_server = iface->nbtsrv;
343
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;
347         }
348
349         return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
350 }