source: vendor/3.6.24/lib/replace/getifaddrs.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 7.8 KB
Line 
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
7
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
11
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.
16
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.
21
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/>.
24*/
25
26#define SOCKET_WRAPPER_NOT_REPLACE
27
28#include "replace.h"
29#include "system/network.h"
30
31#include <unistd.h>
32#include <stdio.h>
33#include <sys/types.h>
34
35#ifdef HAVE_SYS_TIME_H
36#include <sys/time.h>
37#endif
38
39#ifndef SIOCGIFCONF
40#ifdef HAVE_SYS_SOCKIO_H
41#include <sys/sockio.h>
42#endif
43#endif
44
45#ifdef HAVE_IFACE_GETIFADDRS
46#define _FOUND_IFACE_ANY
47#else
48
49void rep_freeifaddrs(struct ifaddrs *ifp)
50{
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);
58 }
59}
60
61static struct sockaddr *sockaddr_dup(struct sockaddr *sa)
62{
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;
75}
76#endif
77
78#if HAVE_IFACE_IFCONF
79
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.
82
83 It probably also works on any BSD style system. */
84
85int rep_getifaddrs(struct ifaddrs **ifap)
86{
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;
93
94 *ifap = NULL;
95
96 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
97 return -1;
98 }
99
100 ifc.ifc_len = sizeof(buff);
101 ifc.ifc_buf = buff;
102
103 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
104 close(fd);
105 return -1;
106 }
107
108 ifr = ifc.ifc_req;
109
110 n = ifc.ifc_len / sizeof(struct ifreq);
111
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;
117 }
118
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;
125
126 curif->ifa_addr = NULL;
127 if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) {
128 curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
129 }
130
131 curif->ifa_netmask = NULL;
132 if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) {
133 curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
134 }
135
136 if (lastif == NULL) {
137 *ifap = curif;
138 } else {
139 lastif->ifa_next = curif;
140 }
141 lastif = curif;
142 }
143
144 close(fd);
145
146 return 0;
147}
148
149#define _FOUND_IFACE_ANY
150#endif /* HAVE_IFACE_IFCONF */
151#ifdef HAVE_IFACE_IFREQ
152
153#ifndef I_STR
154#include <sys/stropts.h>
155#endif
156
157/****************************************************************************
158this should cover most of the streams based systems
159Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
160****************************************************************************/
161int rep_getifaddrs(struct ifaddrs **ifap)
162{
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;
170
171 *ifap = NULL;
172
173 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
174 return -1;
175 }
176
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;
183 }
184
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);
188
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;
196 }
197
198 /* Loop through interfaces */
199
200 for (i = 0; i<n; i++) {
201 ifreq = ifr[i];
202
203 curif = calloc(1, sizeof(struct ifaddrs));
204 if (lastif == NULL) {
205 *ifap = curif;
206 } else {
207 lastif->ifa_next = curif;
208 }
209
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;
216 }
217
218 curif->ifa_flags = ifreq.ifr_flags;
219
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;
226 }
227
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;
234
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;
241 }
242
243 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
244
245 lastif = curif;
246 }
247
248 close(fd);
249
250 return 0;
251}
252
253#define _FOUND_IFACE_ANY
254#endif /* HAVE_IFACE_IFREQ */
255#ifdef HAVE_IFACE_AIX
256
257/****************************************************************************
258this one is for AIX (tested on 4.2)
259****************************************************************************/
260int rep_getifaddrs(struct ifaddrs **ifap)
261{
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;
268
269 *ifap = NULL;
270
271 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
272 return -1;
273 }
274
275 ifc.ifc_len = sizeof(buff);
276 ifc.ifc_buf = buff;
277
278 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
279 close(fd);
280 return -1;
281 }
282
283 ifr = ifc.ifc_req;
284
285 /* Loop through interfaces */
286 i = ifc.ifc_len;
287
288 while (i > 0) {
289 unsigned int inc;
290
291 inc = ifr->ifr_addr.sa_len;
292
293 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
294 freeaddrinfo(*ifap);
295 return -1;
296 }
297
298 curif = calloc(1, sizeof(struct ifaddrs));
299 if (lastif == NULL) {
300 *ifap = curif;
301 } else {
302 lastif->ifa_next = curif;
303 }
304
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;
311
312 if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
313 freeaddrinfo(*ifap);
314 return -1;
315 }
316
317 curif->ifa_flags = ifr->ifr_flags;
318
319 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
320 freeaddrinfo(*ifap);
321 return -1;
322 }
323
324 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
325
326 lastif = curif;
327
328 next:
329 /*
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. */
335
336 if (inc < sizeof(ifr->ifr_addr))
337 inc = sizeof(ifr->ifr_addr);
338 inc += IFNAMSIZ;
339
340 ifr = (struct ifreq*) (((char*) ifr) + inc);
341 i -= inc;
342 }
343
344 close(fd);
345 return 0;
346}
347
348#define _FOUND_IFACE_ANY
349#endif /* HAVE_IFACE_AIX */
350#ifndef _FOUND_IFACE_ANY
351int rep_getifaddrs(struct ifaddrs **ifap)
352{
353 errno = ENOSYS;
354 return -1;
355}
356#endif
Note: See TracBrowser for help on using the repository browser.