b0bc55c05b089511a63b6fc52d3e46d6aa7a934d
[kai/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
32
33 /*
34   receive an incoming request and dispatch it to the right place
35 */
36 static void nbtd_request_handler(struct nbt_name_socket *nbtsock, 
37                                  struct nbt_name_packet *packet, 
38                                  struct socket_address *src)
39 {
40         struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
41                                                        struct nbtd_interface);
42         struct nbtd_server *nbtsrv = iface->nbtsrv;
43
44         nbtsrv->stats.total_received++;
45
46         /* see if its from one of our own interfaces - if so, then ignore it */
47         if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
48                 DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
49                 return;
50         }
51
52         switch (packet->operation & NBT_OPCODE) {
53         case NBT_OPCODE_QUERY:
54                 nbtsrv->stats.query_count++;
55                 nbtd_request_query(nbtsock, packet, src);
56                 break;
57
58         case NBT_OPCODE_REGISTER:
59         case NBT_OPCODE_REFRESH:
60         case NBT_OPCODE_REFRESH2:
61                 nbtsrv->stats.register_count++;
62                 nbtd_request_defense(nbtsock, packet, src);
63                 break;
64
65         case NBT_OPCODE_RELEASE:
66         case NBT_OPCODE_MULTI_HOME_REG:
67                 nbtsrv->stats.release_count++;
68                 nbtd_winsserver_request(nbtsock, packet, src);
69                 break;
70
71         default:
72                 nbtd_bad_packet(packet, src, "Unexpected opcode");
73                 break;
74         }
75 }
76
77
78 /*
79   find a registered name on an interface
80 */
81 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface, 
82                                         struct nbt_name *name, 
83                                         uint16_t nb_flags)
84 {
85         struct nbtd_iface_name *iname;
86         for (iname=iface->names;iname;iname=iname->next) {
87                 if (iname->name.type == name->type &&
88                     strcmp(name->name, iname->name.name) == 0 &&
89                     ((iname->nb_flags & nb_flags) == nb_flags)) {
90                         return iname;
91                 }
92         }
93         return NULL;
94 }
95
96 /*
97   start listening on the given address
98 */
99 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv, 
100                                 const char *bind_address, 
101                                 const char *address, 
102                                 const char *bcast, 
103                                 const char *netmask)
104 {
105         struct nbtd_interface *iface;
106         NTSTATUS status;
107         struct socket_address *bcast_address;
108         struct socket_address *unicast_address;
109
110         /*
111           we actually create two sockets. One listens on the broadcast address
112           for the interface, and the other listens on our specific address. This
113           allows us to run with "bind interfaces only" while still receiving 
114           broadcast addresses, and also simplifies matching incoming requests 
115           to interfaces
116         */
117
118         iface = talloc(nbtsrv, struct nbtd_interface);
119         NT_STATUS_HAVE_NO_MEMORY(iface);
120
121         iface->nbtsrv        = nbtsrv;
122         iface->bcast_address = talloc_steal(iface, bcast);
123         iface->ip_address    = talloc_steal(iface, address);
124         iface->netmask       = talloc_steal(iface, netmask);
125         iface->names         = NULL;
126
127         if (strcmp(netmask, "0.0.0.0") != 0) {
128                 struct nbt_name_socket *bcast_nbtsock;
129
130                 /* listen for broadcasts on port 137 */
131                 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
132                 if (!bcast_nbtsock) {
133                         talloc_free(iface);
134                         return NT_STATUS_NO_MEMORY;
135                 }
136
137                 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name, 
138                                                             bcast, lp_nbt_port());
139                 if (!bcast_address) {
140                         talloc_free(iface);
141                         return NT_STATUS_NO_MEMORY;
142                 }
143
144                 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
145                 if (!NT_STATUS_IS_OK(status)) {
146                         DEBUG(0,("Failed to bind to %s:%d - %s\n", 
147                                  bcast, lp_nbt_port(), nt_errstr(status)));
148                         talloc_free(iface);
149                         return status;
150                 }
151                 talloc_free(bcast_address);
152
153                 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
154         }
155
156         /* listen for unicasts on port 137 */
157         iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
158         if (!iface->nbtsock) {
159                 talloc_free(iface);
160                 return NT_STATUS_NO_MEMORY;
161         }
162
163         unicast_address = socket_address_from_strings(iface->nbtsock, iface->nbtsock->sock->backend_name, 
164                                                       bind_address, lp_nbt_port());
165
166         status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
167         if (!NT_STATUS_IS_OK(status)) {
168                 DEBUG(0,("Failed to bind to %s:%d - %s\n", 
169                          bind_address, lp_nbt_port(), nt_errstr(status)));
170                 talloc_free(iface);
171                 return status;
172         }
173         talloc_free(unicast_address);
174
175         nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
176
177         /* also setup the datagram listeners */
178         status = nbtd_dgram_setup(iface, bind_address);
179         if (!NT_STATUS_IS_OK(status)) {
180                 DEBUG(0,("Failed to setup dgram listen on %s - %s\n", 
181                          bind_address, nt_errstr(status)));
182                 talloc_free(iface);
183                 return status;
184         }
185         
186         if (strcmp(netmask, "0.0.0.0") == 0) {
187                 DLIST_ADD(nbtsrv->bcast_interface, iface);
188         } else {
189                 DLIST_ADD(nbtsrv->interfaces, iface);
190         }
191
192         return NT_STATUS_OK;
193 }
194
195 /*
196   setup a socket for talking to our WINS servers
197 */
198 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
199 {
200         struct nbtd_interface *iface;
201
202         iface = talloc_zero(nbtsrv, struct nbtd_interface);
203         NT_STATUS_HAVE_NO_MEMORY(iface);
204
205         iface->nbtsrv        = nbtsrv;
206
207         DLIST_ADD(nbtsrv->wins_interface, iface);
208
209         return NT_STATUS_OK;
210 }
211
212
213 /*
214   setup our listening sockets on the configured network interfaces
215 */
216 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
217 {
218         int num_interfaces = iface_count();
219         int i;
220         TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
221         NTSTATUS status;
222
223         /* if we are allowing incoming packets from any address, then
224            we also need to bind to the wildcard address */
225         if (!lp_bind_interfaces_only()) {
226                 const char *primary_address;
227
228                 /* the primary address is the address we will return
229                    for non-WINS queries not made on a specific
230                    interface */
231                 if (num_interfaces > 0) {
232                         primary_address = iface_n_ip(0);
233                 } else {
234                         primary_address = sys_inet_ntoa(interpret_addr2(
235                                                                 lp_netbios_name()));
236                 }
237                 primary_address = talloc_strdup(tmp_ctx, primary_address);
238                 NT_STATUS_HAVE_NO_MEMORY(primary_address);
239
240                 status = nbtd_add_socket(nbtsrv, 
241                                          "0.0.0.0",
242                                          primary_address,
243                                          talloc_strdup(tmp_ctx, "255.255.255.255"),
244                                          talloc_strdup(tmp_ctx, "0.0.0.0"));
245                 NT_STATUS_NOT_OK_RETURN(status);
246         }
247
248         for (i=0; i<num_interfaces; i++) {
249                 const char *bcast = iface_n_bcast(i);
250                 const char *address, *netmask;
251
252                 /* we can't assume every interface is broadcast capable */
253                 if (bcast == NULL) continue;
254
255                 address = talloc_strdup(tmp_ctx, iface_n_ip(i));
256                 bcast   = talloc_strdup(tmp_ctx, bcast);
257                 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
258
259                 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
260                 NT_STATUS_NOT_OK_RETURN(status);
261         }
262
263         if (lp_wins_server_list()) {
264                 status = nbtd_add_wins_socket(nbtsrv);
265                 NT_STATUS_NOT_OK_RETURN(status);
266         }
267
268         talloc_free(tmp_ctx);
269
270         return NT_STATUS_OK;
271 }
272
273
274 /*
275   form a list of addresses that we should use in name query replies
276   we always place the IP in the given interface first
277 */
278 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
279 {
280         struct nbtd_server *nbtsrv = iface->nbtsrv;
281         const char **ret = NULL;
282         struct nbtd_interface *iface2;
283         BOOL is_loopback = False;
284
285         if (iface->ip_address) {
286                 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
287                 ret = str_list_add(ret, iface->ip_address);
288         }
289
290         for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
291                 if (iface2 == iface) continue;
292
293                 if (!iface2->ip_address) continue;
294
295                 if (!is_loopback) {
296                         if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
297                                 continue;
298                         }
299                 }
300
301                 ret = str_list_add(ret, iface2->ip_address);
302         }
303
304         talloc_steal(mem_ctx, ret);
305
306         return ret;
307 }
308
309
310 /*
311   find the interface to use for sending a outgoing request
312 */
313 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
314                                                const char *address, BOOL allow_bcast_iface)
315 {
316         struct nbtd_interface *cur;
317
318         /* try to find a exact match */
319         for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
320                 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
321                         return cur;
322                 }
323         }
324
325         /* no exact match, if we have the broadcast interface, use that */
326         if (allow_bcast_iface && nbtd_server->bcast_interface) {
327                 return nbtd_server->bcast_interface;
328         }
329
330         /* fallback to first interface */
331         return nbtd_server->interfaces;
332 }
333
334 /*
335  * find the interface to use for sending a outgoing reply
336  */
337 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
338                                              const char *address, BOOL allow_bcast_iface)
339 {
340         struct nbtd_server *nbtd_server = iface->nbtsrv;
341
342         /* first try to use the given interfacel when it's not the broadcast one */
343         if (iface != nbtd_server->bcast_interface) {
344                 return iface;
345         }
346
347         return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
348 }