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