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 (ip_equal(nmask
, allones_ip
)) {
64 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip
)));
68 iface
= (struct interface
*)malloc(sizeof(*iface
));
75 iface
->bcast
.s_addr
= MKBCADDR(iface
->ip
.s_addr
, iface
->nmask
.s_addr
);
77 DLIST_ADD(local_interfaces
, iface
);
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
)));
86 /****************************************************************************
87 interpret a single element from a interfaces= config line
89 This handles the following different forms:
91 1) wildcard interface name
96 ****************************************************************************/
97 static void interpret_interface(const char *token
)
99 struct in_addr ip
, nmask
;
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
);
116 /* maybe it is a DNS name */
117 p
= strchr_m(token
,'/');
119 ip
= *interpret_addr2(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
);
128 DEBUG(2,("can't determine netmask for %s\n", token
));
132 /* parse it into an IP address/netmasklength pair */
135 ip
= *interpret_addr2(token
);
138 nmask
= *interpret_addr2(p
);
140 nmask
.s_addr
= htonl(((ALLONES
>> atoi(p
)) ^ ALLONES
));
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
);
152 DEBUG(2,("Can't determine ip for broadcast address %s\n", token
));
156 add_interface(ip
, nmask
);
160 /****************************************************************************
161 load the list of network interfaces
162 ****************************************************************************/
163 void load_interfaces(void)
167 struct iface_struct ifaces
[MAX_INTERFACES
];
169 ptr
= lp_interfaces();
171 allones_ip
= *interpret_addr2("255.255.255.255");
172 loopback_ip
= *interpret_addr2("127.0.0.1");
174 SAFE_FREE(probed_ifaces
);
176 /* dump the current interfaces if any */
177 while (local_interfaces
) {
178 struct interface
*iface
= local_interfaces
;
179 DLIST_REMOVE(local_interfaces
, local_interfaces
);
180 ZERO_STRUCTPN(iface
);
184 /* probe the kernel for interfaces */
185 total_probed
= get_interfaces(ifaces
, MAX_INTERFACES
);
187 if (total_probed
> 0) {
188 probed_ifaces
= memdup(ifaces
, sizeof(ifaces
[0])*total_probed
);
191 /* if we don't have a interfaces line then use all broadcast capable
192 interfaces except loopback */
193 if (!ptr
|| !*ptr
|| !**ptr
) {
194 if (total_probed
<= 0) {
195 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
198 for (i
=0;i
<total_probed
;i
++) {
199 if (probed_ifaces
[i
].netmask
.s_addr
!= allones_ip
.s_addr
&&
200 probed_ifaces
[i
].ip
.s_addr
!= loopback_ip
.s_addr
) {
201 add_interface(probed_ifaces
[i
].ip
,
202 probed_ifaces
[i
].netmask
);
210 interpret_interface(*ptr
);
215 if (!local_interfaces
) {
216 DEBUG(0,("WARNING: no network interfaces found\n"));
221 /****************************************************************************
222 return True if the list of probed interfaces has changed
223 ****************************************************************************/
224 BOOL
interfaces_changed(void)
227 struct iface_struct ifaces
[MAX_INTERFACES
];
229 n
= get_interfaces(ifaces
, MAX_INTERFACES
);
231 if ((n
> 0 )&& (n
!= total_probed
||
232 memcmp(ifaces
, probed_ifaces
, sizeof(ifaces
[0])*n
))) {
240 /****************************************************************************
241 check if an IP is one of mine
242 **************************************************************************/
243 BOOL
ismyip(struct in_addr ip
)
246 for (i
=local_interfaces
;i
;i
=i
->next
)
247 if (ip_equal(i
->ip
,ip
)) return True
;
251 /****************************************************************************
252 check if a packet is from a local (known) net
253 **************************************************************************/
254 BOOL
is_local_net(struct in_addr from
)
257 for (i
=local_interfaces
;i
;i
=i
->next
) {
258 if((from
.s_addr
& i
->nmask
.s_addr
) ==
259 (i
->ip
.s_addr
& i
->nmask
.s_addr
))
265 /****************************************************************************
266 how many interfaces do we have
267 **************************************************************************/
268 int iface_count(void)
273 for (i
=local_interfaces
;i
;i
=i
->next
)
278 /****************************************************************************
279 return the Nth interface
280 **************************************************************************/
281 struct interface
*get_interface(int n
)
285 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
292 /****************************************************************************
293 return IP of the Nth interface
294 **************************************************************************/
295 struct in_addr
*iface_n_ip(int n
)
299 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
302 if (i
) return &i
->ip
;
306 /****************************************************************************
307 return bcast of the Nth interface
308 **************************************************************************/
309 struct in_addr
*iface_n_bcast(int n
)
313 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
316 if (i
) return &i
->bcast
;
321 /* these 3 functions return the ip/bcast/nmask for the interface
322 most appropriate for the given ip address. If they can't find
323 an appropriate interface they return the requested field of the
324 first known interface. */
326 struct in_addr
*iface_ip(struct in_addr ip
)
328 struct interface
*i
= iface_find(ip
, True
);
329 return(i
? &i
->ip
: &local_interfaces
->ip
);
333 return True if a IP is directly reachable on one of our interfaces
335 BOOL
iface_local(struct in_addr ip
)
337 return iface_find(ip
, True
) ? True
: False
;