introduce getifaddrs for toolchains without it 84/2884/1
authorDavid <cymerio@gmail.com>
Sat, 12 Jan 2013 12:39:47 +0000 (20:39 +0800)
committerKevron Rees <kevron_m_rees@linux.intel.com>
Thu, 7 Mar 2013 21:01:24 +0000 (13:01 -0800)
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>
README-test-server
configure.ac
lib/Makefile.am
lib/getifaddrs.c [new file with mode: 0644]
lib/getifaddrs.h [new file with mode: 0644]
lib/libwebsockets.c

index a8d9999..a2ce210 100644 (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
 -----------------------------
 
index 8afdd4d..fce0311 100644 (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])
 
index 6fb8d05..b1eb434 100644 (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
diff --git a/lib/getifaddrs.c b/lib/getifaddrs.c
new file mode 100644 (file)
index 0000000..1591a43
--- /dev/null
@@ -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
diff --git a/lib/getifaddrs.h b/lib/getifaddrs.h
new file mode 100644 (file)
index 0000000..5686465
--- /dev/null
@@ -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
index b36a9b2..dd6e8d7 100644 (file)
 #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>