r3169: unlink() is called on the listening unix socket every time a child process
[nivanova/samba-autobuild/.git] / source4 / lib / 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
23 static struct iface_struct *probed_ifaces;
24 static int total_probed;
25
26 static struct in_addr allones_ip;
27 struct in_addr loopback_ip;
28
29 static struct interface *local_interfaces;
30
31 #define ALLONES  ((uint32_t)0xFFFFFFFF)
32 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
33 #define MKNETADDR(_IP, _NM) (_IP & _NM)
34
35 /****************************************************************************
36 Try and find an interface that matches an ip. If we cannot, return NULL
37   **************************************************************************/
38 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
39 {
40         struct interface *i;
41         if (is_zero_ip(ip)) return local_interfaces;
42
43         for (i=local_interfaces;i;i=i->next)
44                 if (CheckMask) {
45                         if (same_net(i->ip,ip,i->nmask)) return i;
46                 } else if ((i->ip).s_addr == ip.s_addr) return i;
47
48         return NULL;
49 }
50
51
52 /****************************************************************************
53 add an interface to the linked list of interfaces
54 ****************************************************************************/
55 static void add_interface(struct in_addr ip, struct in_addr nmask)
56 {
57         struct interface *iface;
58         if (iface_find(ip, False)) {
59                 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
60                 return;
61         }
62
63         if (ip_equal(nmask, allones_ip)) {
64                 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
65                 return;
66         }
67
68         iface = (struct interface *)malloc(sizeof(*iface));
69         if (!iface) return;
70         
71         ZERO_STRUCTPN(iface);
72
73         iface->ip = ip;
74         iface->nmask = nmask;
75         iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
76
77         DLIST_ADD(local_interfaces, iface);
78
79         DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
80         DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
81         DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));             
82 }
83
84
85
86 /****************************************************************************
87 interpret a single element from a interfaces= config line 
88
89 This handles the following different forms:
90
91 1) wildcard interface name
92 2) DNS name
93 3) IP/masklen
94 4) ip/mask
95 5) bcast/mask
96 ****************************************************************************/
97 static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token)
98 {
99         struct in_addr ip, nmask;
100         char *p;
101         int i, added=0;
102
103     zero_ip(&ip);
104     zero_ip(&nmask);
105         
106         /* first check if it is an interface name */
107         for (i=0;i<total_probed;i++) {
108                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
109                         add_interface(probed_ifaces[i].ip,
110                                       probed_ifaces[i].netmask);
111                         added = 1;
112                 }
113         }
114         if (added) return;
115
116         /* maybe it is a DNS name */
117         p = strchr_m(token,'/');
118         if (!p) {
119                 ip = *interpret_addr2(mem_ctx, token);
120                 for (i=0;i<total_probed;i++) {
121                         if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
122                             !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
123                                 add_interface(probed_ifaces[i].ip,
124                                               probed_ifaces[i].netmask);
125                                 return;
126                         }
127                 }
128                 DEBUG(2,("can't determine netmask for %s\n", token));
129                 return;
130         }
131
132         /* parse it into an IP address/netmasklength pair */
133         *p++ = 0;
134
135         ip = *interpret_addr2(mem_ctx, token);
136
137         if (strlen(p) > 2) {
138                 nmask = *interpret_addr2(mem_ctx, p);
139         } else {
140                 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
141         }
142
143         /* maybe the first component was a broadcast address */
144         if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
145             ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
146                 for (i=0;i<total_probed;i++) {
147                         if (same_net(ip, probed_ifaces[i].ip, nmask)) {
148                                 add_interface(probed_ifaces[i].ip, nmask);
149                                 return;
150                         }
151                 }
152                 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
153                 return;
154         }
155
156         add_interface(ip, nmask);
157 }
158
159
160 /****************************************************************************
161 load the list of network interfaces
162 ****************************************************************************/
163 void load_interfaces(void)
164 {
165         const char **ptr;
166         int i;
167         struct iface_struct ifaces[MAX_INTERFACES];
168         TALLOC_CTX *mem_ctx;
169
170         ptr = lp_interfaces();
171         mem_ctx = talloc_init("load_interfaces");
172     if (!mem_ctx) {
173         DEBUG(2,("no memory to load interfaces \n"));
174                 return;
175     }
176
177         allones_ip = *interpret_addr2(mem_ctx, "255.255.255.255");
178         loopback_ip = *interpret_addr2(mem_ctx, "127.0.0.1");
179
180         SAFE_FREE(probed_ifaces);
181
182         /* dump the current interfaces if any */
183         while (local_interfaces) {
184                 struct interface *iface = local_interfaces;
185                 DLIST_REMOVE(local_interfaces, local_interfaces);
186                 ZERO_STRUCTPN(iface);
187                 SAFE_FREE(iface);
188         }
189
190         /* probe the kernel for interfaces */
191         total_probed = get_interfaces(ifaces, MAX_INTERFACES);
192
193         if (total_probed > 0) {
194                 probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
195         }
196
197         /* if we don't have a interfaces line then use all broadcast capable 
198            interfaces except loopback */
199         if (!ptr || !*ptr || !**ptr) {
200                 if (total_probed <= 0) {
201                         DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
202                         exit(1);
203                 }
204                 for (i=0;i<total_probed;i++) {
205                         if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
206                             probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
207                                 add_interface(probed_ifaces[i].ip, 
208                                               probed_ifaces[i].netmask);
209                         }
210                 }
211                 goto exit;
212         }
213
214         if (ptr) {
215                 while (*ptr) {
216                         interpret_interface(mem_ctx, *ptr);
217                         ptr++;
218                 }
219         }
220
221         if (!local_interfaces) {
222                 DEBUG(0,("WARNING: no network interfaces found\n"));
223         }
224         
225 exit:
226         talloc_destroy(mem_ctx);
227 }
228
229
230 /****************************************************************************
231 return True if the list of probed interfaces has changed
232 ****************************************************************************/
233 BOOL interfaces_changed(void)
234 {
235         int n;
236         struct iface_struct ifaces[MAX_INTERFACES];
237
238         n = get_interfaces(ifaces, MAX_INTERFACES);
239
240         if ((n > 0 )&& (n != total_probed ||
241             memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
242                 return True;
243         }
244         
245         return False;
246 }
247
248
249 /****************************************************************************
250   check if an IP is one of mine
251   **************************************************************************/
252 BOOL ismyip(struct in_addr ip)
253 {
254         struct interface *i;
255         for (i=local_interfaces;i;i=i->next)
256                 if (ip_equal(i->ip,ip)) return True;
257         return False;
258 }
259
260 /****************************************************************************
261   check if a packet is from a local (known) net
262   **************************************************************************/
263 BOOL is_local_net(struct in_addr from)
264 {
265         struct interface *i;
266         for (i=local_interfaces;i;i=i->next) {
267                 if((from.s_addr & i->nmask.s_addr) == 
268                    (i->ip.s_addr & i->nmask.s_addr))
269                         return True;
270         }
271         return False;
272 }
273
274 /****************************************************************************
275   how many interfaces do we have
276   **************************************************************************/
277 int iface_count(void)
278 {
279         int ret = 0;
280         struct interface *i;
281
282         for (i=local_interfaces;i;i=i->next)
283                 ret++;
284         return ret;
285 }
286
287 /****************************************************************************
288   return IP of the Nth interface
289   **************************************************************************/
290 struct in_addr *iface_n_ip(int n)
291 {
292         struct interface *i;
293   
294         for (i=local_interfaces;i && n;i=i->next)
295                 n--;
296
297         if (i) return &i->ip;
298         return NULL;
299 }
300
301 /****************************************************************************
302   return bcast of the Nth interface
303   **************************************************************************/
304 struct in_addr *iface_n_bcast(int n)
305 {
306         struct interface *i;
307   
308         for (i=local_interfaces;i && n;i=i->next)
309                 n--;
310
311         if (i) return &i->bcast;
312         return NULL;
313 }
314
315
316 /* these 3 functions return the ip/bcast/nmask for the interface
317    most appropriate for the given ip address. If they can't find
318    an appropriate interface they return the requested field of the
319    first known interface. */
320
321 struct in_addr *iface_ip(struct in_addr ip)
322 {
323         struct interface *i = iface_find(ip, True);
324         return(i ? &i->ip : &local_interfaces->ip);
325 }
326
327 /*
328   return True if a IP is directly reachable on one of our interfaces
329 */
330 BOOL iface_local(struct in_addr ip)
331 {
332         return iface_find(ip, True) ? True : False;
333 }