34
34
#include <sys/ioctl.h>
35
35
#include <net/if.h>
36
36
#include <netinet/in.h>
37
+ #include <netinet/in6_var.h>
37
38
#include <arpa/inet.h>
38
39
39
40
#include <sys/time.h>
@@ -158,28 +159,42 @@ int uv_exepath(char* buffer, size_t* size) {
158
159
159
160
int uv_interface_addresses (uv_interface_address_t * * addresses , int * count ) {
160
161
uv_interface_address_t * address ;
161
- int sockfd , inet6 , size = 1 ;
162
+ int sockfd , sock6fd , inet6 , i , r , size = 1 ;
162
163
struct ifconf ifc ;
163
164
struct ifreq * ifr , * p , flg ;
165
+ struct in6_ifreq if6 ;
164
166
struct sockaddr_dl * sa_addr ;
165
167
168
+ ifc .ifc_req = NULL ;
169
+ sock6fd = -1 ;
170
+ r = 0 ;
166
171
* count = 0 ;
167
172
* addresses = NULL ;
168
173
169
174
if (0 > (sockfd = socket (AF_INET , SOCK_DGRAM , IPPROTO_IP ))) {
170
- return UV__ERR (errno );
175
+ r = UV__ERR (errno );
176
+ goto cleanup ;
177
+ }
178
+
179
+ if (0 > (sock6fd = socket (AF_INET6 , SOCK_DGRAM , IPPROTO_IP ))) {
180
+ r = UV__ERR (errno );
181
+ goto cleanup ;
171
182
}
172
183
173
184
if (ioctl (sockfd , SIOCGSIZIFCONF , & size ) == -1 ) {
174
- uv__close ( sockfd );
175
- return UV__ERR ( errno ) ;
185
+ r = UV__ERR ( errno );
186
+ goto cleanup ;
176
187
}
177
188
178
189
ifc .ifc_req = (struct ifreq * )uv__malloc (size );
190
+ if (ifc .ifc_req == NULL ) {
191
+ r = UV_ENOMEM ;
192
+ goto cleanup ;
193
+ }
179
194
ifc .ifc_len = size ;
180
195
if (ioctl (sockfd , SIOCGIFCONF , & ifc ) == -1 ) {
181
- uv__close ( sockfd );
182
- return UV__ERR ( errno ) ;
196
+ r = UV__ERR ( errno );
197
+ goto cleanup ;
183
198
}
184
199
185
200
#define ADDR_SIZE (p ) MAX((p).sa_len, sizeof(p))
@@ -197,8 +212,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
197
212
198
213
memcpy (flg .ifr_name , p -> ifr_name , sizeof (flg .ifr_name ));
199
214
if (ioctl (sockfd , SIOCGIFFLAGS , & flg ) == -1 ) {
200
- uv__close ( sockfd );
201
- return UV__ERR ( errno ) ;
215
+ r = UV__ERR ( errno );
216
+ goto cleanup ;
202
217
}
203
218
204
219
if (!(flg .ifr_flags & IFF_UP && flg .ifr_flags & IFF_RUNNING ))
@@ -207,16 +222,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
207
222
(* count )++ ;
208
223
}
209
224
210
- if (* count == 0 ) {
211
- uv__close (sockfd );
212
- return 0 ;
213
- }
225
+ if (* count == 0 )
226
+ goto cleanup ;
214
227
215
228
/* Alloc the return interface structs */
216
- * addresses = uv__malloc (* count * sizeof (uv_interface_address_t ));
229
+ * addresses = uv__calloc (* count , sizeof (* * addresses ));
217
230
if (!(* addresses )) {
218
- uv__close ( sockfd ) ;
219
- return UV_ENOMEM ;
231
+ r = UV_ENOMEM ;
232
+ goto cleanup ;
220
233
}
221
234
address = * addresses ;
222
235
@@ -233,10 +246,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
233
246
inet6 = (p -> ifr_addr .sa_family == AF_INET6 );
234
247
235
248
memcpy (flg .ifr_name , p -> ifr_name , sizeof (flg .ifr_name ));
236
- if (ioctl (sockfd , SIOCGIFFLAGS , & flg ) == -1 ) {
237
- uv__close (sockfd );
238
- return UV_ENOSYS ;
239
- }
249
+ if (ioctl (sockfd , SIOCGIFFLAGS , & flg ) == -1 )
250
+ goto syserror ;
240
251
241
252
if (!(flg .ifr_flags & IFF_UP && flg .ifr_flags & IFF_RUNNING ))
242
253
continue ;
@@ -250,28 +261,67 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
250
261
else
251
262
address -> address .address4 = * ((struct sockaddr_in * ) & p -> ifr_addr );
252
263
253
- sa_addr = (struct sockaddr_dl * ) & p -> ifr_addr ;
254
- memcpy (address -> phys_addr , LLADDR (sa_addr ), sizeof (address -> phys_addr ));
255
-
256
- if (ioctl (sockfd , SIOCGIFNETMASK , p ) == -1 ) {
257
- uv__close (sockfd );
258
- return UV_ENOSYS ;
259
- }
260
-
261
- if (inet6 )
262
- address -> netmask .netmask6 = * ((struct sockaddr_in6 * ) & p -> ifr_addr );
263
- else
264
+ if (inet6 ) {
265
+ memset (& if6 , 0 , sizeof (if6 ));
266
+ r = uv__strscpy (if6 .ifr_name , p -> ifr_name , sizeof (if6 .ifr_name ));
267
+ if (r == UV_E2BIG )
268
+ goto cleanup ;
269
+ r = 0 ;
270
+ memcpy (& if6 .ifr_Addr , & p -> ifr_addr , sizeof (if6 .ifr_Addr ));
271
+ if (ioctl (sock6fd , SIOCGIFNETMASK6 , & if6 ) == -1 )
272
+ goto syserror ;
273
+ address -> netmask .netmask6 = * ((struct sockaddr_in6 * ) & if6 .ifr_Addr );
274
+ /* Explicitly set family as the ioctl call appears to return it as 0. */
275
+ address -> netmask .netmask6 .sin6_family = AF_INET6 ;
276
+ } else {
277
+ if (ioctl (sockfd , SIOCGIFNETMASK , p ) == -1 )
278
+ goto syserror ;
264
279
address -> netmask .netmask4 = * ((struct sockaddr_in * ) & p -> ifr_addr );
280
+ /* Explicitly set family as the ioctl call appears to return it as 0. */
281
+ address -> netmask .netmask4 .sin_family = AF_INET ;
282
+ }
265
283
266
284
address -> is_internal = flg .ifr_flags & IFF_LOOPBACK ? 1 : 0 ;
267
285
268
286
address ++ ;
269
287
}
270
288
289
+ /* Fill in physical addresses. */
290
+ ifr = ifc .ifc_req ;
291
+ while ((char * )ifr < (char * )ifc .ifc_req + ifc .ifc_len ) {
292
+ p = ifr ;
293
+ ifr = (struct ifreq * )
294
+ ((char * )ifr + sizeof (ifr -> ifr_name ) + ADDR_SIZE (ifr -> ifr_addr ));
295
+
296
+ if (p -> ifr_addr .sa_family != AF_LINK )
297
+ continue ;
298
+
299
+ address = * addresses ;
300
+ for (i = 0 ; i < * count ; i ++ ) {
301
+ if (strcmp (address -> name , p -> ifr_name ) == 0 ) {
302
+ sa_addr = (struct sockaddr_dl * ) & p -> ifr_addr ;
303
+ memcpy (address -> phys_addr , LLADDR (sa_addr ), sizeof (address -> phys_addr ));
304
+ }
305
+ address ++ ;
306
+ }
307
+ }
308
+
271
309
#undef ADDR_SIZE
310
+ goto cleanup ;
272
311
273
- uv__close (sockfd );
274
- return 0 ;
312
+ syserror :
313
+ uv_free_interface_addresses (* addresses , * count );
314
+ * addresses = NULL ;
315
+ * count = 0 ;
316
+ r = UV_ENOSYS ;
317
+
318
+ cleanup :
319
+ if (sockfd != -1 )
320
+ uv__close (sockfd );
321
+ if (sock6fd != -1 )
322
+ uv__close (sock6fd );
323
+ uv__free (ifc .ifc_req );
324
+ return r ;
275
325
}
276
326
277
327
0 commit comments