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) {
120 curif
= calloc(1, sizeof(struct ifaddrs
));
126 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
127 if (curif
->ifa_name
== NULL
) {
133 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
134 curif
->ifa_dstaddr
= NULL
;
135 curif
->ifa_data
= NULL
;
136 curif
->ifa_next
= NULL
;
138 curif
->ifa_addr
= NULL
;
139 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != -1) {
140 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
141 if (curif
->ifa_addr
== NULL
) {
142 free(curif
->ifa_name
);
150 curif
->ifa_netmask
= NULL
;
151 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != -1) {
152 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
153 if (curif
->ifa_netmask
== NULL
) {
154 if (curif
->ifa_addr
!= NULL
) {
155 free(curif
->ifa_addr
);
157 free(curif
->ifa_name
);
165 if (lastif
== NULL
) {
168 lastif
->ifa_next
= curif
;
178 #define _FOUND_IFACE_ANY
179 #endif /* HAVE_IFACE_IFCONF */
180 #ifdef HAVE_IFACE_IFREQ
183 #include <sys/stropts.h>
186 /****************************************************************************
187 this should cover most of the streams based systems
188 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
189 ****************************************************************************/
190 int rep_getifaddrs(struct ifaddrs
**ifap
)
193 struct strioctl strioctl
;
196 struct ifreq
*ifr
=NULL
;
197 struct ifaddrs
*curif
;
198 struct ifaddrs
*lastif
= NULL
;
202 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
206 strioctl
.ic_cmd
= SIOCGIFCONF
;
207 strioctl
.ic_dp
= buff
;
208 strioctl
.ic_len
= sizeof(buff
);
209 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
214 /* we can ignore the possible sizeof(int) here as the resulting
215 number of interface structures won't change */
216 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
218 /* we will assume that the kernel returns the length as an int
219 at the start of the buffer if the offered size is a
220 multiple of the structure size plus an int */
221 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
222 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
224 ifr
= (struct ifreq
*)buff
;
227 /* Loop through interfaces */
229 for (i
= 0; i
<n
; i
++) {
232 curif
= calloc(1, sizeof(struct ifaddrs
));
233 if (lastif
== NULL
) {
236 lastif
->ifa_next
= curif
;
239 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
240 strioctl
.ic_dp
= (char *)&ifreq
;
241 strioctl
.ic_len
= sizeof(struct ifreq
);
242 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
247 curif
->ifa_flags
= ifreq
.ifr_flags
;
249 strioctl
.ic_cmd
= SIOCGIFADDR
;
250 strioctl
.ic_dp
= (char *)&ifreq
;
251 strioctl
.ic_len
= sizeof(struct ifreq
);
252 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
257 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
258 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
259 curif
->ifa_dstaddr
= NULL
;
260 curif
->ifa_data
= NULL
;
261 curif
->ifa_next
= NULL
;
262 curif
->ifa_netmask
= NULL
;
264 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
265 strioctl
.ic_dp
= (char *)&ifreq
;
266 strioctl
.ic_len
= sizeof(struct ifreq
);
267 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
272 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
282 #define _FOUND_IFACE_ANY
283 #endif /* HAVE_IFACE_IFREQ */
284 #ifdef HAVE_IFACE_AIX
286 /****************************************************************************
287 this one is for AIX (tested on 4.2)
288 ****************************************************************************/
289 int rep_getifaddrs(struct ifaddrs
**ifap
)
294 struct ifreq
*ifr
=NULL
;
295 struct ifaddrs
*curif
;
296 struct ifaddrs
*lastif
= NULL
;
300 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
304 ifc
.ifc_len
= sizeof(buff
);
307 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
314 /* Loop through interfaces */
320 inc
= ifr
->ifr_addr
.sa_len
;
322 if (ioctl(fd
, SIOCGIFADDR
, ifr
) != 0) {
327 curif
= calloc(1, sizeof(struct ifaddrs
));
328 if (lastif
== NULL
) {
331 lastif
->ifa_next
= curif
;
334 curif
->ifa_name
= strdup(ifr
->ifr_name
);
335 curif
->ifa_addr
= sockaddr_dup(&ifr
->ifr_addr
);
336 curif
->ifa_dstaddr
= NULL
;
337 curif
->ifa_data
= NULL
;
338 curif
->ifa_netmask
= NULL
;
339 curif
->ifa_next
= NULL
;
341 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) != 0) {
346 curif
->ifa_flags
= ifr
->ifr_flags
;
348 if (ioctl(fd
, SIOCGIFNETMASK
, ifr
) != 0) {
353 curif
->ifa_netmask
= sockaddr_dup(&ifr
->ifr_addr
);
359 * Patch from Archie Cobbs (archie@whistle.com). The
360 * addresses in the SIOCGIFCONF interface list have a
361 * minimum size. Usually this doesn't matter, but if
362 * your machine has tunnel interfaces, etc. that have
363 * a zero length "link address", this does matter. */
365 if (inc
< sizeof(ifr
->ifr_addr
))
366 inc
= sizeof(ifr
->ifr_addr
);
369 ifr
= (struct ifreq
*) (((char*) ifr
) + inc
);
377 #define _FOUND_IFACE_ANY
378 #endif /* HAVE_IFACE_AIX */
379 #ifndef _FOUND_IFACE_ANY
380 int rep_getifaddrs(struct ifaddrs
**ifap
)