config.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  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 <libubox/blobmsg_json.h>
  20. #include "netifd.h"
  21. #include "interface.h"
  22. #include "interface-ip.h"
  23. #include "iprule.h"
  24. #include "proto.h"
  25. #include "wireless.h"
  26. #include "config.h"
  27. bool config_init = false;
  28. static struct uci_context *uci_ctx;
  29. static struct uci_package *uci_network;
  30. static struct uci_package *uci_wireless;
  31. static struct blob_attr *board_netdevs;
  32. static struct blob_buf b;
  33. static int
  34. config_section_idx(struct uci_section *s)
  35. {
  36. struct uci_element *e;
  37. int idx = 0;
  38. uci_foreach_element(&uci_wireless->sections, e) {
  39. struct uci_section *cur = uci_to_section(e);
  40. if (s == cur)
  41. return idx;
  42. if (!strcmp(cur->type, s->type))
  43. idx++;
  44. }
  45. return -1;
  46. }
  47. static bool
  48. config_bridge_has_vlans(const char *br_name)
  49. {
  50. struct uci_element *e;
  51. uci_foreach_element(&uci_network->sections, e) {
  52. struct uci_section *s = uci_to_section(e);
  53. const char *name;
  54. if (strcmp(s->type, "bridge-vlan") != 0)
  55. continue;
  56. name = uci_lookup_option_string(uci_ctx, s, "device");
  57. if (!name)
  58. continue;
  59. if (!strcmp(name, br_name))
  60. return true;
  61. }
  62. return false;
  63. }
  64. static void
  65. config_fixup_bridge_var(struct uci_section *s, const char *name, const char *val)
  66. {
  67. struct uci_ptr ptr = {
  68. .p = s->package,
  69. .s = s,
  70. .option = name,
  71. .value = val,
  72. };
  73. uci_lookup_ptr(uci_ctx, &ptr, NULL, false);
  74. if (ptr.o)
  75. return;
  76. uci_set(uci_ctx, &ptr);
  77. }
  78. /**
  79. * config_fixup_bridge_ports - translate deprecated configs
  80. *
  81. * Old configs used "ifname" option for specifying bridge ports. For backward
  82. * compatibility translate it into the new "ports" option.
  83. */
  84. static void config_fixup_bridge_ports(struct uci_section *s)
  85. {
  86. struct uci_ptr ptr = {
  87. .p = s->package,
  88. .s = s,
  89. .option = "ifname",
  90. };
  91. if (uci_lookup_option(uci_ctx, s, "ports"))
  92. return;
  93. uci_lookup_ptr(uci_ctx, &ptr, NULL, false);
  94. if (!ptr.o)
  95. return;
  96. ptr.value = "ports";
  97. uci_rename(uci_ctx, &ptr);
  98. }
  99. static void
  100. config_fixup_bridge_vlan_filtering(struct uci_section *s, const char *name)
  101. {
  102. bool has_vlans = config_bridge_has_vlans(name);
  103. config_fixup_bridge_var(s, "__has_vlans", has_vlans ? "1" : "0");
  104. if (!has_vlans)
  105. return;
  106. config_fixup_bridge_var(s, "vlan_filtering", "1");
  107. }
  108. static int
  109. config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
  110. {
  111. char *name;
  112. name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
  113. sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
  114. blobmsg_add_string(&b, "name", name);
  115. config_fixup_bridge_ports(s);
  116. config_fixup_bridge_vlan_filtering(s, name);
  117. uci_to_blob(&b, s, devtype->config_params);
  118. if (!device_create(name, devtype, b.head)) {
  119. D(INTERFACE, "Failed to create '%s' device for interface '%s'",
  120. devtype->name, s->e.name);
  121. }
  122. blob_buf_init(&b, 0);
  123. blobmsg_add_string(&b, "ifname", name);
  124. return 0;
  125. }
  126. static void
  127. config_parse_interface(struct uci_section *s, bool alias)
  128. {
  129. struct interface *iface;
  130. const char *type = NULL, *disabled;
  131. struct blob_attr *config;
  132. bool bridge = false;
  133. struct device_type *devtype = NULL;
  134. disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
  135. if (disabled && !strcmp(disabled, "1"))
  136. return;
  137. blob_buf_init(&b, 0);
  138. if (!alias)
  139. type = uci_lookup_option_string(uci_ctx, s, "type");
  140. if (type)
  141. devtype = device_type_get(type);
  142. if (devtype && devtype->bridge_capability) {
  143. if (config_parse_bridge_interface(s, devtype))
  144. return;
  145. bridge = true;
  146. }
  147. uci_to_blob(&b, s, &interface_attr_list);
  148. iface = interface_alloc(s->e.name, b.head, false);
  149. if (!iface)
  150. return;
  151. if (iface->proto_handler && iface->proto_handler->config_params)
  152. uci_to_blob(&b, s, iface->proto_handler->config_params);
  153. if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params))
  154. iface->device_config = true;
  155. config = blob_memdup(b.head);
  156. if (!config)
  157. goto error;
  158. if (alias) {
  159. if (!interface_add_alias(iface, config))
  160. goto error_free_config;
  161. } else {
  162. if (!interface_add(iface, config))
  163. goto error_free_config;
  164. }
  165. return;
  166. error_free_config:
  167. free(config);
  168. error:
  169. free(iface);
  170. }
  171. static void
  172. config_parse_route(struct uci_section *s, bool v6)
  173. {
  174. void *route;
  175. blob_buf_init(&b, 0);
  176. route = blobmsg_open_array(&b, "route");
  177. uci_to_blob(&b, s, &route_attr_list);
  178. blobmsg_close_array(&b, route);
  179. interface_ip_add_route(NULL, blob_data(b.head), v6);
  180. }
  181. static void
  182. config_parse_neighbor(struct uci_section *s, bool v6)
  183. {
  184. void *neighbor;
  185. blob_buf_init(&b,0);
  186. neighbor = blobmsg_open_array(&b, "neighbor");
  187. uci_to_blob(&b,s, &neighbor_attr_list);
  188. blobmsg_close_array(&b, neighbor);
  189. interface_ip_add_neighbor(NULL, blob_data(b.head), v6);
  190. }
  191. static void
  192. config_parse_rule(struct uci_section *s, bool v6)
  193. {
  194. void *rule;
  195. blob_buf_init(&b, 0);
  196. rule = blobmsg_open_array(&b, "rule");
  197. uci_to_blob(&b, s, &rule_attr_list);
  198. blobmsg_close_array(&b, rule);
  199. iprule_add(blob_data(b.head), v6);
  200. }
  201. static void
  202. config_init_devices(bool bridge)
  203. {
  204. struct uci_element *e;
  205. uci_foreach_element(&uci_network->sections, e) {
  206. const struct uci_blob_param_list *params = NULL;
  207. struct uci_section *s = uci_to_section(e);
  208. struct device_type *devtype = NULL;
  209. struct device *dev;
  210. const char *type, *name;
  211. if (strcmp(s->type, "device") != 0)
  212. continue;
  213. name = uci_lookup_option_string(uci_ctx, s, "name");
  214. if (!name)
  215. continue;
  216. type = uci_lookup_option_string(uci_ctx, s, "type");
  217. if (type)
  218. devtype = device_type_get(type);
  219. if (bridge != (devtype && devtype->bridge_capability))
  220. continue;
  221. if (devtype)
  222. params = devtype->config_params;
  223. if (!params)
  224. params = simple_device_type.config_params;
  225. if (devtype && devtype->bridge_capability) {
  226. config_fixup_bridge_ports(s);
  227. config_fixup_bridge_vlan_filtering(s, name);
  228. }
  229. blob_buf_init(&b, 0);
  230. uci_to_blob(&b, s, params);
  231. if (devtype) {
  232. dev = device_create(name, devtype, b.head);
  233. if (!dev)
  234. continue;
  235. } else {
  236. dev = device_get(name, 1);
  237. if (!dev)
  238. continue;
  239. dev->current_config = true;
  240. device_apply_config(dev, dev->type, b.head);
  241. }
  242. dev->default_config = false;
  243. }
  244. }
  245. static void
  246. config_parse_vlan(struct device *dev, struct uci_section *s)
  247. {
  248. enum {
  249. BRVLAN_ATTR_VID,
  250. BRVLAN_ATTR_LOCAL,
  251. BRVLAN_ATTR_PORTS,
  252. BRVLAN_ATTR_ALIAS,
  253. __BRVLAN_ATTR_MAX,
  254. };
  255. static const struct blobmsg_policy vlan_attrs[__BRVLAN_ATTR_MAX] = {
  256. [BRVLAN_ATTR_VID] = { "vlan", BLOBMSG_TYPE_INT32 },
  257. [BRVLAN_ATTR_LOCAL] = { "local", BLOBMSG_TYPE_BOOL },
  258. [BRVLAN_ATTR_PORTS] = { "ports", BLOBMSG_TYPE_ARRAY },
  259. [BRVLAN_ATTR_ALIAS] = { "alias", BLOBMSG_TYPE_ARRAY },
  260. };
  261. static const struct uci_blob_param_info vlan_attr_info[__BRVLAN_ATTR_MAX] = {
  262. [BRVLAN_ATTR_PORTS] = { .type = BLOBMSG_TYPE_STRING },
  263. [BRVLAN_ATTR_ALIAS] = { .type = BLOBMSG_TYPE_STRING },
  264. };
  265. static const struct uci_blob_param_list vlan_attr_list = {
  266. .n_params = __BRVLAN_ATTR_MAX,
  267. .params = vlan_attrs,
  268. .info = vlan_attr_info,
  269. };
  270. struct blob_attr *tb[__BRVLAN_ATTR_MAX];
  271. struct blob_attr *cur;
  272. struct bridge_vlan_port *port;
  273. struct bridge_vlan *vlan;
  274. unsigned int vid;
  275. const char *val;
  276. char *name_buf;
  277. int name_len = 0;
  278. int n_ports = 0;
  279. size_t rem;
  280. val = uci_lookup_option_string(uci_ctx, s, "vlan");
  281. if (!val)
  282. return;
  283. blob_buf_init(&b, 0);
  284. uci_to_blob(&b, s, &vlan_attr_list);
  285. blobmsg_parse(vlan_attrs, __BRVLAN_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head));
  286. if (!tb[BRVLAN_ATTR_VID])
  287. return;
  288. vid = blobmsg_get_u32(tb[BRVLAN_ATTR_VID]);
  289. if (!vid || vid > 4095)
  290. return;
  291. blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) {
  292. name_len += strlen(blobmsg_get_string(cur)) + 1;
  293. n_ports++;
  294. }
  295. vlan = calloc(1, sizeof(*vlan) + n_ports * sizeof(*port) + name_len);
  296. if (!vlan)
  297. return;
  298. vlan->vid = vid;
  299. vlan->local = true;
  300. if (tb[BRVLAN_ATTR_LOCAL])
  301. vlan->local = blobmsg_get_bool(tb[BRVLAN_ATTR_LOCAL]);
  302. vlan->n_ports = n_ports;
  303. vlan->ports = port = (struct bridge_vlan_port *)&vlan[1];
  304. INIT_LIST_HEAD(&vlan->hotplug_ports);
  305. name_buf = (char *)&port[n_ports];
  306. blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_PORTS], rem) {
  307. char *sep;
  308. port->ifname = name_buf;
  309. port->flags = BRVLAN_F_UNTAGGED;
  310. strcpy(name_buf, blobmsg_get_string(cur));
  311. sep = strchr(name_buf, ':');
  312. if (sep) {
  313. for (*sep = 0, sep++; *sep; sep++)
  314. switch (*sep) {
  315. case '*':
  316. port->flags |= BRVLAN_F_PVID;
  317. break;
  318. case 't':
  319. port->flags &= ~BRVLAN_F_UNTAGGED;
  320. break;
  321. }
  322. }
  323. name_buf += strlen(name_buf) + 1;
  324. port++;
  325. }
  326. blobmsg_for_each_attr(cur, tb[BRVLAN_ATTR_ALIAS], rem)
  327. kvlist_set(&dev->vlan_aliases, blobmsg_get_string(cur), &vid);
  328. vlist_add(&dev->vlans, &vlan->node, &vlan->vid);
  329. }
  330. static void
  331. config_init_vlans(void)
  332. {
  333. struct uci_element *e;
  334. struct device *dev;
  335. device_vlan_update(false);
  336. uci_foreach_element(&uci_network->sections, e) {
  337. struct uci_section *s = uci_to_section(e);
  338. const char *name;
  339. if (strcmp(s->type, "bridge-vlan") != 0)
  340. continue;
  341. name = uci_lookup_option_string(uci_ctx, s, "device");
  342. if (!name)
  343. continue;
  344. dev = device_get(name, 0);
  345. if (!dev || !dev->vlans.update)
  346. continue;
  347. config_parse_vlan(dev, s);
  348. }
  349. device_vlan_update(true);
  350. }
  351. static struct uci_package *
  352. config_init_package(const char *config)
  353. {
  354. struct uci_context *ctx = uci_ctx;
  355. struct uci_package *p = NULL;
  356. if (!ctx) {
  357. ctx = uci_alloc_context();
  358. uci_ctx = ctx;
  359. ctx->flags &= ~UCI_FLAG_STRICT;
  360. if (config_path)
  361. uci_set_confdir(ctx, config_path);
  362. #ifdef DUMMY_MODE
  363. uci_set_savedir(ctx, "./tmp");
  364. #endif
  365. } else {
  366. p = uci_lookup_package(ctx, config);
  367. if (p)
  368. uci_unload(ctx, p);
  369. }
  370. if (uci_load(ctx, config, &p))
  371. return NULL;
  372. return p;
  373. }
  374. static void
  375. config_init_interfaces(void)
  376. {
  377. struct uci_element *e;
  378. uci_foreach_element(&uci_network->sections, e) {
  379. struct uci_section *s = uci_to_section(e);
  380. if (!strcmp(s->type, "interface"))
  381. config_parse_interface(s, false);
  382. }
  383. uci_foreach_element(&uci_network->sections, e) {
  384. struct uci_section *s = uci_to_section(e);
  385. if (!strcmp(s->type, "alias"))
  386. config_parse_interface(s, true);
  387. }
  388. }
  389. static void
  390. config_init_ip(void)
  391. {
  392. struct interface *iface;
  393. struct uci_element *e;
  394. vlist_for_each_element(&interfaces, iface, node)
  395. interface_ip_update_start(&iface->config_ip);
  396. uci_foreach_element(&uci_network->sections, e) {
  397. struct uci_section *s = uci_to_section(e);
  398. if (!strcmp(s->type, "route"))
  399. config_parse_route(s, false);
  400. else if (!strcmp(s->type, "route6"))
  401. config_parse_route(s, true);
  402. if (!strcmp(s->type, "neighbor"))
  403. config_parse_neighbor(s, false);
  404. else if (!strcmp(s->type, "neighbor6"))
  405. config_parse_neighbor(s, true);
  406. }
  407. vlist_for_each_element(&interfaces, iface, node)
  408. interface_ip_update_complete(&iface->config_ip);
  409. }
  410. static void
  411. config_init_rules(void)
  412. {
  413. struct uci_element *e;
  414. iprule_update_start();
  415. uci_foreach_element(&uci_network->sections, e) {
  416. struct uci_section *s = uci_to_section(e);
  417. if (!strcmp(s->type, "rule"))
  418. config_parse_rule(s, false);
  419. else if (!strcmp(s->type, "rule6"))
  420. config_parse_rule(s, true);
  421. }
  422. iprule_update_complete();
  423. }
  424. static void
  425. config_init_globals(void)
  426. {
  427. struct uci_section *globals = uci_lookup_section(
  428. uci_ctx, uci_network, "globals");
  429. if (!globals)
  430. return;
  431. const char *ula_prefix = uci_lookup_option_string(
  432. uci_ctx, globals, "ula_prefix");
  433. interface_ip_set_ula_prefix(ula_prefix);
  434. }
  435. static void
  436. config_parse_wireless_device(struct uci_section *s)
  437. {
  438. struct wireless_driver *drv;
  439. const char *driver_name;
  440. driver_name = uci_lookup_option_string(uci_ctx, s, "type");
  441. if (!driver_name)
  442. return;
  443. drv = avl_find_element(&wireless_drivers, driver_name, drv, node);
  444. if (!drv)
  445. return;
  446. blob_buf_init(&b, 0);
  447. uci_to_blob(&b, s, drv->device.config);
  448. wireless_device_create(drv, s->e.name, b.head);
  449. }
  450. static void
  451. config_parse_wireless_vlan(struct wireless_interface *vif, struct uci_section *s)
  452. {
  453. char *name;
  454. name = alloca(strlen(s->type) + 16);
  455. sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
  456. blob_buf_init(&b, 0);
  457. uci_to_blob(&b, s, vif->wdev->drv->vlan.config);
  458. wireless_vlan_create(vif, b.head, s->anonymous ? name : s->e.name);
  459. }
  460. static void
  461. config_parse_wireless_station(struct wireless_interface *vif, struct uci_section *s)
  462. {
  463. char *name;
  464. name = alloca(strlen(s->type) + 16);
  465. sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
  466. blob_buf_init(&b, 0);
  467. uci_to_blob(&b, s, vif->wdev->drv->station.config);
  468. wireless_station_create(vif, b.head, s->anonymous ? name : s->e.name);
  469. }
  470. static void
  471. config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
  472. {
  473. struct wireless_interface *vif;
  474. struct uci_element *f;
  475. char *name;
  476. name = alloca(strlen(s->type) + 16);
  477. sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
  478. blob_buf_init(&b, 0);
  479. uci_to_blob(&b, s, wdev->drv->interface.config);
  480. vif = wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
  481. if (!vif)
  482. return;
  483. vif->vlan_idx = vif->sta_idx = 0;
  484. vlist_update(&vif->vlans);
  485. vlist_update(&vif->stations);
  486. if (s->anonymous)
  487. goto out;
  488. uci_foreach_element(&uci_wireless->sections, f) {
  489. struct uci_section *cur = uci_to_section(f);
  490. const char *vif_name;
  491. if (strcmp(cur->type, "wifi-vlan") != 0)
  492. continue;
  493. vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
  494. if (vif_name && strcmp(s->e.name, vif_name))
  495. continue;
  496. config_parse_wireless_vlan(vif, cur);
  497. }
  498. uci_foreach_element(&uci_wireless->sections, f) {
  499. struct uci_section *cur = uci_to_section(f);
  500. const char *vif_name;
  501. if (strcmp(cur->type, "wifi-station") != 0)
  502. continue;
  503. vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
  504. if (vif_name && strcmp(s->e.name, vif_name))
  505. continue;
  506. config_parse_wireless_station(vif, cur);
  507. }
  508. out:
  509. vlist_flush(&vif->vlans);
  510. vlist_flush(&vif->stations);
  511. }
  512. static void
  513. config_init_wireless(void)
  514. {
  515. struct wireless_device *wdev;
  516. struct uci_element *e;
  517. const char *dev_name;
  518. if (!uci_wireless) {
  519. D(WIRELESS, "No wireless configuration found");
  520. return;
  521. }
  522. vlist_update(&wireless_devices);
  523. uci_foreach_element(&uci_wireless->sections, e) {
  524. struct uci_section *s = uci_to_section(e);
  525. if (strcmp(s->type, "wifi-device") != 0)
  526. continue;
  527. config_parse_wireless_device(s);
  528. }
  529. vlist_flush(&wireless_devices);
  530. vlist_for_each_element(&wireless_devices, wdev, node) {
  531. wdev->vif_idx = 0;
  532. vlist_update(&wdev->interfaces);
  533. }
  534. uci_foreach_element(&uci_wireless->sections, e) {
  535. struct uci_section *s = uci_to_section(e);
  536. if (strcmp(s->type, "wifi-iface") != 0)
  537. continue;
  538. dev_name = uci_lookup_option_string(uci_ctx, s, "device");
  539. if (!dev_name)
  540. continue;
  541. wdev = vlist_find(&wireless_devices, dev_name, wdev, node);
  542. if (!wdev) {
  543. D(WIRELESS, "device %s not found!", dev_name);
  544. continue;
  545. }
  546. config_parse_wireless_interface(wdev, s);
  547. }
  548. vlist_for_each_element(&wireless_devices, wdev, node)
  549. vlist_flush(&wdev->interfaces);
  550. }
  551. static struct blob_attr *
  552. config_find_blobmsg_attr(struct blob_attr *attr, const char *name, int type)
  553. {
  554. struct blobmsg_policy policy = { .name = name, .type = type };
  555. struct blob_attr *cur;
  556. blobmsg_parse(&policy, 1, &cur, blobmsg_data(attr), blobmsg_len(attr));
  557. return cur;
  558. }
  559. struct ether_addr *config_get_default_macaddr(const char *ifname)
  560. {
  561. struct blob_attr *cur;
  562. if (!board_netdevs)
  563. return NULL;
  564. cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE);
  565. if (!cur)
  566. return NULL;
  567. cur = config_find_blobmsg_attr(cur, "macaddr", BLOBMSG_TYPE_STRING);
  568. if (!cur)
  569. return NULL;
  570. return ether_aton(blobmsg_get_string(cur));
  571. }
  572. int config_get_default_gro(const char *ifname)
  573. {
  574. struct blob_attr *cur;
  575. if (!board_netdevs)
  576. return -1;
  577. cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE);
  578. if (!cur)
  579. return -1;
  580. cur = config_find_blobmsg_attr(cur, "gro", BLOBMSG_TYPE_BOOL);
  581. if (!cur)
  582. return -1;
  583. return blobmsg_get_bool(cur);
  584. }
  585. const char *config_get_default_conduit(const char *ifname)
  586. {
  587. struct blob_attr *cur;
  588. if (!board_netdevs)
  589. return NULL;
  590. cur = config_find_blobmsg_attr(board_netdevs, ifname, BLOBMSG_TYPE_TABLE);
  591. if (!cur)
  592. return NULL;
  593. cur = config_find_blobmsg_attr(cur, "conduit", BLOBMSG_TYPE_STRING);
  594. if (!cur)
  595. return NULL;
  596. return blobmsg_get_string(cur);
  597. }
  598. static void
  599. config_init_board(void)
  600. {
  601. struct blob_attr *cur;
  602. blob_buf_init(&b, 0);
  603. if (!blobmsg_add_json_from_file(&b, DEFAULT_BOARD_JSON))
  604. return;
  605. free(board_netdevs);
  606. board_netdevs = NULL;
  607. cur = config_find_blobmsg_attr(b.head, "network_device",
  608. BLOBMSG_TYPE_TABLE);
  609. if (!cur)
  610. return;
  611. board_netdevs = blob_memdup(cur);
  612. }
  613. int
  614. config_init_all(void)
  615. {
  616. int ret = 0;
  617. char *err;
  618. uci_network = config_init_package("network");
  619. if (!uci_network) {
  620. uci_get_errorstr(uci_ctx, &err, NULL);
  621. netifd_log_message(L_CRIT, "Failed to load network config (%s)\n", err);
  622. free(err);
  623. return -1;
  624. }
  625. uci_wireless = config_init_package("wireless");
  626. if (!uci_wireless && uci_ctx->err != UCI_ERR_NOTFOUND) {
  627. uci_get_errorstr(uci_ctx, &err, NULL);
  628. netifd_log_message(L_CRIT, "Failed to load wireless config (%s)\n", err);
  629. free(err);
  630. ret = -1;
  631. }
  632. config_init_board();
  633. vlist_update(&interfaces);
  634. config_init = true;
  635. device_reset_config();
  636. config_init_devices(true);
  637. config_init_vlans();
  638. config_init_devices(false);
  639. config_init_interfaces();
  640. config_init_ip();
  641. config_init_rules();
  642. config_init_globals();
  643. config_init_wireless();
  644. config_init = false;
  645. device_reset_old();
  646. device_init_pending();
  647. vlist_flush(&interfaces);
  648. interface_refresh_assignments(false);
  649. interface_start_pending();
  650. wireless_start_pending(0);
  651. return ret;
  652. }