You're caching a bit too much here.
What happens if the administrator (or dhcp) changes the address after
the cache is created?
I was about to say "just cache the mapping between what windows calls
it and what sigar does[1]", but didn't we all agree to patch this in
sigar directly?
[1] You'd still need to cross reference the MAC addresses after a
lookup in case a device was removed.
On Wed, Jan 19, 2011 at 7:45 AM, Adam Stokes <astokes(a)fedoraproject.org> wrote:
- Rewrite routines to utilize hash tables for faster lookup
- os variant specific listing of interfaces due to:
- sigar reports interfaces as 'ethX' independent of the OS.
- because of above we are unable to restart devices based on Windows
friendlyname (name shown in the device manager)
- make fewer sigar calls by letting all network routines run an
initialization routine beforehand.
---
src/include/matahari/network.h | 2 +-
src/lib/network.c | 111 +++++++++++++++------------------
src/lib/network_linux.c | 30 +++++++---
src/lib/network_private.h | 9 +++
src/lib/network_windows.c | 133 ++++++++++++++++++++++++++++++++++------
5 files changed, 196 insertions(+), 89 deletions(-)
diff --git a/src/include/matahari/network.h b/src/include/matahari/network.h
index d26133d..47620e2 100644
--- a/src/include/matahari/network.h
+++ b/src/include/matahari/network.h
@@ -22,7 +22,7 @@
#include <glib.h>
#include <stdint.h>
-extern GList *network_get_interfaces(void);
+extern GHashTable *network_get_interfaces(void);
extern const char *network_get_ip_address(const char *iface);
extern const char *network_get_mac_address(const char *iface);
diff --git a/src/lib/network.c b/src/lib/network.c
index 7b66094..0236f4f 100644
--- a/src/lib/network.c
+++ b/src/lib/network.c
@@ -29,38 +29,42 @@
MH_TRACE_INIT_DATA(mh_network);
-static GList *
-query_interface_table(void)
+network_init_t network_init = { NULL, FALSE };
+
+static void
+init(void)
{
- int status;
uint32_t lpc = 0;
- GList *interfaces = NULL;
- sigar_t* sigar;
+ int status;
sigar_net_interface_list_t iflist;
sigar_net_interface_config_t *ifconfig;
- sigar_open(&sigar);
- status = sigar_net_interface_list_get(sigar, &iflist);
+ if(network_init.sigar_init) return;
+ sigar_open(&network_init.sigar);
+ network_init.sigar_init = TRUE;
+ network_init.device_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ status = sigar_net_interface_list_get(network_init.sigar, &iflist);
if(status == SIGAR_OK) {
- for(lpc = 0; lpc < iflist.number; lpc++) {
+ for(lpc; lpc < iflist.number; lpc++) {
ifconfig = g_new0(sigar_net_interface_config_t, 1);
- status = sigar_net_interface_config_get(sigar, iflist.data[lpc],
- ifconfig);
- if(status == SIGAR_OK)
- interfaces = g_list_prepend(interfaces, ifconfig);
+ status = sigar_net_interface_config_get(network_init.sigar,
+ iflist.data[lpc],
+ ifconfig);
+ g_hash_table_insert(network_init.device_hash,
+ (gpointer)ifconfig->name,
+ (gpointer)ifconfig);
}
- sigar_net_interface_list_destroy(sigar, &iflist);
}
- sigar_close(sigar);
- return interfaces;
}
-GList *
+GHashTable *
network_get_interfaces(void)
{
- GList *list = NULL;
- list = query_interface_table();
- return list;
+ init();
+ network_os_get_interfaces(&network_init);
+ return network_init.device_hash;
}
void
@@ -85,36 +89,27 @@ network_restart(const char *iface)
void
network_status(const char *iface, uint64_t *flags)
{
- GList *list = NULL;
- GList *plist;
- sigar_net_interface_config_t *ifconfig;
+ init();
+ sigar_net_interface_config_t *ifconfig =
g_hash_table_lookup(network_init.device_hash,
+ iface);
- list = network_get_interfaces();
- for(plist = g_list_first(list); plist; plist = g_list_next(plist)) {
- ifconfig = (sigar_net_interface_config_t *)plist->data;
- if((g_str_equal(ifconfig->name, iface)) == TRUE) {
- *flags = ifconfig->flags;
- }
- }
+ if(ifconfig != NULL)
+ *flags = ifconfig->flags;
}
const char *
network_get_ip_address(const char *iface)
{
- GList *list = NULL;
- GList *plist;
- sigar_net_interface_config_t *ifconfig;
+ init();
+ sigar_net_interface_config_t *ifconfig =
g_hash_table_lookup(network_init.device_hash,
+ iface);
char addr_str[SIGAR_INET6_ADDRSTRLEN];
- char *paddr_str;
-
- list = network_get_interfaces();
- for(plist = g_list_first(list); plist; plist = g_list_next(plist)) {
- ifconfig = (sigar_net_interface_config_t *)plist->data;
- if((g_str_equal(ifconfig->name, iface)) == TRUE) {
- sigar_net_address_to_string(NULL, &ifconfig->address, addr_str);
- paddr_str = g_strdup(addr_str);
- return paddr_str;
- }
+ char *paddr_str = NULL;
+
+ if(ifconfig != NULL) {
+ sigar_net_address_to_string(NULL, &ifconfig->address, addr_str);
+ paddr_str = g_strdup(addr_str);
+ return paddr_str;
}
return NULL;
}
@@ -122,24 +117,20 @@ network_get_ip_address(const char *iface)
const char *
network_get_mac_address(const char *iface)
{
- GList *list = NULL;
- GList *plist;
- sigar_net_interface_config_t *ifconfig;
- char *mac;
-
- list = network_get_interfaces();
- for(plist = g_list_first(list); plist; plist = g_list_next(plist)) {
- ifconfig = (sigar_net_interface_config_t *)plist->data;
- if((g_str_equal(ifconfig->name, iface)) == TRUE) {
- mac = g_strdup_printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
- ifconfig->hwaddr.addr.mac[0],
- ifconfig->hwaddr.addr.mac[1],
- ifconfig->hwaddr.addr.mac[2],
- ifconfig->hwaddr.addr.mac[3],
- ifconfig->hwaddr.addr.mac[4],
- ifconfig->hwaddr.addr.mac[5]);
- return mac;
- }
+ init();
+ sigar_net_interface_config_t *ifconfig =
g_hash_table_lookup(network_init.device_hash,
+ iface);
+ char *mac = NULL;
+
+ if(ifconfig != NULL) {
+ mac = g_strdup_printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ ifconfig->hwaddr.addr.mac[0],
+ ifconfig->hwaddr.addr.mac[1],
+ ifconfig->hwaddr.addr.mac[2],
+ ifconfig->hwaddr.addr.mac[3],
+ ifconfig->hwaddr.addr.mac[4],
+ ifconfig->hwaddr.addr.mac[5]);
+ return mac;
}
return NULL;
}
diff --git a/src/lib/network_linux.c b/src/lib/network_linux.c
index 2fc1420..b48391e 100644
--- a/src/lib/network_linux.c
+++ b/src/lib/network_linux.c
@@ -21,18 +21,23 @@
*/
#include "matahari/network.h"
+#include "network_private.h"
#include <string.h>
+#include <glib.h>
void
network_os_start(const char *iface)
{
- char *argv[2];
+ char *argv[5];
gboolean ret;
GError *error = NULL;
- argv[0] = "/sbin/ifup";
- argv[1] = strdup(iface);
- argv[2] = NULL;
+ argv[0] = "/sbin/ip";
+ argv[1] = "link";
+ argv[2] = "set";
+ argv[3] = strdup(iface);
+ argv[4] = "up";
+ argv[5] = NULL;
ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL,
&error);
if(ret == FALSE) {
g_error_free(error);
@@ -42,15 +47,24 @@ network_os_start(const char *iface)
void
network_os_stop(const char *iface)
{
- char *argv[2];
+ char *argv[5];
gboolean ret;
GError *error = NULL;
- argv[0] = "/sbin/ifdown";
- argv[1] = strdup(iface);
- argv[2] = NULL;
+ argv[0] = "/sbin/ip";
+ argv[1] = "link";
+ argv[2] = "set";
+ argv[3] = strdup(iface);
+ argv[4] = "down";
+ argv[5] = NULL;
ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL,
&error);
if(ret == FALSE) {
g_error_free(error);
}
}
+
+void
+network_os_get_interfaces(network_init_t *network_init)
+{
+ /* nothing here */
+}
diff --git a/src/lib/network_private.h b/src/lib/network_private.h
index 04ba74f..adc9192 100644
--- a/src/lib/network_private.h
+++ b/src/lib/network_private.h
@@ -17,6 +17,15 @@
*/
#include <glib.h>
+#include <sigar.h>
+
+typedef struct network_init_s
+{
+ sigar_t *sigar;
+ gboolean sigar_init;
+ GHashTable *device_hash;
+} network_init_t;
extern void network_os_stop(const char *iface);
extern void network_os_start(const char *iface);
+extern void network_os_get_interfaces(network_init_t *network_init);
diff --git a/src/lib/network_windows.c b/src/lib/network_windows.c
index d735ef3..14c8eaa 100644
--- a/src/lib/network_windows.c
+++ b/src/lib/network_windows.c
@@ -25,11 +25,24 @@
#endif
#include "matahari/network.h"
+#include "network_private.h"
#include <config.h>
+#include <stdio.h>
+#include <string.h>
#include <glib.h>
#include <windows.h>
+#include <iphlpapi.h>
+#include <sigar.h>
+#include <sigar_private.h>
+#include <sigar_util.h>
+#include <sigar_format.h>
+
+#define GAA_FLAGS ( GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_ANYCAST )
+#define BUFSIZE 256
+
+network_init_t win_network_init = {NULL, FALSE};
void
network_os_stop(const char *iface)
@@ -39,19 +52,23 @@ network_os_stop(const char *iface)
char *p;
char *exe_path;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
p = getenv("WINDIR");
exe_path = g_strdup_printf("%s\\system32\\netsh interface set interface %s
disabled", p, iface);
- gboolean ok = CreateProcess(NULL,
- exe_path,
- NULL,
- NULL,
- TRUE,
- 0,
- NULL,
- NULL,
- &si,
- &pi);
+ CreateProcess(NULL,
+ exe_path,
+ NULL,
+ NULL,
+ TRUE,
+ 0,
+ NULL,
+ NULL,
+ &si,
+ &pi);
+ WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
@@ -66,21 +83,97 @@ network_os_start(const char *iface)
char *p;
char *exe_path;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
p = getenv("WINDIR");
exe_path = g_strdup_printf("%s\\system32\\netsh interface set interface %s
enabled", p, iface);
- gboolean ok = CreateProcess(NULL,
- exe_path,
- NULL,
- NULL,
- TRUE,
- 0,
- NULL,
- NULL,
- &si,
- &pi);
+ CreateProcess(NULL,
+ exe_path,
+ NULL,
+ NULL,
+ TRUE,
+ 0,
+ NULL,
+ NULL,
+ &si,
+ &pi);
+ WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
g_free(exe_path);
}
+
+static void
+set_iface_mac_hash(void)
+{
+ DWORD tableSize = 0;
+ int r = 0;
+ char wName[BUFSIZE];
+ PIP_ADAPTER_ADDRESSES pAddresses = NULL, adapter = NULL;
+ char *mac;
+
+ GetAdaptersAddresses(AF_UNSPEC, GAA_FLAGS, NULL, pAddresses, &tableSize);
+ pAddresses = malloc(tableSize);
+ r = GetAdaptersAddresses(AF_INET, GAA_FLAGS, NULL, pAddresses, &tableSize);
+
+ win_network_init.device_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ for(adapter = pAddresses; adapter; adapter = adapter->Next) {
+ if(adapter->PhysicalAddressLength < 6)
+ continue; /* not proper addr */
+ r = WideCharToMultiByte(CP_ACP,
+ 0,
+ adapter->FriendlyName,
+ -1,
+ wName,
+ sizeof(wName),
+ NULL,
+ NULL);
+
+ mac = g_strdup_printf("%02X%02X%02X%02X%02X%02X",
+ adapter->PhysicalAddress[0],
+ adapter->PhysicalAddress[1],
+ adapter->PhysicalAddress[2],
+ adapter->PhysicalAddress[3],
+ adapter->PhysicalAddress[4],
+ adapter->PhysicalAddress[5]);
+
+ g_hash_table_insert(win_network_init.device_hash,
+ (gpointer)mac,
+ (gpointer)wName);
+ g_free(mac);
+ }
+}
+
+void
+network_os_get_interfaces(network_init_t *network_init)
+{
+ GList *interface_list = NULL, *plist;
+ sigar_net_interface_config_t *ifconfig;
+ char *mac;
+ char *mac_cmp;
+
+ set_iface_mac_hash();
+ interface_list = g_hash_table_get_values(network_init->device_hash);
+ for (plist = g_list_first(interface_list); plist; plist = g_list_next(plist))
+ {
+ ifconfig = (sigar_net_interface_config_t *)plist->data;
+
+ mac = g_strdup_printf("%02X%02X%02X%02X%02X%02X",
+ ifconfig->hwaddr.addr.mac[0],
+ ifconfig->hwaddr.addr.mac[1],
+ ifconfig->hwaddr.addr.mac[2],
+ ifconfig->hwaddr.addr.mac[3],
+ ifconfig->hwaddr.addr.mac[4],
+ ifconfig->hwaddr.addr.mac[5]);
+ mac_cmp = g_hash_table_lookup(win_network_init.device_hash,
+ mac);
+ if(mac_cmp)
+ g_strlcpy(ifconfig->name, mac_cmp, BUFSIZE);
+ g_free(mac);
+ }
+}
--
1.7.3.4
_______________________________________________
Matahari mailing list
Matahari(a)lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/matahari