1 /* Provide stub function getifaddrs(). */
7 #ifndef HAVE_GETIFADDRS
8 /* Downloaded from http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c */
11 * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
12 * (Royal Institute of Technology, Stockholm, Sweden).
13 * All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
26 * 3. Neither the name of the Institute nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 /* ELinksification and improvement of alloc failure handling by Zas.
44 * This file was borrowed from dkftpbench-0.45 sources (http://www.kegel.com/dkftpbench). */
47 #include <sys/types.h> /* SunOS needs this before net/if.h */
48 #ifdef HAVE_SYS_SOCKET_H
49 #include <sys/socket.h> /* SunOS needs this before net/if.h, and need to be after sys/types.h */
57 #ifdef HAVE_NETINET_IN_H
58 #include <netinet/in.h>
60 #ifdef HAVE_NETINET_IN6_VAR_H
61 #include <netinet/in6_var.h>
66 #ifdef HAVE_SYS_IOCTL_H
67 #include <sys/ioctl.h>
70 #include <fcntl.h> /* OS/2 needs this after sys/types.h */
75 #ifdef HAVE_SYS_SOCKIO_H
76 #include <sys/sockio.h>
81 #include "osdep/osdep.h"
82 #include "osdep/getifaddrs.h"
85 #if (defined(PF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)) \
86 || (defined(PF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)) \
87 || (defined(CONFIG_IPV6) && defined(SIOCGIFCONF))
90 getifaddrs2(struct ifaddrs
**ifap
,
91 int pf
, int siocgifconf
, int siocgifflags
, size_t ifreq_sz
)
93 struct sockaddr sa_zero
;
95 struct ifaddrs
*start
;
96 struct ifaddrs
**end
= &start
;
106 memset(&sa_zero
, 0, sizeof(sa_zero
));
107 fd
= socket(pf
, SOCK_DGRAM
, 0);
113 buf
= calloc(1, buf_size
);
118 ifconf
.ifc_len
= buf_size
;
119 ifconf
.ifc_buf
= buf
;
122 * Solaris returns EINVAL when the buffer is too small.
124 if (ioctl(fd
, siocgifconf
, &ifconf
) < 0 && errno
!= EINVAL
) {
129 * Can the difference between a full and a overfull buf
133 if (ifconf
.ifc_len
< (int) buf_size
)
140 num
= ifconf
.ifc_len
/ ifreq_sz
;
142 for (p
= ifconf
.ifc_buf
; p
< ifconf
.ifc_buf
+ ifconf
.ifc_len
; p
+= sz
) {
146 void *tmp_end
, *tmp_name
, *tmp_addr
;
148 ifr
= (struct ifreq
*) p
;
153 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
155 sz
= int_max(sz
, sizeof(ifr
->ifr_name
) + sa
->sa_len
);
159 sz
= int_max(sz
, sizeof(ifr
->ifr_name
) + SA_LEN(sa
));
161 memset(&ifreq
, 0, sizeof(ifreq
));
162 memcpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifr
->ifr_name
));
164 if (ioctl(fd
, siocgifflags
, &ifreq
) < 0) {
169 tmp_end
= malloc(sizeof(**end
));
175 tmp_name
= strdup(ifr
->ifr_name
);
182 tmp_addr
= malloc(salen
);
191 (*end
)->ifa_next
= NULL
;
192 (*end
)->ifa_name
= tmp_name
;
193 (*end
)->ifa_flags
= ifreq
.ifr_flags
;
194 (*end
)->ifa_addr
= tmp_addr
;
195 memcpy((*end
)->ifa_addr
, sa
, salen
);
196 (*end
)->ifa_netmask
= NULL
;
199 /* fix these when we actually need them */
200 if (ifreq
.ifr_flags
& IFF_BROADCAST
) {
201 (*end
)->ifa_broadaddr
=
202 malloc(sizeof(ifr
->ifr_broadaddr
));
203 memcpy((*end
)->ifa_broadaddr
, &ifr
->ifr_broadaddr
,
204 sizeof(ifr
->ifr_broadaddr
));
205 } else if (ifreq
.ifr_flags
& IFF_POINTOPOINT
) {
206 (*end
)->ifa_dstaddr
= malloc(sizeof(ifr
->ifr_dstaddr
));
207 memcpy((*end
)->ifa_dstaddr
, &ifr
->ifr_dstaddr
,
208 sizeof(ifr
->ifr_dstaddr
));
210 (*end
)->ifa_dstaddr
= NULL
;
212 (*end
)->ifa_dstaddr
= NULL
;
215 (*end
)->ifa_data
= NULL
;
217 end
= &(*end
)->ifa_next
;
237 getifaddrs(struct ifaddrs
**ifap
)
243 #if defined(PF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
245 ret
= getifaddrs2(ifap
, PF_INET6
, SIOCGIF6CONF
, SIOCGIF6FLAGS
,
246 sizeof(struct in6_ifreq
));
248 #if defined(CONFIG_IPV6) && defined(SIOCGIFCONF)
250 ret
= getifaddrs2(ifap
, PF_INET6
, SIOCGIFCONF
, SIOCGIFFLAGS
,
251 sizeof(struct ifreq
));
253 #if defined(PF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
255 ret
= getifaddrs2(ifap
, PF_INET
, SIOCGIFCONF
, SIOCGIFFLAGS
,
256 sizeof(struct ifreq
));
263 freeifaddrs(struct ifaddrs
*ifp
)
265 struct ifaddrs
*p
, *q
;
272 free(p
->ifa_dstaddr
);
274 free(p
->ifa_netmask
);
283 #ifdef TEST_GETIFADDRS
286 print_addr(const char *s
, struct sockaddr
*sa
)
290 printf(" %s=%d/", s
, sa
->sa_family
);
291 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
293 i
< sa
->sa_len
- ((long) sa
->sa_data
- (long) &sa
->sa_family
); i
++)
294 printf("%02x", ((unsigned char *) sa
->sa_data
)[i
]);
296 for (i
= 0; i
< sizeof(sa
->sa_data
); i
++)
297 printf("%02x", ((unsigned char *) sa
->sa_data
)[i
]);
303 print_ifaddrs(struct ifaddrs
*x
)
307 for (p
= x
; p
; p
= p
->ifa_next
) {
308 printf("%s\n", p
->ifa_name
);
309 printf(" flags=%x\n", p
->ifa_flags
);
311 print_addr("addr", p
->ifa_addr
);
313 print_addr("dstaddr", p
->ifa_dstaddr
);
315 print_addr("netmask", p
->ifa_netmask
);
316 printf(" %p\n", p
->ifa_data
);
323 struct ifaddrs
*a
= NULL
, *b
;
325 getifaddrs2(&a
, PF_INET
, SIOCGIFCONF
, SIOCGIFFLAGS
,
326 sizeof(struct ifreq
));
334 #endif /* TEST_GETIFADDRS */
336 #endif /* HAVE_GETIFADDRS */