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)
82 #ifndef NO_GET_BROADCAST
83 int sock = -1; /* AF_INET raw socket desc */
85 struct ifreq *ifr=NULL;
92 #elif defined(USE_IFREQ)
94 struct strioctl strioctl;
101 /* get a default netmask and broadcast */
102 default_netmask(if_nmask, if_ipaddr);
104 #ifndef NO_GET_BROADCAST
105 /* Create a socket to the INET kernel. */
107 if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
109 if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
112 DEBUG(0,( "Unable to open socket to get broadcast address\n"));
116 /* Get a list of the configured interfaces */
118 /* This is part of SCO Openserver 5: The ioctls are no longer part
119 if the lower level STREAMS interface glue. They are now real
122 if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
123 DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
125 DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
127 ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
128 ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
130 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
131 DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
135 for (i = 0; i < n_interfaces; ++i) {
136 if (if_ipaddr->s_addr ==
137 ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
144 #elif defined(USE_IFREQ)
145 ifc = (struct ifconf *)buff;
146 ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
147 strioctl.ic_cmd = SIOCGIFCONF;
148 strioctl.ic_dp = (char *)ifc;
149 strioctl.ic_len = sizeof(buff);
150 if (ioctl(sock, I_STR, &strioctl) < 0) {
151 DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
153 ifr = (struct ifreq *)ifc->ifc_req;
155 /* Loop through interfaces, looking for given IP address */
156 for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
157 if (if_ipaddr->s_addr ==
158 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
164 #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41) || defined(__OpenBSD__)
165 ifc.ifc_len = sizeof(buff);
167 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
168 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
171 /* Loop through interfaces, looking for given IP address */
174 if (if_ipaddr->s_addr ==
175 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
179 i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
180 ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
184 ifc.ifc_len = sizeof(buff);
186 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
187 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
191 /* Loop through interfaces, looking for given IP address */
192 for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
194 if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
196 if (if_ipaddr->s_addr ==
197 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
206 DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
208 /* Get the netmask address from the kernel */
212 strioctl.ic_cmd = SIOCGIFNETMASK;
213 strioctl.ic_dp = (char *)&ifreq;
214 strioctl.ic_len = sizeof(struct ifreq);
215 if (ioctl(sock, I_STR, &strioctl) < 0)
216 DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
218 *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
220 if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
221 DEBUG(0,("SIOCGIFNETMASK failed\n"));
223 *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
226 DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name,
227 inet_ntoa(*if_nmask)));
235 /* sanity check on the netmask */
241 nm = ntohl(if_nmask->s_addr);
244 while( (onbc + offbc) < 32 )
246 if( nm & 0x80000000 )
249 if( offbc ) /* already found an off bit, so mask is wrong */
260 if ((onbc < 8)||(onbc == 34)) {
261 DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
262 default_netmask(if_nmask, if_ipaddr);
266 /* derive the broadcast assuming a 1's broadcast, as this is what
267 all MS operating systems do, we have to comply even if the unix
268 box is setup differently */
270 if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
273 DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
274 } /* get_broadcast */
278 /****************************************************************************
279 load a list of network interfaces
280 ****************************************************************************/
281 static void interpret_interfaces(char *s, struct interface **interfaces,
286 struct interface *iface;
290 ipzero = *interpret_addr2("0.0.0.0");
291 allones_ip = *interpret_addr2("255.255.255.255");
292 loopback_ip = *interpret_addr2("127.0.0.1");
294 while (next_token(&ptr,token,NULL)) {
295 /* parse it into an IP address/netmasklength pair */
296 char *p = strchr(token,'/');
299 ip = *interpret_addr2(token);
301 /* maybe we already have it listed */
304 for (i=(*interfaces);i;i=i->next)
305 if (ip_equal(ip,i->ip)) break;
309 iface = (struct interface *)malloc(sizeof(*iface));
316 iface->nmask = *interpret_addr2(p);
318 iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
320 default_netmask(&iface->nmask,&iface->ip);
322 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
325 if (!(*interfaces)) {
326 (*interfaces) = iface;
328 last_iface->next = iface;
331 DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
332 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
333 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
336 if (*interfaces) return;
338 /* setup a default interface */
339 iface = (struct interface *)malloc(sizeof(*iface));
345 iface->ip = default_ip;
347 get_myname(NULL,&iface->ip);
351 iface->bcast = default_bcast;
353 get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
357 iface->nmask = default_nmask;
358 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
361 if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
362 DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
366 (*interfaces) = last_iface = iface;
368 DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
369 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
370 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
374 /****************************************************************************
375 load the remote and local interfaces
376 ****************************************************************************/
377 void load_interfaces(void)
379 /* add the machine's interfaces to local interface structure*/
380 interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
384 /****************************************************************************
385 override the defaults
386 **************************************************************************/
387 void iface_set_default(char *ip,char *bcast,char *nmask)
391 default_ip = *interpret_addr2(ip);
396 default_bcast = *interpret_addr2(bcast);
401 default_nmask = *interpret_addr2(nmask);
406 /****************************************************************************
407 check if an IP is one of mine
408 **************************************************************************/
409 BOOL ismyip(struct in_addr ip)
412 for (i=local_interfaces;i;i=i->next)
413 if (ip_equal(i->ip,ip)) return True;
417 /****************************************************************************
418 check if a bcast is one of mine
419 **************************************************************************/
420 BOOL ismybcast(struct in_addr bcast)
423 for (i=local_interfaces;i;i=i->next)
424 if (ip_equal(i->bcast,bcast)) return True;
428 /****************************************************************************
429 check if a packet is from a local (known) net
430 **************************************************************************/
431 BOOL is_local_net(struct in_addr from)
434 for (i=local_interfaces;i;i=i->next)
435 if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
440 /****************************************************************************
441 how many interfaces do we have
442 **************************************************************************/
443 int iface_count(void)
448 for (i=local_interfaces;i;i=i->next)
453 /****************************************************************************
454 True if we have two or more interfaces.
455 **************************************************************************/
456 BOOL we_are_multihomed()
458 static int multi = -1;
461 multi = (iface_count() > 1 ? True : False);
466 /****************************************************************************
467 return the Nth interface
468 **************************************************************************/
469 struct interface *get_interface(int n)
473 for (i=local_interfaces;i && n;i=i->next)
480 /****************************************************************************
481 return IP of the Nth interface
482 **************************************************************************/
483 struct in_addr *iface_n_ip(int n)
487 for (i=local_interfaces;i && n;i=i->next)
490 if (i) return &i->ip;
494 /****************************************************************************
495 Try and find an interface that matches an ip. If we cannot, return NULL
496 **************************************************************************/
497 static struct interface *iface_find(struct in_addr ip)
500 if (zero_ip(ip)) return local_interfaces;
502 for (i=local_interfaces;i;i=i->next)
503 if (same_net(i->ip,ip,i->nmask)) return i;
508 /* these 3 functions return the ip/bcast/nmask for the interface
509 most appropriate for the given ip address. If they can't find
510 an appropriate interface they return the requested field of the
511 first known interface. */
513 struct in_addr *iface_bcast(struct in_addr ip)
515 struct interface *i = iface_find(ip);
516 return(i ? &i->bcast : &local_interfaces->bcast);
519 struct in_addr *iface_nmask(struct in_addr ip)
521 struct interface *i = iface_find(ip);
522 return(i ? &i->nmask : &local_interfaces->nmask);
525 struct in_addr *iface_ip(struct in_addr ip)
527 struct interface *i = iface_find(ip);
528 return(i ? &i->ip : &local_interfaces->ip);