1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

introduce getifaddrs for toolchains without it

David found that uclibc did not provide this slightly esoteric api
and provided one from BSD that can be built by the library internally.

AG: Made contingent on configure option --enable-builtin-getifaddrs

Signed-off-by: David <cymerio@gmail.com>
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
David 2013-01-12 20:39:47 +08:00 committed by Andy Green
parent 41c5803d0f
commit c4ef7b1609
6 changed files with 375 additions and 0 deletions

View file

@ -24,6 +24,8 @@ disabled when building this way
3) ./configure --prefix=/usr --enable-mingw --host=x86_64-w64-mingw32
4) make
For uClibc, you will likely need --enable-builtin-getifaddrs
otherwise if /usr/local/... and /usr/local/lib are OK then...
$ ./configure
@ -63,6 +65,11 @@ There are a couple of other possible configure options
--enable-x-google-mux Enable experimental x-google-mux support
in the build (see notes later in document)
--enable-builtin-getifaddrs if your libc lacks getifaddrs, you can build an
implementation into the library. By default your libc
one is used.
Testing server with a browser
-----------------------------

View file

@ -123,6 +123,20 @@ fi
AM_CONDITIONAL(DISABLE_DEBUG, test x$disable_debug = xyes)
#
#
#
AC_ARG_ENABLE(builtin-getifaddrs,
[ --enable-builtin-getifaddrs Use BSD getifaddrs implementation from libwebsockets... default is your libc provides it],
[ builtin_getifaddrs=yes
])
if test "x$x_google_mux" = "xyes" ; then
CFLAGS="$CFLAGS -DLWS_BUILTIN_GETIFADDRS"
fi
AM_CONDITIONAL(USE_BUILTIN_GETIFADDRS, test x$builtin_getifaddrs = xyes)
# Checks for header files.
AC_CHECK_HEADERS([zlib.h fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h sys/prctl.h])

View file

@ -11,6 +11,9 @@ dist_libwebsockets_la_SOURCES=libwebsockets.c \
extension-deflate-frame.c extension-deflate-frame.h\
private-libwebsockets.h
if USE_BUILTIN_GETIFADDRS
dist_libwebsockets_la_SOURCES += getifaddrs.c
endif
if EXT_GOOGLE_MUX
dist_libwebsockets_la_SOURCES += extension-x-google-mux.c extension-x-google-mux.h

271
lib/getifaddrs.c Normal file
View file

