Deprecate the "share modes" parameter to address bug #6024, swat disagrees with smbst...
[Samba/gbeck.git] / lib / replace / getifaddrs.c
blobf6f0ec080c2e48ef085635c04c6af7d87c61753d
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 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
24 #include "replace.h"
25 #include "system/network.h"
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_TIME_H
32 #include <sys/time.h>
33 #endif
35 #ifndef SIOCGIFCONF
36 #ifdef HAVE_SYS_SOCKIO_H
37 #include <sys/sockio.h>
38 #endif
39 #endif
41 #ifdef HAVE_IFACE_GETIFADDRS
42 #define _FOUND_IFACE_ANY
43 #else
45 void rep_freeifaddrs(struct ifaddrs *ifp)
47 if (ifp != NULL) {
48 free(ifp->ifa_name);
49 free(ifp->ifa_addr);
50 free(ifp->ifa_netmask);
51 free(ifp->ifa_dstaddr);
52 freeifaddrs(ifp->ifa_next);
53 free(ifp);
57 static struct sockaddr *sockaddr_dup(struct sockaddr *sa)
59 struct sockaddr *ret;
60 socklen_t socklen;
61 #ifdef HAVE_SOCKADDR_SA_LEN
62 socklen = sa->sa_len;
63 #else
64 socklen = sizeof(struct sockaddr_storage);
65 #endif
66 ret = calloc(1, socklen);
67 if (ret == NULL)
68 return NULL;
69 memcpy(ret, sa, socklen);
70 return ret;
72 #endif
74 #if HAVE_IFACE_IFCONF
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)
83 struct ifconf ifc;
84 char buff[8192];
85 int fd, i, n;
86 struct ifreq *ifr=NULL;
87 struct in_addr ipaddr;
88 struct in_addr nmask;
89 char *iname;
90 struct ifaddrs *curif;
91 struct ifaddrs *lastif = NULL;
93 *ifap = NULL;
95 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
96 return -1;
99 ifc.ifc_len = sizeof(buff);
100 ifc.ifc_buf = buff;
102 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
103 close(fd);
104 return -1;
107 ifr = ifc.ifc_req;
109 n = ifc.ifc_len / sizeof(struct ifreq);
111 /* Loop through interfaces, looking for given IP address */
112 for (i=n-1; i>=0; i--) {
113 if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) {
114 freeifaddrs(*ifap);
115 return -1;
118 curif = calloc(1, sizeof(struct ifaddrs));
119 curif->ifa_name = strdup(ifr[i].ifr_name);
120 curif->ifa_flags = ifr[i].ifr_flags;
121 curif->ifa_dstaddr = NULL;
122 curif->ifa_data = NULL;
123 curif->ifa_next = NULL;
125 curif->ifa_addr = NULL;
126 if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) {
127 curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
130 curif->ifa_netmask = NULL;
131 if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) {
132 curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
135 if (lastif == NULL) {
136 *ifap = curif;
137 } else {
138 lastif->ifa_next = curif;
140 lastif = curif;
143 close(fd);
145 return 0;
148 #define _FOUND_IFACE_ANY
149 #endif /* HAVE_IFACE_IFCONF */
150 #ifdef HAVE_IFACE_IFREQ
152 #ifndef I_STR
153 #include <sys/stropts.h>
154 #endif
156 /****************************************************************************
157 this should cover most of the streams based systems
158 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
159 ****************************************************************************/
160 int rep_getifaddrs(struct ifaddrs **ifap)
162 struct ifreq ifreq;
163 struct strioctl strioctl;
164 char buff[8192];
165 int fd, i, n;
166 struct ifreq *ifr=NULL;
167 struct in_addr ipaddr;
168 struct in_addr nmask;
169 char *iname;
170 struct ifaddrs *curif;
171 struct ifaddrs *lastif = NULL;
173 *ifap = NULL;
175 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
176 return -1;
179 strioctl.ic_cmd = SIOCGIFCONF;
180 strioctl.ic_dp = buff;
181 strioctl.ic_len = sizeof(buff);
182 if (ioctl(fd, I_STR, &strioctl) < 0) {
183 close(fd);
184 return -1;
187 /* we can ignore the possible sizeof(int) here as the resulting
188 number of interface structures won't change */
189 n = strioctl.ic_len / sizeof(struct ifreq);
191 /* we will assume that the kernel returns the length as an int
192 at the start of the buffer if the offered size is a
193 multiple of the structure size plus an int */
194 if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
195 ifr = (struct ifreq *)(buff + sizeof(int));
196 } else {
197 ifr = (struct ifreq *)buff;
200 /* Loop through interfaces */
202 for (i = 0; i<n; i++) {
203 ifreq = ifr[i];
205 curif = calloc(1, sizeof(struct ifaddrs));
206 if (lastif == NULL) {
207 *ifap = curif;
208 } else {
209 lastif->ifa_next = curif;
212 strioctl.ic_cmd = SIOCGIFFLAGS;
213 strioctl.ic_dp = (char *)&ifreq;
214 strioctl.ic_len = sizeof(struct ifreq);
215 if (ioctl(fd, I_STR, &strioctl) != 0) {
216 freeifaddrs(*ifap);
217 return -1;
220 curif->ifa_flags = ifreq.ifr_flags;
222 strioctl.ic_cmd = SIOCGIFADDR;
223 strioctl.ic_dp = (char *)&ifreq;
224 strioctl.ic_len = sizeof(struct ifreq);
225 if (ioctl(fd, I_STR, &strioctl) != 0) {
226 freeifaddrs(*ifap);
227 return -1;
230 curif->ifa_name = strdup(ifreq.ifr_name);
231 curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr);
232 curif->ifa_dstaddr = NULL;
233 curif->ifa_data = NULL;
234 curif->ifa_next = NULL;
235 curif->ifa_netmask = NULL;
237 strioctl.ic_cmd = SIOCGIFNETMASK;
238 strioctl.ic_dp = (char *)&ifreq;
239 strioctl.ic_len = sizeof(struct ifreq);
240 if (ioctl(fd, I_STR, &strioctl) != 0) {
241 freeifaddrs(*ifap);
242 return -1;
245 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
247 lastif = curif;
250 close(fd);
252 return 0;
255 #define _FOUND_IFACE_ANY
256 #endif /* HAVE_IFACE_IFREQ */
257 #ifdef HAVE_IFACE_AIX
259 /****************************************************************************
260 this one is for AIX (tested on 4.2)
261 ****************************************************************************/
262 int rep_getifaddrs(struct ifaddrs **ifap)
264 char buff[8192];
265 int fd, i;
266 struct ifconf ifc;
267 struct ifreq *ifr=NULL;
268 struct in_addr ipaddr;
269 struct in_addr nmask;
270 char *iname;
271 struct ifaddrs *curif;
272 struct ifaddrs *lastif = NULL;
274 *ifap = NULL;
276 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
277 return -1;
280 ifc.ifc_len = sizeof(buff);
281 ifc.ifc_buf = buff;
283 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
284 close(fd);
285 return -1;
288 ifr = ifc.ifc_req;
290 /* Loop through interfaces */
291 i = ifc.ifc_len;
293 while (i > 0) {
294 uint_t inc;
296 inc = ifr->ifr_addr.sa_len;
298 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
299 freeaddrinfo(*ifap);
300 return -1;
303 curif = calloc(1, sizeof(struct ifaddrs));
304 if (lastif == NULL) {
305 *ifap = curif;
306 } else {
307 lastif->ifa_next = curif;
310 curif->ifa_name = strdup(ifr->ifr_name);
311 curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
312 curif->ifa_dstaddr = NULL;
313 curif->ifa_data = NULL;
314 curif->ifa_netmask = NULL;
315 curif->ifa_next = NULL;
317 if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
318 freeaddrinfo(*ifap);
319 return -1;
322 curif->ifa_flags = ifr->ifr_flags;
324 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
325 freeaddrinfo(*ifap);
326 return -1;
329 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
331 lastif = curif;
333 next:
335 * Patch from Archie Cobbs (archie@whistle.com). The
336 * addresses in the SIOCGIFCONF interface list have a
337 * minimum size. Usually this doesn't matter, but if
338 * your machine has tunnel interfaces, etc. that have
339 * a zero length "link address", this does matter. */
341 if (inc < sizeof(ifr->ifr_addr))
342 inc = sizeof(ifr->ifr_addr);
343 inc += IFNAMSIZ;
345 ifr = (struct ifreq*) (((char*) ifr) + inc);
346 i -= inc;
349 close(fd);
350 return 0;
353 #define _FOUND_IFACE_ANY
354 #endif /* HAVE_IFACE_AIX */
355 #ifndef _FOUND_IFACE_ANY
356 int rep_getifaddrs(struct ifaddrs **ifap)
358 errno = ENOSYS;
359 return -1;
361 #endif