#endif
#include <net/if.h>
+#include <net/if_arp.h>
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
char *address;
};
-struct connman_ipconfig {
- gint refcount;
+struct connman_ipdevice {
int index;
- char *interface;
+ char *ifname;
unsigned short type;
unsigned int flags;
- struct connman_ipconfig_ops *ops;
+ GSList *address_list;
+ char *gateway;
+};
+
+struct connman_ipconfig {
+ gint refcount;
+ int index;
+
+ const struct connman_ipconfig_ops *ops;
void *ops_data;
enum connman_ipconfig_method method;
- GSList *address_list;
- char *gateway;
};
-static void free_address_list(struct connman_ipconfig *ipconfig)
+static GHashTable *ipdevice_hash = NULL;
+static GList *ipconfig_list = NULL;
+
+static void free_address_list(struct connman_ipdevice *ipdevice)
{
GSList *list;
- for (list = ipconfig->address_list; list; list = list->next) {
+ for (list = ipdevice->address_list; list; list = list->next) {
struct connman_ipaddress *ipaddress = list->data;
g_free(ipaddress->address);
list->data = NULL;
}
- g_slist_free(ipconfig->address_list);
- ipconfig->address_list = NULL;
+ g_slist_free(ipdevice->address_list);
+ ipdevice->address_list = NULL;
}
-static struct connman_ipaddress *find_ipaddress(struct connman_ipconfig *ipconfig,
+static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
unsigned char prefixlen, const char *address)
{
GSList *list;
- for (list = ipconfig->address_list; list; list = list->next) {
+ for (list = ipdevice->address_list; list; list = list->next) {
struct connman_ipaddress *ipaddress = list->data;
if (g_strcmp0(ipaddress->address, address) == 0 &&
return NULL;
}
+static const char *type2str(unsigned short type)
+{
+ switch (type) {
+ case ARPHRD_ETHER:
+ return "ETHER";
+ case ARPHRD_LOOPBACK:
+ return "LOOPBACK";
+ case ARPHRD_PPP:
+ return "PPP";
+ case ARPHRD_NONE:
+ return "NONE";
+ case ARPHRD_VOID:
+ return "VOID";
+ }
+
+ return "";
+}
+
+static const char *scope2str(unsigned char scope)
+{
+ switch (scope) {
+ case 0:
+ return "UNIVERSE";
+ case 253:
+ return "LINK";
+ }
+
+ return "";
+}
+
+static void free_ipdevice(gpointer data)
+{
+ struct connman_ipdevice *ipdevice = data;
+
+ connman_info("%s {remove} index %d", ipdevice->ifname,
+ ipdevice->index);
+
+ free_address_list(ipdevice);
+ g_free(ipdevice->gateway);
+
+ g_free(ipdevice->ifname);
+ g_free(ipdevice);
+}
+
+void __connman_ipconfig_newlink(int index, unsigned short type,
+ unsigned int flags)
+{
+ struct connman_ipdevice *ipdevice;
+ GList *list;
+ GString *str;
+ gboolean up = FALSE, down = FALSE;
+ gboolean lower_up = FALSE, lower_down = FALSE;
+
+ DBG("index %d", index);
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice != NULL)
+ goto update;
+
+ ipdevice = g_try_new0(struct connman_ipdevice, 1);
+ if (ipdevice == NULL)
+ return;
+
+ ipdevice->index = index;
+ ipdevice->ifname = connman_inet_ifname(index);
+ ipdevice->type = type;
+
+ g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
+
+ connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
+ index, type, type2str(type));
+
+update:
+ if (flags == ipdevice->flags)
+ return;
+
+ if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
+ if (flags & IFF_UP)
+ up = TRUE;
+ else
+ down = TRUE;
+ }
+
+ if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
+ (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
+ if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
+ (IFF_RUNNING | IFF_LOWER_UP))
+ lower_up = TRUE;
+ else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
+ lower_down = TRUE;
+ }
+
+ ipdevice->flags = flags;
+
+ str = g_string_new(NULL);
+ if (str == NULL)
+ return;
+
+ if (flags & IFF_UP)
+ g_string_append(str, "UP");
+ else
+ g_string_append(str, "DOWN");
+
+ if (flags & IFF_RUNNING)
+ g_string_append(str, ",RUNNING");
+
+ if (flags & IFF_LOWER_UP)
+ g_string_append(str, ",LOWER_UP");
+
+ connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
+ flags, str->str);
+
+ g_string_free(str, TRUE);
+
+ for (list = g_list_first(ipconfig_list); list;
+ list = g_list_next(list)) {
+ struct connman_ipconfig *ipconfig = list->data;
+
+ if (index != ipconfig->index)
+ continue;
+
+ if (ipconfig->ops) {
+ if (up == TRUE && ipconfig->ops->up)
+ ipconfig->ops->up(ipconfig);
+ if (lower_up == TRUE && ipconfig->ops->lower_up)
+ ipconfig->ops->lower_up(ipconfig);
+
+ if (lower_down == TRUE && ipconfig->ops->lower_down)
+ ipconfig->ops->lower_down(ipconfig);
+ if (down == TRUE && ipconfig->ops->down)
+ ipconfig->ops->down(ipconfig);
+ }
+ }
+}
+
+void __connman_ipconfig_dellink(int index)
+{
+ GList *list;
+
+ DBG("index %d", index);
+
+ for (list = g_list_first(ipconfig_list); list;
+ list = g_list_next(list)) {
+ struct connman_ipconfig *ipconfig = list->data;
+
+ if (index != ipconfig->index)
+ continue;
+
+ ipconfig->index = -1;
+
+ if (ipconfig->ops && ipconfig->ops->lower_down)
+ ipconfig->ops->lower_down(ipconfig);
+ if (ipconfig->ops && ipconfig->ops->down)
+ ipconfig->ops->down(ipconfig);
+ }
+
+ g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
+}
+
+void __connman_ipconfig_newaddr(int index, const char *label,
+ unsigned char prefixlen, const char *address)
+{
+ struct connman_ipdevice *ipdevice;
+ struct connman_ipaddress *ipaddress;
+
+ DBG("index %d", index);
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return;
+
+ ipaddress = g_try_new0(struct connman_ipaddress, 1);
+ if (ipaddress == NULL)
+ return;
+
+ ipaddress->prefixlen = prefixlen;
+ ipaddress->address = g_strdup(address);
+
+ ipdevice->address_list = g_slist_append(ipdevice->address_list,
+ ipaddress);
+
+ connman_info("%s {add} address %s/%u label %s", ipdevice->ifname,
+ address, prefixlen, label);
+}
+
+void __connman_ipconfig_deladdr(int index, const char *label,
+ unsigned char prefixlen, const char *address)
+{
+ struct connman_ipdevice *ipdevice;
+ struct connman_ipaddress *ipaddress;
+
+ DBG("index %d", index);
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return;
+
+ ipaddress = find_ipaddress(ipdevice, prefixlen, address);
+ if (ipaddress == NULL)
+ return;
+
+ ipdevice->address_list = g_slist_remove(ipdevice->address_list,
+ ipaddress);
+
+ g_free(ipaddress->address);
+ g_free(ipaddress);
+
+ connman_info("%s {del} address %s/%u label %s", ipdevice->ifname,
+ address, prefixlen, label);
+}
+
+void __connman_ipconfig_newroute(int index, unsigned char scope,
+ const char *dst, const char *gateway)
+{
+ struct connman_ipdevice *ipdevice;
+
+ DBG("index %d", index);
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return;
+
+ if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
+ g_free(ipdevice->gateway);
+ ipdevice->gateway = g_strdup(gateway);
+ }
+
+ connman_info("%s {add} route %s gw %s scope %u <%s>",
+ ipdevice->ifname, dst, gateway,
+ scope, scope2str(scope));
+}
+
+void __connman_ipconfig_delroute(int index, unsigned char scope,
+ const char *dst, const char *gateway)
+{
+ struct connman_ipdevice *ipdevice;
+
+ DBG("index %d", index);
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return;
+
+ if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
+ g_free(ipdevice->gateway);
+ ipdevice->gateway = NULL;
+ }
+
+ connman_info("%s {del} route %s gw %s scope %u <%s>",
+ ipdevice->ifname, dst, gateway,
+ scope, scope2str(scope));
+}
+
+void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
+ void *user_data)
+{
+ GList *list, *keys;
+
+ keys = g_hash_table_get_keys(ipdevice_hash);
+ if (keys == NULL)
+ return;
+
+ for (list = g_list_first(keys); list; list = g_list_next(list)) {
+ int index = GPOINTER_TO_INT(list->data);
+
+ function(index, user_data);
+ }
+
+ g_list_free(keys);
+}
+
+unsigned short __connman_ipconfig_get_type(int index)
+{
+ struct connman_ipdevice *ipdevice;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return ARPHRD_VOID;
+
+ return ipdevice->type;
+}
+
+unsigned int __connman_ipconfig_get_flags(int index)
+{
+ struct connman_ipdevice *ipdevice;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return 0;
+
+ return ipdevice->flags;
+}
+
+const char *__connman_ipconfig_get_gateway(int index)
+{
+ struct connman_ipdevice *ipdevice;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+ if (ipdevice == NULL)
+ return NULL;
+
+ return ipdevice->gateway;
+}
+
/**
* connman_ipconfig_create:
*
{
struct connman_ipconfig *ipconfig;
- DBG("");
+ DBG("index %d", index);
ipconfig = g_try_new0(struct connman_ipconfig, 1);
if (ipconfig == NULL)
ipconfig->refcount = 1;
ipconfig->index = index;
- ipconfig->interface = connman_inet_ifname(index);
DBG("ipconfig %p", ipconfig);
- connman_info("%s {create} index %d", ipconfig->interface,
- ipconfig->index);
+ ipconfig_list = g_list_append(ipconfig_list, ipconfig);
return ipconfig;
}
void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
{
if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
- connman_info("%s {remove} index %d", ipconfig->interface,
- ipconfig->index);
-
- g_free(ipconfig->gateway);
+ ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
- free_address_list(ipconfig);
-
- g_free(ipconfig->interface);
g_free(ipconfig);
}
}
}
/**
+ * connman_ipconfig_get_index:
+ * @ipconfig: ipconfig structure
+ *
+ * Get interface index
+ */
+int connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
+{
+ return ipconfig->index;
+}
+
+/**
+ * connman_ipconfig_get_ifname:
+ * @ipconfig: ipconfig structure
+ *
+ * Get interface name
+ */
+const char *connman_ipconfig_get_ifname(struct connman_ipconfig *ipconfig)
+{
+ struct connman_ipdevice *ipdevice;
+
+ if (ipconfig->index < 0)
+ return NULL;
+
+ ipdevice = g_hash_table_lookup(ipdevice_hash,
+ GINT_TO_POINTER(ipconfig->index));
+ if (ipdevice == NULL)
+ return NULL;
+
+ return ipdevice->ifname;
+}
+
+/**
* connman_ipconfig_set_ops:
* @ipconfig: ipconfig structure
* @ops: operation callbacks
* Set the operation callbacks
*/
void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
- struct connman_ipconfig_ops *ops)
+ const struct connman_ipconfig_ops *ops)
{
ipconfig->ops = ops;
}
return 0;
}
-int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
-{
- return ipconfig->index;
-}
-
-unsigned short __connman_ipconfig_get_type(struct connman_ipconfig *ipconfig)
-{
- return ipconfig->type;
-}
-
-unsigned int __connman_ipconfig_get_flags(struct connman_ipconfig *ipconfig)
-{
- return ipconfig->flags;
-}
-
-const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig)
-{
- return ipconfig->gateway;
-}
-
-void __connman_ipconfig_update_link(struct connman_ipconfig *ipconfig,
- unsigned flags, unsigned change)
-{
- GString *str;
-
- if (flags == ipconfig->flags)
- return;
-
- ipconfig->flags = flags;
-
- str = g_string_new(NULL);
- if (str == NULL)
- return;
-
- if (flags & IFF_UP)
- g_string_append(str, "UP");
- else
- g_string_append(str, "DOWN");
-
- if (flags & IFF_RUNNING)
- g_string_append(str, ",RUNNING");
-
- if (flags & IFF_LOWER_UP)
- g_string_append(str, ",LOWER_UP");
-
- connman_info("%s {update} flags %u change %u <%s>",
- ipconfig->interface, flags, change, str->str);
-
- g_string_free(str, TRUE);
-}
-
-void __connman_ipconfig_add_address(struct connman_ipconfig *ipconfig,
- const char *label, unsigned char prefixlen,
- const char *address, const char *broadcast)
-{
- struct connman_ipaddress *ipaddress;
-
- ipaddress = g_try_new0(struct connman_ipaddress, 1);
- if (ipaddress == NULL)
- return;
-
- ipaddress->prefixlen = prefixlen;
- ipaddress->address = g_strdup(address);
-
- ipconfig->address_list = g_slist_append(ipconfig->address_list,
- ipaddress);
-
- connman_info("%s {add} address %s/%u label %s", ipconfig->interface,
- address, prefixlen, label);
-}
-
-void __connman_ipconfig_del_address(struct connman_ipconfig *ipconfig,
- const char *label, unsigned char prefixlen,
- const char *address, const char *broadcast)
-{
- struct connman_ipaddress *ipaddress;
-
- ipaddress = find_ipaddress(ipconfig, prefixlen, address);
- if (ipaddress == NULL)
- return;
-
- ipconfig->address_list = g_slist_remove(ipconfig->address_list,
- ipaddress);
-
- g_free(ipaddress->address);
- g_free(ipaddress);
-
- connman_info("%s {del} address %s/%u label %s", ipconfig->interface,
- address, prefixlen, label);
-}
-
-static const char *scope2str(unsigned char scope)
-{
- switch (scope) {
- case 0:
- return "UNIVERSE";
- case 253:
- return "LINK";
- }
-
- return "";
-}
-
-void __connman_ipconfig_add_route(struct connman_ipconfig *ipconfig,
- unsigned char scope, const char *destination,
- const char *gateway)
-{
- if (scope == 0 && g_strcmp0(destination, "0.0.0.0") == 0) {
- g_free(ipconfig->gateway);
- ipconfig->gateway = g_strdup(gateway);
- }
-
- connman_info("%s {add} route %s gw %s scope %u <%s>",
- ipconfig->interface, destination,
- gateway, scope, scope2str(scope));
-}
-
-void __connman_ipconfig_del_route(struct connman_ipconfig *ipconfig,
- unsigned char scope, const char *destination,
- const char *gateway)
-{
- if (scope == 0 && g_strcmp0(destination, "0.0.0.0") == 0) {
- g_free(ipconfig->gateway);
- ipconfig->gateway = NULL;
- }
-
- connman_info("%s {del} route %s gw %s scope %u <%s>",
- ipconfig->interface, destination,
- gateway, scope, scope2str(scope));
-}
-
const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
{
switch (method) {
driver_list = g_slist_remove(driver_list, driver);
}
+
+int __connman_ipconfig_init(void)
+{
+ DBG("");
+
+ ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, free_ipdevice);
+
+ return 0;
+}
+
+void __connman_ipconfig_cleanup(void)
+{
+ DBG("");
+
+ g_hash_table_destroy(ipdevice_hash);
+ ipdevice_hash = NULL;
+}
static GSList *watch_list = NULL;
static unsigned int watch_id = 0;
-static GHashTable *ipconfig_hash = NULL;
-static GSList *ipconfig_list = NULL;
-
-static void register_ipconfig(struct connman_ipconfig *ipconfig)
-{
- ipconfig_list = g_slist_append(ipconfig_list, ipconfig);
-}
-
-static void unregister_ipconfig(struct connman_ipconfig *ipconfig)
-{
- ipconfig_list = g_slist_remove(ipconfig_list, ipconfig);
-}
-
-static void free_ipconfig(gpointer data)
-{
- struct connman_ipconfig *ipconfig = data;
-
- unregister_ipconfig(ipconfig);
-
- connman_ipconfig_unref(ipconfig);
-}
-
/**
* connman_rtnl_add_newlink_watch:
* @index: network device index
unsigned int connman_rtnl_add_newlink_watch(int index,
connman_rtnl_link_cb_t callback, void *user_data)
{
- struct connman_ipconfig *ipconfig;
struct watch_data *watch;
watch = g_try_new0(struct watch_data, 1);
DBG("id %d", watch->id);
- ipconfig = g_hash_table_lookup(ipconfig_hash, GINT_TO_POINTER(index));
- if (ipconfig != NULL) {
- unsigned int flags = __connman_ipconfig_get_flags(ipconfig);
+ if (callback) {
+ unsigned int flags = __connman_ipconfig_get_flags(index);
- if (callback)
+ if (flags > 0)
callback(flags, 0, user_data);
}
}
}
-static void trigger_rtnl(gpointer key, gpointer value, gpointer user_data)
+static void trigger_rtnl(int index, void *user_data)
{
struct connman_rtnl *rtnl = user_data;
- struct connman_ipconfig *ipconfig = value;
- int index = GPOINTER_TO_INT(key);
-
- if (index < 0 || ipconfig == NULL)
- return;
if (rtnl->newlink) {
- unsigned short type = __connman_ipconfig_get_type(ipconfig);
- unsigned int flags = __connman_ipconfig_get_flags(ipconfig);
+ unsigned short type = __connman_ipconfig_get_type(index);
+ unsigned int flags = __connman_ipconfig_get_flags(index);
rtnl->newlink(type, index, flags, 0);
}
if (rtnl->newgateway) {
- const char *gateway = __connman_ipconfig_get_gateway(ipconfig);
+ const char *gateway = __connman_ipconfig_get_gateway(index);
if (gateway != NULL)
rtnl->newgateway(index, gateway);
rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
compare_priority);
- g_hash_table_foreach(ipconfig_hash, trigger_rtnl, rtnl);
+ __connman_ipconfig_foreach(trigger_rtnl, rtnl);
return 0;
}
static void process_newlink(unsigned short type, int index,
unsigned flags, unsigned change)
{
- struct connman_ipconfig *ipconfig;
GSList *list;
switch (type) {
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
case ARPHRD_NONE:
- ipconfig = g_hash_table_lookup(ipconfig_hash,
- GINT_TO_POINTER(index));
- if (ipconfig == NULL) {
- ipconfig = connman_ipconfig_create(index);
- if (ipconfig != NULL) {
- g_hash_table_insert(ipconfig_hash,
- GINT_TO_POINTER(index), ipconfig);
-
- register_ipconfig(ipconfig);
- }
- }
-
- if (ipconfig != NULL)
- __connman_ipconfig_update_link(ipconfig,
- flags, change);
+ __connman_ipconfig_newlink(index, type, flags);
break;
}
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
case ARPHRD_NONE:
- g_hash_table_remove(ipconfig_hash, GINT_TO_POINTER(index));
+ __connman_ipconfig_dellink(index);
break;
}
}
static void process_newaddr(unsigned char family, unsigned char prefixlen,
int index, struct ifaddrmsg *msg, int bytes)
{
- GSList *list;
const char *label;
struct in_addr address = { INADDR_ANY };
extract_addr(msg, bytes, &label, &address, NULL, NULL);
- for (list = ipconfig_list; list; list = list->next) {
- struct connman_ipconfig *ipconfig = list->data;
-
- if (__connman_ipconfig_get_index(ipconfig) != index)
- continue;
-
- __connman_ipconfig_add_address(ipconfig, label, prefixlen,
- inet_ntoa(address), NULL);
- }
+ __connman_ipconfig_newaddr(index, label,
+ prefixlen, inet_ntoa(address));
}
static void process_deladdr(unsigned char family, unsigned char prefixlen,
int index, struct ifaddrmsg *msg, int bytes)
{
- GSList *list;
const char *label;
struct in_addr address = { INADDR_ANY };
extract_addr(msg, bytes, &label, &address, NULL, NULL);
- for (list = ipconfig_list; list; list = list->next) {
- struct connman_ipconfig *ipconfig = list->data;
-
- if (__connman_ipconfig_get_index(ipconfig) != index)
- continue;
-
- __connman_ipconfig_del_address(ipconfig, label, prefixlen,
- inet_ntoa(address), NULL);
- }
+ __connman_ipconfig_deladdr(index, label,
+ prefixlen, inet_ntoa(address));
}
static void extract_route(struct rtmsg *msg, int bytes, int *index,
inet_ntop(family, &dst, dststr, sizeof(dststr));
inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
- for (list = ipconfig_list; list; list = list->next) {
- struct connman_ipconfig *ipconfig = list->data;
-
- if (__connman_ipconfig_get_index(ipconfig) != index)
- continue;
-
- __connman_ipconfig_add_route(ipconfig, scope,
- dststr, gatewaystr);
- }
+ __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
return;
inet_ntop(family, &dst, dststr, sizeof(dststr));
inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
- for (list = ipconfig_list; list; list = list->next) {
- struct connman_ipconfig *ipconfig = list->data;
-
- if (__connman_ipconfig_get_index(ipconfig) != index)
- continue;
-
- __connman_ipconfig_del_route(ipconfig, scope,
- dststr, gatewaystr);
- }
+ __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
return;
DBG("");
- ipconfig_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, free_ipconfig);
-
sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (sk < 0)
return -1;
DBG("");
- g_slist_free(ipconfig_list);
- ipconfig_list = NULL;
-
- g_hash_table_destroy(ipconfig_hash);
- ipconfig_hash = NULL;
-
for (list = watch_list; list; list = list->next) {
struct watch_data *watch = list->data;