config.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * netifd - network interface daemon
  3. * Copyright (C) 2012 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. #include <string.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <uci.h>
  18. #include "netifd.h"
  19. #include "interface.h"
  20. #include "interface-ip.h"
  21. #include "iprule.h"
  22. #include "proto.h"
  23. #include "config.h"
  24. bool config_init = false;
  25. static struct uci_context *uci_ctx;
  26. static struct uci_package *uci_network;
  27. static struct blob_buf b;
  28. static int
  29. config_parse_bridge_interface(struct uci_section *s)
  30. {
  31. char *name;
  32. name = alloca(strlen(s->e.name) + 4);
  33. sprintf(name, "br-%s", s->e.name);
  34. blobmsg_add_string(&b, "name", name);
  35. uci_to_blob(&b, s, bridge_device_type.config_params);
  36. if (!device_create(name, &bridge_device_type, b.head)) {
  37. D(INTERFACE, "Failed to create bridge for interface '%s'\n", s->e.name);
  38. return -EINVAL;
  39. }
  40. blob_buf_init(&b, 0);
  41. blobmsg_add_string(&b, "ifname", name);
  42. return 0;
  43. }
  44. static void
  45. config_parse_interface(struct uci_section *s, bool alias)
  46. {
  47. struct interface *iface;
  48. const char *type = NULL;
  49. struct blob_attr *config;
  50. struct device *dev;
  51. bool bridge = false;
  52. blob_buf_init(&b, 0);
  53. if (!alias)
  54. type = uci_lookup_option_string(uci_ctx, s, "type");
  55. if (type && !strcmp(type, "bridge")) {
  56. if (config_parse_bridge_interface(s))
  57. return;
  58. bridge = true;
  59. }
  60. uci_to_blob(&b, s, &interface_attr_list);
  61. iface = calloc(1, sizeof(*iface));
  62. if (!iface)
  63. return;
  64. interface_init(iface, s->e.name, b.head);
  65. if (iface->proto_handler && iface->proto_handler->config_params)
  66. uci_to_blob(&b, s, iface->proto_handler->config_params);
  67. if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params))
  68. iface->device_config = true;
  69. config = blob_memdup(b.head);
  70. if (!config)
  71. goto error;
  72. if (alias) {
  73. if (!interface_add_alias(iface, config))
  74. goto error_free_config;
  75. } else {
  76. interface_add(iface, config);
  77. }
  78. /*
  79. * need to look up the interface name again, in case of config update,
  80. * the pointer will have changed
  81. */
  82. iface = vlist_find(&interfaces, s->e.name, iface, node);
  83. if (!iface)
  84. return;
  85. dev = iface->main_dev.dev;
  86. if (!dev || !dev->default_config)
  87. return;
  88. blob_buf_init(&b, 0);
  89. uci_to_blob(&b, s, dev->type->config_params);
  90. if (blob_len(b.head) == 0)
  91. return;
  92. device_set_config(dev, dev->type, b.head);
  93. return;
  94. error_free_config:
  95. free(config);
  96. error:
  97. free(iface);
  98. }
  99. static void
  100. config_parse_route(struct uci_section *s, bool v6)
  101. {
  102. void *route;
  103. blob_buf_init(&b, 0);
  104. route = blobmsg_open_array(&b, "route");
  105. uci_to_blob(&b, s, &route_attr_list);
  106. blobmsg_close_array(&b, route);
  107. interface_ip_add_route(NULL, blob_data(b.head), v6);
  108. }
  109. static void
  110. config_parse_rule(struct uci_section *s, bool v6)
  111. {
  112. void *rule;
  113. blob_buf_init(&b, 0);
  114. rule = blobmsg_open_array(&b, "rule");
  115. uci_to_blob(&b, s, &rule_attr_list);
  116. blobmsg_close_array(&b, rule);
  117. iprule_add(blob_data(b.head), v6);
  118. }
  119. static void
  120. config_init_devices(void)
  121. {
  122. struct uci_element *e;
  123. uci_foreach_element(&uci_network->sections, e) {
  124. struct uci_section *s = uci_to_section(e);
  125. const struct device_type *devtype = NULL;
  126. const char *type, *name;
  127. if (strcmp(s->type, "device") != 0)
  128. continue;
  129. name = uci_lookup_option_string(uci_ctx, s, "name");
  130. if (!name)
  131. continue;
  132. type = uci_lookup_option_string(uci_ctx, s, "type");
  133. if (type) {
  134. if (!strcmp(type, "bridge"))
  135. devtype = &bridge_device_type;
  136. else if (!strcmp(type, "tunnel"))
  137. devtype = &tunnel_device_type;
  138. }
  139. if (!devtype)
  140. devtype = &simple_device_type;
  141. blob_buf_init(&b, 0);
  142. uci_to_blob(&b, s, devtype->config_params);
  143. device_create(name, devtype, b.head);
  144. }
  145. }
  146. static struct uci_package *
  147. config_init_package(const char *config)
  148. {
  149. struct uci_context *ctx = uci_ctx;
  150. struct uci_package *p = NULL;
  151. if (!ctx) {
  152. ctx = uci_alloc_context();
  153. uci_ctx = ctx;
  154. #ifdef DUMMY_MODE
  155. uci_set_confdir(ctx, "./config");
  156. uci_set_savedir(ctx, "./tmp");
  157. #endif
  158. } else {
  159. p = uci_lookup_package(ctx, config);
  160. if (p)
  161. uci_unload(ctx, p);
  162. }
  163. if (uci_load(ctx, config, &p))
  164. return NULL;
  165. return p;
  166. }
  167. static void
  168. config_init_interfaces(void)
  169. {
  170. struct uci_element *e;
  171. uci_foreach_element(&uci_network->sections, e) {
  172. struct uci_section *s = uci_to_section(e);
  173. if (!strcmp(s->type, "interface"))
  174. config_parse_interface(s, false);
  175. }
  176. uci_foreach_element(&uci_network->sections, e) {
  177. struct uci_section *s = uci_to_section(e);
  178. if (!strcmp(s->type, "alias"))
  179. config_parse_interface(s, true);
  180. }
  181. }
  182. static void
  183. config_init_routes(void)
  184. {
  185. struct interface *iface;
  186. struct uci_element *e;
  187. vlist_for_each_element(&interfaces, iface, node)
  188. interface_ip_update_start(&iface->config_ip);
  189. uci_foreach_element(&uci_network->sections, e) {
  190. struct uci_section *s = uci_to_section(e);
  191. if (!strcmp(s->type, "route"))
  192. config_parse_route(s, false);
  193. else if (!strcmp(s->type, "route6"))
  194. config_parse_route(s, true);
  195. }
  196. vlist_for_each_element(&interfaces, iface, node)
  197. interface_ip_update_complete(&iface->config_ip);
  198. }
  199. static void
  200. config_init_rules(void)
  201. {
  202. struct uci_element *e;
  203. iprule_update_start();
  204. uci_foreach_element(&uci_network->sections, e) {
  205. struct uci_section *s = uci_to_section(e);
  206. if (!strcmp(s->type, "rule"))
  207. config_parse_rule(s, false);
  208. else if (!strcmp(s->type, "rule6"))
  209. config_parse_rule(s, true);
  210. }
  211. iprule_update_complete();
  212. }
  213. static void
  214. config_init_globals(void)
  215. {
  216. struct uci_section *globals = uci_lookup_section(
  217. uci_ctx, uci_network, "globals");
  218. if (!globals)
  219. return;
  220. const char *ula_prefix = uci_lookup_option_string(
  221. uci_ctx, globals, "ula_prefix");
  222. interface_ip_set_ula_prefix(ula_prefix);
  223. }
  224. void
  225. config_init_all(void)
  226. {
  227. uci_network = config_init_package("network");
  228. if (!uci_network) {
  229. fprintf(stderr, "Failed to load network config\n");
  230. return;
  231. }
  232. vlist_update(&interfaces);
  233. config_init = true;
  234. device_lock();
  235. device_reset_config();
  236. config_init_devices();
  237. config_init_interfaces();
  238. config_init_routes();
  239. config_init_rules();
  240. config_init_globals();
  241. config_init = false;
  242. device_unlock();
  243. device_reset_old();
  244. device_init_pending();
  245. vlist_flush(&interfaces);
  246. device_free_unused(NULL);
  247. interface_refresh_assignments(false);
  248. interface_start_pending();
  249. }