2 Unix SMB/Netbios implementation.
4 multiple interface handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL;
26 struct in_addr ipzero;
27 struct in_addr allones_ip;
28 struct in_addr loopback_ip;
29 static struct in_addr default_ip;
30 static struct in_addr default_bcast;
31 static struct in_addr default_nmask;
32 static BOOL got_ip=False;
33 static BOOL got_bcast=False;
34 static BOOL got_nmask=False;
36 static struct interface *local_interfaces = NULL;
38 struct interface *last_iface;
40 #define ALLONES ((uint32)0xFFFFFFFF)
41 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
42 /****************************************************************************
43 calculate the default netmask for an address
44 ****************************************************************************/
45 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
48 ** Guess a netmask based on the class of the IP address given.
50 switch((ntohl(iad->s_addr) & 0xE0000000)) {
51 case 0x00000000: /* Class A addr */
55 inm->s_addr = htonl(0xFF000000);
58 case 0x80000000: /* Class B addr */
60 inm->s_addr = htonl(0xFFFF0000);
63 case 0xC0000000: /* Class C addr */
64 inm->s_addr = htonl(0xFFFFFF00);
68 inm->s_addr = htonl(0xFFFFFFF0);
73 /****************************************************************************
74 get the broadcast address for our address
75 (troyer@saifr00.ateng.az.honeywell.com)
76 ****************************************************************************/
77 static void get_broadcast(struct in_addr *if_ipaddr,
78 struct in_addr *if_bcast,
79 struct in_addr *if_nmask)
85 /* get a default netmask and broadcast */
86 default_netmask(if_nmask, if_ipaddr);
88 get_netmask(if_ipaddr, if_nmask);
90 /* sanity check on the netmask */
91 nm = ntohl(if_nmask->s_addr);
94 while((onbc + offbc) < 32) {
98 /* already found an off bit, so mask
107 if ((onbc < 8)||(onbc == 34)) {
108 DEBUG(0,("Impossible netmask %s - using defaults\n",
109 inet_ntoa(*if_nmask)));
110 default_netmask(if_nmask, if_ipaddr);
113 /* derive the broadcast assuming a 1's broadcast, as this is what
114 all MS operating systems do, we have to comply even if the unix
115 box is setup differently */
116 if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
118 DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
123 /****************************************************************************
124 load a list of network interfaces
125 ****************************************************************************/
126 static void interpret_interfaces(char *s, struct interface **interfaces,
131 struct interface *iface;
135 ipzero = *interpret_addr2("0.0.0.0");
136 allones_ip = *interpret_addr2("255.255.255.255");
137 loopback_ip = *interpret_addr2("127.0.0.1");
139 while (next_token(&ptr,token,NULL,sizeof(token))) {
140 /* parse it into an IP address/netmasklength pair */
141 char *p = strchr(token,'/');
144 ip = *interpret_addr2(token);
146 /* maybe we already have it listed */
149 for (i=(*interfaces);i;i=i->next)
150 if (ip_equal(ip,i->ip)) break;
154 iface = (struct interface *)malloc(sizeof(*iface));
161 iface->nmask = *interpret_addr2(p);
163 iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
165 default_netmask(&iface->nmask,&iface->ip);
167 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
170 if (!(*interfaces)) {
171 (*interfaces) = iface;
173 last_iface->next = iface;
176 DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
177 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
178 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
181 if (*interfaces) return;
183 /* setup a default interface */
184 iface = (struct interface *)malloc(sizeof(*iface));
190 iface->ip = default_ip;
192 get_myname(NULL,&iface->ip);
196 iface->bcast = default_bcast;
198 get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
202 iface->nmask = default_nmask;
203 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
206 if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
207 DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
211 (*interfaces) = last_iface = iface;
213 DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
214 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
215 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
219 /****************************************************************************
220 load the remote and local interfaces
221 ****************************************************************************/
222 void load_interfaces(void)
224 /* add the machine's interfaces to local interface structure*/
225 interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
229 /****************************************************************************
230 override the defaults
231 **************************************************************************/
232 void iface_set_default(char *ip,char *bcast,char *nmask)
236 default_ip = *interpret_addr2(ip);
241 default_bcast = *interpret_addr2(bcast);
246 default_nmask = *interpret_addr2(nmask);
251 /****************************************************************************
252 check if an IP is one of mine
253 **************************************************************************/
254 BOOL ismyip(struct in_addr ip)
257 for (i=local_interfaces;i;i=i->next)
258 if (ip_equal(i->ip,ip)) return True;
262 /****************************************************************************
263 check if a packet is from a local (known) net
264 **************************************************************************/
265 BOOL is_local_net(struct in_addr from)
268 for (i=local_interfaces;i;i=i->next)
269 if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
274 /****************************************************************************
275 how many interfaces do we have
276 **************************************************************************/
277 int iface_count(void)
282 for (i=local_interfaces;i;i=i->next)
287 /****************************************************************************
288 True if we have two or more interfaces.
289 **************************************************************************/
290 BOOL we_are_multihomed(void)
292 static int multi = -1;
295 multi = (iface_count() > 1 ? True : False);
300 /****************************************************************************
301 return the Nth interface
302 **************************************************************************/
303 struct interface *get_interface(int n)
307 for (i=local_interfaces;i && n;i=i->next)
314 /****************************************************************************
315 return IP of the Nth interface
316 **************************************************************************/
317 struct in_addr *iface_n_ip(int n)
321 for (i=local_interfaces;i && n;i=i->next)
324 if (i) return &i->ip;
328 /****************************************************************************
329 Try and find an interface that matches an ip. If we cannot, return NULL
330 **************************************************************************/
331 static struct interface *iface_find(struct in_addr ip)
334 if (zero_ip(ip)) return local_interfaces;
336 for (i=local_interfaces;i;i=i->next)
337 if (same_net(i->ip,ip,i->nmask)) return i;
343 /****************************************************************************
344 this function provides a simple hash of the configured interfaces. It is
345 used to detect a change in interfaces to tell us whether to discard
346 the current wins.dat file.
347 Note that the result is independent of the order of the interfaces
348 **************************************************************************/
349 unsigned iface_hash(void)
354 for (i=local_interfaces;i;i=i->next) {
355 unsigned x1 = (unsigned)str_checksum(inet_ntoa(i->ip));
356 unsigned x2 = (unsigned)str_checksum(inet_ntoa(i->nmask));
364 /* these 3 functions return the ip/bcast/nmask for the interface
365 most appropriate for the given ip address. If they can't find
366 an appropriate interface they return the requested field of the
367 first known interface. */
369 struct in_addr *iface_bcast(struct in_addr ip)
371 struct interface *i = iface_find(ip);
372 return(i ? &i->bcast : &local_interfaces->bcast);
375 struct in_addr *iface_ip(struct in_addr ip)
377 struct interface *i = iface_find(ip);
378 return(i ? &i->ip : &local_interfaces->ip);