diff --git a/src/Makefile b/src/Makefile
index 37fb88a72cc7dcaaef39228b197982ccce9e50e6..3112326ef1e47cc0c68a7d62decea6ec42fa69b3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,9 +4,10 @@ CFLAGS+=-I. -D_GNU_SOURCE
CFLAGS+= -g3 -Wall -pthread
OBJS = main.o debug.o config.o json_utils.o nodes.o topo_ieee1905.o topologyd.o mdns_avahi.o
-OBJS+= host.o host_nodes.o host_config.o
+OBJS+= host_nodes.o host_config.o host_utils.o host.o
LIBS = -lubus -lubox -ljson-c -lblobmsg_json -luci -pthread -leasy -lieee1905 -lavahi-core -lavahi-common
+LIBS+= -I/usr/include/libnl3 -lnl-3 -lnl-route-3
.PHONY: all check clean FORCE
diff --git a/src/host.c b/src/host.c
index a3a2a6cec2de39fb707e6108eebeb6ab3adcbab8..6036f02b3a7438c9ffb586a8c511c2f1a3b87bbb 100644
--- a/src/host.c
+++ b/src/host.c
@@ -29,6 +29,7 @@
#include "debug.h"
#include "config.h"
#include "json_utils.h"
+#include "host_utils.h"
extern const char *ubus_socket;
@@ -83,7 +84,7 @@ char *topology_stringify_types(enum host_types type)
static void uobjx_lookup(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv)
{
const char *token = "wifi.ap";
- char *p, *mac;
+ char *p;
struct u_list *str = (struct u_list *)priv;
p = strstr(obj->path, token);
@@ -91,8 +92,6 @@ static void uobjx_lookup(struct ubus_context *ctx, struct ubus_object_data *obj,
strcpy(str->ifname[str->count], obj->path);
str->count = str->count + 1;
}
-fail:
- return;
}
static int host_get_wifi_nodes(struct ubus_context *ctx, struct u_list *c)
@@ -181,7 +180,6 @@ void host_dump_node_nbr(struct topologyd_private *priv, struct blob_buf *b)
if (hwaddr_is_zero(p->hwaddr) || memcmp(hwaddr, p->hwaddr, 6)) // TODO: unlikely..
continue;
- printf("%s %d\n", __func__, __LINE__);
table1 = blobmsg_open_table(b, NULL);
hwaddr_ntoa(p->hwaddr, mac_str);
@@ -230,64 +228,6 @@ void host_dump_node_nbr(struct topologyd_private *priv, struct blob_buf *b)
uci_free_context(ctx);
}
-struct host_node *host_topo_node_init(struct topologyd_private *priv, uint8_t *mac_addr)
-{
- struct host_node *p = NULL;
- char mac_str[18] = { 0 };
- time_t tmp_t;
- struct tm *info;
- char str_tm[20];
-
- dbg("Inside %s %d\n", __func__, __LINE__);
-
- if (!priv)
- return -1;
-
- if (priv->host.num_nodes >= HOST_NODE_MAX) {
- err("Number of host more than MAX limit!\n");
- return -1;
- }
-
- if (mac_addr != NULL) {
- int ret;
-
- p = host_node_lookup(priv->host.node_htable, mac_addr);
- if (!p) {
- p = host_node_add(priv->host.node_htable, mac_addr);
- if (p == NULL)
- return -1;
- }
-
- /* Here we need to write this info in the config file
- */
- hwaddr_ntoa(mac_addr, mac_str);
- config_add_default_host_mac("hosts", "host", mac_str);
- host_change_active_state(priv, p, 0);
-
- ret = host_get_wifi_data(priv, p);
- //if (ret != 0)
- // err("Unable to fetch interface type\n");
- if (p->intf_type == HOST_TYPE_WIFI)
- config_set_host_option("hosts", "host", "macaddr", mac_str, "interface_type", "wifi");
- else/* if (p->intf_type == HOST_TYPE_ETHER) */{
- config_set_host_option("hosts", "host", "macaddr", mac_str, "interface_type", "eth");
- }
-
- ret = host_get_ipaddr_hostname(priv, mac_str, p);
- if (ret != 0) {
- printf("%s %d\n", __func__, __LINE__);
- err("Unable to fetch ip adddress and host name\n");
- p->is_ipaddr = 0;
- } else {
- printf("%s %d\n", __func__, __LINE__);
- p->is_ipaddr = 1;
- }
-
-
- }
- return p;
-}
-
struct host_node *host_topo_node_add(struct topologyd_private *priv, struct node *node, uint8_t *mac_addr, uint8_t is_wifi)
{
struct host_node *p = NULL;
@@ -295,7 +235,7 @@ struct host_node *host_topo_node_add(struct topologyd_private *priv, struct node
time_t tmp_t;
struct tm *info;
char str_tm[32] = {0};
- int ret = 0, i = 0;
+ int ret = 0;
dbg("Inside %s %d\n", __func__, __LINE__);
@@ -310,12 +250,8 @@ struct host_node *host_topo_node_add(struct topologyd_private *priv, struct node
if (node != NULL) {
bool send_ev = false;
- if (!memcmp(node->hwaddr, priv->ieee1905_macaddr, 6)) {
- p = &priv->selfnode;
- //Here the node is the selfnode
- //self node does not get added in the hosts
- return 0;
- }
+ if (!memcmp(node->hwaddr, priv->ieee1905_macaddr, 6))
+ return NULL;
/* Add node if not present in host.
*
@@ -344,39 +280,21 @@ struct host_node *host_topo_node_add(struct topologyd_private *priv, struct node
info = localtime(&tmp_t);
strftime(str_tm, sizeof(str_tm), "%Y-%m-%dT%H:%M:%SZ", info);
config_set_host_option("hosts", "host", "macaddr", mac_str, "active_last_change", str_tm);
- //TODO Here Adding the ipv4 address and hostname and ipv6 address
- //As these params will come in the Higher layer response it needs to be
- //populated from there
-
- /* This is a ieee1905 node so we get the interface type via the
- * * topology response media type
- * */
- //if (p->intf_type != HOST_TYPE_WIFI)
host_get_wifi_data(priv, p);
- //if (ret != 0)
- // err("Unable to fetch interface type\n");
- // if (p->intf_type == HOST_TYPE_WIFI)
- // config_set_host_option("hosts", "host", "macaddr", mac_str, "interface_type", "wifi");
- // else/* if (p->intf_type == HOST_TYPE_ETHER) */{
- // config_set_host_option("hosts", "host", "macaddr", mac_str, "interface_type", "eth");
- // }
bool has_ip = p->is_ipaddr;
ret = host_get_ipaddr_hostname(priv, mac_str, p);
if (ret != 0) {
- printf("%s %d\n", __func__, __LINE__);
err("Unable to fetch ip adddress and host name\n");
p->is_ipaddr = 0;
} else {
- printf("%s %d\n", __func__, __LINE__);
p->is_ipaddr = 1;
if (!has_ip && p->intf_type == HOST_TYPE_WIFI && !p->is_in_assoclist) {
if (!host_get_arping_status(p->ipv4addr)) {
host_send_client_event(priv, p, 1);
host_change_active_state(priv, p, 1);
- }
- else
+ } else
host_change_active_state(priv, p, 0);
}
}
@@ -435,18 +353,15 @@ struct host_node *host_topo_node_add(struct topologyd_private *priv, struct node
ret = host_get_ipaddr_hostname(priv, mac_str, p);
if (ret != 0) {
- printf("%s %d\n", __func__, __LINE__);
err("Unable to fetch ip adddress and host name\n");
p->is_ipaddr = 0;
} else {
- printf("%s %d\n", __func__, __LINE__);
p->is_ipaddr = 1;
if (!has_ip && p->intf_type == HOST_TYPE_WIFI && !p->is_in_assoclist) {
if (!host_get_arping_status(p->ipv4addr)) {
//host_send_client_event(priv, p, 1);
host_change_active_state(priv, p, 1);
- }
- else
+ } else
host_change_active_state(priv, p, 0);
}
}
@@ -466,20 +381,15 @@ struct host_node *host_topo_node_del(struct topologyd_private *priv, struct node
{
struct host_node *p = NULL;
char mac_str[18] = { 0 };
- time_t tmp_t;
- struct tm *info;
- char str_tm[20];
dbg("Inside %s %d\n", __func__, __LINE__);
if (!priv)
- return -1;
+ return NULL;
if (node != NULL) {
if (!memcmp(node->hwaddr, priv->ieee1905_macaddr, 6)) {
- p = &priv->selfnode;
- //Here the node is the selfnode
- //self node does not get added in the hosts
+ //self node does not get deleted in the hosts
return NULL;
}
@@ -635,12 +545,10 @@ out_str:
void host_get_network(struct topologyd_private *priv, struct host_node *p)
{
struct json_object *interfaces;
- char *json_str;
int i = 0, len = 0;
- int ret = 0;
if (!priv || !p)
- return ;
+ return;
if (!json_object_is_type(priv->network_dump, json_type_object))
return;
@@ -728,7 +636,7 @@ static void host_get_network_dump(struct topologyd_private *priv)
status = ubus_lookup_id(priv->ctx, "network.interface", &id);
if (status != UBUS_STATUS_OK) {
err("object 'interfacedump' not present!\n");
- return OBJECT_INVALID;
+ return;
}
ret = ubus_invoke(priv->ctx, id, "dump", bb.head,
@@ -736,7 +644,7 @@ static void host_get_network_dump(struct topologyd_private *priv)
if (ret) {
dbg("Failed to get network.interface dump (ret = %d)\n", ret);
blob_buf_free(&bb);
- return -1;
+ return;
}
blob_buf_free(&bb);
@@ -767,50 +675,6 @@ static int active_connections(char *ipaddr)
return connum;
}
-static void get_dhcp_options(struct host_node *host)
-{
- FILE *opts;
- char line[2048];
- char macaddr[24];
- char vcid[128];
- char clid[128];
- char ucid[128];
-
- /* /var/dhcp.client.options format */
- /* <MACADDR> vcid=<VENDOR_CLASS_ID> clid=<CLIENT_ID> ucid=<USER_CLASS_ID> */
- /* vcid: Option 60, clid: Option 61, ucid: Option 77 */
- opts = fopen("/var/dhcp.client.options", "r");
-
- if (opts != NULL) {
- while (fgets(line, sizeof(line), opts) != NULL) {
- uint8_t hwaddr[6] = {0};
-
- remove_newline(line);
- sscanf(line, "%24s vcid=%128s clid=%128s ucid=%128s",
- macaddr,
- vcid,
- clid,
- ucid);
-
- hwaddr_aton(macaddr, hwaddr);
-
- if (!memcmp(hwaddr, host->hwaddr, 6)) {
- if (strcmp(vcid, "-") != 0)
- strncpy(host->dhcpopts.vcid, vcid, 128);
-
- if (strcmp(clid, "-") != 0)
- strncpy(host->dhcpopts.clid, clid, 128);
-
- if (strcmp(ucid, "-") != 0)
- strncpy(host->dhcpopts.ucid, ucid, 128);
-
- break;
- }
- }
- fclose(opts);
- }
-}
-
static unsigned long long get_netdev_stats(char *device, char *stat)
{
FILE *snfile;
@@ -846,7 +710,6 @@ void get_bridge_info(struct host_node *host, char *device)
host->port_no = 0;
if (strstr(device, "br-")) {
chrCmd(brinfo, 16, "brctl showmacs %s | grep %s | awk '{print$1\":\"$4}'", device, macstr);
- printf("brinfo %s\n", brinfo);
sscanf(brinfo, "%d:%d.%d", &host->port_no, &aging, &timer);
}
}
@@ -861,7 +724,7 @@ static void get_ethernet_interface(struct host_node *host, char *bridge, int por
char path_portno[512];
unsigned int pno = 0;
- dbg("Inside %s %d \n", __func__, __LINE__);
+ dbg("Inside %s %d\n", __func__, __LINE__);
if (portno == 0 || !host)
return;
@@ -879,7 +742,6 @@ static void get_ethernet_interface(struct host_node *host, char *bridge, int por
pfile = fopen(path_portno, "r");
if (pfile != NULL) {
- printf("%s %d\n", __func__, __LINE__);
fscanf(pfile, "0x%x", &pno);
fclose(pfile);
}
@@ -950,74 +812,48 @@ int get_ifmask(char *ifname, char *buf)
int host_get_ipaddr_hostname(struct topologyd_private *priv,
char *macaddr_str, struct host_node *p)
{
- FILE *arpt;
- char line[256];
- int clidx = 0;
- int hw, flag;
- char mask[256];
- int i, j;
int ret = -1;
- char macaddr[18] = { 0 };
- char ip_addr[24] = { 0 };
char device[16] = { 0 };
-
- dbg("Inside %s %d mac=[%s]\n", __func__, __LINE__, macaddr_str);
+ char ipv4_address[24] = { 0 };
if (!macaddr_str || !p)
return ret;
- // Walk through ARP table to get the ip address
- arpt = fopen("/proc/net/arp", "r");
- if (arpt != NULL) {
- while (fgets(line, sizeof(line), arpt) != NULL) {
- remove_newline(line);
- if (sscanf(line, "%24s 0x%d 0x%d %24s %256s %32s",
- ip_addr, &hw, &flag, macaddr, mask, device)) {
- dbg("macaddr_str %s macaddr %s, ip %s\n", macaddr_str, macaddr, ip_addr);
- // Search the MAC address entry in the arp table
- if (strncmp(macaddr_str, macaddr, 18) == 0) {
- char mask[24] = {0}, addr[24] = {0};
-
- // Append DHCPv4 information: Hostname, IPv4 Address and Lease Time
- ret = host_append_dhcpv4_info(macaddr, p);
- if (ret != 0) {
- strncpy(p->ipv4addr, ip_addr, 24);
- strncpy(p->ipv4addr_list[0], ip_addr, 24);
- p->leasetmrmn = 0;
- p->addrsrc = HOST_ADDR_STATIC;
- p->ipv4addr_count = 1;
- } else {
- p->addrsrc = HOST_ADDR_DHCP;
- //get_dhcp_options(p);
- }
- dbg("device %s\n", device);
- host_get_network(priv, p);
- get_bridge_info(p, device);
-
- if (p->intf_type == HOST_TYPE_ETHER || !strlen(p->device)) {
- strncpy(p->device, device, 16);
- get_ethernet_interface(p, device, p->port_no);
- //if (!strncmp(p->device, "wds", 3))
- // p->intf_type = HOST_TYPE_WIFI;
- p->stats.tx_bytes = get_netdev_stats(p->device, "rx_bytes");
- p->stats.rx_bytes = get_netdev_stats(p->device, "tx_bytes");
- p->stats.tx_packets = get_netdev_stats(p->device, "rx_packets");
- p->stats.rx_packets = get_netdev_stats(p->device, "tx_packets");
- }
- p->active_connections = active_connections(p->ipv4addr);
-
- dbg("%s %d ipv4addr = [%s]\n", __func__, __LINE__, p->ipv4addr);
- // Append DHCPv6 information: IPv6 Address, DUID, Lease Time
- if (strlen(p->hostname) > 1)
- host_append_dhcpv6_info(p);
- ret = 0;
- break;
- }
- }
- }
- fclose(arpt);
+ ret = host_get_netlink_ip(p->hwaddr, ipv4_address, device);
+
+ if (ret != 0)
+ return ret;
+
+ strncpy(p->ipv4addr, ipv4_address, 24);
+ dbg("The IPv4 address is %s mac is %s device is %s\n", p->ipv4addr, macaddr_str, device);
+ ret = host_append_dhcpv4_info(macaddr_str, p);
+ if (ret != 0) {
+ strncpy(p->ipv4addr_list[0], p->ipv4addr, 24);
+ p->leasetmrmn = 0;
+ p->addrsrc = HOST_ADDR_STATIC;
+ p->ipv4addr_count = 1;
+ } else {
+ p->addrsrc = HOST_ADDR_DHCP;
}
+ host_get_network(priv, p);
+ get_bridge_info(p, device);
+
+ if (p->intf_type == HOST_TYPE_ETHER || !strlen(p->device)) {
+ strncpy(p->device, device, 16);
+ get_ethernet_interface(p, device, p->port_no);
+ p->stats.tx_bytes = get_netdev_stats(p->device, "rx_bytes");
+ p->stats.rx_bytes = get_netdev_stats(p->device, "tx_bytes");
+ p->stats.tx_packets = get_netdev_stats(p->device, "rx_packets");
+ p->stats.rx_packets = get_netdev_stats(p->device, "tx_packets");
+ }
+ p->active_connections = active_connections(p->ipv4addr);
+ dbg("%s %d ipv4addr = [%s]\n", __func__, __LINE__, p->ipv4addr);
+ // Append DHCPv6 information: IPv6 Address, DUID, Lease Time
+ if (strlen(p->hostname) > 1)
+ host_append_dhcpv6_info(p);
+ ret = 0;
+ dbg("Inside %s %d mac=[%s] macinterface =[%d]\n", __func__, __LINE__, macaddr_str, p->intf_type);
return ret;
}
@@ -1135,9 +971,7 @@ void host_gather_stations(struct ubus_request *req, int type, struct blob_attr *
struct json_object *sta_array;
struct json_object *priv_stations;
char *json_str;
- const char *macstr;
int i = 0, len = 0, priv_len = 0;
- int ret = 0;
json_object_object_get_ex(p->wifi_stations, "stations", &priv_stations);
if (!priv_stations)
@@ -1160,8 +994,7 @@ void host_gather_stations(struct ubus_request *req, int type, struct blob_attr *
len = json_object_array_length(sta_array);
for (i = 0; i < len; i++) {
- struct json_object *sta_obj, *sta_obj_macaddr, *jobj_ptr, *stat_obj;
- unsigned char macaddr[6] = {0};
+ struct json_object *sta_obj;
sta_obj = json_object_array_get_idx(sta_array, i);
json_object_array_put_idx(priv_stations, priv_len++, json_object_get(sta_obj));
@@ -1211,13 +1044,6 @@ void host_event_handler(struct ubus_context *ctx,
struct ubus_event_handler *ev, const char *type,
struct blob_attr *msg)
{
- int ret = 0;
- struct cmdu_cstruct *cstruct = NULL;
- uint16_t msg_type = 0;
- uint16_t msg_mid = 0;
- uint8_t *tlv = NULL;
- uint32_t len = 0;
- char itfr_name[256] = {0};
char *str;
struct topologyd_private *priv =
@@ -1266,9 +1092,9 @@ void host_wifi_sta_event_handler(void *c, struct blob_attr *msg)
static const struct blobmsg_policy data_attr[1] = {
[0] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING },
};
- char mac_str[18] = {0}, bssid_str[18] = {0};
- uint8_t mac[6] = {0}, bssid[6] = {0};
+ char mac_str[18] = {0};
+ uint8_t mac[6] = {0};
blobmsg_parse(data_attr, 1, data, blobmsg_data(tb[2]),
blobmsg_data_len(tb[2]));
@@ -1281,11 +1107,8 @@ void host_wifi_sta_event_handler(void *c, struct blob_attr *msg)
if (!hwaddr_aton(mac_str, mac))
return;
- if (add) {
- struct host_node *n;
-
- n = host_topo_node_add(p, NULL, mac, 1);
- }
+ if (add)
+ host_topo_node_add(p, NULL, mac, 1);
else if (del)
host_topo_node_del(p, NULL, mac, 1);
@@ -1298,10 +1121,6 @@ int host_get_interface_type(struct topologyd_private *priv)
struct u_list c;
int i = 0;
int ret = 0;
- char mac_str[18] = { 0 };
- time_t tmp_t;
- struct tm *info;
- char str_tm[20];
if (priv->wifi_stations) {
json_object_put(priv->wifi_stations);
@@ -1349,40 +1168,49 @@ void host_periodic_refresh(struct uloop_timeout *t)
uloop_timeout_set(&priv->host_refresh_timer, HOST_REFRESH_TIMER * 1000);
}
+void host_arp_table_refresh(struct uloop_timeout *t)
+{
+ struct topologyd_private *priv =
+ container_of(t, struct topologyd_private, host_arp_timer);
+
+ dbg("Inside %s %d\n", __func__, __LINE__);
+
+ host_get_table_cb(priv);
+}
+
int host_get_arping_status(char *ipaddr_str)
{
- char cmd[256] = {0};
- FILE *fp = NULL;
- char *line = NULL;
- size_t len = 0;
- int found = 0;
int ret = -1;
dbg("Inside %s %d\n", __func__, __LINE__);
if (ipaddr_str == NULL)
return -1;
+ ret = host_send_arping(ipaddr_str, "br-lan", 1000, 1);
- snprintf(cmd, 256, ARPING_CMD, ipaddr_str);
+ if (ret != 0)
+ ret = 0;
+ else
+ ret = -1;
- fp = popen(cmd, "r");
- if (fp == NULL) {
- err("unable to execute command");
+ return ret;
+}
+
+int host_send_arp_req(char *ipaddr_str)
+{
+ int ret = -1;
+
+ dbg("Inside %s %d\n", __func__, __LINE__);
+
+ if (ipaddr_str == NULL)
return -1;
- }
- dbg("Inside %s %d command is %s\n", __func__, __LINE__, cmd);
- while (getline(&line, &len, fp) != -1) {
- if (len < 2) {
- free(line);
- len = 0;
- continue;
- }
- ret = strncmp(line, "1", 1);
- break;
- }
- free(line);
- pclose(fp);
+ ret = host_send_arping(ipaddr_str, "br-lan", 1000, 0);
+ if (ret != 0)
+ ret = 0;
+ else
+ ret = -1;
+
return ret;
}
@@ -1429,44 +1257,6 @@ int host_get_neigh_status(uint8_t *mac_addr)
return 0;
}
-int host_check_ip_addr(struct host_node *p)
-{
-
- char mac_str[18] = { 0 };
- int ret = -1, i = 0;
-
- dbg("Inside %s %d\n", __func__, __LINE__);
-
- if (p == NULL)
- return -1;
-
- hwaddr_ntoa(p->hwaddr, mac_str);
- for (i = 0; i < p->ipv4addr_count; i++)
- config_del_host_list("hosts", "host", "macaddr", mac_str,
- "ipv4address", p->ipv4addr_list[i]);
- for (i = 0; i < p->ipv6addr_count; i++)
- config_del_host_list("hosts", "host", "macaddr", mac_str,
- "ipv6address", p->ipv6addr[i]);
- //ret = host_get_ipaddr_hostname(priv, mac_str, p);
- if (ret != 0)
- err("Unable to fetch ip adddress and host name\n");
- else {
- p->is_ipaddr = 1;
- config_set_host_option("hosts", "host", "macaddr", mac_str,
- "ipaddress", p->ipv4addr);
- config_set_host_option("hosts", "host", "macaddr", mac_str,
- "hostname", p->hostname);
-
- for (i = 0; i < p->ipv4addr_count; i++)
- config_set_host_list("hosts", "host", "macaddr", mac_str,
- "ipv4address", p->ipv4addr_list[i]);
- for (i = 0; i < p->ipv6addr_count; i++)
- config_set_host_list("hosts", "host", "macaddr",
- mac_str, "ipv6address", p->ipv6addr[i]);
- }
- return ret;
-}
-
/*
{ "topology.host": {"action":"connect","macaddr":"fe:ce:90:d7:5e:64","ipaddr":"192.168.1.157","network":"lan"} }
{ "topology.host": {"action":"disconnect","macaddr":"fe:ce:90:d7:5e:64","ipaddr":"192.168.1.157","network":"lan"} }
@@ -1474,7 +1264,7 @@ int host_check_ip_addr(struct host_node *p)
void host_send_client_event(struct topologyd_private *priv, struct host_node *p, uint8_t state)
{
- char mac[18] = {0}, src_mac[18] = {0};
+ char mac[18] = {0};
struct blob_buf bb = {0};
if (!p || !priv)
@@ -1509,9 +1299,9 @@ void host_change_active_state(struct topologyd_private *priv, struct host_node *
config_add_default_host_mac("hosts", "host", mac_str);
if (state == 0x0)
config_set_host_option("hosts", "host", "macaddr", mac_str, "active", "0");
- else {
+ else
config_set_host_option("hosts", "host", "macaddr", mac_str, "active", "1");
- }
+
tmp_t = p->active_last_change;
info = localtime(&tmp_t);
strftime(str_tm, sizeof(str_tm), "%Y-%m-%dT%H:%M:%SZ", info);
@@ -1528,9 +1318,6 @@ void host_run_status_check(struct topologyd_private *priv)
struct host_node *p;
int i = 0, ret = -1;
char mac_str[18] = { 0 };
- time_t tmp_t;
- struct tm *info;
- char str_tm[20];
dbg("Inside %s %d\n", __func__, __LINE__);
if (!priv)
@@ -1552,20 +1339,7 @@ void host_run_status_check(struct topologyd_private *priv)
continue;
hwaddr_ntoa(p->hwaddr, mac_str);
- /*Here we check if the node has received the
- * ip adddress
- */
- //if (p->is_ipaddr == 0) {
- // dbg("node %s does not have an ip address!\n", mac_str);
- // ret = host_get_ipaddr_hostname(priv, mac_str, p);
- // if (ret != 0)
- // err("Unable to fetch ip adddress and host name\n");
- // else
- // p->is_ipaddr = true;
- //}
- /*Here we check the status of the eth node in
- * the ip neigh
- */
+
if (p->intf_type != HOST_TYPE_ETHER && !p->is_ieee1905_node) {
memset(p->device, 0, 16);
host_get_wifi_data(priv, p);
@@ -1584,8 +1358,7 @@ void host_run_status_check(struct topologyd_private *priv)
if (!host_get_arping_status(p->ipv4addr)) {
host_send_client_event(priv, p, 1);
host_change_active_state(priv, p, 1);
- }
- else {
+ } else {
//host_send_client_event(priv, p, 0);
host_change_active_state(priv, p, 0);
}
@@ -1603,6 +1376,53 @@ void host_run_status_check(struct topologyd_private *priv)
else
p->is_ipaddr = 1;
+ char ipv4addr[24] = { 0 };
+
+ if (strncmp(p->ipv4addr, ipv4addr, 24)) {
+ ret = host_send_arp_req(p->ipv4addr);
+ } else {
+ dbg("ETH node is unreachable " MACFMT "\n", MAC2STR(p->hwaddr));
+ if (p->active != 0) {
+ host_send_client_event(priv, p, 0);
+ host_change_active_state(priv, p, 0);
+ }
+ }
+ }
+ }
+ /* Here we set the timer to check the arp request
+ */
+ uloop_timeout_set(&priv->host_arp_timer, HOST_ARP_TIMER * 1000);
+
+}
+
+void host_get_table_cb(struct topologyd_private *priv)
+{
+ struct host_node *p;
+ int i = 0, ret = -1;
+ char mac_str[18] = { 0 };
+
+ dbg("Inside %s %d\n", __func__, __LINE__);
+ if (!priv)
+ return;
+
+ for (i = 0; i < NODE_HTABLE_SIZE; i++) {
+ if (hlist_empty(&priv->host.node_htable[i]))
+ continue;
+
+ hlist_for_each_entry(p, &priv->host.node_htable[i], hlist) {
+ bool has_ip = p->is_ipaddr;
+
+ if (p->al_node)
+ continue;
+
+ if (hwaddr_is_zero(p->hwaddr)) // TODO: unlikely..
+ continue;
+
+ hwaddr_ntoa(p->hwaddr, mac_str);
+
+ if (p->intf_type != HOST_TYPE_ETHER && !p->is_ieee1905_node)
+ continue;
+
ret = host_get_neigh_status(p->hwaddr);
if (ret == 0 && has_ip) {
/*Here the node is rechable so
@@ -1617,34 +1437,11 @@ void host_run_status_check(struct topologyd_private *priv)
}
} else {
/*Here as the status is not reachable
- * we need to do arping to the node
- * to get the status and turn unreachable accordingly
*/
- char ipv4addr[24] = { 0 };
-
- if (strncmp(p->ipv4addr, ipv4addr, 24)) {
- ret = host_get_arping_status(p->ipv4addr);
- if (ret != 0) {
- dbg("ETH node is unreachable " MACFMT "\n", MAC2STR(p->hwaddr));
- if (p->active != 0) {
- host_send_client_event(priv, p, 0);
- host_change_active_state(priv, p, 0);
- }
- } else {
- if (p->active != 1) {
- dbg("ETH node is reachable " MACFMT "\n", MAC2STR(p->hwaddr));
- host_send_client_event(priv, p, 1);
- host_change_active_state(priv, p, 1);
- } else if (!has_ip)
- host_send_client_event(priv, p, 1);
-
- }
- } else {
- dbg("ETH node is unreachable " MACFMT "\n", MAC2STR(p->hwaddr));
- if (p->active != 0) {
- host_send_client_event(priv, p, 0);
- host_change_active_state(priv, p, 0);
- }
+ dbg("ETH node is unreachable " MACFMT "\n", MAC2STR(p->hwaddr));
+ if (p->active != 0) {
+ host_send_client_event(priv, p, 0);
+ host_change_active_state(priv, p, 0);
}
}
}
@@ -1653,11 +1450,6 @@ void host_run_status_check(struct topologyd_private *priv)
void host_process_topo_notification(uint8_t *tlv, struct topologyd_private *priv)
{
- int i = 0, j = 0;
- uint8_t *ptr;
- uint8_t *p, *ret;
- uint8_t temp = 0;
- uint16_t tlv_length = 0;
if (tlv == NULL || priv == NULL)
return;
@@ -1689,7 +1481,6 @@ void host_process_topo_notification(uint8_t *tlv, struct topologyd_private *priv
dbg(" received a default tlv\n");
break;
}
- i++;
}
void host_agent_event_handler(struct ubus_context *ctx,
diff --git a/src/host.h b/src/host.h
index 8b4cbf779350cf74de345c65c3c23257e6ea8671..aa04d24b39fa4d9a853161af158f860034de003c 100644
--- a/src/host.h
+++ b/src/host.h
@@ -21,6 +21,7 @@
#define HOST_REFRESH_TIMER 15
#define NEIGH_CMD "ip neigh show nud reachable|awk '{print $5}'|grep %s"
#define ARPING_CMD "arping -I br-lan -c 1 -w 1 -D %s| grep Received| awk '{print $2}'"
+#define HOST_ARP_TIMER 2
enum host_types {
@@ -81,8 +82,6 @@ struct host_node {
struct host_node *al_node;
};
-struct host_node *host_topo_node_init(struct topologyd_private *priv,
- uint8_t *mac_addr);
int host_nodes(struct ubus_context *ctx,
struct ubus_object *obj,
struct ubus_request_data *req,
@@ -111,4 +110,5 @@ void host_agent_event_handler(struct ubus_context *ctx,
struct blob_attr *msg);
void host_set_interface_type(struct host_node *p);
int host_get_arping_status(char *ipaddr_str);
+void host_arp_table_refresh(struct uloop_timeout *t);
#endif /* HOSTD_H */
diff --git a/src/host_config.c b/src/host_config.c
index bc76e0d4c175d476cae36c01523860af180e275c..255902351b71e0d644dbbec579742904d66ab93f 100644
--- a/src/host_config.c
+++ b/src/host_config.c
@@ -62,7 +62,7 @@ struct uci_section *config_add_section(struct uci_context *ctx,
{
struct uci_section *section = NULL;
struct uci_ptr ptr = {0};
- int rv = -1, ret = 0;
+ int rv = -1;
char name_section[50] = { 0 };
dbg("Inside %s %d\n", __func__, __LINE__);
@@ -90,8 +90,7 @@ struct uci_section *config_add_section(struct uci_context *ctx,
ptr.p = pkg;
ptr.s = section;
ptr.value = name_section;
- ret = uci_rename(ctx, &ptr);
-
+ uci_rename(ctx, &ptr);
rv = uci_save(ctx, pkg);
if (rv)
goto out_pkg;
@@ -118,7 +117,6 @@ int config_add_default_host_mac(const char *config, const char *type,
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *section;
- int rv = -1;
dbg("Inside %s %d\n", __func__, __LINE__);
@@ -136,7 +134,6 @@ int config_add_default_host_mac(const char *config, const char *type,
return -1;
uci_commit(ctx, &pkg, false);
-out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
@@ -198,109 +195,6 @@ bool config_set_host_option(char *package_name,
return false;
}
-bool config_del_host_list(char *package_name,
- char *section_type, char *search_key, char *search_val,
- char *option, char *value)
-{
- struct uci_context *ctx;
- struct uci_package *pkg;
- struct uci_element *e, *x;
-
- dbg("Inside %s %d\n", __func__, __LINE__);
-
- if (!package_name || !search_val || !option || !value)
- return false;
-
- ctx = uci_alloc_context();
- if (!ctx)
- return false;
-
- if (uci_load(ctx, package_name, &pkg)) {
- uci_free_context(ctx);
- return false;
- }
-
- uci_foreach_element(&pkg->sections, e) {
- struct uci_section *s = uci_to_section(e);
-
- if (!strcmp(s->type, section_type)) {
- struct uci_option *opt = uci_lookup_option(ctx, s,
- search_key);
- if (!opt || opt->type != UCI_TYPE_STRING)
- continue;
- if (strcmp(opt->v.string, search_val) == 0) {
- struct uci_ptr ptr = {0};
-
- ptr.value = value;
- ptr.package = package_name;
- ptr.section = s->e.name;
- ptr.option = option;
- ptr.target = UCI_TYPE_OPTION;
- if (uci_del_list(ctx, &ptr) == UCI_OK)
- uci_save(ctx, ptr.p);
- break;
- }
- }
- }
- uci_commit(ctx, &pkg, false);
- uci_unload(ctx, pkg);
- uci_free_context(ctx);
- return false;
-}
-
-bool config_set_host_list(char *package_name,
- char *section_type, char *search_key, char *search_val,
- char *option, char *value)
-{
- struct uci_context *ctx;
- struct uci_package *pkg;
- struct uci_element *e;
-
- dbg("Inside %s %d\n", __func__, __LINE__);
-
- if (!package_name || !search_val || !option || !value)
- return false;
-
- config_del_host_list(package_name, section_type, search_key,
- search_val, option, value);
-
- ctx = uci_alloc_context();
- if (!ctx)
- return false;
-
- if (uci_load(ctx, package_name, &pkg)) {
- uci_free_context(ctx);
- return false;
- }
-
- uci_foreach_element(&pkg->sections, e) {
- struct uci_section *s = uci_to_section(e);
-
- if (!strcmp(s->type, section_type)) {
- struct uci_option *opt = uci_lookup_option(ctx, s,
- search_key);
- if (!opt || opt->type != UCI_TYPE_STRING)
- continue;
- if (strcmp(opt->v.string, search_val) == 0) {
- struct uci_ptr ptr = {0};
-
- ptr.value = value;
- ptr.package = package_name;
- ptr.section = s->e.name;
- ptr.option = option;
- ptr.target = UCI_TYPE_OPTION;
- if (uci_add_list(ctx, &ptr) == UCI_OK)
- uci_save(ctx, ptr.p);
- break;
- }
- }
- }
- uci_commit(ctx, &pkg, false);
- uci_unload(ctx, pkg);
- uci_free_context(ctx);
- return false;
-}
-
bool config_init_host_data(char *package_name, char *section, struct topologyd_private *priv)
{
diff --git a/src/host_config.h b/src/host_config.h
index fdec2c7938a9f9d94cbc7294826ad8d4a037d552..503f072f65f0a714c2cd7e805654a25eb60aae5a 100644
--- a/src/host_config.h
+++ b/src/host_config.h
@@ -21,10 +21,4 @@ int config_add_default_host_mac(const char *config, const char *type,
bool config_set_host_option(char *package_name,
char *section_type, char *search_key, char *search_val,
char *option, char *value);
-bool config_set_host_list(char *package_name,
- char *section_type, char *search_key, char *search_val,
- char *option, char *value);
-bool config_del_host_list(char *package_name,
- char *section_type, char *search_key, char *search_val,
- char *option, char *value);
#endif /* HOSTD_CONFIG_H */
diff --git a/src/host_utils.c b/src/host_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..87c9fab82d7f1e3cdfa72f7adcfb60fa7ded9e6a
--- /dev/null
+++ b/src/host_utils.c
@@ -0,0 +1,281 @@
+/*
+ * host_utils.c -- utils for host
+ *
+ * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ * Author: Sukru Senli sukru.senli@inteno.se
+ * Author: Nevadita Chatterjee nevadita.chatterjee@iopsys.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 "host_utils.h"
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+
+struct in_addr src;
+struct in_addr dst;
+struct sockaddr_ll me;
+struct sockaddr_ll he;
+int sock_fd;
+
+typedef struct nl_req_s nl_req_t;
+
+struct nl_req_s {
+ struct nlmsghdr hdr;
+ struct rtgenmsg gen;
+};
+
+static int
+send_pack(struct in_addr *src_addr, struct in_addr *dst_addr, struct sockaddr_ll *ME, struct sockaddr_ll *HE)
+{
+ int err;
+ unsigned char buf[256];
+ struct arphdr *ah = (struct arphdr *) buf;
+ unsigned char *p = (unsigned char *) (ah + 1);
+
+ ah->ar_hrd = htons(ARPHRD_ETHER);
+ ah->ar_pro = htons(ETH_P_IP);
+ ah->ar_hln = ME->sll_halen;
+ ah->ar_pln = 4;
+ ah->ar_op = htons(ARPOP_REQUEST);
+
+ p = (unsigned char *)mempcpy((void *)p, (const void *)ME->sll_addr, (size_t)ah->ar_hln);
+ p = (unsigned char *)mempcpy((void *)p, (const void *)src_addr, 4);
+
+ p = (unsigned char *)mempcpy((void *)p, (const void *)HE->sll_addr, (size_t)ah->ar_hln);
+ p = (unsigned char *)mempcpy((void *)p, (const void *)dst_addr, 4);
+
+ err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
+ return err;
+}
+
+static bool
+recv_pack(char *buf, int len, struct sockaddr_ll *FROM)
+{
+ struct arphdr *ah = (struct arphdr *) buf;
+ unsigned char *p = (unsigned char *) (ah + 1);
+ struct in_addr src_ip, dst_ip;
+
+ /* Filter out wild packets */
+ if (FROM->sll_pkttype != PACKET_HOST
+ && FROM->sll_pkttype != PACKET_BROADCAST
+ && FROM->sll_pkttype != PACKET_MULTICAST)
+ return false;
+
+ /* Only these types are recognized */
+ if (ah->ar_op != htons(ARPOP_REPLY))
+ return false;
+
+ /* ARPHRD check and this darned FDDI hack here :-( */
+ if (ah->ar_hrd != htons(FROM->sll_hatype)
+ && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
+ return false;
+
+ /* Protocol must be IP. */
+ if (ah->ar_pro != htons(ETH_P_IP)
+ || (ah->ar_pln != 4)
+ || (ah->ar_hln != me.sll_halen)
+ || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
+ return false;
+
+ (src_ip.s_addr) = *(uint32_t *)(p + ah->ar_hln);
+ (dst_ip.s_addr) = *(uint32_t *)(p + ah->ar_hln + 4 + ah->ar_hln);
+
+ if (dst.s_addr != src_ip.s_addr)
+ return false;
+
+ if ((src.s_addr != dst_ip.s_addr) || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
+ return false;
+
+ return true;
+}
+
+
+bool
+host_send_arping(const char *targetIP, const char *device, int toms, int is_recv)
+{
+ struct sockaddr_in saddr;
+ struct ifreq ifr;
+ int probe_fd;
+ char packet[64];
+ struct sockaddr_ll from;
+ struct timeval timeout;
+
+ dbg("Inside %s %d\n", __func__, __LINE__);
+
+ sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0);
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, IF_NAMESIZE);
+
+ if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr)) < 0) {
+ close(sock_fd);
+ return false;
+ }
+
+ me.sll_family = AF_PACKET;
+ me.sll_ifindex = ifr.ifr_ifindex;
+ me.sll_protocol = htons(ETH_P_ARP);
+ bind(sock_fd, (struct sockaddr *) &me, sizeof(me));
+
+ socklen_t mlen = sizeof(me);
+
+ getsockname(sock_fd, (struct sockaddr *) &me, &mlen);
+
+ he = me;
+ memset(he.sll_addr, -1, he.sll_halen);
+
+ inet_pton(AF_INET, targetIP, &(dst.s_addr));
+
+ /* Get the sender IP address */
+ probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ socklen_t slen = sizeof(saddr);
+
+ saddr.sin_port = htons(1025);
+ saddr.sin_addr = dst;
+ connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
+ getsockname(probe_fd, (struct sockaddr *) &saddr, &slen);
+ src = saddr.sin_addr;
+ close(probe_fd);
+
+ send_pack(&src, &dst, &me, &he);
+
+ /*Here we are just sending the arp packet and returning*/
+ if (is_recv != 1)
+ return 1;
+
+ socklen_t alen = sizeof(from);
+ bool connected = false;
+ int cc = -1;
+
+ fd_set read_fds, write_fds, except_fds;
+
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+ FD_ZERO(&except_fds);
+ FD_SET(sock_fd, &read_fds);
+
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = toms * 1000;
+
+ if (select(sock_fd + 1, &read_fds, &write_fds, &except_fds, &timeout) == 1)
+ cc = recvfrom(sock_fd, packet, sizeof(packet), 0, (struct sockaddr *) &from, &alen);
+
+ if (cc >= 0)
+ connected = recv_pack(packet, cc, &from);
+
+ close(sock_fd);
+ dbg("Inside %s %d connected %d\n", __func__, __LINE__, connected);
+ return connected;
+}
+
+int host_get_netlink_ip(uint8_t *mac_addr, char *ipv4_str, char *device)
+{
+ struct rtnl_neigh *neigh;
+ struct nl_object *nobj;
+ struct nl_cache *cache;
+ uint32_t ifindex = 0;
+ struct nl_sock *sk;
+ int i, num;
+ int ret;
+ char *ifname = NULL;
+
+ dbg("Inside %s %d\n", __func__, __LINE__);
+ sk = nl_socket_alloc();
+ if (!sk) {
+ err("Unable to open nl event socket\n");
+ return -1;
+ }
+
+ if (nl_connect(sk, NETLINK_ROUTE) < 0) {
+ nl_socket_free(sk);
+ return -1;
+ }
+
+ ret = rtnl_neigh_alloc_cache(sk, &cache);
+ if (ret) {
+ nl_socket_free(sk);
+ return -1;
+ }
+
+
+ num = nl_cache_nitems(cache);
+ nobj = nl_cache_get_first(cache);
+ neigh = (struct rtnl_neigh *)nobj;
+
+ for (i = 0; i < num; i++) {
+ struct nl_addr *lladdr;
+ struct nl_addr *ipaddr;
+ struct ip_address ip = {0};
+ uint8_t hwaddr[6] = {0};
+ char addr_str[24];
+
+ nl_object_get((struct nl_object *) neigh);
+
+ ifindex = rtnl_neigh_get_ifindex(neigh);
+ lladdr = rtnl_neigh_get_lladdr(neigh);
+ if (lladdr)
+ memcpy(hwaddr, nl_addr_get_binary_addr(lladdr),
+ nl_addr_get_len(lladdr));
+
+ if (hwaddr_is_zero(hwaddr)) {
+ nl_object_put((struct nl_object *) neigh);
+ nobj = nl_cache_get_next(nobj);
+ neigh = (struct rtnl_neigh *)nobj;
+ continue;
+ }
+
+ ipaddr = rtnl_neigh_get_dst(neigh);
+ if (ipaddr) {
+ ip.family = nl_addr_get_family(ipaddr);
+ if (ip.family == AF_INET6 || ip.family == AF_INET) {
+ memcpy(&ip.addr, nl_addr_get_binary_addr(ipaddr),
+ nl_addr_get_len(ipaddr));
+ }
+ }
+
+ char *addr_s = nl_addr2str(ipaddr, addr_str, sizeof(addr_str));
+
+ if (addr_s == NULL) {
+ /* error */
+ err("nl_addr2str failed\n");
+ return -1;
+ }
+
+ ret = memcmp(hwaddr, mac_addr, 6);
+ if (ret == 0) {
+ strncpy(ipv4_str, addr_str, 24);
+ ifname = if_indextoname(ifindex, device);
+ if (ifname == NULL)
+ return -1;
+ dbg("intfname = [%s] ipv4addr= [%s] mac=["MACFMT"]\n", device, ipv4_str, MAC2STR(hwaddr));
+ break;
+ }
+
+ nl_object_put((struct nl_object *) neigh);
+ nobj = nl_cache_get_next(nobj);
+ neigh = (struct rtnl_neigh *)nobj;
+ }
+
+ nl_cache_free(cache);
+ nl_socket_free(sk);
+
+ return 0;
+}
diff --git a/src/host_utils.h b/src/host_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..375f226932139e272b1e28f5f2a1655b54ad456d
--- /dev/null
+++ b/src/host_utils.h
@@ -0,0 +1,30 @@
+#ifndef HOST_UTILS_H
+#define HOST_UTILS_H
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include "debug.h"
+#include <fcntl.h>
+#include <libubus.h>
+#include <easy/easy.h>
+#include <linux/rtnetlink.h>
+
+#define NLMSG_NEIGH 28
+#define IFLIST_REPLY_BUFFER 8192
+
+bool host_send_arping(const char *targetIP, const char *device, int toms, int is_recv);
+int host_get_neigh(struct nlmsghdr *nlh, char *dev, char *dest_addr, uint8_t *mac_addr);
+int host_get_netlink_ip(uint8_t *mac_addr, char *ipv4_str, char *device);
+
+#endif
diff --git a/src/topologyd.c b/src/topologyd.c
index 840cacc3548ef47e828add0af2fe6297579f102d..df0d359777acbad635e159143ea8b7ee970a77e3 100644
--- a/src/topologyd.c
+++ b/src/topologyd.c
@@ -304,11 +304,13 @@ void topologyd_process_topology_response(struct cmdu_cstruct *cstruct, struct to
iface_node = host_node_lookup(priv->host.node_htable, tlv->local_interfaces[j].mac_address);
if (iface_node) {
struct host_node *node;
+ int rv = -1;
dbg("%s %d we found a node\n", __func__, __LINE__);
node = host_node_lookup(priv->host.node_htable, n.hwaddr);
- if (node) {
+ rv = memcmp(node->hwaddr, iface_node->hwaddr, 6);
+ if (node && rv) {
iface_node->ignore = true;
iface_node->al_node = node;
if (tlv->local_interfaces[j].media_type ==
@@ -1478,6 +1480,9 @@ int topologyd_start(void)
//Here start the host refresh timer
priv->host_refresh_timer.cb = host_periodic_refresh;
+ /*Here we set the cb for the arp table read timer*/
+ priv->host_arp_timer.cb = host_arp_table_refresh;
+
priv->refresh_timer.cb = topologyd_periodic_refresh;
priv->heartbeat.cb = topologyd_start_heartbeat;
priv->topo.changelog = (struct topology_changelog *) calloc
diff --git a/src/topologyd.h b/src/topologyd.h
index b0e903d9df983ed7106c03421d95e69fa3cf8073..9f996e6ab9477411a212a8e78900fd0fd308aafc 100644
--- a/src/topologyd.h
+++ b/src/topologyd.h
@@ -229,6 +229,7 @@ struct topologyd_private {
struct topology topo;
struct host_ntwk host;
struct uloop_timeout host_refresh_timer;
+ struct uloop_timeout host_arp_timer;
void *avahi_serv;
void *simple_poll;
struct json_object *wifi_stations;