Fix bug #8541 - readlink() on Linux clients fails if the symlink target is outside...
[Samba.git] / source3 / nmbd / nmbd_subnetdb.c
blob48dbe66e309c836b25db26abc8bf01b19f6c120f
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-1998
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.
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.
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/>.
21 Revision History:
25 #include "includes.h"
27 extern int global_nmb_port;
29 /* This is the broadcast subnets database. */
30 struct subnet_record *subnetlist = NULL;
32 /* Extra subnets - keep these separate so enumeration code doesn't
33 run onto it by mistake. */
35 struct subnet_record *unicast_subnet = NULL;
36 struct subnet_record *remote_broadcast_subnet = NULL;
37 struct subnet_record *wins_server_subnet = NULL;
39 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
41 /****************************************************************************
42 Add a subnet into the list.
43 **************************************************************************/
45 static void add_subnet(struct subnet_record *subrec)
47 DLIST_ADD(subnetlist, subrec);
50 /****************************************************************************
51 stop listening on a subnet
52 we don't free the record as we don't have proper reference counting for it
53 yet and it may be in use by a response record
54 ****************************************************************************/
56 void close_subnet(struct subnet_record *subrec)
58 if (subrec->nmb_sock != -1) {
59 close(subrec->nmb_sock);
60 subrec->nmb_sock = -1;
62 if (subrec->nmb_bcast != -1) {
63 close(subrec->nmb_bcast);
64 subrec->nmb_bcast = -1;
66 if (subrec->dgram_sock != -1) {
67 close(subrec->dgram_sock);
68 subrec->dgram_sock = -1;
70 if (subrec->dgram_bcast != -1) {
71 close(subrec->dgram_bcast);
72 subrec->dgram_bcast = -1;
75 DLIST_REMOVE(subnetlist, subrec);
78 /****************************************************************************
79 Create a subnet entry.
80 ****************************************************************************/
82 static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
83 struct in_addr myip, struct in_addr bcast_ip,
84 struct in_addr mask_ip)
86 struct subnet_record *subrec = NULL;
87 int nmb_sock = -1;
88 int dgram_sock = -1;
89 int nmb_bcast = -1;
90 int dgram_bcast = -1;
91 bool bind_bcast = lp_nmbd_bind_explicit_broadcast();
93 /* Check if we are creating a non broadcast subnet - if so don't create
94 sockets. */
96 if (type == NORMAL_SUBNET) {
97 struct sockaddr_storage ss;
98 struct sockaddr_storage ss_bcast;
100 in_addr_to_sockaddr_storage(&ss, myip);
101 in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip);
104 * Attempt to open the sockets on port 137/138 for this interface
105 * and bind them.
106 * Fail the subnet creation if this fails.
109 nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,
110 0, &ss, true);
111 if (nmb_sock == -1) {
112 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
113 DEBUGADD(0,(" Failed to open nmb socket on interface %s ",
114 inet_ntoa(myip)));
115 DEBUGADD(0,("for port %d. ", global_nmb_port));
116 DEBUGADD(0,("Error was %s\n", strerror(errno)));
117 goto failed;
119 set_socket_options(nmb_sock,"SO_BROADCAST");
120 set_blocking(nmb_sock, false);
122 if (bind_bcast) {
123 nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port,
124 0, &ss_bcast, true);
125 if (nmb_bcast == -1) {
126 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
127 DEBUGADD(0,(" Failed to open nmb bcast socket on interface %s ",
128 inet_ntoa(bcast_ip)));
129 DEBUGADD(0,("for port %d. ", global_nmb_port));
130 DEBUGADD(0,("Error was %s\n", strerror(errno)));
131 goto failed;
133 set_socket_options(nmb_bcast, "SO_BROADCAST");
134 set_blocking(nmb_bcast, false);
137 dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
138 3, &ss, true);
139 if (dgram_sock == -1) {
140 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
141 DEBUGADD(0,(" Failed to open dgram socket on interface %s ",
142 inet_ntoa(myip)));
143 DEBUGADD(0,("for port %d. ", DGRAM_PORT));
144 DEBUGADD(0,("Error was %s\n", strerror(errno)));
145 goto failed;
147 set_socket_options(dgram_sock, "SO_BROADCAST");
148 set_blocking(dgram_sock, false);
150 if (bind_bcast) {
151 dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
152 3, &ss_bcast, true);
153 if (dgram_bcast == -1) {
154 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
155 DEBUGADD(0,(" Failed to open dgram bcast socket on interface %s ",
156 inet_ntoa(bcast_ip)));
157 DEBUGADD(0,("for port %d. ", DGRAM_PORT));
158 DEBUGADD(0,("Error was %s\n", strerror(errno)));
159 goto failed;
161 set_socket_options(dgram_bcast, "SO_BROADCAST");
162 set_blocking(dgram_bcast, false);
166 subrec = SMB_MALLOC_P(struct subnet_record);
167 if (!subrec) {
168 DEBUG(0,("make_subnet: malloc fail !\n"));
169 goto failed;
172 ZERO_STRUCTP(subrec);
174 if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
175 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
176 goto failed;
179 DEBUG(2, ("making subnet name:%s ", name ));
180 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
181 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
183 subrec->namelist_changed = False;
184 subrec->work_changed = False;
186 subrec->bcast_ip = bcast_ip;
187 subrec->mask_ip = mask_ip;
188 subrec->myip = myip;
189 subrec->type = type;
190 subrec->nmb_sock = nmb_sock;
191 subrec->nmb_bcast = nmb_bcast;
192 subrec->dgram_sock = dgram_sock;
193 subrec->dgram_bcast = dgram_bcast;
195 return subrec;
197 failed:
198 SAFE_FREE(subrec);
199 if (nmb_sock != -1) {
200 close(nmb_sock);
202 if (nmb_bcast != -1) {
203 close(nmb_bcast);
205 if (dgram_sock != -1) {
206 close(dgram_sock);
208 if (dgram_bcast != -1) {
209 close(dgram_bcast);
211 return NULL;
214 /****************************************************************************
215 Create a normal subnet
216 **************************************************************************/
218 struct subnet_record *make_normal_subnet(const struct interface *iface)
221 struct subnet_record *subrec;
222 const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
223 const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
224 const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
226 subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
227 *pip, *pbcast, *pnmask);
228 if (subrec) {
229 add_subnet(subrec);
231 return subrec;
234 /****************************************************************************
235 Create subnet entries.
236 **************************************************************************/
238 bool create_subnets(void)
240 /* We only count IPv4 interfaces whilst we're waiting. */
241 int num_interfaces;
242 int i;
243 struct in_addr unicast_ip, ipzero;
245 try_interfaces_again:
247 /* Only count IPv4, non-loopback interfaces. */
248 if (iface_count_v4_nl() == 0) {
249 DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n"));
250 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
253 /* We only count IPv4, non-loopback interfaces here. */
254 while (iface_count_v4_nl() == 0) {
255 void (*saved_handler)(int);
258 * Whilst we're waiting for an interface, allow SIGTERM to
259 * cause us to exit.
262 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
264 sleep(5);
265 load_interfaces();
268 * We got an interface, restore our normal term handler.
271 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
275 * Here we count v4 and v6 - we know there's at least one
276 * IPv4 interface and we filter on it below.
278 num_interfaces = iface_count();
281 * Create subnets from all the local interfaces and thread them onto
282 * the linked list.
285 for (i = 0 ; i < num_interfaces; i++) {
286 const struct interface *iface = get_interface(i);
288 if (!iface) {
289 DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
290 continue;
293 /* Ensure we're only dealing with IPv4 here. */
294 if (iface->ip.ss_family != AF_INET) {
295 DEBUG(2,("create_subnets: "
296 "ignoring non IPv4 interface.\n"));
297 continue;
301 * We don't want to add a loopback interface, in case
302 * someone has added 127.0.0.1 for smbd, nmbd needs to
303 * ignore it here. JRA.
306 if (is_loopback_addr((struct sockaddr *)&iface->ip)) {
307 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
308 continue;
311 if (!make_normal_subnet(iface))
312 return False;
315 /* We must have at least one subnet. */
316 if (subnetlist == NULL) {
317 void (*saved_handler)(int);
319 DEBUG(0,("create_subnets: Unable to create any subnet from "
320 "given interfaces. Is your interface line in "
321 "smb.conf correct ?\n"));
323 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
325 sleep(5);
326 load_interfaces();
328 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
329 goto try_interfaces_again;
332 if (lp_we_are_a_wins_server()) {
333 /* Pick the first interface IPv4 address as the WINS server
334 * ip. */
335 const struct in_addr *nip = first_ipv4_iface();
337 if (!nip) {
338 return False;
341 unicast_ip = *nip;
342 } else {
343 /* note that we do not set the wins server IP here. We just
344 set it at zero and let the wins registration code cope
345 with getting the IPs right for each packet */
346 zero_ip_v4(&unicast_ip);
350 * Create the unicast and remote broadcast subnets.
351 * Don't put these onto the linked list.
352 * The ip address of the unicast subnet is set to be
353 * the WINS server address, if it exists, or ipzero if not.
356 unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
357 unicast_ip, unicast_ip, unicast_ip);
359 zero_ip_v4(&ipzero);
361 remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
362 REMOTE_BROADCAST_SUBNET,
363 ipzero, ipzero, ipzero);
365 if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
366 return False;
369 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
370 * the linked list.
373 if (lp_we_are_a_wins_server()) {
374 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
375 WINS_SERVER_SUBNET,
376 ipzero, ipzero, ipzero )) == NULL )
377 return False;
380 return True;
383 /*******************************************************************
384 Function to tell us if we can use the unicast subnet.
385 ******************************************************************/
387 bool we_are_a_wins_client(void)
389 if (wins_srv_count() > 0) {
390 return True;
393 return False;
396 /*******************************************************************
397 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
398 ******************************************************************/
400 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
402 if(subrec == unicast_subnet)
403 return NULL;
404 else if((subrec->next == NULL) && we_are_a_wins_client())
405 return unicast_subnet;
406 else
407 return subrec->next;
410 /*******************************************************************
411 Access function used by retransmit_or_expire_response_records() in
412 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
413 Needed when we need to enumerate all the broadcast, unicast and
414 WINS subnets.
415 ******************************************************************/
417 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
419 if(subrec == unicast_subnet) {
420 if(wins_server_subnet)
421 return wins_server_subnet;
422 else
423 return NULL;
426 if(wins_server_subnet && subrec == wins_server_subnet)
427 return NULL;
429 if((subrec->next == NULL) && we_are_a_wins_client())
430 return unicast_subnet;
431 else
432 return subrec->next;