From 573a9a5c5b9021e84267b34638770c13a99b4669 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 2 Dec 2011 13:42:36 +0000 Subject: [PATCH] eeze 1.2 is now operational SVN revision: 65809 --- legacy/eeze/configure.ac | 34 +++ legacy/eeze/src/lib/Eeze_Net.h | 62 +++++ legacy/eeze/src/lib/Makefile.am | 2 + legacy/eeze/src/lib/eeze_main.c | 34 ++- legacy/eeze/src/lib/eeze_net.c | 319 +++++++++++++++++++++++++ legacy/eeze/src/lib/eeze_net_private.h | 53 ++++ 6 files changed, 496 insertions(+), 8 deletions(-) create mode 100644 legacy/eeze/src/lib/Eeze_Net.h create mode 100644 legacy/eeze/src/lib/eeze_net.c create mode 100644 legacy/eeze/src/lib/eeze_net_private.h diff --git a/legacy/eeze/configure.ac b/legacy/eeze/configure.ac index 228cdc65d4..a300a02d32 100644 --- a/legacy/eeze/configure.ac +++ b/legacy/eeze/configure.ac @@ -153,6 +153,38 @@ fi if test -z "$OLD_LIBMOUNT_TRUE" ; then AC_DEFINE_UNQUOTED([OLD_LIBMOUNT], [1], [using first version of libmount]) fi + +AC_CHECK_HEADERS([netinet/in.h]) +want_ipv6="yes" +have_ipv6="no" + +AC_ARG_ENABLE([ipv6], + [AC_HELP_STRING([--disable-ipv6], + [disable ipv6 functionality @<:@default=detect@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_ipv6="yes" + else + want_ipv6="no" + fi], + [want_ipv6="auto"]) + +# Verify IPV6 availability in headers +if test "x${want_ipv6}" != "xno" ; then + AC_CHECK_TYPES([struct ipv6_mreq], + [have_ipv6="yes"], + [have_ipv6="no"], + [[ +#ifdef HAVE_NETINET_IN_H +# include +#endif + ]]) +fi + +if test "x${have_ipv6}" = "xyes" ; then + AC_DEFINE(HAVE_IPV6, 1, [Define if IPV6 is supported]) +fi + ### Checks for header files @@ -226,6 +258,8 @@ echo echo "Utilities..............:" echo " eeze_scanner.........: ${have_eeze_scanner}" echo +echo "IPv6...................: ${have_ipv6}" +echo echo "Documentation..........: ${build_doc}" echo echo "Compilation............: make (or gmake)" diff --git a/legacy/eeze/src/lib/Eeze_Net.h b/legacy/eeze/src/lib/Eeze_Net.h new file mode 100644 index 0000000000..97a17ca00a --- /dev/null +++ b/legacy/eeze/src/lib/Eeze_Net.h @@ -0,0 +1,62 @@ +#ifndef EEZE_NET_H +#define EEZE_NET_H + +#ifdef EAPI +# undef EAPI +#endif + +#ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#else +# define EAPI +#endif + +#include +#include + +/** + * @file Eeze_Net.h + * @brief Network manipulation + * + * Eeze net functions allow you to gather information about network objects + * + * @addtogroup net Net + * @{ + */ + +typedef struct Eeze_Net Eeze_Net; + +typedef enum +{ + EEZE_NET_ADDR_TYPE_IP, + EEZE_NET_ADDR_TYPE_IP6, + EEZE_NET_ADDR_TYPE_BROADCAST, + EEZE_NET_ADDR_TYPE_BROADCAST6, + EEZE_NET_ADDR_TYPE_NETMASK, + EEZE_NET_ADDR_TYPE_NETMASK6, +} Eeze_Net_Addr_Type; + +#ifdef __cplusplus +extern "C" { +#endif + +EAPI Eeze_Net *eeze_net_new(const char *name); +EAPI void eeze_net_free(Eeze_Net *net); +EAPI const char *eeze_net_mac_get(Eeze_Net *net); +EAPI int eeze_net_idx_get(Eeze_Net *net); +EAPI Eina_Bool eeze_net_scan(Eeze_Net *net); +EAPI const char *eeze_net_addr_get(Eeze_Net *net, Eeze_Net_Addr_Type type); +EAPI const char *eeze_net_attribute_get(Eeze_Net *net, const char *attr); +EAPI const char *eeze_net_syspath_get(Eeze_Net *net); +EAPI Eina_List *eeze_net_list(void); + +#ifdef __cplusplus +} +#endif +/** @} */ + +#endif diff --git a/legacy/eeze/src/lib/Makefile.am b/legacy/eeze/src/lib/Makefile.am index e92fe459a2..3eedae976e 100644 --- a/legacy/eeze/src/lib/Makefile.am +++ b/legacy/eeze/src/lib/Makefile.am @@ -23,6 +23,8 @@ includesdir = $(includedir)/eeze-@VMAJ@ libeeze_la_SOURCES = \ eeze_main.c \ +eeze_net.c \ +eeze_net_private.h \ eeze_udev_find.c \ eeze_udev_private.h \ eeze_udev_private.c \ diff --git a/legacy/eeze/src/lib/eeze_main.c b/legacy/eeze/src/lib/eeze_main.c index 0ca5986799..e1fe7f0842 100644 --- a/legacy/eeze/src/lib/eeze_main.c +++ b/legacy/eeze/src/lib/eeze_main.c @@ -6,11 +6,13 @@ #include #include #include "eeze_udev_private.h" +#include "eeze_net_private.h" #include "eeze_disk_private.h" _udev *udev; int _eeze_udev_log_dom = -1; +int _eeze_net_log_dom = -1; int _eeze_init_count = 0; static Eeze_Version _version = { VMAJ, VMIN, VMIC, VREV }; @@ -25,36 +27,51 @@ eeze_init(void) if (!eina_init()) return 0; - _eeze_udev_log_dom = eina_log_domain_register - ("eeze_udev", EINA_COLOR_CYAN); - + _eeze_udev_log_dom = eina_log_domain_register("eeze_udev", EINA_COLOR_CYAN); if (_eeze_udev_log_dom < 0) { EINA_LOG_ERR("Could not register 'eeze_udev' log domain."); goto eina_fail; } + _eeze_net_log_dom = eina_log_domain_register("eeze_net", EINA_COLOR_GREEN); + if (_eeze_net_log_dom < 0) + { + EINA_LOG_ERR("Could not register 'eeze_net' log domain."); + goto eina_net_fail; + } + if (!ecore_init()) - goto fail; + goto ecore_fail; #ifdef HAVE_EEZE_MOUNT if (!eeze_disk_init()) goto eeze_fail; #endif - if (!((udev) = udev_new())) + if (!(udev = udev_new())) { EINA_LOG_ERR("Could not initialize udev library!"); - goto ecore_fail; + goto fail; + } + if (!eeze_net_init()) + { + EINA_LOG_ERR("Error initializing eeze_net subsystems!"); + goto net_fail; } return _eeze_init_count; -ecore_fail: +net_fail: + udev_unref(udev); +fail: #ifdef HAVE_EEZE_MOUNT eeze_disk_shutdown(); eeze_fail: #endif ecore_shutdown(); -fail: +ecore_fail: + eina_log_domain_unregister(_eeze_net_log_dom); + _eeze_net_log_dom = -1; +eina_net_fail: eina_log_domain_unregister(_eeze_udev_log_dom); _eeze_udev_log_dom = -1; eina_fail: @@ -72,6 +89,7 @@ eeze_shutdown(void) #ifdef HAVE_EEZE_MOUNT eeze_disk_shutdown(); #endif + eeze_net_shutdown(); ecore_shutdown(); eina_log_domain_unregister(_eeze_udev_log_dom); _eeze_udev_log_dom = -1; diff --git a/legacy/eeze/src/lib/eeze_net.c b/legacy/eeze/src/lib/eeze_net.c new file mode 100644 index 0000000000..a57f7ac4a4 --- /dev/null +++ b/legacy/eeze/src/lib/eeze_net.c @@ -0,0 +1,319 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "eeze_udev_private.h" +#include "eeze_net_private.h" + +static Eina_Hash *eeze_nets = NULL; + +Eina_Bool +eeze_net_init(void) +{ + eeze_nets = eina_hash_string_superfast_new(NULL); + return !!eeze_nets; +} + +void +eeze_net_shutdown(void) +{ + eina_hash_free(eeze_nets); + eeze_nets = NULL; +} + +/** @addtogroup net Net + * @{ + */ + +/** + * @brief Create a new net object + * @param name The name of the underlying device (eth0, br1, etc) + * @return A newly allocated net object, or NULL on failure + * + * This function creates a new net object based on @p name. + * Only the most minimal lookups are performed at creation in order + * to save memory. + */ +Eeze_Net * +eeze_net_new(const char *name) +{ + const char *syspath; + const char *idx; + _udev_enumerate *en; + _udev_list_entry *devs, *cur; + _udev_device *device; + Eeze_Net *net; + + net = eina_hash_find(eeze_nets, name); + if (net) + { + EINA_REFCOUNT_REF(net); + return net; + } + + en = udev_enumerate_new(udev); + udev_enumerate_add_match_sysname(en, name); + udev_enumerate_add_match_subsystem(en, "net"); + udev_enumerate_scan_devices(en); + devs = udev_enumerate_get_list_entry(en); + udev_list_entry_foreach(cur, devs) + { + const char *devname, *test; + + devname = udev_list_entry_get_name(cur); + test = strrchr(devname, '/'); + if (strcmp(++test, name)) continue; + device = _new_device(devname); + syspath = eina_stringshare_add(name); + break; + } + if (!device) return NULL; + net = calloc(1, sizeof(Eeze_Net)); + if (!net) return NULL; + EINA_REFCOUNT_INIT(net); + net->device = device; + net->syspath = syspath; + net->name = eina_stringshare_add(name); + idx = udev_device_get_sysattr_value(net->device, "ifindex"); + net->index = atoi(idx); + eina_hash_add(eeze_nets, name, net); + udev_enumerate_unref(en); + return net; +} + +/** + * @brief Free a net object + * @param net The object to free + * + * Use this function to free a net object. + * @see eeze_net_new() + * @see eeze_net_list() + */ +void +eeze_net_free(Eeze_Net *net) +{ + EINA_SAFETY_ON_NULL_RETURN(net); + + EINA_REFCOUNT_UNREF(net) + { + udev_device_unref(net->device); + eina_stringshare_del(net->syspath); + eina_stringshare_del(net->name); + eina_stringshare_del(net->ip); + eina_stringshare_del(net->broadip); + eina_stringshare_del(net->netmask); +#ifdef HAVE_IPV6 + eina_stringshare_del(net->ip6); + eina_stringshare_del(net->broadip6); + eina_stringshare_del(net->netmask6); +#endif + free(net); + } +} + +/** + * @brief Get the MAC address of a net object + * @param net The net object + * @return The MAC address, NULL on failure + * Use this function to retrieve the non-stringshared MAC address of @p net. + */ +const char * +eeze_net_mac_get(Eeze_Net *net) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(net, NULL); + + return udev_device_get_sysattr_value(net->device, "address"); +} + +/** + * @brief Get the index of a net object + * @param net The net object + * @return The ifindex of the object, -1 on failure + * Use this function to get the hardware index of @p net + */ +int +eeze_net_idx_get(Eeze_Net *net) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(net, -1); + return net->index; +} + +/** + * @brief Scan an interface to cache its network addresses + * @param net The net object to scan + * @return EINA_TRUE on success, EINA_FALSE on failure + * Use this function to scan and cache the ip address, netmask, and broadcast + * address for an interface. This function will perform a full scan every time + * it is called, and IPv6 addresses will be cached if Eeze was compiled with IPv6 + * support was enabled at compile time. + * @see eeze_net_addr_get() + */ +Eina_Bool +eeze_net_scan(Eeze_Net *net) +{ + char ip[INET_ADDRSTRLEN]; +#ifdef HAVE_IPV6 + char ip6[INET6_ADDRSTRLEN]; + struct sockaddr_in6 *sa6; +#endif + int sock; + int ioctls[5] = {SIOCGIFADDR, SIOCGIFBRDADDR, SIOCGIFNETMASK}, *i = ioctls; + struct ifreq ifr; + struct sockaddr_in *sa; + + EINA_SAFETY_ON_NULL_RETURN_VAL(net, EINA_FALSE); + + /* ensure that we have the right name, mostly for hahas */ + if_indextoname((unsigned int)net->index, ifr.ifr_name); + ifr.ifr_addr.sa_family = AF_INET; + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return EINA_FALSE; + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa = (struct sockaddr_in*) & (ifr.ifr_addr); + inet_ntop(AF_INET, (struct in_addr*)&sa->sin_addr, ip, INET_ADDRSTRLEN); + eina_stringshare_replace_length(&net->ip, ip, INET_ADDRSTRLEN); + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa = (struct sockaddr_in*) & (ifr.ifr_broadaddr); + inet_ntop(AF_INET, (struct in_addr*)&sa->sin_addr, ip, INET_ADDRSTRLEN); + eina_stringshare_replace_length(&net->broadip, ip, INET_ADDRSTRLEN); + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa = (struct sockaddr_in*) & (ifr.ifr_netmask); + inet_ntop(AF_INET, (struct in_addr*)&sa->sin_addr, ip, INET_ADDRSTRLEN); + eina_stringshare_replace_length(&net->netmask, ip, INET_ADDRSTRLEN); + + close(sock); +#ifdef HAVE_IPV6 + ifr.ifr_addr.sa_family = AF_INET6; + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) return EINA_FALSE; + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa6 = (struct sockaddr_in6*) & (ifr.ifr_addr); + inet_ntop(AF_INET6, (struct in6_addr*)&sa6->sin6_addr, ip6, INET6_ADDRSTRLEN); + eina_stringshare_replace_length(&net->ip6, ip6, INET6_ADDRSTRLEN); + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa6 = (struct sockaddr_in6*) & (ifr.ifr_broadaddr); + inet_ntop(AF_INET6, (struct in6_addr*)&sa6->sin6_addr, ip6, INET6_ADDRSTRLEN); + eina_stringshare_replace_length(&net->broadip6, ip6, INET6_ADDRSTRLEN); + + if (ioctl(sock, *i++, &ifr) < 0) goto error; + sa6 = (struct sockaddr_in6*) & (ifr.ifr_netmask); + inet_ntop(AF_INET6, (struct in6_addr*)&sa6->sin6_addr, ip6, INET6_ADDRSTRLEN); + eina_stringshare_replace_length(&net->netmask6, ip6, INET6_ADDRSTRLEN); + + close(sock); +#endif + + return EINA_TRUE; +error: + close(sock); + return EINA_FALSE; +} + +/** + * @brief Get the address of a net object + * @param net The net object + * @param type The type of address to retrieve + * @return The stringshared address for @p net corresponding to @p type, NULL on failure + * This function returns a value previously cached. + * @see eeze_net_scan() + */ +const char * +eeze_net_addr_get(Eeze_Net *net, Eeze_Net_Addr_Type type) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(net, NULL); + + switch (type) + { + case EEZE_NET_ADDR_TYPE_IP6: +#ifdef HAVE_IPV6 + return net->ip6; +#else + return NULL; +#endif + case EEZE_NET_ADDR_TYPE_BROADCAST: + return net->broadip; + case EEZE_NET_ADDR_TYPE_BROADCAST6: +#ifdef HAVE_IPV6 + return net->broadip6; +#else + return NULL; +#endif + case EEZE_NET_ADDR_TYPE_NETMASK: + return net->netmask; + case EEZE_NET_ADDR_TYPE_NETMASK6: +#ifdef HAVE_IPV6 + return net->netmask6; +#else + return NULL; +#endif + default: + break; + } + return net->ip; +} + +/** + * @brief Get a system attribute of a net object + * @param net The net object + * @param attr The attribute to retrieve + * @return The non-stringshared value of the attribute, NULL on failure + * Use this function to perform a udev sysattr lookup on the underlying device of @p net + */ +const char * +eeze_net_attribute_get(Eeze_Net *net, const char *attr) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(net, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(attr, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(!attr[0], NULL); + + return udev_device_get_sysattr_value(net->device, attr); +} + +/** + * @brief Get the /sys/ path of a net object + * @param net The net object + * @return The stringshared /sys/ path of the interface, NULL on failure + */ +const char * +eeze_net_syspath_get(Eeze_Net *net) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(net, NULL); + + return net->syspath; +} + +/** + * @brief Get a list of all the network interfaces available + * @return A list of Eeze_Net objects + * Use this function to get all network interfaces available to the application. + * This list must be freed by the user. + */ +Eina_List * +eeze_net_list(void) +{ + struct if_nameindex *ifs, *i; + Eina_List *ret = NULL; + Eeze_Net *net; + + ifs = if_nameindex(); + for (i = ifs; i && i->if_name && i->if_name[0]; i++) + { + net = eeze_net_new(i->if_name); + if (net) ret = eina_list_append(ret, net); + } + + if_freenameindex(ifs); + return ret; +} +/** @} */ diff --git a/legacy/eeze/src/lib/eeze_net_private.h b/legacy/eeze/src/lib/eeze_net_private.h new file mode 100644 index 0000000000..d9b8faf115 --- /dev/null +++ b/legacy/eeze/src/lib/eeze_net_private.h @@ -0,0 +1,53 @@ +#ifndef EEZE_NET_PRIVATE_H +#define EEZE_NET_PRIVATE_H +#include +#include "eeze_udev_private.h" + +#ifndef EEZE_NET_COLOR_DEFAULT +#define EEZE_NET_COLOR_DEFAULT EINA_COLOR_GREEN +#endif +extern int _eeze_net_log_dom; +#ifdef CRI +#undef CRI +#endif + +#ifdef ERR +#undef ERR +#endif +#ifdef INF +#undef INF +#endif +#ifdef WARN +#undef WARN +#endif +#ifdef DBG +#undef DBG +#endif + +#define CRI(...) EINA_LOG_DOM_CRIT(_eeze_net_log_dom, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(_eeze_net_log_dom, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_eeze_net_log_dom, __VA_ARGS__) +#define WARN(...) EINA_LOG_DOM_WARN(_eeze_net_log_dom, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_eeze_net_log_dom, __VA_ARGS__) + +struct Eeze_Net +{ + EINA_REFCOUNT; + int index; + _udev_device *device; + const char *syspath; + const char *name; + + const char *ip; + const char *broadip; + const char *netmask; +#ifdef HAVE_IPV6 + const char *ip6; + const char *broadip6; + const char *netmask6; +#endif +}; + +Eina_Bool eeze_net_init(void); +void eeze_net_shutdown(void); +#endif