move to SAFE_FREE()
[tprouty/samba.git] / source / lib / interface.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    multiple interface handling
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #define MAX_INTERFACES 128
25
26 static struct iface_struct *probed_ifaces;
27 static int total_probed;
28
29 extern int DEBUGLEVEL;
30
31 struct in_addr ipzero;
32 struct in_addr allones_ip;
33 struct in_addr loopback_ip;
34
35 static struct interface *local_interfaces  = NULL;
36
37 #define ALLONES  ((uint32)0xFFFFFFFF)
38 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
39 #define MKNETADDR(_IP, _NM) (_IP & _NM)
40
41 /****************************************************************************
42 Try and find an interface that matches an ip. If we cannot, return NULL
43   **************************************************************************/
44 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
45 {
46         struct interface *i;
47         if (zero_ip(ip)) return local_interfaces;
48
49         for (i=local_interfaces;i;i=i->next)
50                 if (CheckMask) {
51                         if (same_net(i->ip,ip,i->nmask)) return i;
52                 } else if ((i->ip).s_addr == ip.s_addr) return i;
53
54         return NULL;
55 }
56
57
58 /****************************************************************************
59 add an interface to the linked list of interfaces
60 ****************************************************************************/
61 static void add_interface(struct in_addr ip, struct in_addr nmask)
62 {
63         struct interface *iface;
64         if (iface_find(ip, False)) {
65                 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
66                 return;
67         }
68
69         if (ip_equal(nmask, allones_ip)) {
70                 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
71                 return;
72         }
73
74         iface = (struct interface *)malloc(sizeof(*iface));
75         if (!iface) return;
76         
77         ZERO_STRUCTPN(iface);
78
79         iface->ip = ip;
80         iface->nmask = nmask;
81         iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
82
83         DLIST_ADD(local_interfaces, iface);
84
85         DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
86         DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
87         DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));             
88 }
89
90
91
92 /****************************************************************************
93 interpret a single element from a interfaces= config line 
94
95 This handles the following different forms:
96
97 1) wildcard interface name
98 2) DNS name
99 3) IP/masklen
100 4) ip/mask
101 5) bcast/mask
102 ****************************************************************************/
103 static void interpret_interface(char *token)
104 {
105         struct in_addr ip, nmask;
106         char *p;
107         int i, added=0;
108
109         ip = ipzero;
110         nmask = ipzero;
111         
112         /* first check if it is an interface name */
113         for (i=0;i<total_probed;i++) {
114                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
115                         add_interface(probed_ifaces[i].ip,
116                                       probed_ifaces[i].netmask);
117                         added = 1;
118                 }
119         }
120         if (added) return;
121
122         /* maybe it is a DNS name */
123         p = strchr_m(token,'/');
124         if (!p) {
125                 ip = *interpret_addr2(token);
126                 for (i=0;i<total_probed;i++) {
127                         if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
128                             !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
129                                 add_interface(probed_ifaces[i].ip,
130                                               probed_ifaces[i].netmask);
131                                 return;
132                         }
133                 }
134                 DEBUG(2,("can't determine netmask for %s\n", token));
135                 return;
136         }
137
138         /* parse it into an IP address/netmasklength pair */
139         *p++ = 0;
140
141         ip = *interpret_addr2(token);
142
143         if (strlen(p) > 2) {
144                 nmask = *interpret_addr2(p);
145         } else {
146                 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
147         }
148
149         /* maybe the first component was a broadcast address */
150         if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
151             ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
152                 for (i=0;i<total_probed;i++) {
153                         if (same_net(ip, probed_ifaces[i].ip, nmask)) {
154                                 add_interface(probed_ifaces[i].ip, nmask);
155                                 return;
156                         }
157                 }
158                 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
159                 return;
160         }
161
162         add_interface(ip, nmask);
163 }
164
165
166 /****************************************************************************
167 load the list of network interfaces
168 ****************************************************************************/
169 void load_interfaces(void)
170 {
171         char **ptr;
172         int i;
173         struct iface_struct ifaces[MAX_INTERFACES];
174
175         ptr = lp_interfaces();
176
177         ipzero = *interpret_addr2("0.0.0.0");
178         allones_ip = *interpret_addr2("255.255.255.255");
179         loopback_ip = *interpret_addr2("127.0.0.1");
180
181         SAFE_FREE(probed_ifaces);
182
183         /* dump the current interfaces if any */
184         while (local_interfaces) {
185                 struct interface *iface = local_interfaces;
186                 DLIST_REMOVE(local_interfaces, local_interfaces);
187                 ZERO_STRUCTPN(iface);
188                 SAFE_FREE(iface);
189         }
190
191         /* probe the kernel for interfaces */
192         total_probed = get_interfaces(ifaces, MAX_INTERFACES);
193
194         if (total_probed > 0) {
195                 probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
196         }
197
198         /* if we don't have a interfaces line then use all broadcast capable 
199            interfaces except loopback */
200         if (!ptr || !*ptr || !**ptr) {
201                 if (total_probed <= 0) {
202                         DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
203                         exit(1);
204                 }
205                 for (i=0;i<total_probed;i++) {
206                         if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
207                             probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
208                                 add_interface(probed_ifaces[i].ip, 
209                                               probed_ifaces[i].netmask);
210                         }
211                 }
212                 return;
213         }
214
215         if (ptr) {
216                 while (*ptr) {
217                         interpret_interface(*ptr);
218                         ptr++;
219                 }
220         }
221
222         if (!local_interfaces) {
223                 DEBUG(0,("WARNING: no network interfaces found\n"));
224         }
225 }
226
227
228 /****************************************************************************
229 return True if the list of probed interfaces has changed
230 ****************************************************************************/
231 BOOL interfaces_changed(void)
232 {
233         int n;
234         struct iface_struct ifaces[MAX_INTERFACES];
235
236         n = get_interfaces(ifaces, MAX_INTERFACES);
237
238         if ((n > 0 )&& (n != total_probed ||
239             memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
240                 return True;
241         }
242         
243         return False;
244 }
245
246
247 /****************************************************************************
248   check if an IP is one of mine
249   **************************************************************************/
250 BOOL ismyip(struct in_addr ip)
251 {
252         struct interface *i;
253         for (i=local_interfaces;i;i=i->next)
254                 if (ip_equal(i->ip,ip)) return True;
255         return False;
256 }
257
258 /****************************************************************************
259   check if a packet is from a local (known) net
260   **************************************************************************/
261 BOOL is_local_net(struct in_addr from)
262 {
263         struct interface *i;
264         for (i=local_interfaces;i;i=i->next) {
265                 if((from.s_addr & i->nmask.s_addr) == 
266                    (i->ip.s_addr & i->nmask.s_addr))
267                         return True;
268         }
269         return False;
270 }
271
272 /****************************************************************************
273   how many interfaces do we have
274   **************************************************************************/
275 int iface_count(void)
276 {
277         int ret = 0;
278         struct interface *i;
279
280         for (i=local_interfaces;i;i=i->next)
281                 ret++;
282         return ret;
283 }
284
285 /****************************************************************************
286  True if we have two or more interfaces.
287   **************************************************************************/
288 BOOL we_are_multihomed(void)
289 {
290         static int multi = -1;
291
292         if(multi == -1)
293                 multi = (iface_count() > 1 ? True : False);
294         
295         return multi;
296 }
297
298 /****************************************************************************
299   return the Nth interface
300   **************************************************************************/
301 struct interface *get_interface(int n)
302
303         struct interface *i;
304   
305         for (i=local_interfaces;i && n;i=i->next)
306                 n--;
307
308         if (i) return i;
309         return NULL;
310 }
311
312 /****************************************************************************
313   return IP of the Nth interface
314   **************************************************************************/
315 struct in_addr *iface_n_ip(int n)
316 {
317         struct interface *i;
318   
319         for (i=local_interfaces;i && n;i=i->next)
320                 n--;
321
322         if (i) return &i->ip;
323         return NULL;
324 }
325
326 /****************************************************************************
327   return bcast of the Nth interface
328   **************************************************************************/
329 struct in_addr *iface_n_bcast(int n)
330 {
331         struct interface *i;
332   
333         for (i=local_interfaces;i && n;i=i->next)
334                 n--;
335
336         if (i) return &i->bcast;
337         return NULL;
338 }
339
340
341 /****************************************************************************
342 this function provides a simple hash of the configured interfaces. It is
343 used to detect a change in interfaces to tell us whether to discard
344 the current wins.dat file.
345 Note that the result is independent of the order of the interfaces
346   **************************************************************************/
347 unsigned iface_hash(void)
348 {
349         unsigned ret = 0;
350         struct interface *i;
351
352         for (i=local_interfaces;i;i=i->next) {
353                 unsigned x1 = (unsigned)str_checksum(inet_ntoa(i->ip));
354                 unsigned x2 = (unsigned)str_checksum(inet_ntoa(i->nmask));
355                 ret ^= (x1 ^ x2);
356         }
357
358         return ret;
359 }
360
361
362 /* these 3 functions return the ip/bcast/nmask for the interface
363    most appropriate for the given ip address. If they can't find
364    an appropriate interface they return the requested field of the
365    first known interface. */
366
367 struct in_addr *iface_bcast(struct in_addr ip)
368 {
369         struct interface *i = iface_find(ip, True);
370         return(i ? &i->bcast : &local_interfaces->bcast);
371 }
372
373 struct in_addr *iface_ip(struct in_addr ip)
374 {
375         struct interface *i = iface_find(ip, True);
376         return(i ? &i->ip : &local_interfaces->ip);
377 }