Code indentation.
[midnight-commander.git] / src / vfs / smbfs / helpers / lib / interface.c
blob9244f6a9d088fa9597aaf2f686e5765da206304f
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 multiple interface handling
6 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) 2011
9 The Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "includes.h"
29 extern int DEBUGLEVEL;
31 struct in_addr ipzero;
32 struct in_addr allones_ip;
33 struct in_addr loopback_ip;
34 static struct in_addr default_ip;
35 static struct in_addr default_bcast;
36 static struct in_addr default_nmask;
37 static BOOL got_ip = False;
38 static BOOL got_bcast = False;
39 static BOOL got_nmask = False;
41 static struct interface *local_interfaces = NULL;
43 struct interface *last_iface;
45 #define ALLONES ((uint32)0xFFFFFFFF)
46 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
47 /****************************************************************************
48 calculate the default netmask for an address
49 ****************************************************************************/
50 static void
51 default_netmask (struct in_addr *inm, struct in_addr *iad)
54 ** Guess a netmask based on the class of the IP address given.
56 switch ((ntohl (iad->s_addr) & 0xE0000000))
58 case 0x00000000: /* Class A addr */
59 case 0x20000000:
60 case 0x40000000:
61 case 0x60000000:
62 inm->s_addr = htonl (0xFF000000);
63 break;
65 case 0x80000000: /* Class B addr */
66 case 0xA0000000:
67 inm->s_addr = htonl (0xFFFF0000);
68 break;
70 case 0xC0000000: /* Class C addr */
71 inm->s_addr = htonl (0xFFFFFF00);
72 break;
74 default: /* ??? */
75 inm->s_addr = htonl (0xFFFFFFF0);
80 /****************************************************************************
81 get the broadcast address for our address
82 (troyer@saifr00.ateng.az.honeywell.com)
83 ****************************************************************************/
84 static void
85 get_broadcast (struct in_addr *if_ipaddr, struct in_addr *if_bcast, struct in_addr *if_nmask)
87 uint32 nm;
88 short onbc;
89 short offbc;
91 /* get a default netmask and broadcast */
92 default_netmask (if_nmask, if_ipaddr);
94 get_netmask (if_ipaddr, if_nmask);
96 /* sanity check on the netmask */
97 nm = ntohl (if_nmask->s_addr);
98 onbc = 0;
99 offbc = 0;
100 while ((onbc + offbc) < 32)
102 if (nm & 0x80000000)
104 onbc++;
105 if (offbc)
107 /* already found an off bit, so mask
108 is wrong */
109 onbc = 34;
112 else
114 offbc++;
116 nm <<= 1;
118 if ((onbc < 8) || (onbc == 34))
120 DEBUG (0, ("Impossible netmask %s - using defaults\n", inet_ntoa (*if_nmask)));
121 default_netmask (if_nmask, if_ipaddr);
124 /* derive the broadcast assuming a 1's broadcast, as this is what
125 all MS operating systems do, we have to comply even if the unix
126 box is setup differently */
127 if_bcast->s_addr = MKBCADDR (if_ipaddr->s_addr, if_nmask->s_addr);
129 DEBUG (4, ("Derived broadcast address %s\n", inet_ntoa (*if_bcast)));
134 /****************************************************************************
135 load a list of network interfaces
136 ****************************************************************************/
137 static void
138 interpret_interfaces (char *s, struct interface **interfaces, const char *description)
140 char *ptr;
141 fstring token;
142 struct interface *iface;
143 struct in_addr ip;
145 ptr = s;
146 ipzero = *interpret_addr2 ("0.0.0.0");
147 allones_ip = *interpret_addr2 ("255.255.255.255");
148 loopback_ip = *interpret_addr2 ("127.0.0.1");
150 while (next_token (&ptr, token, NULL, sizeof (token)))
152 /* parse it into an IP address/netmasklength pair */
153 char *p = strchr (token, '/');
154 if (p)
155 *p++ = 0;
157 ip = *interpret_addr2 (token);
159 /* maybe we already have it listed */
161 struct interface *i;
162 for (i = (*interfaces); i; i = i->next)
163 if (ip_equal (ip, i->ip))
164 break;
165 if (i)
166 continue;
169 iface = (struct interface *) malloc (sizeof (*iface));
170 if (!iface)
171 return;
173 iface->ip = ip;
175 if (p)
177 if (strlen (p) > 2)
178 iface->nmask = *interpret_addr2 (p);
179 else
180 iface->nmask.s_addr = htonl (((ALLONES >> atoi (p)) ^ ALLONES));
182 else
184 default_netmask (&iface->nmask, &iface->ip);
186 iface->bcast.s_addr = MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr);
187 iface->next = NULL;
189 if (!(*interfaces))
191 (*interfaces) = iface;
193 else
195 last_iface->next = iface;
197 last_iface = iface;
198 DEBUG (2, ("Added %s ip=%s ", description, inet_ntoa (iface->ip)));
199 DEBUG (2, ("bcast=%s ", inet_ntoa (iface->bcast)));
200 DEBUG (2, ("nmask=%s\n", inet_ntoa (iface->nmask)));
203 if (*interfaces)
204 return;
206 /* setup a default interface */
207 iface = (struct interface *) malloc (sizeof (*iface));
208 if (!iface)
209 return;
211 iface->next = NULL;
213 if (got_ip)
215 iface->ip = default_ip;
217 else
219 get_myname (NULL, &iface->ip);
222 if (got_bcast)
224 iface->bcast = default_bcast;
226 else
228 get_broadcast (&iface->ip, &iface->bcast, &iface->nmask);
231 if (got_nmask)
233 iface->nmask = default_nmask;
234 iface->bcast.s_addr = MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr);
237 if (iface->bcast.s_addr != MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr))
239 DEBUG (2, ("Warning: inconsistant interface %s\n", inet_ntoa (iface->ip)));
242 iface->next = NULL;
243 (*interfaces) = last_iface = iface;
245 DEBUG (2, ("Added interface ip=%s ", inet_ntoa (iface->ip)));
246 DEBUG (2, ("bcast=%s ", inet_ntoa (iface->bcast)));
247 DEBUG (2, ("nmask=%s\n", inet_ntoa (iface->nmask)));
251 /****************************************************************************
252 load the remote and local interfaces
253 ****************************************************************************/
254 void
255 load_interfaces (void)
257 /* add the machine's interfaces to local interface structure */
258 interpret_interfaces (lp_interfaces (), &local_interfaces, "interface");
262 /****************************************************************************
263 override the defaults
264 **************************************************************************/
265 void
266 iface_set_default (char *ip, char *bcast, char *nmask)
268 if (ip)
270 got_ip = True;
271 default_ip = *interpret_addr2 (ip);
274 if (bcast)
276 got_bcast = True;
277 default_bcast = *interpret_addr2 (bcast);
280 if (nmask)
282 got_nmask = True;
283 default_nmask = *interpret_addr2 (nmask);
288 /****************************************************************************
289 check if an IP is one of mine
290 **************************************************************************/
291 BOOL
292 ismyip (struct in_addr ip)
294 struct interface *i;
295 for (i = local_interfaces; i; i = i->next)
296 if (ip_equal (i->ip, ip))
297 return True;
298 return False;
301 /****************************************************************************
302 check if a packet is from a local (known) net
303 **************************************************************************/
304 BOOL
305 is_local_net (struct in_addr from)
307 struct interface *i;
308 for (i = local_interfaces; i; i = i->next)
309 if ((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
310 return True;
311 return False;
314 /****************************************************************************
315 how many interfaces do we have
316 **************************************************************************/
318 iface_count (void)
320 int ret = 0;
321 struct interface *i;
323 for (i = local_interfaces; i; i = i->next)
324 ret++;
325 return ret;
328 /****************************************************************************
329 True if we have two or more interfaces.
330 **************************************************************************/
331 BOOL
332 we_are_multihomed (void)
334 static int multi = -1;
336 if (multi == -1)
337 multi = (iface_count () > 1 ? True : False);
339 return multi;
342 /****************************************************************************
343 return the Nth interface
344 **************************************************************************/
345 struct interface *
346 get_interface (int n)
348 struct interface *i;
350 for (i = local_interfaces; i && n; i = i->next)
351 n--;
353 if (i)
354 return i;
355 return NULL;
358 /****************************************************************************
359 return IP of the Nth interface
360 **************************************************************************/
361 struct in_addr *
362 iface_n_ip (int n)
364 struct interface *i;
366 for (i = local_interfaces; i && n; i = i->next)
367 n--;
369 if (i)
370 return &i->ip;
371 return NULL;
374 /****************************************************************************
375 Try and find an interface that matches an ip. If we cannot, return NULL
376 **************************************************************************/
377 static struct interface *
378 iface_find (struct in_addr ip)
380 struct interface *i;
381 if (zero_ip (ip))
382 return local_interfaces;
384 for (i = local_interfaces; i; i = i->next)
385 if (same_net (i->ip, ip, i->nmask))
386 return i;
388 return NULL;
392 /****************************************************************************
393 this function provides a simple hash of the configured interfaces. It is
394 used to detect a change in interfaces to tell us whether to discard
395 the current wins.dat file.
396 Note that the result is independent of the order of the interfaces
397 **************************************************************************/
398 unsigned
399 iface_hash (void)
401 unsigned ret = 0;
402 struct interface *i;
404 for (i = local_interfaces; i; i = i->next)
406 unsigned x1 = (unsigned) str_checksum (inet_ntoa (i->ip));
407 unsigned x2 = (unsigned) str_checksum (inet_ntoa (i->nmask));
408 ret ^= (x1 ^ x2);
411 return ret;
415 /* these 3 functions return the ip/bcast/nmask for the interface
416 most appropriate for the given ip address. If they can't find
417 an appropriate interface they return the requested field of the
418 first known interface. */
420 struct in_addr *
421 iface_bcast (struct in_addr ip)
423 struct interface *i = iface_find (ip);
424 return (i ? &i->bcast : &local_interfaces->bcast);
427 struct in_addr *
428 iface_ip (struct in_addr ip)
430 struct interface *i = iface_find (ip);
431 return (i ? &i->ip : &local_interfaces->ip);