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 3 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, see <http://www.gnu.org/licenses/>.
22 static struct iface_struct *probed_ifaces;
23 static int total_probed;
25 struct in_addr allones_ip;
26 struct in_addr loopback_ip;
28 static struct interface *local_interfaces;
30 #define ALLONES ((uint32)0xFFFFFFFF)
31 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
32 #define MKNETADDR(_IP, _NM) (_IP & _NM)
34 /****************************************************************************
35 Try and find an interface that matches an ip. If we cannot, return NULL.
36 **************************************************************************/
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;
51 /****************************************************************************
52 Add an interface to the linked list of interfaces.
53 ****************************************************************************/
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",
71 iface = SMB_MALLOC_P(struct interface);
78 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
80 DLIST_ADD(local_interfaces, iface);
82 DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
83 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
84 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
87 /****************************************************************************
88 Interpret a single element from a interfaces= config line.
90 This handles the following different forms:
92 1) wildcard interface name
97 ****************************************************************************/
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].iface_addr.ip,
112 probed_ifaces[i].iface_netmask.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].iface_addr.ip.s_addr
124 && !ip_equal(allones_ip,
125 probed_ifaces[i].iface_netmask.netmask)) {
126 add_interface(probed_ifaces[i].iface_addr.ip,
127 probed_ifaces[i].iface_netmask.netmask);
131 DEBUG(2,("can't determine netmask for %s\n", token));
135 /* parse it into an IP address/netmasklength pair */
137 ip = *interpret_addr2(token);
141 nmask = *interpret_addr2(p);
143 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
146 /* maybe the first component was a broadcast address */
147 if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
148 ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
149 for (i=0;i<total_probed;i++) {
150 if (same_net(ip, probed_ifaces[i].iface_addr.ip,
152 add_interface(probed_ifaces[i].iface_addr.ip,
157 DEBUG(2,("Can't determine ip for broadcast address %s\n",
162 add_interface(ip, nmask);
165 /****************************************************************************
166 Load the list of network interfaces.
167 ****************************************************************************/
169 void load_interfaces(void)
173 struct iface_struct ifaces[MAX_INTERFACES];
175 ptr = lp_interfaces();
177 allones_ip = *interpret_addr2("255.255.255.255");
178 loopback_ip = *interpret_addr2("127.0.0.1");
180 SAFE_FREE(probed_ifaces);
182 /* dump the current interfaces if any */
183 while (local_interfaces) {
184 struct interface *iface = local_interfaces;
185 DLIST_REMOVE(local_interfaces, local_interfaces);
186 ZERO_STRUCTPN(iface);
190 /* probe the kernel for interfaces */
191 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
193 if (total_probed > 0) {
194 probed_ifaces = (struct iface_struct *)memdup(ifaces,
195 sizeof(ifaces[0])*total_probed);
196 if (!probed_ifaces) {
197 DEBUG(0,("ERROR: memdup failed\n"));
202 /* if we don't have a interfaces line then use all broadcast capable
203 interfaces except loopback */
204 if (!ptr || !*ptr || !**ptr) {
205 if (total_probed <= 0) {
206 DEBUG(0,("ERROR: Could not determine network "
207 "interfaces, you must use a interfaces config line\n"));
210 for (i=0;i<total_probed;i++) {
212 #if !defined(__s390__)
213 probed_ifaces[i].iface_netmask.netmask.s_addr !=
216 probed_ifaces[i].iface_addr.ip.s_addr !=
217 loopback_ip.s_addr) {
218 add_interface(probed_ifaces[i].iface_addr.ip,
219 probed_ifaces[i].iface_netmask.netmask);
227 char *ptr_cpy = SMB_STRDUP(*ptr);
229 interpret_interface(ptr_cpy);
236 if (!local_interfaces) {
237 DEBUG(0,("WARNING: no network interfaces found\n"));
242 void gfree_interfaces(void)
244 while (local_interfaces) {
245 struct interface *iface = local_interfaces;
246 DLIST_REMOVE(local_interfaces, local_interfaces);
247 ZERO_STRUCTPN(iface);
251 SAFE_FREE(probed_ifaces);
254 /****************************************************************************
255 Return True if the list of probed interfaces has changed.
256 ****************************************************************************/
258 BOOL interfaces_changed(void)
261 struct iface_struct ifaces[MAX_INTERFACES];
263 n = get_interfaces(ifaces, MAX_INTERFACES);
265 if ((n > 0 )&& (n != total_probed ||
266 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
273 /****************************************************************************
274 Check if an IP is one of mine.
275 **************************************************************************/
277 BOOL ismyip(struct in_addr ip)
280 for (i=local_interfaces;i;i=i->next)
281 if (ip_equal(i->ip,ip)) return True;
285 /****************************************************************************
286 Check if a packet is from a local (known) net.
287 **************************************************************************/
289 BOOL is_local_net(struct in_addr from)
292 for (i=local_interfaces;i;i=i->next) {
293 if((from.s_addr & i->nmask.s_addr) ==
294 (i->ip.s_addr & i->nmask.s_addr))
300 /****************************************************************************
301 How many interfaces do we have
302 **************************************************************************/
304 int iface_count(void)
309 for (i=local_interfaces;i;i=i->next)
314 /****************************************************************************
315 Return the Nth interface.
316 **************************************************************************/
318 struct interface *get_interface(int n)
322 for (i=local_interfaces;i && n;i=i->next)
329 /****************************************************************************
330 Return IP of the Nth interface.
331 **************************************************************************/
333 struct in_addr *iface_n_ip(int n)
337 for (i=local_interfaces;i && n;i=i->next)
340 if (i) return &i->ip;
344 /****************************************************************************
345 Return bcast of the Nth interface.
346 **************************************************************************/
348 struct in_addr *iface_n_bcast(int n)
352 for (i=local_interfaces;i && n;i=i->next)
355 if (i) return &i->bcast;
359 /* these 3 functions return the ip/bcast/nmask for the interface
360 most appropriate for the given ip address. If they can't find
361 an appropriate interface they return the requested field of the
362 first known interface. */
364 struct in_addr *iface_ip(struct in_addr ip)
366 struct interface *i = iface_find(ip, True);
367 return(i ? &i->ip : &local_interfaces->ip);
371 return True if a IP is directly reachable on one of our interfaces
374 BOOL iface_local(struct in_addr ip)
376 return iface_find(ip, True) ? True : False;