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.
22 #include "system/network.h"
23 #include "lib/netif/netif.h"
24 #include "dlinklist.h"
26 static struct iface_struct *probed_ifaces;
27 static int total_probed;
29 static struct ipv4_addr allones_ip;
30 struct ipv4_addr loopback_ip;
32 /* used for network interfaces */
34 struct interface *next, *prev;
36 struct ipv4_addr bcast;
37 struct ipv4_addr nmask;
40 static struct interface *local_interfaces;
42 #define ALLONES ((uint32_t)0xFFFFFFFF)
43 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
44 #define MKNETADDR(_IP, _NM) (_IP & _NM)
46 static struct ipv4_addr tov4(struct in_addr in)
53 /****************************************************************************
54 Try and find an interface that matches an ip. If we cannot, return NULL
55 **************************************************************************/
56 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
59 if (is_zero_ip(tov4(ip))) return local_interfaces;
61 for (i=local_interfaces;i;i=i->next)
63 if (same_net(i->ip,tov4(ip),i->nmask)) return i;
64 } else if (i->ip.addr == ip.s_addr) return i;
70 /****************************************************************************
71 add an interface to the linked list of interfaces
72 ****************************************************************************/
73 static void add_interface(struct in_addr ip, struct in_addr nmask)
75 struct interface *iface;
76 if (iface_find(ip, False)) {
77 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
81 if (nmask.s_addr == allones_ip.addr) {
82 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
86 iface = malloc_p(struct interface);
92 iface->nmask = tov4(nmask);
93 iface->bcast.addr = MKBCADDR(iface->ip.addr, iface->nmask.addr);
95 DLIST_ADD(local_interfaces, iface);
97 DEBUG(2,("added interface ip=%s ",sys_inet_ntoa(iface->ip)));
98 DEBUG(2,("bcast=%s ",sys_inet_ntoa(iface->bcast)));
99 DEBUG(2,("nmask=%s\n",sys_inet_ntoa(iface->nmask)));
104 /****************************************************************************
105 interpret a single element from a interfaces= config line
107 This handles the following different forms:
109 1) wildcard interface name
114 ****************************************************************************/
115 static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token)
117 struct in_addr ip, nmask;
124 /* first check if it is an interface name */
125 for (i=0;i<total_probed;i++) {
126 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
127 add_interface(probed_ifaces[i].ip,
128 probed_ifaces[i].netmask);
134 /* maybe it is a DNS name */
135 p = strchr_m(token,'/');
137 ip.s_addr = interpret_addr2(token).addr;
138 for (i=0;i<total_probed;i++) {
139 if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
140 allones_ip.addr != probed_ifaces[i].netmask.s_addr) {
141 add_interface(probed_ifaces[i].ip,
142 probed_ifaces[i].netmask);
146 DEBUG(2,("can't determine netmask for %s\n", token));
150 /* parse it into an IP address/netmasklength pair */
153 ip.s_addr = interpret_addr2(token).addr;
156 nmask.s_addr = interpret_addr2(p).addr;
158 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
161 /* maybe the first component was a broadcast address */
162 if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
163 ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
164 for (i=0;i<total_probed;i++) {
165 if (same_net(tov4(ip), tov4(probed_ifaces[i].ip), tov4(nmask))) {
166 add_interface(probed_ifaces[i].ip, nmask);
170 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
174 add_interface(ip, nmask);
178 /****************************************************************************
179 load the list of network interfaces
180 ****************************************************************************/
181 void load_interfaces(void)
185 struct iface_struct ifaces[MAX_INTERFACES];
188 ptr = lp_interfaces();
189 mem_ctx = talloc_init("load_interfaces");
191 DEBUG(2,("no memory to load interfaces \n"));
195 allones_ip = interpret_addr2("255.255.255.255");
196 loopback_ip = interpret_addr2("127.0.0.1");
198 SAFE_FREE(probed_ifaces);
200 /* dump the current interfaces if any */
201 while (local_interfaces) {
202 struct interface *iface = local_interfaces;
203 DLIST_REMOVE(local_interfaces, local_interfaces);
204 ZERO_STRUCTPN(iface);
208 /* probe the kernel for interfaces */
209 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
211 if (total_probed > 0) {
212 probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
215 /* if we don't have a interfaces line then use all broadcast capable
216 interfaces except loopback */
217 if (!ptr || !*ptr || !**ptr) {
218 if (total_probed <= 0) {
219 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
222 for (i=0;i<total_probed;i++) {
223 if (probed_ifaces[i].netmask.s_addr != allones_ip.addr &&
224 probed_ifaces[i].ip.s_addr != loopback_ip.addr) {
225 add_interface(probed_ifaces[i].ip,
226 probed_ifaces[i].netmask);
234 interpret_interface(mem_ctx, *ptr);
239 if (!local_interfaces) {
240 DEBUG(0,("WARNING: no network interfaces found\n"));
244 talloc_free(mem_ctx);
248 /****************************************************************************
249 return True if the list of probed interfaces has changed
250 ****************************************************************************/
251 BOOL interfaces_changed(void)
254 struct iface_struct ifaces[MAX_INTERFACES];
256 n = get_interfaces(ifaces, MAX_INTERFACES);
258 if ((n > 0 )&& (n != total_probed ||
259 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
267 /****************************************************************************
268 check if an IP is one of mine
269 **************************************************************************/
270 BOOL ismyip(struct ipv4_addr ip)
273 for (i=local_interfaces;i;i=i->next)
274 if (ipv4_equal(i->ip,ip)) return True;
278 /****************************************************************************
279 check if a packet is from a local (known) net
280 **************************************************************************/
281 BOOL is_local_net(struct ipv4_addr from)
284 for (i=local_interfaces;i;i=i->next) {
285 if((from.addr & i->nmask.addr) ==
286 (i->ip.addr & i->nmask.addr))
292 /****************************************************************************
293 how many interfaces do we have
294 **************************************************************************/
295 int iface_count(void)
300 for (i=local_interfaces;i;i=i->next)
305 /****************************************************************************
306 return IP of the Nth interface
307 **************************************************************************/
308 struct ipv4_addr *iface_n_ip(int n)
312 for (i=local_interfaces;i && n;i=i->next)
315 if (i) return &i->ip;
319 /****************************************************************************
320 return bcast of the Nth interface
321 **************************************************************************/
322 struct ipv4_addr *iface_n_bcast(int n)
326 for (i=local_interfaces;i && n;i=i->next)
329 if (i) return &i->bcast;
334 /* these 3 functions return the ip/bcast/nmask for the interface
335 most appropriate for the given ip address. If they can't find
336 an appropriate interface they return the requested field of the
337 first known interface. */
339 struct ipv4_addr *iface_ip(struct ipv4_addr ip)
344 i = iface_find(in, True);
345 return(i ? &i->ip : &local_interfaces->ip);
349 return True if a IP is directly reachable on one of our interfaces
351 BOOL iface_local(struct ipv4_addr ip)
355 return iface_find(in, True) ? True : False;