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