diff --git a/dongle.c b/dongle.c
index 90ea905939898e80dc6262e35e40d6b2e3ee7410..43995bdcb7f9b66a2511c1107877559af77a603e 100644
--- a/dongle.c
+++ b/dongle.c
@@ -7,27 +7,36 @@
 struct ubus_context *global_ctx;
 int debug;
 struct uloop_timeout timeout = { .cb = devices_status };
-
 static struct option long_options[] = {
 	{"debug", required_argument, NULL, 'd'},
 	{0,	0,	0,	0}
 };
 
-void uloop_add_get_devices(struct uloop_timeout *t)
-{
-	uloop_timeout_set(t, 5000);
-	uloop_timeout_add(t);
-}
+enum {
+	DEV,
+	__DEV_MAX
+};
+
+const struct blobmsg_policy dev_policy[__DEV_MAX] = {
+	[DEV] = {.name = "dev", .type = BLOBMSG_TYPE_STRING},
+};
+
+LIST_HEAD(devices);
+LIST_HEAD(stack);
+LIST_HEAD(visited);
 
 int parse_args(int argc, char **argv)
 {
 	char ch;
 
-	while ((ch = getopt_long(argc, argv, "d:", long_options, NULL)) != -1) {
-		switch (ch) {
+	while ((ch = getopt_long(argc, argv, "d:", long_options, NULL)) != -1)
+	{
+		switch (ch)
+		{
 		case 'd':
 			debug = atoi(optarg);
-			if (debug > 1 || debug < 0) {
+			if (debug > 1 || debug < 0)
+			{
 				printf("%s: option '-%c' is invalid.\n", argv[0], optopt); //cant exactly do debug print in here...
 				goto fail;
 			}
@@ -47,6 +56,514 @@ fail:
 	return -1;
 }
 
+int devices_status(struct uloop_timeout *t)
+{
+	get_devices();
+	tag_missing_devices();
+
+	uloop_add_get_devices(t);
+
+	return 0;
+}
+
+int tag_missing_devices(void)
+{
+	struct device *dev, *tmp;
+
+	list_for_each_entry_safe(dev, tmp, &devices, list) {
+		if (dev->present) {
+			dev->missing = 0;
+			dev->present = false;
+			continue;
+		}
+
+		dev->missing++;
+		if (dev->missing == 1)
+			delete_device(dev);
+	}
+
+	return 0;
+}
+
+int add_device(struct device *new_dev)
+{
+	struct device *dev;
+
+	dev = search_list(new_dev->usb.if_name);
+	if (dev) {
+		if (dev->ip)
+			free(dev->ip);
+		dev->ip = new_dev->ip;
+
+		dev->present = true;
+		goto already_present;
+	}
+
+	new_dev->present = true;
+	if (list_empty(&devices))
+		INIT_LIST_HEAD(&devices);
+
+	list_add_tail(&new_dev->list, &devices);
+	if (new_dev->ip) {
+		new_dev->ubus_obj = dongle_create_dynamic_object(new_dev);
+		if (new_dev->ubus_obj)
+			publish_ubus_object(global_ctx, new_dev->ubus_obj);
+	}
+
+	return 0;
+already_present:
+	return -1;
+}
+
+int delete_all_devices(void)
+{
+	struct device *dev, *tmp;
+
+	list_for_each_entry_safe(dev, tmp, &devices, list) {
+		delete_device(dev);
+	}
+
+	return 0;
+}
+
+int delete_device_by_name(char *name)
+{
+	struct device *dev, *tmp;
+
+	list_for_each_entry_safe(dev, tmp, &devices, list) {
+		if (strncmp(dev->usb.if_name, name, 128) != 0)
+			continue;
+
+		delete_device(dev);
+		return 0;
+	}
+
+	return -1;
+}
+
+int delete_device(struct device *dev)
+{
+	if (dev->ubus_obj)
+		unpublish_ubus_object(global_ctx, dev->ubus_obj);
+	// is it necessary to check if list contains this node?
+	list_del(&dev->list);
+	free_device(dev);
+	return 0;
+}
+
+void free_device(struct device *dev)
+{
+	if (!dev)
+		return;
+	free(dev->ip);
+	free(&(dev->usb));
+}
+
+void free_usb(struct USB *usb)
+{
+	if (!usb)
+		return;
+	free(usb->product);
+	free(usb->product_id);
+	free(usb->vendor_id);
+	free(usb->if_name);
+}
+
+struct device *search_list(char *name)
+{
+	struct device *dev;
+
+	list_for_each_entry(dev, &devices, list) {
+		if (strncmp(name, dev->usb.if_name, 128) == 0)
+			return dev;
+	}
+	return NULL;
+}
+
+char *lexer(char **input, char *delimiter)
+{
+	char *token, *substr;
+
+	if (strlen(*input) == 0) {
+		debug_print("empty input!\n");
+		return NULL;
+	} else if (strlen(delimiter) == 0) {
+		debug_print("empty delimiter!\n");
+		return NULL;
+	}
+
+	token = strstr(*input, delimiter);
+
+	if (token) {
+		*token = '\0';
+		substr = strdup(*input);
+		if (!substr) {
+			perror("strdup");
+			goto fail_strdup;
+		}
+
+		*input = token + strlen(delimiter);
+	} else {
+		substr = strdup(*input);
+		if (!substr) {
+			perror("strdup");
+			goto fail_strdup;
+		}
+
+		*input[0] = '\0';
+	}
+
+fail_strdup:
+	return substr;
+}
+
+void remove_newline(char *input)
+{
+	char *pos;
+
+	pos = strchr(input, '\n');
+	if (!pos)
+		return;
+
+	*pos = '\0';
+}
+
+char *get_usb_stat(char *path, char *dir, char *stat)
+{
+	char stat_path[PATH_MAX], contents[1024];
+	FILE *f;
+
+	snprintf(stat_path, PATH_MAX, "%s/%s/%s", path, dir, stat);
+	f = fopen(stat_path, "r");
+	if (!f) {
+		perror("fopen");
+		goto fail;
+	}
+
+	fgets(contents, 1024, f);
+	remove_newline(contents);
+	fclose(f);
+
+	return strdup(contents);
+fail:
+	return NULL;
+}
+
+char *get_device_name(char *dir_name)
+{
+	char path[PATH_MAX], *name = NULL;
+	struct directory *dr, *sub_dr;
+	struct dirent *de;
+	struct stat st;
+	DIR *dir;
+
+	dr = (struct directory *)malloc(sizeof(*dr));
+	if (!dr) {
+		perror("malloc");
+		goto fail_dr;
+	}
+
+	dr->path = strdup(dir_name);
+	if (!dr->path)
+		goto fail_path;
+
+	push(dr, &stack);
+
+	while (!list_empty(&stack) && !name) {
+		dr = pop(&stack);
+		dir = opendir(dr->path);
+		if (!dir)
+			continue;
+
+		push(dr, &visited);
+
+		while ((de = readdir(dir)) != NULL) {
+			if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+				continue;
+
+			if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
+				perror("fstatat");
+				continue;
+			}
+
+			if (!S_ISDIR(st.st_mode))
+				continue;
+
+			if (!strstr(dr->path, "net")) {
+				snprintf(path, PATH_MAX, "%s%s/", dr->path, de->d_name);
+
+				if (search(path, &visited))
+					continue;
+
+				sub_dr = (struct directory *)malloc(sizeof(*sub_dr));
+				if (!sub_dr) {
+					perror("malloc");
+					continue;
+				}
+
+				sub_dr->path = strdup(path);
+				if (!sub_dr->path) {
+					free(sub_dr);
+					continue;
+				}
+
+				push(sub_dr, &stack);
+				continue;
+			}
+
+			if (!strstr(de->d_name, "eth") && !strstr(de->d_name, "usb"))
+				break;
+
+			name = strdup(de->d_name);
+			// how to manage failure on this strdup
+			break;
+		}
+		closedir(dir);
+	}
+
+	clear_list(&visited);
+	clear_list(&stack);
+	return name;
+fail_path:
+	free(dr);
+fail_dr:
+	return NULL;
+}
+
+int get_devices(void)
+{
+	char usb_path[PATH_MAX], product_path[PATH_MAX], path[PATH_MAX], *name;
+	struct dirent *de;
+	DIR *dir;
+	struct stat st;
+	struct device *dev;
+	int rv;
+
+	strncpy(usb_path, "/sys/bus/usb/devices/", PATH_MAX);
+	dir = opendir(usb_path);
+	if (!dir) {
+		perror("opendir");
+		goto fail_dr;
+	}
+	while ((de = readdir(dir)) != NULL) {
+		if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+			continue;
+		if (strstr(de->d_name, ":") || strstr(de->d_name, "usb"))
+			continue;
+
+		snprintf(product_path, PATH_MAX, "%s%s/product", usb_path, de->d_name);
+		memset(&st, 0, sizeof(st));
+
+		rv = stat(product_path, &st);
+		if (rv < 0) {
+			//perror("stat");
+			continue;
+		}
+
+		snprintf(path, PATH_MAX, "%s%s/", usb_path, de->d_name);
+		name = get_device_name(path);
+		if (!name)
+			continue;
+
+		dev = (struct device *)calloc(1, sizeof(*dev));
+		if (!dev) {
+			perror("calloc");
+			goto fail_dev;
+		}
+
+		dev->usb.product = get_usb_stat(usb_path, de->d_name, "product");
+		dev->usb.product_id = get_usb_stat(usb_path, de->d_name, "idProduct");
+		dev->usb.vendor_id = get_usb_stat(usb_path, de->d_name, "idVendor");
+		dev->usb.if_name = name;
+		dev->ip = get_device_ip(dev->usb.if_name);
+
+		add_device(dev);
+	}
+
+	closedir(dir);
+	return 0;
+fail_dev:
+	closedir(dir);
+fail_dr:
+	return -1;
+}
+
+char *get_device_ip(char *device_name)
+{
+	char *iface, *destination, *gateway, *flags, *route, *ipv4_addr = NULL;
+	bool host_flag;
+	struct in_addr addr;
+	FILE *fp;
+
+	fp = fopen("/proc/net/route", "r");
+	if (!fp) {
+		perror("fopen");
+		goto fail;
+	}
+
+	route = (char *)malloc(1024);
+	if (!route) {
+		perror("malloc");
+		goto fail_route;
+	}
+	memset(route, 0, 1024);
+	while ((fgets(route, 1024, fp)) != NULL) {
+		remove_newline(route);
+
+		iface = lexer(&route, "\t");
+		destination = lexer(&route, "\t");
+		gateway = lexer(&route, "\t");
+		flags = lexer(&route, "\t");
+
+		if (strncmp(iface, device_name, 10) != 0)
+			continue;
+
+		host_flag = atoi(flags) & 4;
+		if (!host_flag)
+			continue;
+
+		ipv4_addr = (char *)calloc(1, IPV4_MAX);
+		if (!ipv4_addr)
+			break;
+
+		addr.s_addr = strtoul(destination, NULL, IPV4_MAX);
+		inet_ntop(AF_INET, &(addr.s_addr), ipv4_addr, IPV4_MAX);
+		printf("ipv4_addr %s\n", ipv4_addr);
+	}
+
+	free(iface);
+	free(destination);
+	free(gateway);
+	free(flags);
+fail_route:
+	fclose(fp);
+fail:
+	return ipv4_addr;
+}
+
+int list_to_blob(void)
+{
+	struct device *net_dev;
+	struct blob_buf bb;
+	void *arr, *table;
+	int rv;
+
+	memset(&bb, 0, sizeof(bb));
+	rv = blob_buf_init(&bb, 0);
+	if (rv != 0)
+		goto fail;
+
+	arr = blobmsg_open_array(&bb, "network_devices");
+	if (!arr)
+		goto fail_arr;
+
+	list_for_each_entry(net_dev, &devices, list)
+	{
+		table = blobmsg_open_table(&bb, "");
+		if (!table)
+			goto fail_table;
+
+		rv = blobmsg_add_string(&bb, "product", net_dev->usb.product);
+		if (rv < 0)
+			goto fail_string;
+
+		rv = blobmsg_add_string(&bb, "interface_name", net_dev->usb.if_name);
+		if (rv < 0)
+			goto fail_string;
+
+		rv = blobmsg_add_string(&bb, "idproduct", net_dev->usb.product_id);
+		if (rv < 0)
+			goto fail_string;
+
+		rv = blobmsg_add_string(&bb, "idvendor", net_dev->usb.vendor_id);
+		if (rv < 0)
+			goto fail_string;
+
+		if (net_dev->ip)
+		{
+			rv = blobmsg_add_string(&bb, "ip", net_dev->ip);
+			if (rv < 0)
+				goto fail_string;
+		}
+		blobmsg_close_table(&bb, table);
+	}
+	blobmsg_close_array(&bb, arr);
+	ubus_send_reply(ctx, req, bb.head);
+
+	blob_buf_free(&bb);
+	return 0;
+fail_string:
+fail_table:
+fail_arr:
+	blob_buf_free(&bb);
+fail:
+	return UBUS_STATUS_UNKNOWN_ERROR;
+}
+
+int print_list(struct ubus_context *ctx, struct ubus_object *obj,
+			   struct ubus_request_data *req, const char *method,
+			   struct blob_attr *msg)
+{
+	return list_to_blob();
+}
+
+int clear(struct ubus_context *ctx, struct ubus_object *obj,
+		  struct ubus_request_data *req, const char *method,
+		  struct blob_attr *msg)
+{
+	printf("%d\n", delete_all_devices());
+	return 0;
+}
+
+int test(struct ubus_context *ctx, struct ubus_object *obj,
+		 struct ubus_request_data *req, const char *method,
+		 struct blob_attr *msg)
+{
+	printf("%s\n", get_device_ip("usb0"));
+	return 0;
+}
+
+int remove_device(struct ubus_context *ctx, struct ubus_object *obj,
+				  struct ubus_request_data *req, const char *method,
+				  struct blob_attr *msg)
+{
+	struct blob_attr *tb[__DEV_MAX];
+	char *dev;
+
+	blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
+
+	if (!tb[DEV])
+		goto fail;
+	dev = (char *)blobmsg_data(tb[DEV]);
+
+	printf("%d\n", delete_device_by_name(dev));
+
+	return 0;
+fail:
+	return UBUS_STATUS_INVALID_ARGUMENT;
+}
+
+struct ubus_method infrastructure_object_methods[] = {
+	UBUS_METHOD_NOARG("test", test),
+	UBUS_METHOD_NOARG("list", print_list),
+	UBUS_METHOD_NOARG("clear", clear),
+	UBUS_METHOD("remove_device", remove_device, dev_policy)};
+
+struct ubus_object_type infrastructure_object_type = UBUS_OBJECT_TYPE("dongle", infrastructure_object_methods);
+
+struct ubus_object infrastructure_object = {
+	.name = "dongle",
+	.type = &infrastructure_object_type,
+	.methods = infrastructure_object_methods,
+	.n_methods = ARRAY_SIZE(infrastructure_object_methods),
+};
+
+void uloop_add_get_devices(struct uloop_timeout *t)
+{
+	uloop_timeout_set(t, 5000);
+	uloop_timeout_add(t);
+}
+
 void init_ubus(void)
 {
 	global_ctx = ubus_connect(NULL);
diff --git a/dongle_infrastructure.c b/dongle_infrastructure.c
index 409bd29bea7c2bc6dab3c4cbf90cef5262693d56..7f0cc790eef080d980bd80c2c86c39e13f378065 100644
--- a/dongle_infrastructure.c
+++ b/dongle_infrastructure.c
@@ -18,7 +18,6 @@
 #include "dongle.h"
 #include "stack_operations.h"
 
-
 struct ubus_object *dongle_create_dynamic_object(struct device *dev_instance);
 int publish_ubus_object(struct ubus_context *ctx, struct ubus_object *obj);
 int unpublish_ubus_object(struct ubus_context *ctx, struct ubus_object *obj);
@@ -35,6 +34,7 @@ void free_device(struct device *dev);
 void free_usb(struct USB *usb);
 struct device *search_list(char *name);
 
+<<<<<<< HEAD
 
 const struct blobmsg_policy dev_policy[__DEV_MAX] = {
 	[DEV] = {.name = "dev", .type = BLOBMSG_TYPE_STRING},
@@ -294,251 +294,10 @@ char *get_device_name(char *dir_name)
 					free(sub_dr);
 					continue;
 				}
+=======
+>>>>>>> 7e47c50... refactor static dongle object from dongle_infrastructure to dongle.c
 
-				push(sub_dr, &stack);
-				continue;
-			}
-
-			if (!strstr(de->d_name, "eth") && !strstr(de->d_name, "usb"))
-				break;
-
-			name = strdup(de->d_name);
-			// how to manage failure on this strdup
-			break;
-		}
-		closedir(dir);
-	}
-
-	clear_list(&visited);
-	clear_list(&stack);
-	return name;
-fail_path:
-	free(dr);
-fail_dr:
-	return NULL;
-}
-
-int get_devices(void)
-{
-	char usb_path[PATH_MAX], product_path[PATH_MAX], path[PATH_MAX], *name;
-	struct dirent *de;
-	DIR *dir;
-	struct stat st;
-	struct device *dev;
-	int rv;
-
-	strncpy(usb_path, "/sys/bus/usb/devices/", PATH_MAX);
-	dir = opendir(usb_path);
-	if (!dir) {
-		perror("opendir");
-		goto fail_dr;
-	}
-	while ((de = readdir(dir)) != NULL) {
-		if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
-			continue;
-		if (strstr(de->d_name, ":") || strstr(de->d_name, "usb"))
-			continue;
-
-		snprintf(product_path, PATH_MAX, "%s%s/product", usb_path, de->d_name);
-		memset(&st, 0, sizeof(st));
-
-		rv = stat(product_path, &st);
-		if (rv < 0) {
-			//perror("stat");
-			continue;
-		}
-
-		snprintf(path, PATH_MAX, "%s%s/", usb_path, de->d_name);
-		name = get_device_name(path);
-		if (!name)
-			continue;
-
-		dev = (struct device *)calloc(1, sizeof(*dev));
-		if (!dev) {
-			perror("calloc");
-			goto fail_dev;
-		}
-
-		dev->usb.product = get_usb_stat(usb_path, de->d_name, "product");
-		dev->usb.product_id = get_usb_stat(usb_path, de->d_name, "idProduct");
-		dev->usb.vendor_id = get_usb_stat(usb_path, de->d_name, "idVendor");
-		dev->usb.if_name = name;
-		dev->ip = get_device_ip(dev->usb.if_name);
-
-		add_device(dev);
-	}
-
-	closedir(dir);
-	return 0;
-fail_dev:
-	closedir(dir);
-fail_dr:
-	return -1;
-}
-
-char *get_device_ip(char *device_name)
-{
-	char *iface, *destination, *gateway, *flags, *route, *ipv4_addr = NULL;
-	bool host_flag;
-	struct in_addr addr;
-	FILE *fp;
-
-	fp = fopen("/proc/net/route", "r");
-	if (!fp) {
-		perror("fopen");
-		goto fail;
-	}
-
-	route = (char *)malloc(1024);
-	if (!route) {
-		perror("malloc");
-		goto fail_route;
-	}
-	memset(route, 0, 1024);
-	while ((fgets(route, 1024, fp)) != NULL) {
-		remove_newline(route);
-
-		iface = lexer(&route, "\t");
-		destination = lexer(&route, "\t");
-		gateway = lexer(&route, "\t");
-		flags = lexer(&route, "\t");
-
-		if (strncmp(iface, device_name, 10) != 0)
-			continue;
-
-		host_flag = atoi(flags) & 4;
-		if (!host_flag)
-			continue;
-
-		ipv4_addr = (char *)calloc(1, IPV4_MAX);
-		if (!ipv4_addr)
-			break;
-
-		addr.s_addr = strtoul(destination, NULL, IPV4_MAX);
-		inet_ntop(AF_INET, &(addr.s_addr), ipv4_addr, IPV4_MAX);
-		printf("ipv4_addr %s\n", ipv4_addr);
-	}
 
-	free(iface);
-	free(destination);
-	free(gateway);
-	free(flags);
-fail_route:
-	fclose(fp);
-fail:
-	return ipv4_addr;
-}
-
-int print_list(struct ubus_context *ctx, struct ubus_object *obj,
-			struct ubus_request_data *req, const char *method,
-			struct blob_attr *msg)
-{
-	struct device *net_dev;
-	struct blob_buf bb;
-	void *arr, *table;
-	int rv;
-
-	memset(&bb, 0, sizeof(bb));
-	rv = blob_buf_init(&bb, 0);
-	if (rv != 0)
-		goto fail;
-
-	arr = blobmsg_open_array(&bb, "network_devices");
-	if (!arr)
-		goto fail_arr;
-
-	list_for_each_entry(net_dev, &devices, list) {
-		table = blobmsg_open_table(&bb, "");
-		if (!table)
-			goto fail_table;
-
-		rv = blobmsg_add_string(&bb, "product", net_dev->usb.product);
-		if (rv < 0)
-			goto fail_string;
-
-		rv = blobmsg_add_string(&bb, "interface_name", net_dev->usb.if_name);
-		if (rv < 0)
-			goto fail_string;
-
-		rv = blobmsg_add_string(&bb, "idproduct", net_dev->usb.product_id);
-		if (rv < 0)
-			goto fail_string;
-
-		rv = blobmsg_add_string(&bb, "idvendor", net_dev->usb.vendor_id);
-		if (rv < 0)
-			goto fail_string;
-
-		if (net_dev->ip) {
-			rv = blobmsg_add_string(&bb, "ip", net_dev->ip);
-			if (rv < 0)
-				goto fail_string;
-		}
-		blobmsg_close_table(&bb, table);
-	}
-	blobmsg_close_array(&bb, arr);
-	ubus_send_reply(ctx, req, bb.head);
-
-	blob_buf_free(&bb);
-	return 0;
-fail_string:
-fail_table:
-fail_arr:
-	blob_buf_free(&bb);
-fail:
-	return UBUS_STATUS_UNKNOWN_ERROR;
-}
-
-int clear(struct ubus_context *ctx, struct ubus_object *obj,
-			struct ubus_request_data *req, const char *method,
-			struct blob_attr *msg)
-{
-	printf("%d\n", delete_all_devices());
-	return 0;
-}
-
-int test(struct ubus_context *ctx, struct ubus_object *obj,
-			struct ubus_request_data *req, const char *method,
-			struct blob_attr *msg)
-{
-	printf("%s\n", get_device_ip("usb0"));
-	return 0;
-}
-
-int remove_device(struct ubus_context *ctx, struct ubus_object *obj,
-			struct ubus_request_data *req, const char *method,
-			struct blob_attr *msg)
-{
-	struct blob_attr *tb[__DEV_MAX];
-	char *dev;
-
-	blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
-
-	if (!tb[DEV])
-		goto fail;
-	dev = (char *)blobmsg_data(tb[DEV]);
-
-	printf("%d\n", delete_device_by_name(dev));
-
-	return 0;
-fail:
-	return UBUS_STATUS_INVALID_ARGUMENT;
-}
-
-struct ubus_method infrastructure_object_methods[] = {
-	UBUS_METHOD_NOARG("test", test),
-	UBUS_METHOD_NOARG("list", print_list),
-	UBUS_METHOD_NOARG("clear", clear),
-	UBUS_METHOD("remove_device", remove_device, dev_policy)
-};
-
-struct ubus_object_type infrastructure_object_type = UBUS_OBJECT_TYPE("dongle", infrastructure_object_methods);
-
-struct ubus_object infrastructure_object = {
-	.name = "dongle",
-	.type = &infrastructure_object_type,
-	.methods = infrastructure_object_methods,
-	.n_methods = ARRAY_SIZE(infrastructure_object_methods),
-};
 
 int expose_infrastructure_object(struct ubus_context *ctx)
 {