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