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 ifaddrs
*curif
;
88 struct ifaddrs
*lastif
= NULL
;
92 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
96 ifc
.ifc_len
= sizeof(buff
);
99 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
106 n
= ifc
.ifc_len
/ sizeof(struct ifreq
);
108 /* Loop through interfaces, looking for given IP address */
109 for (i
=n
-1; i
>=0; i
--) {
110 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
[i
]) == -1) {
115 curif
= calloc(1, sizeof(struct ifaddrs
));
116 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
117 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
118 curif
->ifa_dstaddr
= NULL
;
119 curif
->ifa_data
= NULL
;
120 curif
->ifa_next
= NULL
;
122 curif
->ifa_addr
= NULL
;
123 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != -1) {
124 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
127 curif
->ifa_netmask
= NULL
;
128 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != -1) {
129 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
132 if (lastif
== NULL
) {
135 lastif
->ifa_next
= curif
;
145 #define _FOUND_IFACE_ANY
146 #endif /* HAVE_IFACE_IFCONF */
147 #ifdef HAVE_IFACE_IFREQ
150 #include <sys/stropts.h>
153 /****************************************************************************
154 this should cover most of the streams based systems
155 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
156 ****************************************************************************/
157 int rep_getifaddrs(struct ifaddrs
**ifap
)
160 struct strioctl strioctl
;
163 struct ifreq
*ifr
=NULL
;
164 struct ifaddrs
*curif
;
165 struct ifaddrs
*lastif
= NULL
;
169 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
173 strioctl
.ic_cmd
= SIOCGIFCONF
;
174 strioctl
.ic_dp
= buff
;
175 strioctl
.ic_len
= sizeof(buff
);
176 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
181 /* we can ignore the possible sizeof(int) here as the resulting
182 number of interface structures won't change */
183 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
185 /* we will assume that the kernel returns the length as an int
186 at the start of the buffer if the offered size is a
187 multiple of the structure size plus an int */
188 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
189 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
191 ifr
= (struct ifreq
*)buff
;
194 /* Loop through interfaces */
196 for (i
= 0; i
<n
; i
++) {
199 curif
= calloc(1, sizeof(struct ifaddrs
));
200 if (lastif
== NULL
) {
203 lastif
->ifa_next
= curif
;
206 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
207 strioctl
.ic_dp
= (char *)&ifreq
;
208 strioctl
.ic_len
= sizeof(struct ifreq
);
209 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
214 curif
->ifa_flags
= ifreq
.ifr_flags
;
216 strioctl
.ic_cmd
= SIOCGIFADDR
;
217 strioctl
.ic_dp
= (char *)&ifreq
;
218 strioctl
.ic_len
= sizeof(struct ifreq
);
219 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
224 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
225 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
226 curif
->ifa_dstaddr
= NULL
;
227 curif
->ifa_data
= NULL
;
228 curif
->ifa_next
= NULL
;
229 curif
->ifa_netmask
= NULL
;
231 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
232 strioctl
.ic_dp
= (char *)&ifreq
;
233 strioctl
.ic_len
= sizeof(struct ifreq
);
234 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
239 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
249 #define _FOUND_IFACE_ANY
250 #endif /* HAVE_IFACE_IFREQ */
251 #ifdef HAVE_IFACE_AIX
253 /****************************************************************************
254 this one is for AIX (tested on 4.2)
255 ****************************************************************************/
256 int rep_getifaddrs(struct ifaddrs
**ifap
)
261 struct ifreq
*ifr
=NULL
;
262 struct ifaddrs
*curif
;
263 struct ifaddrs
*lastif
= NULL
;
267 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
271 ifc
.ifc_len
= sizeof(buff
);
274 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
281 /* Loop through interfaces */
287 inc
= ifr
->ifr_addr
.sa_len
;
289 if (ioctl(fd
, SIOCGIFADDR
, ifr
) != 0) {
294 curif
= calloc(1, sizeof(struct ifaddrs
));
295 if (lastif
== NULL
) {
298 lastif
->ifa_next
= curif
;
301 curif
->ifa_name
= strdup(ifr
->ifr_name
);
302 curif
->ifa_addr
= sockaddr_dup(&ifr
->ifr_addr
);
303 curif
->ifa_dstaddr
= NULL
;
304 curif
->ifa_data
= NULL
;
305 curif
->ifa_netmask
= NULL
;
306 curif
->ifa_next
= NULL
;
308 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) != 0) {
313 curif
->ifa_flags
= ifr
->ifr_flags
;
315 if (ioctl(fd
, SIOCGIFNETMASK
, ifr
) != 0) {
320 curif
->ifa_netmask
= sockaddr_dup(&ifr
->ifr_addr
);
326 * Patch from Archie Cobbs (archie@whistle.com). The
327 * addresses in the SIOCGIFCONF interface list have a
328 * minimum size. Usually this doesn't matter, but if
329 * your machine has tunnel interfaces, etc. that have
330 * a zero length "link address", this does matter. */
332 if (inc
< sizeof(ifr
->ifr_addr
))
333 inc
= sizeof(ifr
->ifr_addr
);
336 ifr
= (struct ifreq
*) (((char*) ifr
) + inc
);
344 #define _FOUND_IFACE_ANY
345 #endif /* HAVE_IFACE_AIX */
346 #ifndef _FOUND_IFACE_ANY
347 int rep_getifaddrs(struct ifaddrs
**ifap
)