r17586: merge lib/netif into lib/socket and use -lnsl -lsocket on the
[sfrench/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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "dlinklist.h"
25 #include "nbt_server/nbt_server.h"
26 #include "smbd/service_task.h"
27 #include "lib/socket/socket.h"
28 #include "nbt_server/wins/winsserver.h"
29 #include "nbt_server/dgram/proto.h"
30 #include "system/network.h"
31 #include "lib/socket/netif.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());
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(), 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, iface->nbtsock->sock->backend_name, 
165                                                       bind_address, lp_nbt_port());
166
167         status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
168         if (!NT_STATUS_IS_OK(status)) {
169                 DEBUG(0,("Failed to bind to %s:%d - %s\n", 
170                          bind_address, lp_nbt_port(), nt_errstr(status)));
171                 talloc_free(iface);
172                 return status;
173         }
174         talloc_free(unicast_address);
175
176         nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
177
178         /* also setup the datagram listeners */
179         status = nbtd_dgram_setup(iface, bind_address);
180         if (!NT_STATUS_IS_OK(status)) {
181                 DEBUG(0,("Failed to setup dgram listen on %s - %s\n", 
182                          bind_address, nt_errstr(status)));
183                 talloc_free(iface);
184                 return status;
185         }
186         
187         if (strcmp(netmask, "0.0.0.0") == 0) {
188                 DLIST_ADD(nbtsrv->bcast_interface, iface);
189         } else {
190                 DLIST_ADD(nbtsrv->interfaces, iface);
191         }
192
193         return NT_STATUS_OK;
194 }
195
196 /*
197   setup a socket for talking to our WINS servers
198 */
199 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
200 {
201         struct nbtd_interface *iface;
202
203         iface = talloc_zero(nbtsrv, struct nbtd_interface);
204         NT_STATUS_HAVE_NO_MEMORY(iface);
205
206         iface->nbtsrv        = nbtsrv;
207
208         DLIST_ADD(nbtsrv->wins_interface, iface);
209
210         return NT_STATUS_OK;
211 }
212
213
214 /*
215   setup our listening sockets on the configured network interfaces
216 */
217 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
218 {
219         int num_interfaces = iface_count();
220         int i;
221         TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
222         NTSTATUS status;
223
224         /* if we are allowing incoming packets from any address, then
225            we also need to bind to the wildcard address */
226         if (!lp_bind_interfaces_only()) {
227                 const char *primary_address;
228
229                 /* the primary address is the address we will return
230                    for non-WINS queries not made on a specific
231                    interface */
232                 if (num_interfaces > 0) {
233                         primary_address = iface_n_ip(0);
234                 } else {
235                         primary_address = sys_inet_ntoa(interpret_addr2(
236                                                                 lp_netbios_name()));
237                 }
238                 primary_address = talloc_strdup(tmp_ctx, primary_address);
239                 NT_STATUS_HAVE_NO_MEMORY(primary_address);
240
241                 status = nbtd_add_socket(nbtsrv, 
242                                          "0.0.0.0",
243                                          primary_address,
244                                          talloc_strdup(tmp_ctx, "255.255.255.255"),
245                                          talloc_strdup(tmp_ctx, "0.0.0.0"));
246                 NT_STATUS_NOT_OK_RETURN(status);
247         }
248
249         for (i=0; i<num_interfaces; i++) {
250                 const char *bcast = iface_n_bcast(i);
251                 const char *address, *netmask;
252
253                 /* we can't assume every interface is broadcast capable */
254                 if (bcast == NULL) continue;
255
256                 address = talloc_strdup(tmp_ctx, iface_n_ip(i));
257                 bcast   = talloc_strdup(tmp_ctx, bcast);
258                 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
259
260                 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
261                 NT_STATUS_NOT_OK_RETURN(status);
262         }
263
264         if (lp_wins_server_list()) {
265                 status = nbtd_add_wins_socket(nbtsrv);
266                 NT_STATUS_NOT_OK_RETURN(status);
267         }
268
269         talloc_free(tmp_ctx);
270
271         return NT_STATUS_OK;
272 }
273
274
275 /*
276   form a list of addresses that we should use in name query replies
277   we always place the IP in the given interface first
278 */
279 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
280 {
281         struct nbtd_server *nbtsrv = iface->nbtsrv;
282         const char **ret = NULL;
283         struct nbtd_interface *iface2;
284         BOOL is_loopback = False;
285
286         if (iface->ip_address) {
287                 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
288                 ret = str_list_add(ret, iface->ip_address);
289         }
290
291         for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
292                 if (iface2 == iface) continue;
293
294                 if (!iface2->ip_address) continue;
295
296                 if (!is_loopback) {
297                         if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
298                                 continue;
299                         }
300                 }
301
302                 ret = str_list_add(ret, iface2->ip_address);
303         }
304
305         talloc_steal(mem_ctx, ret);
306
307         return ret;
308 }
309
310
311 /*
312   find the interface to use for sending a outgoing request
313 */
314 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
315                                                const char *address, BOOL allow_bcast_iface)
316 {
317         struct nbtd_interface *cur;
318
319         /* try to find a exact match */
320         for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
321                 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
322                         return cur;
323                 }
324         }
325
326         /* no exact match, if we have the broadcast interface, use that */
327         if (allow_bcast_iface && nbtd_server->bcast_interface) {
328                 return nbtd_server->bcast_interface;
329         }
330
331         /* fallback to first interface */
332         return nbtd_server->interfaces;
333 }
334
335 /*
336  * find the interface to use for sending a outgoing reply
337  */
338 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
339                                              const char *address, BOOL allow_bcast_iface)
340 {
341         struct nbtd_server *nbtd_server = iface->nbtsrv;
342
343         /* first try to use the given interfacel when it's not the broadcast one */
344         if (iface != nbtd_server->bcast_interface) {
345                 return iface;
346         }
347
348         return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);
349 }