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 ** NOTE! The following LGPL license applies to the replace
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #define SOCKET_WRAPPER_NOT_REPLACE
29 #include "system/network.h"
33 #include <sys/types.h>
35 #ifdef HAVE_SYS_TIME_H
40 #ifdef HAVE_SYS_SOCKIO_H
41 #include <sys/sockio.h>
45 #ifdef HAVE_IFACE_GETIFADDRS
46 #define _FOUND_IFACE_ANY
49 void rep_freeifaddrs(struct ifaddrs
*ifp
)
54 free(ifp
->ifa_netmask
);
55 free(ifp
->ifa_dstaddr
);
56 freeifaddrs(ifp
->ifa_next
);
61 static struct sockaddr
*sockaddr_dup(struct sockaddr
*sa
)
65 #ifdef HAVE_SOCKADDR_SA_LEN
68 socklen
= sizeof(struct sockaddr_storage
);
70 ret
= calloc(1, socklen
);
73 memcpy(ret
, sa
, socklen
);
80 /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
81 V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
83 It probably also works on any BSD style system. */
85 int rep_getifaddrs(struct ifaddrs
**ifap
)
90 struct ifreq
*ifr
=NULL
;
91 struct ifaddrs
*curif
;
92 struct ifaddrs
*lastif
= NULL
;
96 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
100 ifc
.ifc_len
= sizeof(buff
);
103 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
110 n
= ifc
.ifc_len
/ sizeof(struct ifreq
);
112 /* Loop through interfaces, looking for given IP address */
113 for (i
=n
-1; i
>=0; i
--) {
114 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
[i
]) == -1) {
119 curif
= calloc(1, sizeof(struct ifaddrs
));
120 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
121 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
122 curif
->ifa_dstaddr
= NULL
;
123 curif
->ifa_data
= NULL
;
124 curif
->ifa_next
= NULL
;
126 curif
->ifa_addr
= NULL
;
127 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != -1) {
128 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
131 curif
->ifa_netmask
= NULL
;
132 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != -1) {
133 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
136 if (lastif
== NULL
) {
139 lastif
->ifa_next
= curif
;
149 #define _FOUND_IFACE_ANY
150 #endif /* HAVE_IFACE_IFCONF */
151 #ifdef HAVE_IFACE_IFREQ
154 #include <sys/stropts.h>
157 /****************************************************************************
158 this should cover most of the streams based systems
159 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
160 ****************************************************************************/
161 int rep_getifaddrs(struct ifaddrs
**ifap
)
164 struct strioctl strioctl
;
167 struct ifreq
*ifr
=NULL
;
168 struct ifaddrs
*curif
;
169 struct ifaddrs
*lastif
= NULL
;
173 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
177 strioctl
.ic_cmd
= SIOCGIFCONF
;
178 strioctl
.ic_dp
= buff
;
179 strioctl
.ic_len
= sizeof(buff
);
180 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
185 /* we can ignore the possible sizeof(int) here as the resulting
186 number of interface structures won't change */
187 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
189 /* we will assume that the kernel returns the length as an int
190 at the start of the buffer if the offered size is a
191 multiple of the structure size plus an int */
192 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
193 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
195 ifr
= (struct ifreq
*)buff
;
198 /* Loop through interfaces */
200 for (i
= 0; i
<n
; i
++) {
203 curif
= calloc(1, sizeof(struct ifaddrs
));
204 if (lastif
== NULL
) {
207 lastif
->ifa_next
= curif
;
210 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
211 strioctl
.ic_dp
= (char *)&ifreq
;
212 strioctl
.ic_len
= sizeof(struct ifreq
);
213 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
218 curif
->ifa_flags
= ifreq
.ifr_flags
;
220 strioctl
.ic_cmd
= SIOCGIFADDR
;
221 strioctl
.ic_dp
= (char *)&ifreq
;
222 strioctl
.ic_len
= sizeof(struct ifreq
);
223 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
228 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
229 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
230 curif
->ifa_dstaddr
= NULL
;
231 curif
->ifa_data
= NULL
;
232 curif
->ifa_next
= NULL
;
233 curif
->ifa_netmask
= NULL
;
235 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
236 strioctl
.ic_dp
= (char *)&ifreq
;
237 strioctl
.ic_len
= sizeof(struct ifreq
);
238 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
243 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
253 #define _FOUND_IFACE_ANY
254 #endif /* HAVE_IFACE_IFREQ */
255 #ifdef HAVE_IFACE_AIX
257 /****************************************************************************
258 this one is for AIX (tested on 4.2)
259 ****************************************************************************/
260 int rep_getifaddrs(struct ifaddrs
**ifap
)
265 struct ifreq
*ifr
=NULL
;
266 struct ifaddrs
*curif
;
267 struct ifaddrs
*lastif
= NULL
;
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
= curif
;
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 rep_getifaddrs(struct ifaddrs
**ifap
)