handler.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * netifd - network interface daemon
  3. * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #define _GNU_SOURCE
  15. #include <glob.h>
  16. #include <fcntl.h>
  17. #include <stdio.h>
  18. #include "netifd.h"
  19. #include "system.h"
  20. #include "handler.h"
  21. static int
  22. netifd_dir_push(int fd)
  23. {
  24. int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
  25. system_fd_set_cloexec(prev_fd);
  26. if (fd >= 0)
  27. if (fchdir(fd)) {}
  28. return prev_fd;
  29. }
  30. static void
  31. netifd_dir_pop(int prev_fd)
  32. {
  33. if (prev_fd < 0)
  34. return;
  35. if (fchdir(prev_fd)) {}
  36. close(prev_fd);
  37. }
  38. int netifd_open_subdir(const char *name)
  39. {
  40. int prev_dir;
  41. int ret = -1;
  42. prev_dir = netifd_dir_push(-1);
  43. if (chdir(main_path)) {
  44. perror("chdir(main path)");
  45. goto out;
  46. }
  47. ret = open(name, O_RDONLY | O_DIRECTORY);
  48. if (ret >= 0)
  49. system_fd_set_cloexec(ret);
  50. out:
  51. netifd_dir_pop(prev_dir);
  52. return ret;
  53. }
  54. static void
  55. netifd_init_script_handler(const char *script, json_object *obj, script_dump_cb cb)
  56. {
  57. json_object *tmp;
  58. const char *name;
  59. if (!json_check_type(obj, json_type_object))
  60. return;
  61. tmp = json_get_field(obj, "name", json_type_string);
  62. if (!tmp)
  63. return;
  64. name = json_object_get_string(tmp);
  65. cb(script, name, obj);
  66. }
  67. static void
  68. netifd_parse_script_handler(const char *name, script_dump_cb cb)
  69. {
  70. struct json_tokener *tok = NULL;
  71. json_object *obj;
  72. static char buf[512];
  73. char *start, *cmd;
  74. FILE *f;
  75. int len;
  76. #define DUMP_SUFFIX " '' dump"
  77. cmd = alloca(strlen(name) + 1 + sizeof(DUMP_SUFFIX));
  78. sprintf(cmd, "%s" DUMP_SUFFIX, name);
  79. f = popen(cmd, "r");
  80. if (!f)
  81. return;
  82. do {
  83. start = fgets(buf, sizeof(buf), f);
  84. if (!start)
  85. continue;
  86. len = strlen(start);
  87. if (!tok)
  88. tok = json_tokener_new();
  89. obj = json_tokener_parse_ex(tok, start, len);
  90. if (obj) {
  91. netifd_init_script_handler(name, obj, cb);
  92. json_object_put(obj);
  93. json_tokener_free(tok);
  94. tok = NULL;
  95. } else if (start[len - 1] == '\n') {
  96. json_tokener_free(tok);
  97. tok = NULL;
  98. }
  99. } while (!feof(f) && !ferror(f));
  100. if (tok)
  101. json_tokener_free(tok);
  102. pclose(f);
  103. }
  104. void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
  105. {
  106. glob_t g;
  107. int i, prev_fd;
  108. prev_fd = netifd_dir_push(dir_fd);
  109. if (glob("./*.sh", 0, NULL, &g)) {
  110. netifd_dir_pop(prev_fd);
  111. return;
  112. }
  113. for (i = 0; i < g.gl_pathc; i++)
  114. netifd_parse_script_handler(g.gl_pathv[i], cb);
  115. netifd_dir_pop(prev_fd);
  116. globfree(&g);
  117. }
  118. char *
  119. netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
  120. {
  121. struct blobmsg_policy *attrs;
  122. char *str_buf, *str_cur;
  123. char const **validate;
  124. int str_len = 0;
  125. int i;
  126. config->n_params = json_object_array_length(obj);
  127. attrs = calloc(1, sizeof(*attrs) * config->n_params);
  128. if (!attrs)
  129. return NULL;
  130. validate = calloc(1, sizeof(char*) * config->n_params);
  131. if (!validate)
  132. goto error;
  133. config->params = attrs;
  134. config->validate = validate;
  135. for (i = 0; i < config->n_params; i++) {
  136. json_object *cur, *name, *type;
  137. cur = json_check_type(json_object_array_get_idx(obj, i), json_type_array);
  138. if (!cur)
  139. goto error;
  140. name = json_check_type(json_object_array_get_idx(cur, 0), json_type_string);
  141. if (!name)
  142. goto error;
  143. type = json_check_type(json_object_array_get_idx(cur, 1), json_type_int);
  144. if (!type)
  145. goto error;
  146. attrs[i].name = json_object_get_string(name);
  147. attrs[i].type = json_object_get_int(type);
  148. if (attrs[i].type > BLOBMSG_TYPE_LAST)
  149. goto error;
  150. str_len += strlen(attrs[i].name) + 1;
  151. }
  152. str_buf = malloc(str_len);
  153. if (!str_buf)
  154. goto error;
  155. str_cur = str_buf;
  156. for (i = 0; i < config->n_params; i++) {
  157. const char *name = attrs[i].name;
  158. char *delim;
  159. attrs[i].name = str_cur;
  160. str_cur += sprintf(str_cur, "%s", name) + 1;
  161. delim = strchr(attrs[i].name, ':');
  162. if (delim) {
  163. *delim = '\0';
  164. validate[i] = ++delim;
  165. } else {
  166. validate[i] = NULL;
  167. }
  168. }
  169. return str_buf;
  170. error:
  171. free(attrs);
  172. if (validate)
  173. free(validate);
  174. config->n_params = 0;
  175. return NULL;
  176. }