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/>.
27 #include "system/network.h"
31 #include <sys/types.h>
33 #ifdef HAVE_SYS_TIME_H
38 #ifdef HAVE_SYS_SOCKIO_H
39 #include <sys/sockio.h>
43 #ifdef HAVE_IFACE_GETIFADDRS
44 #define _FOUND_IFACE_ANY
47 void rep_freeifaddrs(struct ifaddrs
*ifp
)
52 free(ifp
->ifa_netmask
);
53 free(ifp
->ifa_dstaddr
);
54 freeifaddrs(ifp
->ifa_next
);
59 static struct sockaddr
*sockaddr_dup(struct sockaddr
*sa
)
63 #ifdef HAVE_SOCKADDR_SA_LEN
66 socklen
= sizeof(struct sockaddr_storage
);
68 ret
= calloc(1, socklen
);
71 memcpy(ret
, sa
, socklen
);
78 /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
79 V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
81 It probably also works on any BSD style system. */
83 int rep_getifaddrs(struct ifaddrs
**ifap
)
88 struct ifreq
*ifr
=NULL
;
89 struct ifaddrs
*curif
;
90 struct ifaddrs
*lastif
= NULL
;
94 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
98 ifc
.ifc_len
= sizeof(buff
);
101 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
108 n
= ifc
.ifc_len
/ sizeof(struct ifreq
);
110 /* Loop through interfaces, looking for given IP address */
111 for (i
=n
-1; i
>=0; i
--) {
112 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
[i
]) == -1) {
118 curif
= calloc(1, sizeof(struct ifaddrs
));
124 curif
->ifa_name
= strdup(ifr
[i
].ifr_name
);
125 if (curif
->ifa_name
== NULL
) {
131 curif
->ifa_flags
= ifr
[i
].ifr_flags
;
132 curif
->ifa_dstaddr
= NULL
;
133 curif
->ifa_data
= NULL
;
134 curif
->ifa_next
= NULL
;
136 curif
->ifa_addr
= NULL
;
137 if (ioctl(fd
, SIOCGIFADDR
, &ifr
[i
]) != -1) {
138 curif
->ifa_addr
= sockaddr_dup(&ifr
[i
].ifr_addr
);
139 if (curif
->ifa_addr
== NULL
) {
140 free(curif
->ifa_name
);
148 curif
->ifa_netmask
= NULL
;
149 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
[i
]) != -1) {
150 curif
->ifa_netmask
= sockaddr_dup(&ifr
[i
].ifr_addr
);
151 if (curif
->ifa_netmask
== NULL
) {
152 if (curif
->ifa_addr
!= NULL
) {
153 free(curif
->ifa_addr
);
155 free(curif
->ifa_name
);
163 if (lastif
== NULL
) {
166 lastif
->ifa_next
= curif
;
176 #define _FOUND_IFACE_ANY
177 #endif /* HAVE_IFACE_IFCONF */
178 #ifdef HAVE_IFACE_IFREQ
181 #include <sys/stropts.h>
184 /****************************************************************************
185 this should cover most of the streams based systems
186 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
187 ****************************************************************************/
188 int rep_getifaddrs(struct ifaddrs
**ifap
)
191 struct strioctl strioctl
;
194 struct ifreq
*ifr
=NULL
;
195 struct ifaddrs
*curif
;
196 struct ifaddrs
*lastif
= NULL
;
200 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
204 strioctl
.ic_cmd
= SIOCGIFCONF
;
205 strioctl
.ic_dp
= buff
;
206 strioctl
.ic_len
= sizeof(buff
);
207 if (ioctl(fd
, I_STR
, &strioctl
) < 0) {
212 /* we can ignore the possible sizeof(int) here as the resulting
213 number of interface structures won't change */
214 n
= strioctl
.ic_len
/ sizeof(struct ifreq
);
216 /* we will assume that the kernel returns the length as an int
217 at the start of the buffer if the offered size is a
218 multiple of the structure size plus an int */
219 if (n
*sizeof(struct ifreq
) + sizeof(int) == strioctl
.ic_len
) {
220 ifr
= (struct ifreq
*)(buff
+ sizeof(int));
222 ifr
= (struct ifreq
*)buff
;
225 /* Loop through interfaces */
227 for (i
= 0; i
<n
; i
++) {
230 curif
= calloc(1, sizeof(struct ifaddrs
));
231 if (lastif
== NULL
) {
234 lastif
->ifa_next
= curif
;
237 strioctl
.ic_cmd
= SIOCGIFFLAGS
;
238 strioctl
.ic_dp
= (char *)&ifreq
;
239 strioctl
.ic_len
= sizeof(struct ifreq
);
240 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
245 curif
->ifa_flags
= ifreq
.ifr_flags
;
247 strioctl
.ic_cmd
= SIOCGIFADDR
;
248 strioctl
.ic_dp
= (char *)&ifreq
;
249 strioctl
.ic_len
= sizeof(struct ifreq
);
250 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
255 curif
->ifa_name
= strdup(ifreq
.ifr_name
);
256 curif
->ifa_addr
= sockaddr_dup(&ifreq
.ifr_addr
);
257 curif
->ifa_dstaddr
= NULL
;
258 curif
->ifa_data
= NULL
;
259 curif
->ifa_next
= NULL
;
260 curif
->ifa_netmask
= NULL
;
262 strioctl
.ic_cmd
= SIOCGIFNETMASK
;
263 strioctl
.ic_dp
= (char *)&ifreq
;
264 strioctl
.ic_len
= sizeof(struct ifreq
);
265 if (ioctl(fd
, I_STR
, &strioctl
) != 0) {
270 curif
->ifa_netmask
= sockaddr_dup(&ifreq
.ifr_addr
);
280 #define _FOUND_IFACE_ANY
281 #endif /* HAVE_IFACE_IFREQ */
282 #ifdef HAVE_IFACE_AIX
284 /****************************************************************************
285 this one is for AIX (tested on 4.2)
286 ****************************************************************************/
287 int rep_getifaddrs(struct ifaddrs
**ifap
)
292 struct ifreq
*ifr
=NULL
;
293 struct ifaddrs
*curif
;
294 struct ifaddrs
*lastif
= NULL
;
298 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
302 ifc
.ifc_len
= sizeof(buff
);
305 if (ioctl(fd
, SIOCGIFCONF
, &ifc
) != 0) {
312 /* Loop through interfaces */
318 inc
= ifr
->ifr_addr
.sa_len
;
320 if (ioctl(fd
, SIOCGIFADDR
, ifr
) != 0) {
325 curif
= calloc(1, sizeof(struct ifaddrs
));
326 if (lastif
== NULL
) {
329 lastif
->ifa_next
= curif
;
332 curif
->ifa_name
= strdup(ifr
->ifr_name
);
333 curif
->ifa_addr
= sockaddr_dup(&ifr
->ifr_addr
);
334 curif
->ifa_dstaddr
= NULL
;
335 curif
->ifa_data
= NULL
;
336 curif
->ifa_netmask
= NULL
;
337 curif
->ifa_next
= NULL
;
339 if (ioctl(fd
, SIOCGIFFLAGS
, ifr
) != 0) {
344 curif
->ifa_flags
= ifr
->ifr_flags
;
346 if (ioctl(fd
, SIOCGIFNETMASK
, ifr
) != 0) {
351 curif
->ifa_netmask
= sockaddr_dup(&ifr
->ifr_addr
);
357 * Patch from Archie Cobbs (archie@whistle.com). The
358 * addresses in the SIOCGIFCONF interface list have a
359 * minimum size. Usually this doesn't matter, but if
360 * your machine has tunnel interfaces, etc. that have
361 * a zero length "link address", this does matter. */
363 if (inc
< sizeof(ifr
->ifr_addr
))
364 inc
= sizeof(ifr
->ifr_addr
);
367 ifr
= (struct ifreq
*) (((char*) ifr
) + inc
);
375 #define _FOUND_IFACE_ANY
376 #endif /* HAVE_IFACE_AIX */
377 #ifndef _FOUND_IFACE_ANY
378 int rep_getifaddrs(struct ifaddrs
**ifap
)