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