Add SMB encryption. Still fixing client decrypt but
[ira/wip.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 = iface_count_v4();
199         int i;
200         struct in_addr unicast_ip, ipzero;
201
202         if(num_interfaces == 0) {
203                 void (*saved_handler)(int);
204
205                 DEBUG(0,("create_subnets: No local interfaces !\n"));
206                 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
207
208                 /*
209                  * Whilst we're waiting for an interface, allow SIGTERM to
210                  * cause us to exit.
211                  */
212
213                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
214
215                 /* We only count IPv4 interfaces here. */
216                 while (iface_count_v4() == 0) {
217                         sleep(5);
218                         load_interfaces();
219                 }
220
221                 /*
222                  * We got an interface, restore our normal term handler.
223                  */
224
225                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
226         }
227
228         /*
229          * Here we count v4 and v6 - we know there's at least one
230          * IPv4 interface and we filter on it below.
231          */
232         num_interfaces = iface_count();
233
234         /*
235          * Create subnets from all the local interfaces and thread them onto
236          * the linked list.
237          */
238
239         for (i = 0 ; i < num_interfaces; i++) {
240                 const struct interface *iface = get_interface(i);
241
242                 if (!iface) {
243                         DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
244                         continue;
245                 }
246
247                 /* Ensure we're only dealing with IPv4 here. */
248                 if (iface->ip.ss_family != AF_INET) {
249                         DEBUG(2,("create_subnets: "
250                                 "ignoring non IPv4 interface.\n"));
251                         continue;
252                 }
253
254                 /*
255                  * We don't want to add a loopback interface, in case
256                  * someone has added 127.0.0.1 for smbd, nmbd needs to
257                  * ignore it here. JRA.
258                  */
259
260                 if (is_loopback_addr(&iface->ip)) {
261                         DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
262                         continue;
263                 }
264
265                 if (!make_normal_subnet(iface))
266                         return False;
267         }
268
269         /* We must have at least one subnet. */
270         if (subnetlist == NULL) {
271                 DEBUG(0,("create_subnets: unable to create any subnet from "
272                                 "given interfaces. nmbd is terminating\n"));
273                 return False;
274         }
275
276         if (lp_we_are_a_wins_server()) {
277                 /* Pick the first interface IPv4 address as the WINS server ip. */
278                 const struct in_addr *nip = first_ipv4_iface();
279
280                 if (!nip) {
281                         return False;
282                 }
283
284                 unicast_ip = *nip;
285         } else {
286                 /* note that we do not set the wins server IP here. We just
287                         set it at zero and let the wins registration code cope
288                         with getting the IPs right for each packet */
289                 zero_ip_v4(&unicast_ip);
290         }
291
292         /*
293          * Create the unicast and remote broadcast subnets.
294          * Don't put these onto the linked list.
295          * The ip address of the unicast subnet is set to be
296          * the WINS server address, if it exists, or ipzero if not.
297          */
298
299         unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, 
300                                 unicast_ip, unicast_ip, unicast_ip);
301
302         zero_ip_v4(&ipzero);
303
304         remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
305                                 REMOTE_BROADCAST_SUBNET,
306                                 ipzero, ipzero, ipzero);
307
308         if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
309                 return False;
310
311         /* 
312          * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
313          * the linked list.
314          */
315
316         if (lp_we_are_a_wins_server()) {
317                 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
318                                                 WINS_SERVER_SUBNET, 
319                                                 ipzero, ipzero, ipzero )) == NULL )
320                         return False;
321         }
322
323         return True;
324 }
325
326 /*******************************************************************
327 Function to tell us if we can use the unicast subnet.
328 ******************************************************************/
329
330 bool we_are_a_wins_client(void)
331 {
332         if (wins_srv_count() > 0) {
333                 return True;
334         }
335
336         return False;
337 }
338
339 /*******************************************************************
340 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
341 ******************************************************************/
342
343 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
344 {
345         if(subrec == unicast_subnet)
346                 return NULL;
347         else if((subrec->next == NULL) && we_are_a_wins_client())
348                 return unicast_subnet;
349         else
350                 return subrec->next;
351 }
352
353 /*******************************************************************
354  Access function used by retransmit_or_expire_response_records() in
355  nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
356  Needed when we need to enumerate all the broadcast, unicast and
357  WINS subnets.
358 ******************************************************************/
359
360 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
361 {
362         if(subrec == unicast_subnet) {
363                 if(wins_server_subnet)
364                         return wins_server_subnet;
365                 else
366                         return NULL;
367         }
368
369         if(wins_server_subnet && subrec == wins_server_subnet)
370                 return NULL;
371
372         if((subrec->next == NULL) && we_are_a_wins_client())
373                 return unicast_subnet;
374         else
375                 return subrec->next;
376 }