loadparm: rename variable for "hosts allow" from hostsallow to hosts_allow
[Samba/wip.git] / lib / replace / getifaddrs.c
blobf07d7005e4bf64bfd8eaf2a789f95099d2b5ff87
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 close(fd);
117 return -1;
120 curif = calloc(1, sizeof(struct ifaddrs));
121 if (curif == NULL) {
122 freeifaddrs(*ifap);
123 close(fd);
124 return -1;
126 curif->ifa_name = strdup(ifr[i].ifr_name);
127 if (curif->ifa_name == NULL) {
128 free(curif);
129 freeifaddrs(*ifap);
130 close(fd);
131 return -1;
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);
143 free(curif);
144 freeifaddrs(*ifap);
145 close(fd);
146 return -1;
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);
158 free(curif);
159 freeifaddrs(*ifap);
160 close(fd);
161 return -1;
165 if (lastif == NULL) {
166 *ifap = curif;
167 } else {
168 lastif->ifa_next = curif;
170 lastif = curif;
173 close(fd);
175 return 0;
178 #define _FOUND_IFACE_ANY
179 #endif /* HAVE_IFACE_IFCONF */
180 #ifdef HAVE_IFACE_IFREQ
182 #ifndef I_STR
183 #include <sys/stropts.h>
184 #endif
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)
192 struct ifreq ifreq;
193 struct strioctl strioctl;
194 char buff[8192];
195 int fd, i, n;
196 struct ifreq *ifr=NULL;
197 struct ifaddrs *curif;
198 struct ifaddrs *lastif = NULL;
200 *ifap = NULL;
202 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
203 return -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) {
210 close(fd);
211 return -1;
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));
223 } else {
224 ifr = (struct ifreq *)buff;
227 /* Loop through interfaces */
229 for (i = 0; i<n; i++) {
230 ifreq = ifr[i];
232 curif = calloc(1, sizeof(struct ifaddrs));
233 if (lastif == NULL) {
234 *ifap = curif;
235 } else {
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) {
243 freeifaddrs(*ifap);
244 return -1;
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) {
253 freeifaddrs(*ifap);
254 return -1;
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) {
268 freeifaddrs(*ifap);
269 return -1;
272 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
274 lastif = curif;
277 close(fd);
279 return 0;
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)
291 char buff[8192];
292 int fd, i;
293 struct ifconf ifc;
294 struct ifreq *ifr=NULL;
295 struct ifaddrs *curif;
296 struct ifaddrs *lastif = NULL;
298 *ifap = NULL;
300 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
301 return -1;
304 ifc.ifc_len = sizeof(buff);
305 ifc.ifc_buf = buff;
307 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
308 close(fd);
309 return -1;
312 ifr = ifc.ifc_req;
314 /* Loop through interfaces */
315 i = ifc.ifc_len;
317 while (i > 0) {
318 unsigned int inc;
320 inc = ifr->ifr_addr.sa_len;
322 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
323 freeaddrinfo(*ifap);
324 return -1;
327 curif = calloc(1, sizeof(struct ifaddrs));
328 if (lastif == NULL) {
329 *ifap = curif;
330 } else {
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) {
342 freeaddrinfo(*ifap);
343 return -1;
346 curif->ifa_flags = ifr->ifr_flags;
348 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
349 freeaddrinfo(*ifap);
350 return -1;
353 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
355 lastif = curif;
357 next:
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);
367 inc += IFNAMSIZ;
369 ifr = (struct ifreq*) (((char*) ifr) + inc);
370 i -= inc;
373 close(fd);
374 return 0;
377 #define _FOUND_IFACE_ANY
378 #endif /* HAVE_IFACE_AIX */
379 #ifndef _FOUND_IFACE_ANY
380 int rep_getifaddrs(struct ifaddrs **ifap)
382 errno = ENOSYS;
383 return -1;
385 #endif