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/>.
22 #define SOCKET_WRAPPER_NOT_REPLACE
25 #include "system/network.h"
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_TIME_H
36 #ifdef HAVE_SYS_SOCKIO_H
37 #include <sys/sockio.h>
41 #ifdef HAVE_IFACE_GETIFADDRS
42 #define _FOUND_IFACE_ANY
45 void rep_freeifaddrs(struct ifaddrs
*ifp
)
50 free(ifp
->ifa_netmask
);
51 free(ifp
->ifa_dstaddr
);
52 freeifaddrs(ifp
->ifa_next
);
57 static struct sockaddr
*sockaddr_dup(struct sockaddr
*sa
)
61 #ifdef HAVE_SOCKADDR_SA_LEN
64 socklen
= sizeof(struct sockaddr_storage
);
66 ret
= calloc(1, socklen
);
69 memcpy(ret
, sa
, socklen
);
76 /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
77 V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
79 It probably also works on any BSD style system. */
81 int rep_getifaddrs(struct ifaddrs
**ifap
)
86 struct ifreq
*ifr
=NULL
;
87 struct in_addr ipaddr
;
90 struct ifaddrs
*curif
;
91 struct ifaddrs
*lastif
= NULL
;
95 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
99 ifc
.ifc_len
= sizeof(buff
);
102 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
109 n
= ifc
.ifc_len
/ sizeof(struct ifreq
);
111 /* Loop through interfaces, looking for given IP address */
112 for (i
=n
-1; i
>=0; i
--) {
113 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
[i
]) == -1) {
118 curif
= calloc(1, sizeof(struct ifaddrs
));
119 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
120 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
121 curif
->ifa_dstaddr
= NULL
;
122 curif
->ifa_data
= NULL
;
123 curif
->ifa_next
= NULL
;
125 curif
->ifa_addr
= NULL
;
126 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != -1) {
127 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
130 curif
->ifa_netmask
= NULL
;
131 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != -1) {
132 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
135 if (lastif
== NULL
) {
138 lastif
->ifa_next
= curif
;
148 #define _FOUND_IFACE_ANY
149 #endif /* HAVE_IFACE_IFCONF */
150 #ifdef HAVE_IFACE_IFREQ
153 #include <sys/stropts.h>
156 /****************************************************************************
157 this should cover most of the streams based systems
158 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
159 ****************************************************************************/
160 int rep_getifaddrs(struct ifaddrs
**ifap
)
163 struct strioctl strioctl
;
166 struct ifreq
*ifr
=NULL
;
167 struct in_addr ipaddr
;
168 struct in_addr nmask
;
170 struct ifaddrs
*curif
;
171 struct ifaddrs
*lastif
= NULL
;
175 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
179 strioctl
.ic_cmd
= SIOCGIFCONF
;
180 strioctl
.ic_dp
= buff
;
181 strioctl
.ic_len
= sizeof(buff
);
182 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
187 /* we can ignore the possible sizeof(int) here as the resulting
188 number of interface structures won't change */
189 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
191 /* we will assume that the kernel returns the length as an int
192 at the start of the buffer if the offered size is a
193 multiple of the structure size plus an int */
194 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
195 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
197 ifr
= (struct ifreq
*)buff
;
200 /* Loop through interfaces */
202 for (i
= 0; i
<n
; i
++) {
205 curif
= calloc(1, sizeof(struct ifaddrs
));
206 if (lastif
== NULL
) {
209 lastif
->ifa_next
= curif
;
212 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
213 strioctl
.ic_dp
= (char *)&ifreq
;
214 strioctl
.ic_len
= sizeof(struct ifreq
);
215 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
220 curif
->ifa_flags
= ifreq
.ifr_flags
;
222 strioctl
.ic_cmd
= SIOCGIFADDR
;
223 strioctl
.ic_dp
= (char *)&ifreq
;
224 strioctl
.ic_len
= sizeof(struct ifreq
);
225 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
230 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
231 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
232 curif
->ifa_dstaddr
= NULL
;
233 curif
->ifa_data
= NULL
;
234 curif
->ifa_next
= NULL
;
235 curif
->ifa_netmask
= NULL
;
237 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
238 strioctl
.ic_dp
= (char *)&ifreq
;
239 strioctl
.ic_len
= sizeof(struct ifreq
);
240 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
245 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
255 #define _FOUND_IFACE_ANY
256 #endif /* HAVE_IFACE_IFREQ */
257 #ifdef HAVE_IFACE_AIX
259 /****************************************************************************
260 this one is for AIX (tested on 4.2)
261 ****************************************************************************/
262 int rep_getifaddrs(struct ifaddrs
**ifap
)
267 struct ifreq
*ifr
=NULL
;
268 struct in_addr ipaddr
;
269 struct in_addr nmask
;
271 struct ifaddrs
*curif
;
272 struct ifaddrs
*lastif
= NULL
;
276 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
280 ifc
.ifc_len
= sizeof(buff
);
283 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
290 /* Loop through interfaces */
296 inc
= ifr
->ifr_addr
.sa_len
;
298 if (ioctl(fd
, SIOCGIFADDR
, ifr
) != 0) {
303 curif
= calloc(1, sizeof(struct ifaddrs
));
304 if (lastif
== NULL
) {
307 lastif
->ifa_next
= curif
;
310 curif
->ifa_name
= strdup(ifr
->ifr_name
);
311 curif
->ifa_addr
= sockaddr_dup(&ifr
->ifr_addr
);
312 curif
->ifa_dstaddr
= NULL
;
313 curif
->ifa_data
= NULL
;
314 curif
->ifa_netmask
= NULL
;
315 curif
->ifa_next
= NULL
;
317 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) != 0) {
322 curif
->ifa_flags
= ifr
->ifr_flags
;
324 if (ioctl(fd
, SIOCGIFNETMASK
, ifr
) != 0) {
329 curif
->ifa_netmask
= sockaddr_dup(&ifr
->ifr_addr
);
335 * Patch from Archie Cobbs (archie@whistle.com). The
336 * addresses in the SIOCGIFCONF interface list have a
337 * minimum size. Usually this doesn't matter, but if
338 * your machine has tunnel interfaces, etc. that have
339 * a zero length "link address", this does matter. */
341 if (inc
< sizeof(ifr
->ifr_addr
))
342 inc
= sizeof(ifr
->ifr_addr
);
345 ifr
= (struct ifreq
*) (((char*) ifr
) + inc
);
353 #define _FOUND_IFACE_ANY
354 #endif /* HAVE_IFACE_AIX */
355 #ifndef _FOUND_IFACE_ANY
356 int rep_getifaddrs(struct ifaddrs
**ifap
)