config.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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_neighbor(struct uci_section *s, bool v6)
  118. {
  119. void *neighbor;
  120. blob_buf_init(&b,0);
  121. neighbor = blobmsg_open_array(&b, "neighbor");
  122. uci_to_blob(&b,s, &neighbor_attr_list);
  123. blobmsg_close_array(&b, neighbor);
  124. interface_ip_add_neighbor(NULL, blob_data(b.head), v6);
  125. }
  126. static void
  127. config_parse_rule(struct uci_section *s, bool v6)
  128. {
  129. void *rule;
  130. blob_buf_init(&b, 0);
  131. rule = blobmsg_open_array(&b, "rule");
  132. uci_to_blob(&b, s, &rule_attr_list);
  133. blobmsg_close_array(&b, rule);
  134. iprule_add(blob_data(b.head), v6);
  135. }
  136. static void
  137. config_init_devices(void)
  138. {
  139. struct uci_element *e;
  140. uci_foreach_element(&uci_network->sections, e) {
  141. const struct uci_blob_param_list *params = NULL;
  142. struct uci_section *s = uci_to_section(e);
  143. struct device_type *devtype = NULL;
  144. struct device *dev;
  145. const char *type, *name;
  146. if (strcmp(s->type, "device") != 0)
  147. continue;
  148. name = uci_lookup_option_string(uci_ctx, s, "name");
  149. if (!name)
  150. continue;
  151. type = uci_lookup_option_string(uci_ctx, s, "type");
  152. if (type)
  153. devtype = device_type_get(type);
  154. if (devtype)
  155. params = devtype->config_params;
  156. if (!params)
  157. params = simple_device_type.config_params;
  158. blob_buf_init(&b, 0);
  159. uci_to_blob(&b, s, params);
  160. if (devtype) {
  161. dev = device_create(name, devtype, b.head);
  162. if (!dev)
  163. continue;
  164. } else {
  165. dev = device_get(name, 1);
  166. if (!dev)
  167. continue;
  168. dev->current_config = true;
  169. device_apply_config(dev, dev->type, b.head);
  170. }
  171. dev->default_config = false;
  172. }
  173. }
  174. static struct uci_package *
  175. config_init_package(const char *config)
  176. {
  177. struct uci_context *ctx = uci_ctx;
  178. struct uci_package *p = NULL;
  179. if (!ctx) {
  180. ctx = uci_alloc_context();
  181. uci_ctx = ctx;
  182. ctx->flags &= ~UCI_FLAG_STRICT;
  183. if (config_path)
  184. uci_set_confdir(ctx, config_path);
  185. #ifdef DUMMY_MODE
  186. uci_set_savedir(ctx, "./tmp");
  187. #endif
  188. } else {
  189. p = uci_lookup_package(ctx, config);
  190. if (p)
  191. uci_unload(ctx, p);
  192. }
  193. if (uci_load(ctx, config, &p))
  194. return NULL;
  195. return p;
  196. }
  197. static void
  198. config_init_interfaces(void)
  199. {
  200. struct uci_element *e;
  201. uci_foreach_element(&uci_network->sections, e) {
  202. struct uci_section *s = uci_to_section(e);
  203. if (!strcmp(s->type, "interface"))
  204. config_parse_interface(s, false);
  205. }
  206. uci_foreach_element(&uci_network->sections, e) {
  207. struct uci_section *s = uci_to_section(e);
  208. if (!strcmp(s->type, "alias"))
  209. config_parse_interface(s, true);
  210. }
  211. }
  212. static void
  213. config_init_ip(void)
  214. {
  215. struct interface *iface;
  216. struct uci_element *e;
  217. vlist_for_each_element(&interfaces, iface, node)
  218. interface_ip_update_start(&iface->config_ip);
  219. uci_foreach_element(&uci_network->sections, e) {
  220. struct uci_section *s = uci_to_section(e);
  221. if (!strcmp(s->type, "route"))
  222. config_parse_route(s, false);
  223. else if (!strcmp(s->type, "route6"))
  224. config_parse_route(s, true);
  225. if (!strcmp(s->type, "neighbor"))
  226. config_parse_neighbor(s, false);
  227. else if (!strcmp(s->type, "neighbor6"))
  228. config_parse_neighbor(s, true);
  229. }
  230. vlist_for_each_element(&interfaces, iface, node)
  231. interface_ip_update_complete(&iface->config_ip);
  232. }
  233. static void
  234. config_init_rules(void)
  235. {
  236. struct uci_element *e;
  237. iprule_update_start();
  238. uci_foreach_element(&uci_network->sections, e) {
  239. struct uci_section *s = uci_to_section(e);
  240. if (!strcmp(s->type, "rule"))
  241. config_parse_rule(s, false);
  242. else if (!strcmp(s->type, "rule6"))
  243. config_parse_rule(s, true);
  244. }
  245. iprule_update_complete();
  246. }
  247. static void
  248. config_init_globals(void)
  249. {
  250. struct uci_section *globals = uci_lookup_section(
  251. uci_ctx, uci_network, "globals");
  252. if (!globals)
  253. return;
  254. const char *ula_prefix = uci_lookup_option_string(
  255. uci_ctx, globals, "ula_prefix");
  256. interface_ip_set_ula_prefix(ula_prefix);
  257. }
  258. static void
  259. config_parse_wireless_device(struct uci_section *s)
  260. {
  261. struct wireless_driver *drv;
  262. const char *driver_name;
  263. driver_name = uci_lookup_option_string(uci_ctx, s, "type");
  264. if (!driver_name)
  265. return;
  266. drv = avl_find_element(&wireless_drivers, driver_name, drv, node);
  267. if (!drv)
  268. return;
  269. blob_buf_init(&b, 0);
  270. uci_to_blob(&b, s, drv->device.config);
  271. wireless_device_create(drv, s->e.name, b.head);
  272. }
  273. static void
  274. config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
  275. {
  276. char *name;
  277. name = alloca(strlen(s->type) + 16);
  278. sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
  279. blob_buf_init(&b, 0);
  280. uci_to_blob(&b, s, wdev->drv->interface.config);
  281. wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
  282. }
  283. static void
  284. config_init_wireless(void)
  285. {
  286. struct wireless_device *wdev;
  287. struct uci_element *e;
  288. const char *dev_name;
  289. if (!uci_wireless) {
  290. DPRINTF("No wireless configuration found\n");
  291. return;
  292. }
  293. vlist_update(&wireless_devices);
  294. uci_foreach_element(&uci_wireless->sections, e) {
  295. struct uci_section *s = uci_to_section(e);
  296. if (strcmp(s->type, "wifi-device") != 0)
  297. continue;
  298. config_parse_wireless_device(s);
  299. }
  300. vlist_flush(&wireless_devices);
  301. vlist_for_each_element(&wireless_devices, wdev, node) {
  302. wdev->vif_idx = 0;
  303. vlist_update(&wdev->interfaces);
  304. }
  305. uci_foreach_element(&uci_wireless->sections, e) {
  306. struct uci_section *s = uci_to_section(e);
  307. if (strcmp(s->type, "wifi-iface") != 0)
  308. continue;
  309. dev_name = uci_lookup_option_string(uci_ctx, s, "device");
  310. if (!dev_name)
  311. continue;
  312. wdev = vlist_find(&wireless_devices, dev_name, wdev, node);
  313. if (!wdev) {
  314. DPRINTF("device %s not found!\n", dev_name);
  315. continue;
  316. }
  317. config_parse_wireless_interface(wdev, s);
  318. }
  319. vlist_for_each_element(&wireless_devices, wdev, node)
  320. vlist_flush(&wdev->interfaces);
  321. }
  322. int
  323. config_init_all(void)
  324. {
  325. int ret = 0;
  326. char *err;
  327. uci_network = config_init_package("network");
  328. if (!uci_network) {
  329. uci_get_errorstr(uci_ctx, &err, NULL);
  330. netifd_log_message(L_CRIT, "Failed to load network config (%s)\n", err);
  331. free(err);
  332. return -1;
  333. }
  334. uci_wireless = config_init_package("wireless");
  335. if (!uci_wireless && uci_ctx->err != UCI_ERR_NOTFOUND) {
  336. uci_get_errorstr(uci_ctx, &err, NULL);
  337. netifd_log_message(L_CRIT, "Failed to load wireless config (%s)\n", err);
  338. free(err);
  339. ret = -1;
  340. }
  341. vlist_update(&interfaces);
  342. config_init = true;
  343. device_lock();
  344. device_reset_config();
  345. config_init_devices();
  346. config_init_interfaces();
  347. config_init_ip();
  348. config_init_rules();
  349. config_init_globals();
  350. config_init_wireless();
  351. config_init = false;
  352. device_unlock();
  353. device_reset_old();
  354. device_init_pending();
  355. vlist_flush(&interfaces);
  356. device_free_unused(NULL);
  357. interface_refresh_assignments(false);
  358. interface_start_pending();
  359. wireless_start_pending();
  360. return ret;
  361. }