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)
{