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(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 */
134 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 char *ptr_cpy = strdup(*ptr);
212 interpret_interface(ptr_cpy);
219 if (!local_interfaces) {
220 DEBUG(0,("WARNING: no network interfaces found\n"));
225 /****************************************************************************
226 return True if the list of probed interfaces has changed
227 ****************************************************************************/
228 BOOL interfaces_changed(void)
231 struct iface_struct ifaces[MAX_INTERFACES];
233 n = get_interfaces(ifaces, MAX_INTERFACES);
235 if ((n > 0 )&& (n != total_probed ||
236 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
244 /****************************************************************************
245 check if an IP is one of mine
246 **************************************************************************/
247 BOOL ismyip(struct in_addr ip)
250 for (i=local_interfaces;i;i=i->next)
251 if (ip_equal(i->ip,ip)) return True;
255 /****************************************************************************
256 check if a packet is from a local (known) net
257 **************************************************************************/
258 BOOL is_local_net(struct in_addr from)
261 for (i=local_interfaces;i;i=i->next) {
262 if((from.s_addr & i->nmask.s_addr) ==
263 (i->ip.s_addr & i->nmask.s_addr))
269 /****************************************************************************
270 how many interfaces do we have
271 **************************************************************************/
272 int iface_count(void)
277 for (i=local_interfaces;i;i=i->next)
282 /****************************************************************************
283 return the Nth interface
284 **************************************************************************/
285 struct interface *get_interface(int n)
289 for (i=local_interfaces;i && n;i=i->next)
296 /****************************************************************************
297 return IP of the Nth interface
298 **************************************************************************/
299 struct in_addr *iface_n_ip(int n)
303 for (i=local_interfaces;i && n;i=i->next)
306 if (i) return &i->ip;
310 /****************************************************************************
311 return bcast of the Nth interface
312 **************************************************************************/
313 struct in_addr *iface_n_bcast(int n)
317 for (i=local_interfaces;i && n;i=i->next)
320 if (i) return &i->bcast;
325 /* these 3 functions return the ip/bcast/nmask for the interface
326 most appropriate for the given ip address. If they can't find
327 an appropriate interface they return the requested field of the
328 first known interface. */
330 struct in_addr *iface_ip(struct in_addr ip)
332 struct interface *i = iface_find(ip, True);
333 return(i ? &i->ip : &local_interfaces->ip);
337 return True if a IP is directly reachable on one of our interfaces
339 BOOL iface_local(struct in_addr ip)
341 return iface_find(ip, True) ? True : False;