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 **************************************************************************/
37 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
40 if (is_zero_ip(ip)) return local_interfaces;
42 for (i=local_interfaces;i;i=i->next)
44 if (same_net(i->ip,ip,i->nmask)) return i;
45 } else if ((i->ip).s_addr == ip.s_addr) return i;
51 /****************************************************************************
52 add an interface to the linked list of interfaces
53 ****************************************************************************/
54 static void add_interface(struct in_addr ip, struct in_addr nmask)
56 struct interface *iface;
57 if (iface_find(ip, False)) {
58 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
62 #if !defined(__s390__)
63 if (ip_equal(nmask, allones_ip)) {
64 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
69 iface = SMB_MALLOC_P(struct interface);
76 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
78 DLIST_ADD(local_interfaces, iface);
80 DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
81 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
82 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 ****************************************************************************/
98 static void interpret_interface(char *token)
100 struct in_addr ip, nmask;
107 /* first check if it is an interface name */
108 for (i=0;i<total_probed;i++) {
109 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
110 add_interface(probed_ifaces[i].ip,
111 probed_ifaces[i].netmask);
117 /* maybe it is a DNS name */
118 p = strchr_m(token,'/');
120 ip = *interpret_addr2(token);
121 for (i=0;i<total_probed;i++) {
122 if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
123 !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
124 add_interface(probed_ifaces[i].ip,
125 probed_ifaces[i].netmask);
129 DEBUG(2,("can't determine netmask for %s\n", token));
133 /* parse it into an IP address/netmasklength pair */
135 ip = *interpret_addr2(token);
139 nmask = *interpret_addr2(p);
141 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
144 /* maybe the first component was a broadcast address */
145 if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
146 ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
147 for (i=0;i<total_probed;i++) {
148 if (same_net(ip, probed_ifaces[i].ip, nmask)) {
149 add_interface(probed_ifaces[i].ip, nmask);
153 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
157 add_interface(ip, nmask);
161 /****************************************************************************
162 load the list of network interfaces
163 ****************************************************************************/
164 void load_interfaces(void)
168 struct iface_struct ifaces[MAX_INTERFACES];
170 ptr = lp_interfaces();
172 allones_ip = *interpret_addr2("255.255.255.255");
173 loopback_ip = *interpret_addr2("127.0.0.1");
175 SAFE_FREE(probed_ifaces);
177 /* dump the current interfaces if any */
178 while (local_interfaces) {
179 struct interface *iface = local_interfaces;
180 DLIST_REMOVE(local_interfaces, local_interfaces);
181 ZERO_STRUCTPN(iface);
185 /* probe the kernel for interfaces */
186 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
188 if (total_probed > 0) {
189 probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed);
190 if (!probed_ifaces) {
191 DEBUG(0,("ERROR: memdup failed\n"));
196 /* if we don't have a interfaces line then use all broadcast capable
197 interfaces except loopback */
198 if (!ptr || !*ptr || !**ptr) {
199 if (total_probed <= 0) {
200 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
203 for (i=0;i<total_probed;i++) {
205 #if !defined(__s390__)
206 probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
208 probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
209 add_interface(probed_ifaces[i].ip,
210 probed_ifaces[i].netmask);
218 char *ptr_cpy = SMB_STRDUP(*ptr);
220 interpret_interface(ptr_cpy);
227 if (!local_interfaces) {
228 DEBUG(0,("WARNING: no network interfaces found\n"));
233 void gfree_interfaces(void)
235 while (local_interfaces) {
236 struct interface *iface = local_interfaces;
237 DLIST_REMOVE(local_interfaces, local_interfaces);
238 ZERO_STRUCTPN(iface);
242 SAFE_FREE(probed_ifaces);
245 /****************************************************************************
246 return True if the list of probed interfaces has changed
247 ****************************************************************************/
248 BOOL interfaces_changed(void)
251 struct iface_struct ifaces[MAX_INTERFACES];
253 n = get_interfaces(ifaces, MAX_INTERFACES);
255 if ((n > 0 )&& (n != total_probed ||
256 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
264 /****************************************************************************
265 check if an IP is one of mine
266 **************************************************************************/
267 BOOL ismyip(struct in_addr ip)
270 for (i=local_interfaces;i;i=i->next)
271 if (ip_equal(i->ip,ip)) return True;
275 /****************************************************************************
276 check if a packet is from a local (known) net
277 **************************************************************************/
278 BOOL is_local_net(struct in_addr from)
281 for (i=local_interfaces;i;i=i->next) {
282 if((from.s_addr & i->nmask.s_addr) ==
283 (i->ip.s_addr & i->nmask.s_addr))
289 /****************************************************************************
290 how many interfaces do we have
291 **************************************************************************/
292 int iface_count(void)
297 for (i=local_interfaces;i;i=i->next)
302 /****************************************************************************
303 return the Nth interface
304 **************************************************************************/
305 struct interface *get_interface(int n)
309 for (i=local_interfaces;i && n;i=i->next)
316 /****************************************************************************
317 return IP of the Nth interface
318 **************************************************************************/
319 struct in_addr *iface_n_ip(int n)
323 for (i=local_interfaces;i && n;i=i->next)
326 if (i) return &i->ip;
330 /****************************************************************************
331 return bcast of the Nth interface
332 **************************************************************************/
333 struct in_addr *iface_n_bcast(int n)
337 for (i=local_interfaces;i && n;i=i->next)
340 if (i) return &i->bcast;
345 /* these 3 functions return the ip/bcast/nmask for the interface
346 most appropriate for the given ip address. If they can't find
347 an appropriate interface they return the requested field of the
348 first known interface. */
350 struct in_addr *iface_ip(struct in_addr ip)
352 struct interface *i = iface_find(ip, True);
353 return(i ? &i->ip : &local_interfaces->ip);
357 return True if a IP is directly reachable on one of our interfaces
359 BOOL iface_local(struct in_addr ip)
361 return iface_find(ip, True) ? True : False;