summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-10-07 09:45:39 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-10-16 14:27:24 -0400
commit01bf2fcf57944104f9a774c8716950f397d666ce (patch)
tree7d20b82674596a0946a2b339f807cf84fc58c769
parent82648b5af3cb5e68a48fe1e798ef48254ccbecb8 (diff)
downloadsssd-01bf2fcf57944104f9a774c8716950f397d666ce.tar.gz
sssd-01bf2fcf57944104f9a774c8716950f397d666ce.tar.xz
sssd-01bf2fcf57944104f9a774c8716950f397d666ce.zip
ELAPI Compatibility code for getifaddr()
Addreses ticket #94 Actually works pretty well. To try use --enable-compat when build ELAPI. It will use compatibility code instead of getifaddr(). The trick in the elapi_ioctl.h with memory allocation is taken from Stevens book.
-rw-r--r--common/elapi/Makefile.am4
-rw-r--r--common/elapi/conf_macros.m415
-rw-r--r--common/elapi/configure.ac3
-rw-r--r--common/elapi/elapi_basic.h5
-rw-r--r--common/elapi/elapi_defines.h27
-rw-r--r--common/elapi/elapi_event.c35
-rw-r--r--common/elapi/elapi_ioctl.c142
-rw-r--r--common/elapi/elapi_ioctl.h39
-rw-r--r--common/elapi/elapi_net.h103
-rw-r--r--common/elapi/elapi_test/Makefile.am4
10 files changed, 357 insertions, 20 deletions
diff --git a/common/elapi/Makefile.am b/common/elapi/Makefile.am
index 53f2c3eff..747a3883b 100644
--- a/common/elapi/Makefile.am
+++ b/common/elapi/Makefile.am
@@ -55,13 +55,17 @@ libelapi_la_SOURCES = \
elapi_resolve.c \
elapi_async.c \
elapi_subst.c \
+ elapi_ioctl.c \
elapi_event.h \
elapi_priv.h \
elapi_sink.h \
elapi_log.h \
elapi_async.h \
+ elapi_net.h \
+ elapi_ioctl.h \
elapi_fd.h \
elapi_tm.h \
+ elapi_defines.h \
elapi.h
libelapi_la_LIBADD = libprovider.la libelapibasic.la
diff --git a/common/elapi/conf_macros.m4 b/common/elapi/conf_macros.m4
index e20dfdbaf..e3de2b7ff 100644
--- a/common/elapi/conf_macros.m4
+++ b/common/elapi/conf_macros.m4
@@ -54,3 +54,18 @@ AC_DEFUN([WITH_APP_NAME_SIZE],
fi
AC_SUBST(appnamesize)
])
+
+AC_DEFUN([WITH_COMPAT],
+ [ AC_ARG_ENABLE([compat],
+ [AC_HELP_STRING([--enable-compat],
+ [use platform compatibility code])
+ ],
+ ,
+ [AC_CHECK_FUNC([getifaddrs],
+ AC_DEFINE([HAVE_GETIFADDRS], [1],
+ [Define if platform has getifaddrs()])
+ )
+ ]
+ )
+
+ ])
diff --git a/common/elapi/configure.ac b/common/elapi/configure.ac
index ad2ffceec..82be136df 100644
--- a/common/elapi/configure.ac
+++ b/common/elapi/configure.ac
@@ -14,6 +14,7 @@ AM_SILENT_RULES
AC_CONFIG_HEADERS([config.h])
+
# Enable trace build
AC_ARG_ENABLE([trace],
[AS_HELP_STRING([--enable-trace[=LEVEL]],[build with low level tracing enabled])],
@@ -21,12 +22,14 @@ AC_ARG_ENABLE([trace],
[trace_level="0"])
AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])])
+
m4_include(conf_macros.m4)
WITH_CONFIG_DIR
WITH_CONFIG_APP_DIR
WITH_APP_NAME
WITH_APP_NAME_SIZE
+WITH_COMPAT
m4_include(def_macros.m4)
diff --git a/common/elapi/elapi_basic.h b/common/elapi/elapi_basic.h
index 8d23c7db7..480ef1bf8 100644
--- a/common/elapi/elapi_basic.h
+++ b/common/elapi/elapi_basic.h
@@ -21,10 +21,7 @@
#define ELAPI_BASIC_H
#include <stdint.h>
-
-#ifndef EOK
-#define EOK 0
-#endif
+#include "elapi_defines.h"
/* Generic data structure for the data output */
struct elapi_data_out {
diff --git a/common/elapi/elapi_defines.h b/common/elapi/elapi_defines.h
new file mode 100644
index 000000000..84030e86f
--- /dev/null
+++ b/common/elapi/elapi_defines.h
@@ -0,0 +1,27 @@
+/*
+ ELAPI
+
+ Global defines for ELAPI
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ELAPI_DEFINES_H
+#define ELAPI_DEFINES_H
+
+#ifndef EOK
+#define EOK 0
+#endif
+
+#endif
diff --git a/common/elapi/elapi_event.c b/common/elapi/elapi_event.c
index e7a5d779e..ff7393933 100644
--- a/common/elapi/elapi_event.c
+++ b/common/elapi/elapi_event.c
@@ -31,10 +31,10 @@
#include <ctype.h> /* for isspace() */
#include <stdarg.h> /* for va_arg() */
#include <string.h> /* for strndup() */
-#include <ifaddrs.h> /* for getifaddrs() */
#include "elapi_priv.h"
#include "elapi_event.h"
+#include "elapi_net.h"
#include "trace.h"
#include "config.h"
@@ -69,7 +69,9 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
char host[NI_MAXHOST];
char address[NI_MAXHOST];
char *hnm, *haddr;
- struct ifaddrs *ifaddr, *ifa;
+ ELAPI_ADDRLIST ifaddr;
+ ELAPI_ADDRITEM ifa;
+ struct sockaddr *addr;
int family;
int set_hostname = 0;
int set_ip = 0;
@@ -88,26 +90,27 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
/* If we are not asked for ip then say we already have it */
if (!(base & E_HAVE_HOSTIP)) set_ip = 1;
- if (getifaddrs(&ifaddr) == EOK) {
+ if (ELAPI_GET_ADDRLIST(&ifaddr) == EOK) {
TRACE_FLOW_STRING("getifaddrs", "Ok");
/* Walk through linked list, maintaining head pointer so we
can free list later */
+ ELAPI_GET_FIRST_ADDR_ITEM(ifaddr, ifa);
- ifa = ifaddr;
while (ifa != NULL) {
TRACE_FLOW_STRING("Top of the loop", "");
used_this_ip = 0;
- if (!ifa->ifa_addr) {
- ifa = ifa->ifa_next;
+ ELAPI_GET_ADDR(ifa, addr);
+ if (!addr) {
+ ELAPI_GET_NEXT_ADDR_ITEM(ifaddr, ifa);
continue;
}
- family = ifa->ifa_addr->sa_family;
+ family = addr->sa_family;
TRACE_FLOW_NUMBER("Family", family);
@@ -121,7 +124,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
* We will trust it here and not clear memory using memset.
*/
- gai_ret_host = getnameinfo(ifa->ifa_addr,
+ gai_ret_host = getnameinfo(addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host,
@@ -130,7 +133,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
0,
0 /* Gets host name */);
- gai_ret_addr = getnameinfo(ifa->ifa_addr,
+ gai_ret_addr = getnameinfo(addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
address,
@@ -173,7 +176,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
error = col_add_str_property(tpl, NULL, E_HOSTNAME, hnm, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to add host name. Error", error);
- freeifaddrs(ifaddr);
+ ELAPI_ADDR_LIST_CLEANUP(ifaddr);
return error;
}
/* Done with the name */
@@ -201,7 +204,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
error = col_add_str_property(tpl, NULL, E_HOSTIP, haddr, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to add host name. Error", error);
- freeifaddrs(ifaddr);
+ ELAPI_ADDR_LIST_CLEANUP(ifaddr);
return error;
}
set_ip = 1;
@@ -230,7 +233,7 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
error = col_add_str_property(tpl, NULL, E_HOSTALIAS, hnm, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to add host name. Error", error);
- freeifaddrs(ifaddr);
+ ELAPI_ADDR_LIST_CLEANUP(ifaddr);
return error;
}
}
@@ -253,18 +256,18 @@ static int add_host_identity(struct collection_item *tpl, unsigned base)
error = col_add_str_property(tpl, NULL, E_HOSTIPS, haddr, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to add host name. Error", error);
- freeifaddrs(ifaddr);
+ ELAPI_ADDR_LIST_CLEANUP(ifaddr);
return error;
}
}
}
}
- TRACE_INFO_NUMBER("Moving to next", ifa->ifa_next);
- ifa = ifa->ifa_next;
+ TRACE_INFO_STRING("Moved to next", "");
+ ELAPI_GET_NEXT_ADDR_ITEM(ifaddr, ifa);
TRACE_INFO_NUMBER("Moved to", ifa);
}
- freeifaddrs(ifaddr);
+ ELAPI_ADDR_LIST_CLEANUP(ifaddr);
}
/* Make sure that we really have the name after all */
diff --git a/common/elapi/elapi_ioctl.c b/common/elapi/elapi_ioctl.c
new file mode 100644
index 000000000..c2a42a17c
--- /dev/null
+++ b/common/elapi/elapi_ioctl.c
@@ -0,0 +1,142 @@
+/*
+ ELAPI
+
+ Special platform specific functions related to networking
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "elapi_ioctl.h"
+#include "trace.h"
+#include "config.h"
+
+#ifndef HAVE_GETIFADDRS
+
+/* These functions are taken form Stevens's
+ * UNIX Network Programming Volume 1
+ */
+
+int elapi_get_addrlist(struct ifconf *ifc)
+{
+ int sockfd;
+ int length, lastlen;
+ int error;
+ char *buffer;
+
+ TRACE_FLOW_STRING("elapi_get_addrlist", "Entry");
+
+ /* Open socket */
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ lastlen = 0;
+ length = INTERFACE_NUM_GUESS * sizeof(struct ifreq);
+
+ /* Allocate right amount of memory */
+ /* This is a trick from Stevens book */
+ /* Search web for "get_ifi_info" to get original code */
+ for ( ; ; ) {
+
+ buffer = malloc(length);
+ ifc->ifc_len = length;
+ ifc->ifc_buf = buffer;
+
+ /* Read list */
+ if (ioctl(sockfd, SIOCGIFCONF, ifc) < 0) {
+ error = errno;
+ TRACE_INFO_NUMBER("Ioctl call failed", error);
+ if (error != EINVAL || lastlen != 0) {
+ free(buffer);
+ TRACE_ERROR_NUMBER("ioctl failed", error);
+ return error;
+ }
+ } else {
+ TRACE_INFO_NUMBER("Length returned", ifc->ifc_len);
+ TRACE_INFO_NUMBER("Previous length", lastlen);
+ /* Break if length is same */
+ if (ifc->ifc_len == lastlen) break;
+ lastlen = ifc->ifc_len;
+ }
+
+ /* Grow length */
+ length += INTERFACE_NUM_INC * sizeof(struct ifreq);
+ free(buffer);
+ }
+
+ TRACE_FLOW_STRING("elapi_get_addrlist", "Exit");
+ return EOK;
+}
+
+/* Get the variable part of the size of the address */
+static int elapi_get_addrlen(struct ifreq *ifr)
+{
+ int len;
+
+ TRACE_FLOW_STRING("elapi_get_addrlen", "Entry");
+
+#ifdef HAVE_SOCKADDR_SA_LEN
+ len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
+#else
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef IPV6
+ case AF_INET6:
+ len = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ case AF_INET:
+ default:
+ len = sizeof(struct sockaddr);
+ break;
+ }
+#endif /* HAVE_SOCKADDR_SA_LEN */
+
+ TRACE_FLOW_NUMBER("elapi_get_addrlen Returning", len);
+ return len;
+}
+
+/* Get next address */
+struct ifreq *elapi_get_next_addr(struct ifconf *ifc, struct ifreq *current)
+{
+ char *ifr;
+
+ TRACE_FLOW_STRING("elapi_get_next_addr", "Entry");
+
+ TRACE_INFO_NUMBER("Current ifi", current);
+ TRACE_INFO_NUMBER("Address", &current->ifr_addr);
+
+ /* Move to the next item */
+ ifr = (char *)current + sizeof(current->ifr_name) + elapi_get_addrlen(current);
+
+ TRACE_INFO_NUMBER("New ifi", ifr);
+
+ /* Check if we are beyond the end of the allocated area */
+ /* Have to cast otherwise get warnings */
+ if (ifr >= ((char *)ifc->ifc_buf + ifc->ifc_len)) ifr = NULL;
+
+ TRACE_INFO_NUMBER("New ifi adjusted", ifr);
+
+ TRACE_FLOW_STRING("elapi_get_next_addr", "Exit");
+
+ return (struct ifreq *)ifr;
+}
+
+
+#endif /* HAVE_GETIFADDRS */
diff --git a/common/elapi/elapi_ioctl.h b/common/elapi/elapi_ioctl.h
new file mode 100644
index 000000000..409cb0047
--- /dev/null
+++ b/common/elapi/elapi_ioctl.h
@@ -0,0 +1,39 @@
+/*
+ ELAPI
+
+ Header file for the ELAPI handling of network interfaces.
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ELAPI_IOCTL_H
+#define ELAPI_IOCTL_H
+
+#include "config.h"
+
+#ifndef HAVE_GETIFADDRS
+
+#include "elapi_defines.h"
+#include <net/if.h>
+
+/* Function prototypes */
+int elapi_get_addrlist(struct ifconf *ifc);
+struct ifreq *elapi_get_next_addr(struct ifconf *ifc, struct ifreq *current);
+
+#define INTERFACE_NUM_GUESS 3
+#define INTERFACE_NUM_INC 1
+
+#endif /* HAVE_GETIFADDRS */
+
+#endif
diff --git a/common/elapi/elapi_net.h b/common/elapi/elapi_net.h
new file mode 100644
index 000000000..c9f8af7e7
--- /dev/null
+++ b/common/elapi/elapi_net.h
@@ -0,0 +1,103 @@
+/*
+ ELAPI
+
+ Header file for the ELAPI handling of netwok interfaces.
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ELAPI_NET_H
+#define ELAPI_NET_H
+
+#include "config.h"
+
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h> /* for getifaddrs() */
+
+/* Macros then just wrap the getifaddrs() interface */
+
+/* Type of the variable that stores the list */
+#define ELAPI_ADDRLIST struct ifaddrs *
+
+/* Type of the variable that stores the item */
+#define ELAPI_ADDRITEM struct ifaddrs *
+
+/* Function to build list of the interfaces */
+#define ELAPI_GET_ADDRLIST getifaddrs
+
+/* Macro to get first item from the list */
+#define ELAPI_GET_FIRST_ADDR_ITEM(list, item) \
+ do { \
+ item = list; \
+ } while(0)
+
+/* Macro to get next item from the list */
+#define ELAPI_GET_NEXT_ADDR_ITEM(list, item) \
+ do { \
+ item = item->ifa_next; \
+ } while(0)
+
+
+/* Macro to get address */
+#define ELAPI_GET_ADDR(item, addr) \
+ do { \
+ addr = item->ifa_addr; \
+ } while(0)
+
+/* Function to free the list */
+#define ELAPI_ADDR_LIST_CLEANUP freeifaddrs
+
+#else
+/* Do everything using ioctl yourself... */
+
+#include "elapi_ioctl.h"
+
+/* Type of the variable that stores the list */
+#define ELAPI_ADDRLIST struct ifconf
+
+/* Type of valiable that is used as a pointer */
+#define ELAPI_ADDRITEM struct ifreq *
+
+/* Function to build list of the interfaces */
+#define ELAPI_GET_ADDRLIST elapi_get_addrlist
+
+/* Macro to get first item from the list */
+#define ELAPI_GET_FIRST_ADDR_ITEM(list, item) \
+ do { \
+ item = (struct ifreq *)list.ifc_buf; \
+ } while(0)
+
+/* Macro to get next item from the list */
+#define ELAPI_GET_NEXT_ADDR_ITEM(list, item) \
+ do { \
+ item = elapi_get_next_addr(&list, item); \
+ } while(0)
+
+
+/* Macro to get address */
+#define ELAPI_GET_ADDR(item, addr) \
+ do { \
+ addr = &(item->ifr_addr); \
+ } while(0)
+
+/* Function to free the list */
+#define ELAPI_ADDR_LIST_CLEANUP(list) \
+ do { \
+ free(list.ifc_buf); \
+ } while(0)
+
+
+#endif /* HAVE_GETIFADDRS */
+
+#endif
diff --git a/common/elapi/elapi_test/Makefile.am b/common/elapi/elapi_test/Makefile.am
index c0eac8a5d..d9f1bb0b2 100644
--- a/common/elapi/elapi_test/Makefile.am
+++ b/common/elapi/elapi_test/Makefile.am
@@ -33,13 +33,17 @@ libelapi_test_la_SOURCES = \
../elapi_resolve.c \
../elapi_async.c \
../elapi_subst.c \
+ ../elapi_ioctl.c \
../elapi_event.h \
../elapi_priv.h \
../elapi_sink.h \
../elapi_log.h \
../elapi_async.h \
+ ../elapi_ioctl.h \
+ ../elapi_net.h \
../elapi_fd.h \
../elapi_tm.h \
+ ../elapi_defines.h \
../elapi.h \
../providers/file/file_provider.c \
../providers/file/file_provider.h \