@ -0,0 +1,271 @@
/* downloaded from http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c */
#if !HAVE_GETIFADDRS
/*
* Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#ifdef HAVE_NETINET_IN6_VAR_H
#include <netinet/in6_var.h>
#endif
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
#include "getifaddrs.h"
static int
getifaddrs2(struct ifaddrs **ifap,
int af, int siocgifconf, int siocgifflags,
size_t ifreq_sz)
{
int ret;
int fd;
size_t buf_size;
char *buf;
struct ifconf ifconf;
char *p;
size_t sz;
struct sockaddr sa_zero;
struct ifreq *ifr;
struct ifaddrs *start, **end = &start;
buf = NULL;
memset (&sa_zero, 0, sizeof(sa_zero));
fd = socket(af, SOCK_DGRAM, 0);
if (fd < 0)
return -1;
buf_size = 8192;
for (;;) {
buf = calloc(1, buf_size);
if (buf == NULL) {
ret = ENOMEM;
goto error_out;
}
ifconf.ifc_len = buf_size;
ifconf.ifc_buf = buf;
/*
* Solaris returns EINVAL when the buffer is too small.
*/
if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
ret = errno;
goto error_out;
}
/*
* Can the difference between a full and a overfull buf
* be determined?
*/
if (ifconf.ifc_len < (int)buf_size)
break;
free (buf);
buf_size *= 2;
}
for (p = ifconf.ifc_buf;
p < ifconf.ifc_buf + ifconf.ifc_len;
p += sz) {
struct ifreq ifreq;
struct sockaddr *sa;
size_t salen;
ifr = (struct ifreq *)p;
sa = &ifr->ifr_addr;
sz = ifreq_sz;
salen = sizeof(struct sockaddr);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
salen = sa->sa_len;
sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
#endif
#ifdef SA_LEN
salen = SA_LEN(sa);
sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
#endif
memset (&ifreq, 0, sizeof(ifreq));
memcpy (ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
if (ioctl(fd, siocgifflags, &ifreq) < 0) {
ret = errno;
goto error_out;
}
*end = malloc(sizeof(**end));
(*end)->ifa_next = NULL;
(*end)->ifa_name = strdup(ifr->ifr_name);
(*end)->ifa_flags = ifreq.ifr_flags;
(*end)->ifa_addr = malloc(salen);
memcpy((*end)->ifa_addr, sa, salen);
(*end)->ifa_netmask = NULL;
#if 0
/* fix these when we actually need them */
if(ifreq.ifr_flags & IFF_BROADCAST) {
(*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
sizeof(ifr->ifr_broadaddr));
} else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
(*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
sizeof(ifr->ifr_dstaddr));
} else
(*end)->ifa_dstaddr = NULL;
#else
(*end)->ifa_dstaddr = NULL;
#endif
(*end)->ifa_data = NULL;
end = &(*end)->ifa_next;
}
*ifap = start;
close(fd);
free(buf);
return 0;
error_out:
close(fd);
free(buf);
errno = ret;
return -1;
}
int
getifaddrs(struct ifaddrs **ifap)
{
int ret = -1;
errno = ENXIO;
#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
if (ret)
ret = getifaddrs2 (ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
sizeof(struct in6_ifreq));
#endif
#if defined(HAVE_IPV6) && defined(SIOCGIFCONF)
if (ret)
ret = getifaddrs2 (ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
sizeof(struct ifreq));
#endif
#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
if (ret)
ret = getifaddrs2 (ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
sizeof(struct ifreq));
#endif
return ret;
}
void
freeifaddrs(struct ifaddrs *ifp)
{
struct ifaddrs *p, *q;
for(p = ifp; p; ) {
free(p->ifa_name);
if(p->ifa_addr)
free(p->ifa_addr);
if(p->ifa_dstaddr)
free(p->ifa_dstaddr);
if(p->ifa_netmask)
free(p->ifa_netmask);
if(p->ifa_data)
free(p->ifa_data);
q = p;
p = p->ifa_next;
free(q);
}
}
#ifdef TEST
void
print_addr(const char *s, struct sockaddr *sa)
{
int i;
printf(" %s=%d/", s, sa->sa_family);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
for(i = 0; i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
printf("%02x", ((unsigned char*)sa->sa_data)[i]);
#else
for(i = 0; i < sizeof(sa->sa_data); i++)
printf("%02x", ((unsigned char*)sa->sa_data)[i]);
#endif
printf("\n");
}
void
print_ifaddrs(struct ifaddrs *x)
{
struct ifaddrs *p;
for(p = x; p; p = p->ifa_next) {
printf("%s\n", p->ifa_name);
printf(" flags=%x\n", p->ifa_flags);
if(p->ifa_addr)
print_addr("addr", p->ifa_addr);
if(p->ifa_dstaddr)
print_addr("dstaddr", p->ifa_dstaddr);
if(p->ifa_netmask)
print_addr("netmask", p->ifa_netmask);
printf(" %p\n", p->ifa_data);
}
}
int
main()
{
struct ifaddrs *a = NULL, *b;
getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq));
print_ifaddrs(a);
printf("---\n");
getifaddrs(&b);
print_ifaddrs(b);
return 0;
}
#endif
#endif

76
lib/getifaddrs.h Normal file
View file

@ -0,0 +1,76 @@
#if HAVE_GETIFADDRS
#include <sys/types.h>
#include <ifaddrs.h>
#else
#ifdef __cplusplus
extern "C" {
#endif
/*
* Copyright (c) 2000 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ */
#ifndef __ifaddrs_h__
#define __ifaddrs_h__
/*
* the interface is defined in terms of the fields below, and this is
* sometimes #define'd, so there seems to be no simple way of solving
* this and this seemed the best. */
#undef ifa_dstaddr
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
#ifndef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr
#endif
int getifaddrs(struct ifaddrs**);
void freeifaddrs(struct ifaddrs*);
#endif /* __ifaddrs_h__ */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -25,7 +25,11 @@
#include <tchar.h>
#include <io.h>
#else
#ifdef LWS_BUILTIN_GETIFADDRS
#include <getifaddrs.h>
#else
#include <ifaddrs.h>
#endif
#include <sys/un.h>
#include <sys/socket.h>
#include <netdb.h>