2 Unix SMB/Netbios implementation.
4 multiple interface handling
5 Copyright (C) Andrew Tridgell 1992-1995
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 wins_ip
;
28 static struct in_addr default_ip
;
29 static struct in_addr default_bcast
;
30 static struct in_addr default_nmask
;
31 static BOOL got_ip
=False
;
32 static BOOL got_bcast
=False
;
33 static BOOL got_nmask
=False
;
35 struct interface
*local_interfaces
= NULL
;
37 struct interface
*last_iface
;
39 /****************************************************************************
40 calculate the default netmask for an address
41 ****************************************************************************/
42 static void default_netmask(struct in_addr
*inm
, struct in_addr
*iad
)
44 uint32 ad
= ntohl(iad
->s_addr
);
47 ** Guess a netmask based on the class of the IP address given.
49 if ( (ad
& 0x80000000) == 0 ) {
52 } else if ( (ad
& 0xC0000000) == 0x80000000 ) {
55 } else if ( (ad
& 0xE0000000) == 0xC0000000 ) {
59 /* class D or E; netmask doesn't make much sense - guess 4 bits */
62 inm
->s_addr
= htonl(nm
);
66 /****************************************************************************
67 get the broadcast address for our address
68 (troyer@saifr00.ateng.az.honeywell.com)
69 ****************************************************************************/
70 static void get_broadcast(struct in_addr
*if_ipaddr
,
71 struct in_addr
*if_bcast
,
72 struct in_addr
*if_nmask
)
75 #ifndef NO_GET_BROADCAST
76 int sock
= -1; /* AF_INET raw socket desc */
78 struct ifreq
*ifr
=NULL
;
85 #elif defined(USE_IFREQ)
87 struct strioctl strioctl
;
94 /* get a default netmask and broadcast */
95 default_netmask(if_nmask
, if_ipaddr
);
97 #ifndef NO_GET_BROADCAST
98 /* Create a socket to the INET kernel. */
100 if ((sock
= socket(AF_INET
, SOCK_RAW
, PF_INET
)) < 0)
102 if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0 )) < 0)
105 DEBUG(0,( "Unable to open socket to get broadcast address\n"));
109 /* Get a list of the configured interfaces */
111 /* This is part of SCO Openserver 5: The ioctls are no longer part
112 if the lower level STREAMS interface glue. They are now real
115 if (ioctl(sock
, SIOCGIFANUM
, &n_interfaces
) < 0) {
116 DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno
)));
118 DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces
));
120 ifc
.ifc_len
= sizeof(struct ifreq
) * n_interfaces
;
121 ifc
.ifc_buf
= (caddr_t
) alloca(ifc
.ifc_len
);
123 if (ioctl(sock
, SIOCGIFCONF
, &ifc
) < 0)
124 DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno
)));
128 for (i
= 0; i
< n_interfaces
; ++i
) {
129 if (if_ipaddr
->s_addr
==
130 ((struct sockaddr_in
*) &ifr
[i
].ifr_addr
)->sin_addr
.s_addr
) {
137 #elif defined(USE_IFREQ)
138 ifc
= (struct ifconf
*)buff
;
139 ifc
->ifc_len
= BUFSIZ
- sizeof(struct ifconf
);
140 strioctl
.ic_cmd
= SIOCGIFCONF
;
141 strioctl
.ic_dp
= (char *)ifc
;
142 strioctl
.ic_len
= sizeof(buff
);
143 if (ioctl(sock
, I_STR
, &strioctl
) < 0) {
144 DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno
)));
146 ifr
= (struct ifreq
*)ifc
->ifc_req
;
148 /* Loop through interfaces, looking for given IP address */
149 for (i
= ifc
->ifc_len
/ sizeof(struct ifreq
); --i
>= 0; ifr
++) {
150 if (if_ipaddr
->s_addr
==
151 (*(struct sockaddr_in
*) &ifr
->ifr_addr
).sin_addr
.s_addr
) {
157 #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA)
158 ifc
.ifc_len
= sizeof(buff
);
160 if (ioctl(sock
, SIOCGIFCONF
, &ifc
) < 0) {
161 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno
)));
164 /* Loop through interfaces, looking for given IP address */
167 if (if_ipaddr
->s_addr
==
168 (*(struct sockaddr_in
*) &ifr
->ifr_addr
).sin_addr
.s_addr
) {
172 i
-= ifr
->ifr_addr
.sa_len
+ IFNAMSIZ
;
173 ifr
= (struct ifreq
*) ((char*) ifr
+ ifr
->ifr_addr
.sa_len
+ IFNAMSIZ
);
177 ifc
.ifc_len
= sizeof(buff
);
179 if (ioctl(sock
, SIOCGIFCONF
, &ifc
) < 0) {
180 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno
)));
184 /* Loop through interfaces, looking for given IP address */
185 for (i
= ifc
.ifc_len
/ sizeof(struct ifreq
); --i
>= 0; ifr
++) {
187 if (ioctl(sock
, SIOCGIFADDR
, ifr
) < 0) break;
189 if (if_ipaddr
->s_addr
==
190 (*(struct sockaddr_in
*) &ifr
->ifr_addr
).sin_addr
.s_addr
) {
199 DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr
)));
201 /* Get the netmask address from the kernel */
205 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
206 strioctl
.ic_dp
= (char *)&ifreq
;
207 strioctl
.ic_len
= sizeof(struct ifreq
);
208 if (ioctl(sock
, I_STR
, &strioctl
) < 0)
209 DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno
)));
211 *if_nmask
= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
;
213 if (ioctl(sock
, SIOCGIFNETMASK
, ifr
) < 0)
214 DEBUG(0,("SIOCGIFNETMASK failed\n"));
216 *if_nmask
= ((struct sockaddr_in
*)&ifr
->ifr_addr
)->sin_addr
;
219 DEBUG(4,("Netmask for %s = %s\n", ifr
->ifr_name
,
220 inet_ntoa(*if_nmask
)));
228 /* sanity check on the netmask */
230 uint32 nm
= ntohl(if_nmask
->s_addr
);
231 if ((nm
>> 24) != 0xFF) {
232 DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask
)));
233 default_netmask(if_nmask
, if_ipaddr
);
237 /* derive the broadcast assuming a 1's broadcast, as this is what
238 all MS operating systems do, we have to comply even if the unix
239 box is setup differently */
241 uint32 ad
= ntohl(if_ipaddr
->s_addr
);
242 uint32 nm
= ntohl(if_nmask
->s_addr
);
243 uint32 bc
= (ad
& nm
) | (0xffffffff & ~nm
);
244 if_bcast
->s_addr
= htonl(bc
);
247 DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast
)));
248 } /* get_broadcast */
252 /****************************************************************************
253 load a list of network interfaces
254 ****************************************************************************/
255 static void interpret_interfaces(char *s
, struct interface
**interfaces
,
260 struct interface
*iface
;
263 ipzero
= *interpret_addr2("0.0.0.0");
264 wins_ip
= *interpret_addr2("255.255.255.255");
266 while (next_token(&ptr
,token
,NULL
)) {
267 /* parse it into an IP address/netmasklength pair */
268 char *p
= strchr(token
,'/');
271 ip
= *interpret_addr2(token
);
273 /* maybe we already have it listed */
276 for (i
=(*interfaces
);i
;i
=i
->next
)
277 if (ip_equal(ip
,i
->ip
)) break;
281 iface
= (struct interface
*)malloc(sizeof(*iface
));
288 iface
->nmask
= *interpret_addr2(p
+1);
290 iface
->nmask
.s_addr
= htonl(~((1<<(32-atoi(p
+1)))-1));
292 default_netmask(&iface
->nmask
,&iface
->ip
);
294 iface
->bcast
.s_addr
= iface
->ip
.s_addr
| ~iface
->nmask
.s_addr
;
297 if (!(*interfaces
)) {
298 (*interfaces
) = iface
;
300 last_iface
->next
= iface
;
303 DEBUG(1,("Added %s ip=%s ",description
,inet_ntoa(iface
->ip
)));
304 DEBUG(1,("bcast=%s ",inet_ntoa(iface
->bcast
)));
305 DEBUG(1,("nmask=%s\n",inet_ntoa(iface
->nmask
)));
308 if (*interfaces
) return;
310 /* setup a default interface */
311 iface
= (struct interface
*)malloc(sizeof(*iface
));
317 iface
->ip
= default_ip
;
319 get_myname(NULL
,&iface
->ip
);
323 iface
->bcast
= default_bcast
;
325 get_broadcast(&iface
->ip
,&iface
->bcast
,&iface
->nmask
);
329 iface
->nmask
= default_nmask
;
330 iface
->bcast
.s_addr
= iface
->ip
.s_addr
| ~iface
->nmask
.s_addr
;
333 if (iface
->bcast
.s_addr
!= (iface
->ip
.s_addr
| ~iface
->nmask
.s_addr
)) {
334 DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface
->ip
)));
338 (*interfaces
) = last_iface
= iface
;
340 DEBUG(1,("Added interface ip=%s ",inet_ntoa(iface
->ip
)));
341 DEBUG(1,("bcast=%s ",inet_ntoa(iface
->bcast
)));
342 DEBUG(1,("nmask=%s\n",inet_ntoa(iface
->nmask
)));
346 /****************************************************************************
347 load the remote and local interfaces
348 ****************************************************************************/
349 void load_interfaces(void)
351 /* add the machine's interfaces to local interface structure*/
352 interpret_interfaces(lp_interfaces(), &local_interfaces
,"interface");
356 /****************************************************************************
357 override the defaults
358 **************************************************************************/
359 void iface_set_default(char *ip
,char *bcast
,char *nmask
)
363 default_ip
= *interpret_addr2(ip
);
368 default_bcast
= *interpret_addr2(bcast
);
373 default_nmask
= *interpret_addr2(nmask
);
378 /****************************************************************************
379 check if an IP is one of mine
380 **************************************************************************/
381 BOOL
ismyip(struct in_addr ip
)
384 for (i
=local_interfaces
;i
;i
=i
->next
)
385 if (ip_equal(i
->ip
,ip
)) return True
;
389 /****************************************************************************
390 check if a bcast is one of mine
391 **************************************************************************/
392 BOOL
ismybcast(struct in_addr bcast
)
395 for (i
=local_interfaces
;i
;i
=i
->next
)
396 if (ip_equal(i
->bcast
,bcast
)) return True
;
400 /****************************************************************************
401 how many interfaces do we have
402 **************************************************************************/
403 int iface_count(void)
408 for (i
=local_interfaces
;i
;i
=i
->next
)
413 /****************************************************************************
414 return IP of the Nth interface
415 **************************************************************************/
416 struct in_addr
*iface_n_ip(int n
)
420 for (i
=local_interfaces
;i
&& n
;i
=i
->next
)
423 if (i
) return &i
->ip
;
427 static struct interface
*iface_find(struct in_addr ip
)
430 if (zero_ip(ip
)) return local_interfaces
;
432 for (i
=local_interfaces
;i
;i
=i
->next
)
433 if (same_net(i
->ip
,ip
,i
->nmask
)) return i
;
435 return local_interfaces
;
438 /* these 3 functions return the ip/bcast/nmask for the interface
439 most appropriate for the given ip address */
441 struct in_addr
*iface_bcast(struct in_addr ip
)
443 return(&iface_find(ip
)->bcast
);
446 struct in_addr
*iface_nmask(struct in_addr ip
)
448 return(&iface_find(ip
)->nmask
);
451 struct in_addr
*iface_ip(struct in_addr ip
)
453 return(&iface_find(ip
)->ip
);