2 Unix SMB/Netbios implementation.
4 multiple interface handling
6 Copyright (C) Andrew Tridgell 1992-1998
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/>.
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 ****************************************************************************/
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 */
62 inm
->s_addr
= htonl (0xFF000000);
65 case 0x80000000: /* Class B addr */
67 inm
->s_addr
= htonl (0xFFFF0000);
70 case 0xC0000000: /* Class C addr */
71 inm
->s_addr
= htonl (0xFFFFFF00);
75 inm
->s_addr
= htonl (0xFFFFFFF0);
80 /****************************************************************************
81 get the broadcast address for our address
82 (troyer@saifr00.ateng.az.honeywell.com)
83 ****************************************************************************/
85 get_broadcast (struct in_addr
*if_ipaddr
, struct in_addr
*if_bcast
, struct in_addr
*if_nmask
)
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
);
100 while ((onbc
+ offbc
) < 32)
107 /* already found an off bit, so mask
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 ****************************************************************************/
138 interpret_interfaces (char *s
, struct interface
**interfaces
, const char *description
)
142 struct interface
*iface
;
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
, '/');
157 ip
= *interpret_addr2 (token
);
159 /* maybe we already have it listed */
162 for (i
= (*interfaces
); i
; i
= i
->next
)
163 if (ip_equal (ip
, i
->ip
))
169 iface
= (struct interface
*) malloc (sizeof (*iface
));
178 iface
->nmask
= *interpret_addr2 (p
);
180 iface
->nmask
.s_addr
= htonl (((ALLONES
>> atoi (p
)) ^ ALLONES
));
184 default_netmask (&iface
->nmask
, &iface
->ip
);
186 iface
->bcast
.s_addr
= MKBCADDR (iface
->ip
.s_addr
, iface
->nmask
.s_addr
);
191 (*interfaces
) = iface
;
195 last_iface
->next
= 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
)));
206 /* setup a default interface */
207 iface
= (struct interface
*) malloc (sizeof (*iface
));
215 iface
->ip
= default_ip
;
219 get_myname (NULL
, &iface
->ip
);
224 iface
->bcast
= default_bcast
;
228 get_broadcast (&iface
->ip
, &iface
->bcast
, &iface
->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
)));
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 ****************************************************************************/
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 **************************************************************************/
266 iface_set_default (char *ip
, char *bcast
, char *nmask
)
271 default_ip
= *interpret_addr2 (ip
);
277 default_bcast
= *interpret_addr2 (bcast
);
283 default_nmask
= *interpret_addr2 (nmask
);
288 /****************************************************************************
289 check if an IP is one of mine
290 **************************************************************************/
292 ismyip (struct in_addr ip
)
295 for (i
= local_interfaces
; i
; i
= i
->next
)
296 if (ip_equal (i
->ip
, ip
))
301 /****************************************************************************
302 check if a packet is from a local (known) net
303 **************************************************************************/
305 is_local_net (struct in_addr from
)
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
))
314 /****************************************************************************
315 how many interfaces do we have
316 **************************************************************************/
323 for (i
= local_interfaces
; i
; i
= i
->next
)
328 /****************************************************************************
329 True if we have two or more interfaces.
330 **************************************************************************/
332 we_are_multihomed (void)
334 static int multi
= -1;
337 multi
= (iface_count () > 1 ? True
: False
);
342 /****************************************************************************
343 return the Nth interface
344 **************************************************************************/
346 get_interface (int n
)
350 for (i
= local_interfaces
; i
&& n
; i
= i
->next
)
358 /****************************************************************************
359 return IP of the Nth interface
360 **************************************************************************/
366 for (i
= local_interfaces
; i
&& n
; i
= i
->next
)
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
)
382 return local_interfaces
;
384 for (i
= local_interfaces
; i
; i
= i
->next
)
385 if (same_net (i
->ip
, ip
, i
->nmask
))
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 **************************************************************************/
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
));
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. */
421 iface_bcast (struct in_addr ip
)
423 struct interface
*i
= iface_find (ip
);
424 return (i
? &i
->bcast
: &local_interfaces
->bcast
);
428 iface_ip (struct in_addr ip
)
430 struct interface
*i
= iface_find (ip
);
431 return (i
? &i
->ip
: &local_interfaces
->ip
);