config.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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. #define _GNU_SOURCE
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <uci.h>
  19. #include "netifd.h"
  20. #include "interface.h"
  21. #include "interface-ip.h"
  22. #include "iprule.h"
  23. #include "proto.h"
  24. #include "wireless.h"
  25. #include "config.h"
  26. bool config_init = false;
  27. static struct uci_context *uci_ctx;
  28. static struct uci_package *uci_network;
  29. static struct uci_package *uci_wireless;
  30. static struct blob_buf b;
  31. static int
  32. config_section_idx(struct uci_section *s)
  33. {
  34. struct uci_element *e;
  35. int idx = 0;
  36. uci_foreach_element(&uci_wireless->sections, e) {
  37. struct uci_section *cur = uci_to_section(e);
  38. if (s == cur)
  39. return idx;
  40. if (!strcmp(cur->type, s->type))
  41. idx++;
  42. }
  43. return -1;
  44. }
  45. static int
  46. config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
  47. {
  48. char *name;
  49. name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
  50. sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
  51. blobmsg_add_string(&b, "name", name);
  52. uci_to_blob(&b, s, devtype->config_params);
  53. if (!device_create(name, devtype, b.head)) {
  54. D(INTERFACE, "Failed to create '%s' device for interface '%s'\n",
  55. devtype->name, s->e.name);
  56. }
  57. blob_buf_init(&b, 0);
  58. blobmsg_add_string(&b, "ifname", name);
  59. return 0;
  60. }
  61. static void
  62. config_parse_interface(struct uci_section *s, bool alias)
  63. {
  64. struct interface *iface;
  65. const char *type = NULL, *disabled;
  66. struct blob_attr *config;
  67. bool bridge = false;
  68. struct device_type *devtype = NULL;
  69. disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
  70. if (disabled && !strcmp(disabled, "1"))
  71. return;
  72. blob_buf_init(&b, 0);
  73. if (!alias)
  74. type = uci_lookup_option_string(uci_ctx, s, "type");
  75. if (type)
  76. devtype = device_type_get(type);
  77. if (devtype && devtype->bridge_capability) {
  78. if (config_parse_bridge_interface(s, devtype))
  79. return;
  80. bridge = true;
  81. }
  82. uci_to_blob(&b, s, &interface_attr_list);
  83. iface = interface_alloc(s->e.name, b.head, false);
  84. if (!iface)
  85. return;
  86. if (iface->proto_handler && iface->proto_handler->config_params)
  87. uci_to_blob(&b, s, iface->proto_handler->config_params);
  88. if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params))
  89. iface->device_config = true;
  90. config = blob_memdup(b.head);
  91. if (!config)
  92. goto error;
  93. if (alias) {
  94. if (!interface_add_alias(iface, config))
  95. goto error_free_config;
  96. } else {
  97. if (!interface_add(iface, config))
  98. goto error_free_config;
  99. }
  100. return;
  101. error_free_config:
  102. free(config);
  103. error:
  104. free(iface);
  105. }
  106. static void
  107. config_parse_route(struct uci_section *s, bool v6)
  108. {
  109. void *route;
  110. blob_buf_init(&b, 0);
  111. route = blobmsg_open_array(&b, "route");
  112. uci_to_blob(&b, s, &route_attr_list);
  113. blobmsg_close_array(&b, route);
  114. interface_ip_add_route(NULL, blob_data(b.head), v6);
  115. }
  116. static void
  117. config_parse_rule(struct uci_section *s, bool v6)
  118. {
  119. void *rule;
  120. blob_buf_init(&b, 0);
  121. rule = blobmsg_open_array(&b, "rule");
  122. uci_to_blob(&b, s, &rule_attr_list);
  123. blobmsg_close_array(&b, rule);
  124. iprule_add(blob_data(b.head), v6);
  125. }
  126. static void
  127. config_init_devices(void)
  128. {
  129. struct uci_element *e;
  130. uci_foreach_element(&uci_network->sections, e) {
  131. const struct uci_blob_param_list *params = NULL;
  132. struct uci_section *s = uci_to_section(e);
  133. struct device_type *devtype = NULL;
  134. struct device *dev;
  135. const char *type, *name;
  136. if (strcmp(s->type, "device") != 0)
  137. continue;
  138. name = uci_lookup_option_string(uci_ctx, s, "name");
  139. if (!name)
  140. continue;
  141. type = uci_lookup_option_string(uci_ctx, s, "type");
  142. if (type)
  143. devtype = device_type_get(type);
  144. if (devtype)
  145. params = devtype->config_params;
  146. if (!params)
  147. params = simple_device_type.config_params;
  148. blob_buf_init(&b, 0);
  149. uci_to_blob(&b, s, params);
  150. if (devtype) {
  151. dev = device_create(name, devtype, b.head);
  152. if (!dev)
  153. continue;
  154. } else {
  155. dev = device_get(name, 1);
  156. if (!dev)
  157. continue;
  158. dev->current_config = true;
  159. device_apply_config(dev, dev->type, b.head);
  160. }
  161. dev->default_config = false;
  162. }
  163. }
  164. static struct uci_package *
  165. config_init_package(const char *config)
  166. {
  167. struct uci_context *ctx = uci_ctx;
  168. struct uci_package *p = NULL;
  169. if (!ctx) {
  170. ctx = uci_alloc_context();
  171. uci_ctx = ctx;
  172. ctx->flags &= ~UCI_FLAG_STRICT;
  173. if (config_path)
  174. uci_set_confdir(ctx, config_path);
  175. #ifdef DUMMY_MODE
  176. uci_set_savedir(ctx, "./tmp");
  177. #endif
  178. } else {
  179. p = uci_lookup_package(ctx, config);
  180. if (p)
  181. uci_unload(ctx, p);
  182. }
  183. if (uci_load(ctx, config, &p))
  184. return NULL;
  185. return p;
  186. }
  187. static void
  188. config_init_interfaces(void)
  189. {
  190. struct uci_element *e;
  191. uci_foreach_element(&uci_network->sections, e) {
  192. struct uci_section *s = uci_to_section(e);
  193. if (!strcmp(s->type, "interface"))
  194. config_parse_interface(s, false);
  195. }
  196. uci_foreach_element(&uci_network->sections, e) {
  197. struct uci_section *s = uci_to_section(e);
  198. if (!strcmp(s->type, "alias"))
  199. config_parse_interface(s, true);
  200. }
  201. }
  202. static void
  203. config_init_routes(void)
  204. {
  205. struct interface *iface;
  206. struct uci_element *e;
  207. vlist_for_each_element(&interfaces, iface, node)
  208. interface_ip_update_start(&iface->config_ip);
  209. uci_foreach_element(&uci_network->sections, e) {
  210. struct uci_section *s = uci_to_section(e);
  211. if (!strcmp(s->type, "route"))
  212. config_parse_route(s, false);
  213. else if (!strcmp(s->type, "route6"))
  214. config_parse_route(s, true);
  215. }
  216. vlist_for_each_element(&interfaces, iface, node)
  217. interface_ip_update_complete(&iface->config_ip);
  218. }
  219. static void
  220. config_init_rules(void)
  221. {
  222. struct uci_element *e;
  223. iprule_update_start();
  224. uci_foreach_element(&uci_network->sections, e) {
  225. struct uci_section *s = uci_to_section(e);
  226. if (!strcmp(s->type, "rule"))
  227. config_parse_rule(s, false);
  228. else if (!strcmp(s->type, "rule6"))
  229. config_parse_rule(s, true);
  230. }
  231. iprule_update_complete();
  232. }
  233. static void
  234. config_init_globals(void)
  235. {
  236. struct uci_section *globals = uci_lookup_section(
  237. uci_ctx, uci_network, "globals");
  238. if (!globals)
  239. return;
  240. const char *ula_prefix = uci_lookup_option_string(
  241. uci_ctx, globals, "ula_prefix");
  242. interface_ip_set_ula_prefix(ula_prefix);
  243. }
  244. static void
  245. config_parse_wireless_device(struct uci_section *s)
  246. {
  247. struct wireless_driver *drv;
  248. const char *driver_name;
  249. driver_name = uci_lookup_option_string(uci_ctx, s, "type");
  250. if (!driver_name)
  251. return;
  252. drv = avl_find_element(&wireless_drivers, driver_name, drv, node);
  253. if (!drv)
  254. return;
  255. blob_buf_init(&b, 0);
  256. uci_to_blob(&b, s, drv->device.config);
  257. wireless_device_create(drv, s->e.name, b.head);
  258. }
  259. static void
  260. config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
  261. {
  262. char *name;
  263. name = alloca(strlen(s->type) + 16);
  264. sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
  265. blob_buf_init(&b, 0);
  266. uci_to_blob(&b, s, wdev->drv->interface.config);
  267. wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
  268. }
  269. static void
  270. config_init_wireless(void)
  271. {
  272. struct wireless_device *wdev;
  273. struct uci_element *e;
  274. const char *dev_name;
  275. if (!uci_wireless) {
  276. DPRINTF("No wireless configuration found\n");
  277. return;
  278. }
  279. vlist_update(&wireless_devices);
  280. uci_foreach_element(&uci_wireless->sections, e) {
  281. struct uci_section *s = uci_to_section(e);
  282. if (strcmp(s->type, "wifi-device") != 0)
  283. continue;
  284. config_parse_wireless_device(s);
  285. }
  286. vlist_flush(&wireless_devices);
  287. vlist_for_each_element(&wireless_devices, wdev, node) {
  288. wdev->vif_idx = 0;
  289. vlist_update(&wdev->interfaces);
  290. }
  291. uci_foreach_element(&uci_wireless->sections, e) {
  292. struct uci_section *s = uci_to_section(e);
  293. if (strcmp(s->type, "wifi-iface") != 0)
  294. continue;
  295. dev_name = uci_lookup_option_string(uci_ctx, s, "device");
  296. if (!dev_name)
  297. continue;
  298. wdev = vlist_find(&wireless_devices, dev_name, wdev, node);
  299. if (!wdev) {
  300. DPRINTF("device %s not found!\n", dev_name);
  301. continue;
  302. }
  303. config_parse_wireless_interface(wdev, s);
  304. }
  305. vlist_for_each_element(&wireless_devices, wdev, node)
  306. vlist_flush(&wdev->interfaces);
  307. }
  308. int
  309. config_init_all(void)
  310. {
  311. int ret = 0;
  312. char *err;
  313. uci_network = config_init_package("network");
  314. if (!uci_network) {
  315. uci_get_errorstr(uci_ctx, &err, NULL);
  316. netifd_log_message(L_CRIT, "Failed to load network config (%s)\n", err);
  317. free(err);
  318. return -1;
  319. }
  320. uci_wireless = config_init_package("wireless");
  321. if (!uci_wireless && uci_ctx->err != UCI_ERR_NOTFOUND) {
  322. uci_get_errorstr(uci_ctx, &err, NULL);
  323. netifd_log_message(L_CRIT, "Failed to load wireless config (%s)\n", err);
  324. free(err);
  325. ret = -1;
  326. }
  327. vlist_update(&interfaces);
  328. config_init = true;
  329. device_lock();
  330. device_reset_config();
  331. config_init_devices();
  332. config_init_interfaces();
  333. config_init_routes();
  334. config_init_rules();
  335. config_init_globals();
  336. config_init_wireless();
  337. config_init = false;
  338. device_unlock();
  339. device_reset_old();
  340. device_init_pending();
  341. vlist_flush(&interfaces);
  342. device_free_unused(NULL);
  343. interface_refresh_assignments(false);
  344. interface_start_pending();
  345. wireless_start_pending();
  346. return ret;
  347. }