2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Jeremy Allison 2007
6 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/network.h"
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_TIME_H
34 #ifdef HAVE_SYS_SOCKIO_H
35 #include <sys/sockio.h>
39 #ifdef HAVE_IFACE_GETIFADDRS
40 #define _FOUND_IFACE_ANY
43 void freeifaddrs(struct ifaddrs
*ifp
)
47 free(ifp
->ifa_netmask
);
48 free(ifp
->ifa_dstaddr
);
49 if (ifp
->ifa_next
!= NULL
)
50 freeifaddrs(ifp
->ifa_next
);
54 struct sockaddr
*sockaddr_dup(struct sockaddr
*sa
)
56 struct sockaddr
*ret
= calloc(1, sa
->sa_len
);
59 memcpy(ret
, sa
, sa
->sa_len
);
66 /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
67 V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
69 It probably also works on any BSD style system. */
71 int getifaddrs(struct ifaddrs
**ifap
)
76 struct ifreq
*ifr
=NULL
;
78 struct in_addr ipaddr
;
81 struct ifaddrs
*curif
, *lastif
;
85 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
89 ifc
.ifc_len
= sizeof(buff
);
92 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
99 n
= ifc
.ifc_len
/ sizeof(struct ifreq
);
101 /* Loop through interfaces, looking for given IP address */
102 for (i
=n
-1;i
>=0 && total
< max_interfaces
;i
--) {
103 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != 0) {
107 curif
= calloc(1, sizeof(struct ifaddrs
));
108 if (lastif
== NULL
) {
111 lastif
->ifa_next
= (*ifap
);
114 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
115 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
116 curif
->ifa_dstaddr
= NULL
;
117 curif
->ifa_data
= NULL
;
118 curif
->ifa_next
= NULL
;
119 curif
->ifa_netmask
= NULL
;
121 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
[i
]) != 0) {
126 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
128 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != 0) {
133 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
143 #define _FOUND_IFACE_ANY
144 #endif /* HAVE_IFACE_IFCONF */
145 #ifdef HAVE_IFACE_IFREQ
148 #include <sys/stropts.h>
151 /****************************************************************************
152 this should cover most of the streams based systems
153 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
154 ****************************************************************************/
155 int getifaddrs(struct ifaddrs
**ifap
)
158 struct strioctl strioctl
;
161 struct ifreq
*ifr
=NULL
;
163 struct in_addr ipaddr
;
164 struct in_addr nmask
;
166 struct ifaddrs
*curif
;
170 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
174 strioctl
.ic_cmd
= SIOCGIFCONF
;
175 strioctl
.ic_dp
= buff
;
176 strioctl
.ic_len
= sizeof(buff
);
177 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
182 /* we can ignore the possible sizeof(int) here as the resulting
183 number of interface structures won't change */
184 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
186 /* we will assume that the kernel returns the length as an int
187 at the start of the buffer if the offered size is a
188 multiple of the structure size plus an int */
189 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
190 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
192 ifr
= (struct ifreq
*)buff
;
195 /* Loop through interfaces */
197 for (i
= 0; i
<n
&& total
< max_interfaces
; i
++) {
200 curif
= calloc(1, sizeof(struct ifaddrs
));
201 if (lastif
== NULL
) {
204 lastif
->ifa_next
= (*ifap
);
207 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
208 strioctl
.ic_dp
= (char *)&ifreq
;
209 strioctl
.ic_len
= sizeof(struct ifreq
);
210 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
215 curif
->ifa_flags
= ifreq
.ifr_flags
;
217 strioctl
.ic_cmd
= SIOCGIFADDR
;
218 strioctl
.ic_dp
= (char *)&ifreq
;
219 strioctl
.ic_len
= sizeof(struct ifreq
);
220 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
225 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
226 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
227 curif
->ifa_dstaddr
= NULL
;
228 curif
->ifa_data
= NULL
;
229 curif
->ifa_next
= NULL
;
230 curif
->ifa_netmask
= NULL
;
232 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
233 strioctl
.ic_dp
= (char *)&ifreq
;
234 strioctl
.ic_len
= sizeof(struct ifreq
);
235 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
240 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
250 #define _FOUND_IFACE_ANY
251 #endif /* HAVE_IFACE_IFREQ */
252 #ifdef HAVE_IFACE_AIX
254 /****************************************************************************
255 this one is for AIX (tested on 4.2)
256 ****************************************************************************/
257 int getifaddrs(struct ifaddrs
**ifap
)
262 struct ifreq
*ifr
=NULL
;
263 struct in_addr ipaddr
;
264 struct in_addr nmask
;
267 struct ifaddrs
*curif
, *lastif
;
271 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
275 ifc
.ifc_len
= sizeof(buff
);
278 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
285 /* Loop through interfaces */
291 inc
= ifr
->ifr_addr
.sa_len
;
293 if (ioctl(fd
, SIOCGIFADDR
, ifr
) != 0) {
298 curif
= calloc(1, sizeof(struct ifaddrs
));
299 if (lastif
== NULL
) {
302 lastif
->ifa_next
= (*ifap
);
305 curif
->ifa_name
= strdup(ifr
->ifr_name
);
306 curif
->ifa_addr
= sockaddr_dup(&ifr
->ifr_addr
);
307 curif
->ifa_dstaddr
= NULL
;
308 curif
->ifa_data
= NULL
;
309 curif
->ifa_netmask
= NULL
;
310 curif
->ifa_next
= NULL
;
312 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) != 0) {
317 curif
->ifa_flags
= ifr
->ifr_flags
;
319 if (ioctl(fd
, SIOCGIFNETMASK
, ifr
) != 0) {
324 curif
->ifa_netmask
= sockaddr_dup(&ifr
->ifr_addr
);
330 * Patch from Archie Cobbs (archie@whistle.com). The
331 * addresses in the SIOCGIFCONF interface list have a
332 * minimum size. Usually this doesn't matter, but if
333 * your machine has tunnel interfaces, etc. that have
334 * a zero length "link address", this does matter. */
336 if (inc
< sizeof(ifr
->ifr_addr
))
337 inc
= sizeof(ifr
->ifr_addr
);
340 ifr
= (struct ifreq
*) (((char*) ifr
) + inc
);
348 #define _FOUND_IFACE_ANY
349 #endif /* HAVE_IFACE_AIX */
350 #ifndef _FOUND_IFACE_ANY
351 int getifaddrs(struct ifaddrs
**ifap
)
359 /* this is the autoconf driver to test get_interfaces() */
363 struct ifaddrs
*ifs
= NULL
;
366 ret
= getifaddrs(&ifs
);
368 perror("getifaddrs() failed");
373 printf("%-10s ", ifs
->ifa_name
);
374 if (ifs
->ifa_addr
!= NULL
&&
375 ifs
->ifa_addr
->sa_family
== AF_INET
) {
376 printf("IP=%s ", inet_ntoa(((struct sockaddr_in
*)ifs
->ifa_addr
)->sin_addr
));
377 if (ifs
->ifa_netmask
!= NULL
)
378 printf("NETMASK=%s", inet_ntoa(((struct sockaddr_in
*)ifs
->ifa_netmask
)->sin_addr
));