2 Unix SMB/CIFS implementation.
3 multiple interface handling
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
23 static struct iface_struct
*probed_ifaces
;
24 static int total_probed
;
26 struct in_addr allones_ip
;
27 struct in_addr loopback_ip
;
29 static struct interface
*local_interfaces
;
31 #define ALLONES ((uint32)0xFFFFFFFF)
32 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
33 #define MKNETADDR(_IP, _NM) (_IP & _NM)
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
)
41 if (is_zero_ip(ip
)) return local_interfaces
;
43 for (i
=local_interfaces
;i
;i
=i
->next
)
45 if (same_net(i
->ip
,ip
,i
->nmask
)) return i
;
46 } else if ((i
->ip
).s_addr
== ip
.s_addr
) return i
;
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
)
57 struct interface
*iface
;
58 if (iface_find(ip
, False
)) {
59 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip
)));
63 #if !defined(__s390__)
64 if (ip_equal(nmask
, allones_ip
)) {
65 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip
)));
70 iface
= SMB_MALLOC_P(struct interface
);
77 iface
->bcast
.s_addr
= MKBCADDR(iface
->ip
.s_addr
, iface
->nmask
.s_addr
);
79 DLIST_ADD(local_interfaces
, iface
);
81 DEBUG(2,("added interface ip=%s ",inet_ntoa(iface
->ip
)));
82 DEBUG(2,("bcast=%s ",inet_ntoa(iface
->bcast
)));
83 DEBUG(2,("nmask=%s\n",inet_ntoa(iface
->nmask
)));
88 /****************************************************************************
89 interpret a single element from a interfaces= config line
91 This handles the following different forms:
93 1) wildcard interface name
98 ****************************************************************************/
99 static void interpret_interface(char *token
)
101 struct in_addr ip
, nmask
;
108 /* first check if it is an interface name */
109 for (i
=0;i
<total_probed
;i
++) {
110 if (gen_fnmatch(token
, probed_ifaces
[i
].name
) == 0) {
111 add_interface(probed_ifaces
[i
].ip
,
112 probed_ifaces
[i
].netmask
);
118 /* maybe it is a DNS name */
119 p
= strchr_m(token
,'/');
121 ip
= *interpret_addr2(token
);
122 for (i
=0;i
<total_probed
;i
++) {
123 if (ip
.s_addr
== probed_ifaces
[i
].ip
.s_addr
&&
124 !ip_equal(allones_ip
, probed_ifaces
[i
].netmask
)) {
125 add_interface(probed_ifaces
[i
].ip
,
126 probed_ifaces
[i
].netmask
);
130 DEBUG(2,("can't determine netmask for %s\n", token
));
134 /* parse it into an IP address/netmasklength pair */
136 ip
= *interpret_addr2(token
);
140 nmask
= *interpret_addr2(p
);
142 nmask
.s_addr
= htonl(((ALLONES
>> atoi(p
)) ^ ALLONES
));
145 /* maybe the first component was a broadcast address */
146 if (ip
.s_addr
== MKBCADDR(ip
.s_addr
, nmask
.s_addr
) ||
147 ip
.s_addr
== MKNETADDR(ip
.s_addr
, nmask
.s_addr
)) {
148 for (i
=0;i
<total_probed
;i
++) {
149 if (same_net(ip
, probed_ifaces
[i
].ip
, nmask
)) {
150 add_interface(probed_ifaces
[i
].ip
, nmask
);
154 DEBUG(2,("Can't determine ip for broadcast address %s\n", token
));
158 add_interface(ip
, nmask
);
162 /****************************************************************************
163 load the list of network interfaces
164 ****************************************************************************/
165 void load_interfaces(void)
169 struct iface_struct ifaces
[MAX_INTERFACES
];
171 ptr
= lp_interfaces();
173 allones_ip
= *interpret_addr2("255.255.255.255");
174 loopback_ip
= *interpret_addr2("127.0.0.1");
176 SAFE_FREE(probed_ifaces
);
178 /* dump the current interfaces if any */
179 while (local_interfaces
) {
180 struct interface
*iface
= local_interfaces
;
181 DLIST_REMOVE(local_interfaces
, local_interfaces
);
182 ZERO_STRUCTPN(iface
);
186 /* probe the kernel for interfaces */
187 total_probed
= get_interfaces(ifaces
, MAX_INTERFACES
);
189 if (total_probed
> 0) {
190 probed_ifaces
= (struct iface_struct
*)memdup(ifaces
, sizeof(ifaces
[0])*total_probed
);
191 if (!probed_ifaces
) {
192 DEBUG(0,("ERROR: memdup failed\n"));
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"));
204 for (i
=0;i
<total_probed
;i
++) {
206 #if !defined(__s390__)
207 probed_ifaces
[i
].netmask
.s_addr
!= allones_ip
.s_addr
&&
209 probed_ifaces
[i
].ip
.s_addr
!= loopback_ip
.s_addr
) {
210 add_interface(probed_ifaces
[i
].ip
,
211 probed_ifaces
[i
].netmask
);
219 char *ptr_cpy
= SMB_STRDUP(*ptr
);
221 interpret_interface(ptr_cpy
);
228 if (!local_interfaces
) {
229 DEBUG(0,("WARNING: no network interfaces found\n"));
234 void gfree_interfaces(void)
236 while (local_interfaces
) {
237 struct interface
*iface
= local_interfaces
;
238 DLIST_REMOVE(local_interfaces
, local_interfaces
);
239 ZERO_STRUCTPN(iface
);
243 SAFE_FREE(probed_ifaces
);
246 /****************************************************************************
247 return True if the list of probed interfaces has changed
248 ****************************************************************************/
249 BOOL
interfaces_changed(void)
252 struct iface_struct ifaces
[MAX_INTERFACES
];
254 n
= get_interfaces(ifaces
, MAX_INTERFACES
);
256 if ((n
> 0 )&& (n
!= total_probed
||
257 memcmp(ifaces
, probed_ifaces
, sizeof(ifaces
[0])*n
))) {
265 /****************************************************************************
266 check if an IP is one of mine
267 **************************************************************************/
268 BOOL
ismyip(struct in_addr ip
)
271 for (i
=local_interfaces
;i
;i
=i
->next
)
272 if (ip_equal(i
->ip
,ip
)) return True
;
276 /****************************************************************************
277 check if a packet is from a local (known) net
278 **************************************************************************/
279 BOOL
is_local_net(struct in_addr from
)
282 for (i
=local_interfaces
;i
;i
=i
->next
) {
283 if((from
.s_addr
& i
->nmask
.s_addr
) ==
284 (i
->ip
.s_addr
& i
->nmask
.s_addr
))
290 /****************************************************************************
291 how many interfaces do we have
292 **************************************************************************/
293 int iface_count(void)
298 for (i
=local_interfaces
;i
;i
=i
->next
)
303 /****************************************************************************
304 return the Nth interface
305 **************************************************************************/
306 struct interface
*get_interface(int n
)
310 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
317 /****************************************************************************
318 return IP of the Nth interface
319 **************************************************************************/
320 struct in_addr
*iface_n_ip(int n
)
324 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
327 if (i
) return &i
->ip
;
331 /****************************************************************************
332 return bcast of the Nth interface
333 **************************************************************************/
334 struct in_addr
*iface_n_bcast(int n
)
338 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
341 if (i
) return &i
->bcast
;
346 /* these 3 functions return the ip/bcast/nmask for the interface
347 most appropriate for the given ip address. If they can't find
348 an appropriate interface they return the requested field of the
349 first known interface. */
351 struct in_addr
*iface_ip(struct in_addr ip
)
353 struct interface
*i
= iface_find(ip
, True
);
354 return(i
? &i
->ip
: &local_interfaces
->ip
);
358 return True if a IP is directly reachable on one of our interfaces
360 BOOL
iface_local(struct in_addr ip
)
362 return iface_find(ip
, True
) ? True
: False
;