OLD | NEW |
| (Empty) |
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 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. | |
12 | |
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. | |
17 | |
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/>. | |
20 */ | |
21 | |
22 #define SOCKET_WRAPPER_NOT_REPLACE | |
23 | |
24 #include "replace.h" | |
25 #include "system/network.h" | |
26 | |
27 #include <unistd.h> | |
28 #include <stdio.h> | |
29 #include <sys/types.h> | |
30 | |
31 #ifdef HAVE_SYS_TIME_H | |
32 #include <sys/time.h> | |
33 #endif | |
34 | |
35 #ifndef SIOCGIFCONF | |
36 #ifdef HAVE_SYS_SOCKIO_H | |
37 #include <sys/sockio.h> | |
38 #endif | |
39 #endif | |
40 | |
41 #ifdef HAVE_IFACE_GETIFADDRS | |
42 #define _FOUND_IFACE_ANY | |
43 #else | |
44 | |
45 void rep_freeifaddrs(struct ifaddrs *ifp) | |
46 { | |
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); | |
54 } | |
55 } | |
56 | |
57 static struct sockaddr *sockaddr_dup(struct sockaddr *sa) | |
58 { | |
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; | |
71 } | |
72 #endif | |
73 | |
74 #if HAVE_IFACE_IFCONF | |
75 | |
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. | |
78 | |
79 It probably also works on any BSD style system. */ | |
80 | |
81 int rep_getifaddrs(struct ifaddrs **ifap) | |
82 { | |
83 struct ifconf ifc; | |
84 char buff[8192]; | |
85 int fd, i, n; | |
86 struct ifreq *ifr=NULL; | |
87 struct ifaddrs *curif; | |
88 struct ifaddrs *lastif = NULL; | |
89 | |
90 *ifap = NULL; | |
91 | |
92 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { | |
93 return -1; | |
94 } | |
95 | |
96 ifc.ifc_len = sizeof(buff); | |
97 ifc.ifc_buf = buff; | |
98 | |
99 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { | |
100 close(fd); | |
101 return -1; | |
102 } | |
103 | |
104 ifr = ifc.ifc_req; | |
105 | |
106 n = ifc.ifc_len / sizeof(struct ifreq); | |
107 | |
108 /* Loop through interfaces, looking for given IP address */ | |
109 for (i=n-1; i>=0; i--) { | |
110 if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) { | |
111 freeifaddrs(*ifap); | |
112 return -1; | |
113 } | |
114 | |
115 curif = calloc(1, sizeof(struct ifaddrs)); | |
116 curif->ifa_name = strdup(ifr[i].ifr_name); | |
117 curif->ifa_flags = ifr[i].ifr_flags; | |
118 curif->ifa_dstaddr = NULL; | |
119 curif->ifa_data = NULL; | |
120 curif->ifa_next = NULL; | |
121 | |
122 curif->ifa_addr = NULL; | |
123 if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) { | |
124 curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr); | |
125 } | |
126 | |
127 curif->ifa_netmask = NULL; | |
128 if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) { | |
129 curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr); | |
130 } | |
131 | |
132 if (lastif == NULL) { | |
133 *ifap = curif; | |
134 } else { | |
135 lastif->ifa_next = curif; | |
136 } | |
137 lastif = curif; | |
138 } | |
139 | |
140 close(fd); | |
141 | |
142 return 0; | |
143 } | |
144 | |
145 #define _FOUND_IFACE_ANY | |
146 #endif /* HAVE_IFACE_IFCONF */ | |
147 #ifdef HAVE_IFACE_IFREQ | |
148 | |
149 #ifndef I_STR | |
150 #include <sys/stropts.h> | |
151 #endif | |
152 | |
153 /**************************************************************************** | |
154 this should cover most of the streams based systems | |
155 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code | |
156 ****************************************************************************/ | |
157 int rep_getifaddrs(struct ifaddrs **ifap) | |
158 { | |
159 struct ifreq ifreq; | |
160 struct strioctl strioctl; | |
161 char buff[8192]; | |
162 int fd, i, n; | |
163 struct ifreq *ifr=NULL; | |
164 struct ifaddrs *curif; | |
165 struct ifaddrs *lastif = NULL; | |
166 | |
167 *ifap = NULL; | |
168 | |
169 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { | |
170 return -1; | |
171 } | |
172 | |
173 strioctl.ic_cmd = SIOCGIFCONF; | |
174 strioctl.ic_dp = buff; | |
175 strioctl.ic_len = sizeof(buff); | |
176 if (ioctl(fd, I_STR, &strioctl) < 0) { | |
177 close(fd); | |
178 return -1; | |
179 } | |
180 | |
181 /* we can ignore the possible sizeof(int) here as the resulting | |
182 number of interface structures won't change */ | |
183 n = strioctl.ic_len / sizeof(struct ifreq); | |
184 | |
185 /* we will assume that the kernel returns the length as an int | |
186 at the start of the buffer if the offered size is a | |
187 multiple of the structure size plus an int */ | |
188 if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { | |
189 ifr = (struct ifreq *)(buff + sizeof(int)); | |
190 } else { | |
191 ifr = (struct ifreq *)buff; | |
192 } | |
193 | |
194 /* Loop through interfaces */ | |
195 | |
196 for (i = 0; i<n; i++) { | |
197 ifreq = ifr[i]; | |
198 | |
199 curif = calloc(1, sizeof(struct ifaddrs)); | |
200 if (lastif == NULL) { | |
201 *ifap = curif; | |
202 } else { | |
203 lastif->ifa_next = curif; | |
204 } | |
205 | |
206 strioctl.ic_cmd = SIOCGIFFLAGS; | |
207 strioctl.ic_dp = (char *)&ifreq; | |
208 strioctl.ic_len = sizeof(struct ifreq); | |
209 if (ioctl(fd, I_STR, &strioctl) != 0) { | |
210 freeifaddrs(*ifap); | |
211 return -1; | |
212 } | |
213 | |
214 curif->ifa_flags = ifreq.ifr_flags; | |
215 | |
216 strioctl.ic_cmd = SIOCGIFADDR; | |
217 strioctl.ic_dp = (char *)&ifreq; | |
218 strioctl.ic_len = sizeof(struct ifreq); | |
219 if (ioctl(fd, I_STR, &strioctl) != 0) { | |
220 freeifaddrs(*ifap); | |
221 return -1; | |
222 } | |
223 | |
224 curif->ifa_name = strdup(ifreq.ifr_name); | |
225 curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr); | |
226 curif->ifa_dstaddr = NULL; | |
227 curif->ifa_data = NULL; | |
228 curif->ifa_next = NULL; | |
229 curif->ifa_netmask = NULL; | |
230 | |
231 strioctl.ic_cmd = SIOCGIFNETMASK; | |
232 strioctl.ic_dp = (char *)&ifreq; | |
233 strioctl.ic_len = sizeof(struct ifreq); | |
234 if (ioctl(fd, I_STR, &strioctl) != 0) { | |
235 freeifaddrs(*ifap); | |
236 return -1; | |
237 } | |
238 | |
239 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr); | |
240 | |
241 lastif = curif; | |
242 } | |
243 | |
244 close(fd); | |
245 | |
246 return 0; | |
247 } | |
248 | |
249 #define _FOUND_IFACE_ANY | |
250 #endif /* HAVE_IFACE_IFREQ */ | |
251 #ifdef HAVE_IFACE_AIX | |
252 | |
253 /**************************************************************************** | |
254 this one is for AIX (tested on 4.2) | |
255 ****************************************************************************/ | |
256 int rep_getifaddrs(struct ifaddrs **ifap) | |
257 { | |
258 char buff[8192]; | |
259 int fd, i; | |
260 struct ifconf ifc; | |
261 struct ifreq *ifr=NULL; | |
262 struct ifaddrs *curif; | |
263 struct ifaddrs *lastif = NULL; | |
264 | |
265 *ifap = NULL; | |
266 | |
267 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { | |
268 return -1; | |
269 } | |
270 | |
271 ifc.ifc_len = sizeof(buff); | |
272 ifc.ifc_buf = buff; | |
273 | |
274 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { | |
275 close(fd); | |
276 return -1; | |
277 } | |
278 | |
279 ifr = ifc.ifc_req; | |
280 | |
281 /* Loop through interfaces */ | |
282 i = ifc.ifc_len; | |
283 | |
284 while (i > 0) { | |
285 uint_t inc; | |
286 | |
287 inc = ifr->ifr_addr.sa_len; | |
288 | |
289 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { | |
290 freeaddrinfo(*ifap); | |
291 return -1; | |
292 } | |
293 | |
294 curif = calloc(1, sizeof(struct ifaddrs)); | |
295 if (lastif == NULL) { | |
296 *ifap = curif; | |
297 } else { | |
298 lastif->ifa_next = curif; | |
299 } | |
300 | |
301 curif->ifa_name = strdup(ifr->ifr_name); | |
302 curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); | |
303 curif->ifa_dstaddr = NULL; | |
304 curif->ifa_data = NULL; | |
305 curif->ifa_netmask = NULL; | |
306 curif->ifa_next = NULL; | |
307 | |
308 if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { | |
309 freeaddrinfo(*ifap); | |
310 return -1; | |
311 } | |
312 | |
313 curif->ifa_flags = ifr->ifr_flags; | |
314 | |
315 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { | |
316 freeaddrinfo(*ifap); | |
317 return -1; | |
318 } | |
319 | |
320 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); | |
321 | |
322 lastif = curif; | |
323 | |
324 next: | |
325 /* | |
326 * Patch from Archie Cobbs (archie@whistle.com). The | |
327 * addresses in the SIOCGIFCONF interface list have a | |
328 * minimum size. Usually this doesn't matter, but if | |
329 * your machine has tunnel interfaces, etc. that have | |
330 * a zero length "link address", this does matter. */ | |
331 | |
332 if (inc < sizeof(ifr->ifr_addr)) | |
333 inc = sizeof(ifr->ifr_addr); | |
334 inc += IFNAMSIZ; | |
335 | |
336 ifr = (struct ifreq*) (((char*) ifr) + inc); | |
337 i -= inc; | |
338 } | |
339 | |
340 close(fd); | |
341 return 0; | |
342 } | |
343 | |
344 #define _FOUND_IFACE_ANY | |
345 #endif /* HAVE_IFACE_AIX */ | |
346 #ifndef _FOUND_IFACE_ANY | |
347 int rep_getifaddrs(struct ifaddrs **ifap) | |
348 { | |
349 errno = ENOSYS; | |
350 return -1; | |
351 } | |
352 #endif | |
OLD | NEW |