486acfbad535f8a24c7640c6b8f3c86a9d556068
[bbaumbach/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
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                                  struct interface *ifaces)
221 {
222         int num_interfaces = iface_count(ifaces);
223         int i;
224         TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
225         NTSTATUS status;
226
227         /* if we are allowing incoming packets from any address, then
228            we also need to bind to the wildcard address */
229         if (!lp_bind_interfaces_only(lp_ctx)) {
230                 const char *primary_address;
231
232                 /* the primary address is the address we will return
233                    for non-WINS queries not made on a specific
234                    interface */
235                 if (num_interfaces > 0) {
236                         primary_address = iface_n_ip(ifaces, 0);
237                 } else {
238                         primary_address = inet_ntoa(interpret_addr2(
239                                                         lp_netbios_name(lp_ctx)));
240                 }
241                 primary_address = talloc_strdup(tmp_ctx, primary_address);
242                 NT_STATUS_HAVE_NO_MEMORY(primary_address);
243
244                 status = nbtd_add_socket(nbtsrv, 
245                                          lp_ctx,
246                                          "0.0.0.0",
247                                          primary_address,
248                                          talloc_strdup(tmp_ctx, "255.255.255.255"),
249                                          talloc_strdup(tmp_ctx, "0.0.0.0"));
250                 NT_STATUS_NOT_OK_RETURN(status);
251         }
252
253         for (i=0; i<num_interfaces; i++) {
254                 const char *bcast = iface_n_bcast(ifaces, i);
255                 const char *address, *netmask;
256
257                 /* we can't assume every interface is broadcast capable */
258                 if (bcast == NULL) continue;
259
260                 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
261                 bcast   = talloc_strdup(tmp_ctx, bcast);
262                 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
263
264                 status = nbtd_add_socket(nbtsrv, lp_ctx, 
265                                          address, address, bcast, netmask);
266                 NT_STATUS_NOT_OK_RETURN(status);
267         }
268
269         if (lp_wins_server_list(lp_ctx)) {
270                 status = nbtd_add_wins_socket(nbtsrv);
271                 NT_STATUS_NOT_OK_RETURN(status);
272         }
273
274         talloc_free(tmp_ctx);
275
276         return NT_STATUS_OK;
277 }
278
279
280 /*
281   form a list of addresses that we should use in name query replies
282   we always place the IP in the given interface first
283 */
284 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
285 {
286         struct nbtd_server *nbtsrv = iface->nbtsrv;
287         const char **ret = NULL;
288         struct nbtd_interface *iface2;
289         bool is_loopback = false;
290
291         if (iface->ip_address) {
292                 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
293                 ret = str_list_add(ret, iface->ip_address);
294         }
295
296         for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
297                 if (iface2 == iface) continue;
298
299                 if (!iface2->ip_address) continue;
300
301                 if (!is_loopback) {
302                         if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
303                                 continue;
304                         }
305                 }
306
307                 ret = str_list_add(ret, iface2->ip_address);
308         }
309
310         talloc_steal(mem_ctx, ret);
311
312         return ret;
313 }
314
315
316 /*
317   find the interface to use for sending a outgoing request
318 */
319 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
320                                                const char *address, bool allow_bcast_iface)
321 {
322         struct nbtd_interface *cur;
323
324         /* try to find a exact match */
325         for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
326                 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
327                         return cur;
328                 }
329         }
330
331         /* no exact match, if we have the broadcast interface, use that */
332         if (allow_bcast_iface && nbtd_server->bcast_interface) {
333                 return nbtd_server->bcast_interface;
334         }
335
336         /* fallback to first interface */
337         return nbtd_server->interfaces;
338 }
339
340 /*
341  * find the interface to use for sending a outgoing reply
342  */
343 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
344                                              const char *address, bool allow_bcast_iface)
345 {
346         struct nbtd_server *nbtd_server = iface->nbtsrv;
347
348         /* first try to use the given interfacel when it's not the broadcast one */
349         if (iface != nbtd_server->bcast_interface) {
350                 return iface;
351         }
352
353         return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
354 }