fix unannotated fall-through warnings
[project/netifd.git] / handler.c
index f5db43803a4480c287068dc3564863940c63912d..04bdbee89a04a4ab76111b36efcf512c32cced90 100644 (file)
--- a/handler.c
+++ b/handler.c
@@ -16,7 +16,6 @@
 #include <glob.h>
 #include <fcntl.h>
 #include <stdio.h>
-#include <unistd.h>
 
 #include "netifd.h"
 #include "system.h"
@@ -28,14 +27,17 @@ netifd_dir_push(int fd)
        int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
        system_fd_set_cloexec(prev_fd);
        if (fd >= 0)
-               fchdir(fd);
+               if (fchdir(fd)) {}
        return prev_fd;
 }
 
 static void
 netifd_dir_pop(int prev_fd)
 {
-       fchdir(prev_fd);
+       if (prev_fd < 0)
+               return;
+
+       if (fchdir(prev_fd)) {}
        close(prev_fd);
 }
 
@@ -60,7 +62,83 @@ out:
 }
 
 static void
-netifd_init_script_handler(const char *name, script_dump_cb cb)
+netifd_init_script_handler(const char *script, json_object *obj, script_dump_cb cb)
+{
+       json_object *tmp;
+       const char *name;
+
+       if (!json_check_type(obj, json_type_object))
+               return;
+
+       tmp = json_get_field(obj, "name", json_type_string);
+       if (!tmp)
+               return;
+
+       name = json_object_get_string(tmp);
+       cb(script, name, obj);
+}
+
+static void
+netifd_init_extdev_handler(const char *config_file, json_object *obj,
+                          create_extdev_handler_cb cb)
+{
+       json_object *tmp, *cfg, *info, *stats;
+       const char *name, *ubus_name, *br_prefix = NULL;
+       bool bridge_support = true;
+       char *err_missing;
+
+       if (!json_check_type(obj, json_type_object))
+               return;
+
+       tmp = json_get_field(obj, "name", json_type_string);
+       if (!tmp) {
+               err_missing = "name";
+               goto field_missing;
+       }
+
+       name = json_object_get_string(tmp);
+
+       tmp = json_get_field(obj, "ubus_name", json_type_string);
+       if (!tmp) {
+               err_missing = "ubus_name";
+               goto field_missing;
+       }
+
+       ubus_name = json_object_get_string(tmp);
+
+       tmp = json_get_field(obj, "bridge", json_type_string);
+       if (!tmp || !strcmp(json_object_get_string(tmp), "0"))
+               bridge_support = false;
+
+       if (bridge_support) {
+               tmp = json_get_field(obj, "br-prefix", json_type_string);
+               if (!tmp)
+                       br_prefix = name;
+               else
+                       br_prefix = json_object_get_string(tmp);
+       }
+
+       tmp = json_get_field(obj, "config", json_type_array);
+       if (!tmp) {
+               err_missing = "config";
+               goto field_missing;
+       }
+
+       cfg = tmp;
+
+       info = json_get_field(obj, "info", json_type_array);
+       stats = json_get_field(obj, "stats", json_type_array);
+
+       cb(config_file, name, ubus_name, bridge_support, br_prefix, cfg, info, stats);
+       return;
+
+field_missing:
+       netifd_log_message(L_WARNING, "external device handler description '%s' is"
+                              "missing field '%s'\n", config_file, err_missing);
+}
+
+static void
+netifd_parse_script_handler(const char *name, script_dump_cb cb)
 {
        struct json_tokener *tok = NULL;
        json_object *obj;
@@ -89,8 +167,8 @@ netifd_init_script_handler(const char *name, script_dump_cb cb)
                        tok = json_tokener_new();
 
                obj = json_tokener_parse_ex(tok, start, len);
-               if (!is_error(obj)) {
-                       cb(name, obj);
+               if (obj) {
+                       netifd_init_script_handler(name, obj, cb);
                        json_object_put(obj);
                        json_tokener_free(tok);
                        tok = NULL;
@@ -106,15 +184,76 @@ netifd_init_script_handler(const char *name, script_dump_cb cb)
        pclose(f);
 }
 
+static void
+netifd_parse_extdev_handler(const char *path_to_file, create_extdev_handler_cb cb)
+{
+       struct json_tokener *tok = NULL;
+       json_object *obj;
+       FILE *file;
+       int len;
+       char buf[512], *start;
+
+       file = fopen(path_to_file, "r");
+       if (!file)
+               return;
+
+       do {
+               start = fgets(buf, sizeof(buf), file);
+               if (!start)
+                       continue;
+
+               len = strlen(start);
+
+               if (!tok)
+                       tok = json_tokener_new();
+
+               obj = json_tokener_parse_ex(tok, start, len);
+
+               if (obj) {
+                       netifd_init_extdev_handler(path_to_file, obj, cb);
+                       json_object_put(obj);
+                       json_tokener_free(tok);
+                       tok = NULL;
+               } else if (start[len - 1] == '\n') {
+                       json_tokener_free(tok);
+                       tok = NULL;
+               }
+       } while (!feof(file) && !ferror(file));
+
+       if (tok)
+               json_tokener_free(tok);
+
+       fclose(file);
+}
+
 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
 {
        glob_t g;
        int i, prev_fd;
 
        prev_fd = netifd_dir_push(dir_fd);
-       glob("./*.sh", 0, NULL, &g);
+       if (glob("./*.sh", 0, NULL, &g)) {
+               netifd_dir_pop(prev_fd);
+               return;
+       }
+
        for (i = 0; i < g.gl_pathc; i++)
-               netifd_init_script_handler(g.gl_pathv[i], cb);
+               netifd_parse_script_handler(g.gl_pathv[i], cb);
+       netifd_dir_pop(prev_fd);
+
+       globfree(&g);
+}
+
+void
+netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
+{
+       glob_t g;
+       int prev_fd;
+
+       prev_fd = netifd_dir_push(dir_fd);
+       glob("*.json", 0, NULL, &g);
+       for (int i = 0; i < g.gl_pathc; i++)
+               netifd_parse_extdev_handler(g.gl_pathv[i], cb);
        netifd_dir_pop(prev_fd);
 }
 
@@ -123,6 +262,7 @@ netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj
 {
        struct blobmsg_policy *attrs;
        char *str_buf, *str_cur;
+       char const **validate;
        int str_len = 0;
        int i;
 
@@ -131,7 +271,12 @@ netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj
        if (!attrs)
                return NULL;
 
+       validate = calloc(1, sizeof(char*) * config->n_params);
+       if (!validate)
+               goto error;
+
        config->params = attrs;
+       config->validate = validate;
        for (i = 0; i < config->n_params; i++) {
                json_object *cur, *name, *type;
 
@@ -162,15 +307,25 @@ netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj
        str_cur = str_buf;
        for (i = 0; i < config->n_params; i++) {
                const char *name = attrs[i].name;
+               char *delim;
 
                attrs[i].name = str_cur;
                str_cur += sprintf(str_cur, "%s", name) + 1;
+               delim = strchr(attrs[i].name, ':');
+               if (delim) {
+                       *delim = '\0';
+                       validate[i] = ++delim;
+               } else {
+                       validate[i] = NULL;
+               }
        }
 
        return str_buf;
 
 error:
        free(attrs);
+       if (validate)
+               free(validate);
        config->n_params = 0;
        return NULL;
 }