librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / lib / replace / getifaddrs.c
blob8da022f270dc4fa33ad23cbbcd15529a3703af68
1 /*
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
10 ** under the LGPL
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
28 #include "replace.h"
29 #include "system/network.h"
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <sys/types.h>
35 #ifdef HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
39 #ifndef SIOCGIFCONF
40 #ifdef HAVE_SYS_SOCKIO_H
41 #include <sys/sockio.h>
42 #endif
43 #endif
45 #ifdef HAVE_IFACE_GETIFADDRS
46 #define _FOUND_IFACE_ANY
47 #else
49 void rep_freeifaddrs(struct ifaddrs *ifp)
51 if (ifp != NULL) {
52 free(ifp->ifa_name);
53 free(ifp->ifa_addr);
54 free(ifp->ifa_netmask);
55 free(ifp->ifa_dstaddr);
56 freeifaddrs(ifp->ifa_next);
57 free(ifp);
61 static struct sockaddr *sockaddr_dup(struct sockaddr *sa)
63 struct sockaddr *ret;
64 socklen_t socklen;
65 #ifdef HAVE_SOCKADDR_SA_LEN
66 socklen = sa->sa_len;
67 #else
68 socklen = sizeof(struct sockaddr_storage);
69 #endif
70 ret = calloc(1, socklen);
71 if (ret == NULL)
72 return NULL;
73 memcpy(ret, sa, socklen);
74 return ret;
76 #endif
78 #if HAVE_IFACE_IFCONF
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)
87 struct ifconf ifc;
88 char buff[8192];
89 int fd, i, n;
90 struct ifreq *ifr=NULL;
91 struct ifaddrs *curif;
92 struct ifaddrs *lastif = NULL;
94 *ifap = NULL;
96 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
97 return -1;
100 ifc.ifc_len = sizeof(buff);
101 ifc.ifc_buf = buff;
103 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
104 close(fd);
105 return -1;
108 ifr = ifc.ifc_req;
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) {
115 freeifaddrs(*ifap);
116 return -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) {
137 *ifap = curif;
138 } else {
139 lastif->ifa_next = curif;
141 lastif = curif;
144 close(fd);
146 return 0;
149 #define _FOUND_IFACE_ANY
150 #endif /* HAVE_IFACE_IFCONF */
151 #ifdef HAVE_IFACE_IFREQ
153 #ifndef I_STR
154 #include <sys/stropts.h>
155 #endif
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)
163 struct ifreq ifreq;
164 struct strioctl strioctl;
165 char buff[8192];
166 int fd, i, n;
167 struct ifreq *ifr=NULL;
168 struct ifaddrs *curif;
169 struct ifaddrs *lastif = NULL;
171 *ifap = NULL;
173 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
174 return -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) {
181 close(fd);
182 return -1;
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));
194 } else {
195 ifr = (struct ifreq *)buff;
198 /* Loop through interfaces */
200 for (i = 0; i<n; i++) {
201 ifreq = ifr[i];
203 curif = calloc(1, sizeof(struct ifaddrs));
204 if (lastif == NULL) {
205 *ifap = curif;
206 } else {
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) {
214 freeifaddrs(*ifap);
215 return -1;
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) {
224 freeifaddrs(*ifap);
225 return -1;
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) {
239 freeifaddrs(*ifap);
240 return -1;
243 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
245 lastif = curif;
248 close(fd);
250 return 0;
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)
262 char buff[8192];
263 int fd, i;
264 struct ifconf ifc;
265 struct ifreq *ifr=NULL;
266 struct ifaddrs *curif;
267 struct ifaddrs *lastif = NULL;
269 *ifap = NULL;
271 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
272 return -1;
275 ifc.ifc_len = sizeof(buff);
276 ifc.ifc_buf = buff;
278 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
279 close(fd);
280 return -1;
283 ifr = ifc.ifc_req;
285 /* Loop through interfaces */
286 i = ifc.ifc_len;
288 while (i > 0) {
289 unsigned int inc;
291 inc = ifr->ifr_addr.sa_len;
293 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
294 freeaddrinfo(*ifap);
295 return -1;
298 curif = calloc(1, sizeof(struct ifaddrs));
299 if (lastif == NULL) {
300 *ifap = curif;
301 } else {
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) {
313 freeaddrinfo(*ifap);
314 return -1;
317 curif->ifa_flags = ifr->ifr_flags;
319 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
320 freeaddrinfo(*ifap);
321 return -1;
324 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
326 lastif = curif;
328 next:
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);
338 inc += IFNAMSIZ;
340 ifr = (struct ifreq*) (((char*) ifr) + inc);
341 i -= inc;
344 close(fd);
345 return 0;
348 #define _FOUND_IFACE_ANY
349 #endif /* HAVE_IFACE_AIX */
350 #ifndef _FOUND_IFACE_ANY
351 int rep_getifaddrs(struct ifaddrs **ifap)
353 errno = ENOSYS;
354 return -1;
356 #endif