s3:nmbd: don't leak state_path() to talloc_tos() in wins_write_database()
[amitay/samba.git] / source3 / nmbd / nmbd_subnetdb.c
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
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    Revision History:
22
23 */
24
25 #include "includes.h"
26
27 extern int global_nmb_port;
28
29 /* This is the broadcast subnets database. */
30 struct subnet_record *subnetlist = NULL;
31
32 /* Extra subnets - keep these separate so enumeration code doesn't
33    run onto it by mistake. */
34
35 struct subnet_record *unicast_subnet = NULL;
36 struct subnet_record *remote_broadcast_subnet = NULL;
37 struct subnet_record *wins_server_subnet = NULL;
38
39 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
40
41 /****************************************************************************
42   Add a subnet into the list.
43   **************************************************************************/
44
45 static void add_subnet(struct subnet_record *subrec)
46 {
47         DLIST_ADD(subnetlist, subrec);
48 }
49
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   ****************************************************************************/
55
56 void close_subnet(struct subnet_record *subrec)
57 {
58         if (subrec->dgram_sock != -1) {
59                 close(subrec->dgram_sock);
60                 subrec->dgram_sock = -1;
61         }
62         if (subrec->nmb_sock != -1) {
63                 close(subrec->nmb_sock);
64                 subrec->nmb_sock = -1;
65         }
66
67         DLIST_REMOVE(subnetlist, subrec);
68 }
69
70 /****************************************************************************
71   Create a subnet entry.
72   ****************************************************************************/
73
74 static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
75                                          struct in_addr myip, struct in_addr bcast_ip, 
76                                          struct in_addr mask_ip)
77 {
78         struct subnet_record *subrec = NULL;
79         int nmb_sock, dgram_sock;
80
81         /* Check if we are creating a non broadcast subnet - if so don't create
82                 sockets.  */
83
84         if(type != NORMAL_SUBNET) {
85                 nmb_sock = -1;
86                 dgram_sock = -1;
87         } else {
88                 struct sockaddr_storage ss;
89
90                 in_addr_to_sockaddr_storage(&ss, myip);
91
92                 /*
93                  * Attempt to open the sockets on port 137/138 for this interface
94                  * and bind them.
95                  * Fail the subnet creation if this fails.
96                  */
97
98                 if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, &ss,true)) == -1) {
99                         if( DEBUGLVL( 0 ) ) {
100                                 Debug1( "nmbd_subnetdb:make_subnet()\n" );
101                                 Debug1( "  Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
102                                 Debug1( "for port %d.  ", global_nmb_port );
103                                 Debug1( "Error was %s\n", strerror(errno) );
104                         }
105                         return NULL;
106                 }
107
108                 if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, &ss, true)) == -1) {
109                         if( DEBUGLVL( 0 ) ) {
110                                 Debug1( "nmbd_subnetdb:make_subnet()\n" );
111                                 Debug1( "  Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
112                                 Debug1( "for port %d.  ", DGRAM_PORT );
113                                 Debug1( "Error was %s\n", strerror(errno) );
114                         }
115                         return NULL;
116                 }
117
118                 /* Make sure we can broadcast from these sockets. */
119                 set_socket_options(nmb_sock,"SO_BROADCAST");
120                 set_socket_options(dgram_sock,"SO_BROADCAST");
121
122                 /* Set them non-blocking. */
123                 set_blocking(nmb_sock, False);
124                 set_blocking(dgram_sock, False);
125         }
126
127         subrec = SMB_MALLOC_P(struct subnet_record);
128         if (!subrec) {
129                 DEBUG(0,("make_subnet: malloc fail !\n"));
130                 if (nmb_sock != -1) {
131                         close(nmb_sock);
132                 }
133                 if (dgram_sock != -1) {
134                         close(dgram_sock);
135                 }
136                 return(NULL);
137         }
138   
139         ZERO_STRUCTP(subrec);
140
141         if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
142                 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
143                 if (nmb_sock != -1) {
144                         close(nmb_sock);
145                 }
146                 if (dgram_sock != -1) {
147                         close(dgram_sock);
148                 }
149                 ZERO_STRUCTP(subrec);
150                 SAFE_FREE(subrec);
151                 return(NULL);
152         }
153
154         DEBUG(2, ("making subnet name:%s ", name ));
155         DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
156         DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
157  
158         subrec->namelist_changed = False;
159         subrec->work_changed = False;
160  
161         subrec->bcast_ip = bcast_ip;
162         subrec->mask_ip  = mask_ip;
163         subrec->myip = myip;
164         subrec->type = type;
165         subrec->nmb_sock = nmb_sock;
166         subrec->dgram_sock = dgram_sock;
167   
168         return subrec;
169 }
170
171 /****************************************************************************
172   Create a normal subnet
173 **************************************************************************/
174
175 struct subnet_record *make_normal_subnet(const struct interface *iface)
176 {
177
178         struct subnet_record *subrec;
179         const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
180         const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
181         const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
182
183         subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
184                              *pip, *pbcast, *pnmask);
185         if (subrec) {
186                 add_subnet(subrec);
187         }
188         return subrec;
189 }
190
191 /****************************************************************************
192   Create subnet entries.
193 **************************************************************************/
194
195 bool create_subnets(void)
196 {
197         /* We only count IPv4 interfaces whilst we're waiting. */
198         int num_interfaces;
199         int i;
200         struct in_addr unicast_ip, ipzero;
201
202   try_interfaces_again:
203
204         /* Only count IPv4, non-loopback interfaces. */
205         if (iface_count_v4_nl() == 0) {
206                 DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n"));
207                 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
208         }
209
210         /* We only count IPv4, non-loopback interfaces here. */
211         while (iface_count_v4_nl() == 0) {
212                 void (*saved_handler)(int);
213
214                 /*
215                  * Whilst we're waiting for an interface, allow SIGTERM to
216                  * cause us to exit.
217                  */
218
219                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
220
221                 sleep(5);
222                 load_interfaces();
223
224                 /*
225                  * We got an interface, restore our normal term handler.
226                  */
227
228                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
229         }
230
231         /*
232          * Here we count v4 and v6 - we know there's at least one
233          * IPv4 interface and we filter on it below.
234          */
235         num_interfaces = iface_count();
236
237         /*
238          * Create subnets from all the local interfaces and thread them onto
239          * the linked list.
240          */
241
242         for (i = 0 ; i < num_interfaces; i++) {
243                 const struct interface *iface = get_interface(i);
244
245                 if (!iface) {
246                         DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
247                         continue;
248                 }
249
250                 /* Ensure we're only dealing with IPv4 here. */
251                 if (iface->ip.ss_family != AF_INET) {
252                         DEBUG(2,("create_subnets: "
253                                 "ignoring non IPv4 interface.\n"));
254                         continue;
255                 }
256
257                 /*
258                  * We don't want to add a loopback interface, in case
259                  * someone has added 127.0.0.1 for smbd, nmbd needs to
260                  * ignore it here. JRA.
261                  */
262
263                 if (is_loopback_addr((struct sockaddr *)&iface->ip)) {
264                         DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
265                         continue;
266                 }
267
268                 if (!make_normal_subnet(iface))
269                         return False;
270         }
271
272         /* We must have at least one subnet. */
273         if (subnetlist == NULL) {
274                 void (*saved_handler)(int);
275
276                 DEBUG(0,("create_subnets: Unable to create any subnet from "
277                                 "given interfaces. Is your interface line in "
278                                 "smb.conf correct ?\n"));
279
280                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
281
282                 sleep(5);
283                 load_interfaces();
284
285                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
286                 goto try_interfaces_again;
287         }
288
289         if (lp_we_are_a_wins_server()) {
290                 /* Pick the first interface IPv4 address as the WINS server ip. */
291                 const struct in_addr *nip = first_ipv4_iface();
292
293                 if (!nip) {
294                         return False;
295                 }
296
297                 unicast_ip = *nip;
298         } else {
299                 /* note that we do not set the wins server IP here. We just
300                         set it at zero and let the wins registration code cope
301                         with getting the IPs right for each packet */
302                 zero_ip_v4(&unicast_ip);
303         }
304
305         /*
306          * Create the unicast and remote broadcast subnets.
307          * Don't put these onto the linked list.
308          * The ip address of the unicast subnet is set to be
309          * the WINS server address, if it exists, or ipzero if not.
310          */
311
312         unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, 
313                                 unicast_ip, unicast_ip, unicast_ip);
314
315         zero_ip_v4(&ipzero);
316
317         remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
318                                 REMOTE_BROADCAST_SUBNET,
319                                 ipzero, ipzero, ipzero);
320
321         if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
322                 return False;
323
324         /* 
325          * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
326          * the linked list.
327          */
328
329         if (lp_we_are_a_wins_server()) {
330                 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
331                                                 WINS_SERVER_SUBNET, 
332                                                 ipzero, ipzero, ipzero )) == NULL )
333                         return False;
334         }
335
336         return True;
337 }
338
339 /*******************************************************************
340 Function to tell us if we can use the unicast subnet.
341 ******************************************************************/
342
343 bool we_are_a_wins_client(void)
344 {
345         if (wins_srv_count() > 0) {
346                 return True;
347         }
348
349         return False;
350 }
351
352 /*******************************************************************
353 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
354 ******************************************************************/
355
356 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
357 {
358         if(subrec == unicast_subnet)
359                 return NULL;
360         else if((subrec->next == NULL) && we_are_a_wins_client())
361                 return unicast_subnet;
362         else
363                 return subrec->next;
364 }
365
366 /*******************************************************************
367  Access function used by retransmit_or_expire_response_records() in
368  nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
369  Needed when we need to enumerate all the broadcast, unicast and
370  WINS subnets.
371 ******************************************************************/
372
373 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
374 {
375         if(subrec == unicast_subnet) {
376                 if(wins_server_subnet)
377                         return wins_server_subnet;
378                 else
379                         return NULL;
380         }
381
382         if(wins_server_subnet && subrec == wins_server_subnet)
383                 return NULL;
384
385         if((subrec->next == NULL) && we_are_a_wins_client())
386                 return unicast_subnet;
387         else
388                 return subrec->next;
389 }