ubus.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  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 <arpa/inet.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include "netifd.h"
  19. #include "interface.h"
  20. #include "proto.h"
  21. #include "ubus.h"
  22. #include "system.h"
  23. static struct ubus_context *ctx = NULL;
  24. static struct blob_buf b;
  25. static const char *ubus_path;
  26. /* global object */
  27. static int
  28. netifd_handle_restart(struct ubus_context *ctx, struct ubus_object *obj,
  29. struct ubus_request_data *req, const char *method,
  30. struct blob_attr *msg)
  31. {
  32. netifd_restart();
  33. return 0;
  34. }
  35. static int
  36. netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj,
  37. struct ubus_request_data *req, const char *method,
  38. struct blob_attr *msg)
  39. {
  40. netifd_reload();
  41. return 0;
  42. }
  43. enum {
  44. HR_TARGET,
  45. HR_V6,
  46. HR_INTERFACE,
  47. __HR_MAX
  48. };
  49. static const struct blobmsg_policy route_policy[__HR_MAX] = {
  50. [HR_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
  51. [HR_V6] = { .name = "v6", .type = BLOBMSG_TYPE_BOOL },
  52. [HR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
  53. };
  54. static int
  55. netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
  56. struct ubus_request_data *req, const char *method,
  57. struct blob_attr *msg)
  58. {
  59. struct blob_attr *tb[__HR_MAX];
  60. struct interface *iface = NULL;
  61. union if_addr a;
  62. bool v6 = false;
  63. blobmsg_parse(route_policy, __HR_MAX, tb, blob_data(msg), blob_len(msg));
  64. if (!tb[HR_TARGET])
  65. return UBUS_STATUS_INVALID_ARGUMENT;
  66. if (tb[HR_V6])
  67. v6 = blobmsg_get_bool(tb[HR_V6]);
  68. if (tb[HR_INTERFACE])
  69. iface = vlist_find(&interfaces, blobmsg_data(tb[HR_INTERFACE]), iface, node);
  70. memset(&a, 0, sizeof(a));
  71. if (!inet_pton(v6 ? AF_INET6 : AF_INET, blobmsg_data(tb[HR_TARGET]), &a))
  72. return UBUS_STATUS_INVALID_ARGUMENT;
  73. iface = interface_ip_add_target_route(&a, v6, iface);
  74. if (!iface)
  75. return UBUS_STATUS_NOT_FOUND;
  76. blob_buf_init(&b, 0);
  77. blobmsg_add_string(&b, "interface", iface->name);
  78. ubus_send_reply(ctx, req, b.head);
  79. return 0;
  80. }
  81. static int
  82. netifd_get_proto_handlers(struct ubus_context *ctx, struct ubus_object *obj,
  83. struct ubus_request_data *req, const char *method,
  84. struct blob_attr *msg)
  85. {
  86. blob_buf_init(&b, 0);
  87. proto_dump_handlers(&b);
  88. ubus_send_reply(ctx, req, b.head);
  89. return 0;
  90. }
  91. static struct ubus_method main_object_methods[] = {
  92. { .name = "restart", .handler = netifd_handle_restart },
  93. { .name = "reload", .handler = netifd_handle_reload },
  94. UBUS_METHOD("add_host_route", netifd_add_host_route, route_policy),
  95. { .name = "get_proto_handlers", .handler = netifd_get_proto_handlers },
  96. };
  97. static struct ubus_object_type main_object_type =
  98. UBUS_OBJECT_TYPE("netifd", main_object_methods);
  99. static struct ubus_object main_object = {
  100. .name = "network",
  101. .type = &main_object_type,
  102. .methods = main_object_methods,
  103. .n_methods = ARRAY_SIZE(main_object_methods),
  104. };
  105. enum {
  106. DEV_NAME,
  107. __DEV_MAX,
  108. };
  109. static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
  110. [DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  111. };
  112. static int
  113. netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj,
  114. struct ubus_request_data *req, const char *method,
  115. struct blob_attr *msg)
  116. {
  117. struct device *dev = NULL;
  118. struct blob_attr *tb[__DEV_MAX];
  119. blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
  120. if (tb[DEV_NAME]) {
  121. dev = device_get(blobmsg_data(tb[DEV_NAME]), false);
  122. if (!dev)
  123. return UBUS_STATUS_INVALID_ARGUMENT;
  124. }
  125. blob_buf_init(&b, 0);
  126. device_dump_status(&b, dev);
  127. ubus_send_reply(ctx, req, b.head);
  128. return 0;
  129. }
  130. enum {
  131. ALIAS_ATTR_ALIAS,
  132. ALIAS_ATTR_DEV,
  133. __ALIAS_ATTR_MAX,
  134. };
  135. static const struct blobmsg_policy alias_attrs[__ALIAS_ATTR_MAX] = {
  136. [ALIAS_ATTR_ALIAS] = { "alias", BLOBMSG_TYPE_ARRAY },
  137. [ALIAS_ATTR_DEV] = { "device", BLOBMSG_TYPE_STRING },
  138. };
  139. static int
  140. netifd_handle_alias(struct ubus_context *ctx, struct ubus_object *obj,
  141. struct ubus_request_data *req, const char *method,
  142. struct blob_attr *msg)
  143. {
  144. struct device *dev = NULL;
  145. struct blob_attr *tb[__ALIAS_ATTR_MAX];
  146. struct blob_attr *cur;
  147. int rem;
  148. blobmsg_parse(alias_attrs, __ALIAS_ATTR_MAX, tb, blob_data(msg), blob_len(msg));
  149. if (!tb[ALIAS_ATTR_ALIAS])
  150. return UBUS_STATUS_INVALID_ARGUMENT;
  151. if ((cur = tb[ALIAS_ATTR_DEV]) != NULL) {
  152. dev = device_get(blobmsg_data(cur), true);
  153. if (!dev)
  154. return UBUS_STATUS_NOT_FOUND;
  155. }
  156. blobmsg_for_each_attr(cur, tb[ALIAS_ATTR_ALIAS], rem) {
  157. if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
  158. goto error;
  159. if (!blobmsg_check_attr(cur, NULL))
  160. goto error;
  161. alias_notify_device(blobmsg_data(cur), dev);
  162. }
  163. return 0;
  164. error:
  165. device_free_unused(dev);
  166. return UBUS_STATUS_INVALID_ARGUMENT;
  167. }
  168. enum {
  169. DEV_STATE_NAME,
  170. DEV_STATE_DEFER,
  171. __DEV_STATE_MAX,
  172. };
  173. static const struct blobmsg_policy dev_state_policy[__DEV_STATE_MAX] = {
  174. [DEV_STATE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  175. [DEV_STATE_DEFER] = { .name = "defer", .type = BLOBMSG_TYPE_BOOL },
  176. };
  177. static int
  178. netifd_handle_set_state(struct ubus_context *ctx, struct ubus_object *obj,
  179. struct ubus_request_data *req, const char *method,
  180. struct blob_attr *msg)
  181. {
  182. struct device *dev = NULL;
  183. struct blob_attr *tb[__DEV_STATE_MAX];
  184. struct blob_attr *cur;
  185. blobmsg_parse(dev_state_policy, __DEV_STATE_MAX, tb, blob_data(msg), blob_len(msg));
  186. cur = tb[DEV_STATE_NAME];
  187. if (!cur)
  188. return UBUS_STATUS_INVALID_ARGUMENT;
  189. dev = device_get(blobmsg_data(cur), false);
  190. if (!dev)
  191. return UBUS_STATUS_NOT_FOUND;
  192. cur = tb[DEV_STATE_DEFER];
  193. if (cur)
  194. device_set_deferred(dev, !!blobmsg_get_u8(cur));
  195. return 0;
  196. }
  197. static struct ubus_method dev_object_methods[] = {
  198. UBUS_METHOD("status", netifd_dev_status, dev_policy),
  199. UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
  200. UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
  201. };
  202. static struct ubus_object_type dev_object_type =
  203. UBUS_OBJECT_TYPE("device", dev_object_methods);
  204. static struct ubus_object dev_object = {
  205. .name = "network.device",
  206. .type = &dev_object_type,
  207. .methods = dev_object_methods,
  208. .n_methods = ARRAY_SIZE(dev_object_methods),
  209. };
  210. static void
  211. netifd_ubus_add_fd(void)
  212. {
  213. ubus_add_uloop(ctx);
  214. system_fd_set_cloexec(ctx->sock.fd);
  215. }
  216. static void
  217. netifd_ubus_reconnect_timer(struct uloop_timeout *timeout)
  218. {
  219. static struct uloop_timeout retry = {
  220. .cb = netifd_ubus_reconnect_timer,
  221. };
  222. int t = 2;
  223. if (ubus_reconnect(ctx, ubus_path) != 0) {
  224. DPRINTF("failed to reconnect, trying again in %d seconds\n", t);
  225. uloop_timeout_set(&retry, t * 1000);
  226. return;
  227. }
  228. DPRINTF("reconnected to ubus, new id: %08x\n", ctx->local_id);
  229. netifd_ubus_add_fd();
  230. }
  231. static void
  232. netifd_ubus_connection_lost(struct ubus_context *ctx)
  233. {
  234. netifd_ubus_reconnect_timer(NULL);
  235. }
  236. /* per-interface object */
  237. static int
  238. netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
  239. struct ubus_request_data *req, const char *method,
  240. struct blob_attr *msg)
  241. {
  242. struct interface *iface;
  243. iface = container_of(obj, struct interface, ubus);
  244. interface_set_up(iface);
  245. return 0;
  246. }
  247. static int
  248. netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
  249. struct ubus_request_data *req, const char *method,
  250. struct blob_attr *msg)
  251. {
  252. struct interface *iface;
  253. iface = container_of(obj, struct interface, ubus);
  254. interface_set_down(iface);
  255. return 0;
  256. }
  257. static void
  258. netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
  259. {
  260. struct interface_error *error;
  261. void *e, *e2, *e3;
  262. int i;
  263. e = blobmsg_open_array(b, "errors");
  264. list_for_each_entry(error, &iface->errors, list) {
  265. e2 = blobmsg_open_table(b, NULL);
  266. blobmsg_add_string(b, "subsystem", error->subsystem);
  267. blobmsg_add_string(b, "code", error->code);
  268. if (error->data[0]) {
  269. e3 = blobmsg_open_array(b, "data");
  270. for (i = 0; error->data[i]; i++)
  271. blobmsg_add_string(b, NULL, error->data[i]);
  272. blobmsg_close_array(b, e3);
  273. }
  274. blobmsg_close_table(b, e2);
  275. }
  276. blobmsg_close_array(b, e);
  277. }
  278. static void
  279. interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6,
  280. bool enabled)
  281. {
  282. struct device_addr *addr;
  283. char *buf;
  284. void *a;
  285. int buflen = 128;
  286. int af;
  287. time_t now = system_get_rtime();
  288. vlist_for_each_element(&ip->addr, addr, node) {
  289. if (addr->enabled != enabled)
  290. continue;
  291. if ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
  292. af = AF_INET;
  293. else
  294. af = AF_INET6;
  295. if (af != (v6 ? AF_INET6 : AF_INET))
  296. continue;
  297. a = blobmsg_open_table(&b, NULL);
  298. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  299. inet_ntop(af, &addr->addr, buf, buflen);
  300. blobmsg_add_string_buffer(&b);
  301. blobmsg_add_u32(&b, "mask", addr->mask);
  302. if (addr->preferred_until) {
  303. int preferred = addr->preferred_until - now;
  304. if (preferred < 0)
  305. preferred = 0;
  306. blobmsg_add_u32(&b, "preferred", preferred);
  307. }
  308. if (addr->valid_until)
  309. blobmsg_add_u32(&b, "valid", addr->valid_until - now);
  310. blobmsg_close_table(&b, a);
  311. }
  312. }
  313. static void
  314. interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
  315. {
  316. struct device_route *route;
  317. int buflen = 128;
  318. char *buf;
  319. void *r;
  320. int af;
  321. time_t now = system_get_rtime();
  322. vlist_for_each_element(&ip->route, route, node) {
  323. if (route->enabled != enabled)
  324. continue;
  325. if ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
  326. af = AF_INET;
  327. else
  328. af = AF_INET6;
  329. r = blobmsg_open_table(&b, NULL);
  330. buf = blobmsg_alloc_string_buffer(&b, "target", buflen);
  331. inet_ntop(af, &route->addr, buf, buflen);
  332. blobmsg_add_string_buffer(&b);
  333. blobmsg_add_u32(&b, "mask", route->mask);
  334. buf = blobmsg_alloc_string_buffer(&b, "nexthop", buflen);
  335. inet_ntop(af, &route->nexthop, buf, buflen);
  336. blobmsg_add_string_buffer(&b);
  337. if (route->flags & DEVROUTE_MTU)
  338. blobmsg_add_u32(&b, "mtu", route->mtu);
  339. if (route->flags & DEVROUTE_METRIC)
  340. blobmsg_add_u32(&b, "metric", route->metric);
  341. if (route->flags & DEVROUTE_TABLE)
  342. blobmsg_add_u32(&b, "table", route->table);
  343. if (route->valid_until)
  344. blobmsg_add_u32(&b, "valid", route->valid_until - now);
  345. blobmsg_close_table(&b, r);
  346. }
  347. }
  348. static void
  349. interface_ip_dump_prefix_list(struct interface_ip_settings *ip)
  350. {
  351. struct device_prefix *prefix;
  352. char *buf;
  353. void *a, *c;
  354. const int buflen = INET6_ADDRSTRLEN;
  355. time_t now = system_get_rtime();
  356. vlist_for_each_element(&ip->prefix, prefix, node) {
  357. a = blobmsg_open_table(&b, NULL);
  358. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  359. inet_ntop(AF_INET6, &prefix->addr, buf, buflen);
  360. blobmsg_add_string_buffer(&b);
  361. blobmsg_add_u32(&b, "mask", prefix->length);
  362. if (prefix->preferred_until) {
  363. int preferred = prefix->preferred_until - now;
  364. if (preferred < 0)
  365. preferred = 0;
  366. blobmsg_add_u32(&b, "preferred", preferred);
  367. }
  368. if (prefix->valid_until)
  369. blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
  370. blobmsg_add_string(&b, "class", prefix->pclass);
  371. c = blobmsg_open_table(&b, "assigned");
  372. struct device_prefix_assignment *assign;
  373. list_for_each_entry(assign, &prefix->assignments, head) {
  374. if (!assign->name[0])
  375. continue;
  376. struct in6_addr addr = prefix->addr;
  377. addr.s6_addr32[1] |= htonl(assign->assigned);
  378. void *d = blobmsg_open_table(&b, assign->name);
  379. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  380. inet_ntop(AF_INET6, &addr, buf, buflen);
  381. blobmsg_add_string_buffer(&b);
  382. blobmsg_add_u32(&b, "mask", assign->length);
  383. blobmsg_close_table(&b, d);
  384. }
  385. blobmsg_close_table(&b, c);
  386. blobmsg_close_table(&b, a);
  387. }
  388. }
  389. static void
  390. interface_ip_dump_prefix_assignment_list(struct interface *iface)
  391. {
  392. void *a;
  393. char *buf;
  394. const int buflen = INET6_ADDRSTRLEN;
  395. time_t now = system_get_rtime();
  396. struct device_prefix *prefix;
  397. list_for_each_entry(prefix, &prefixes, head) {
  398. struct device_prefix_assignment *assign;
  399. list_for_each_entry(assign, &prefix->assignments, head) {
  400. if (strcmp(assign->name, iface->name))
  401. continue;
  402. struct in6_addr addr = prefix->addr;
  403. addr.s6_addr32[1] |= htonl(assign->assigned);
  404. a = blobmsg_open_table(&b, NULL);
  405. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  406. inet_ntop(AF_INET6, &addr, buf, buflen);
  407. blobmsg_add_string_buffer(&b);
  408. blobmsg_add_u32(&b, "mask", assign->length);
  409. if (prefix->preferred_until) {
  410. int preferred = prefix->preferred_until - now;
  411. if (preferred < 0)
  412. preferred = 0;
  413. blobmsg_add_u32(&b, "preferred", preferred);
  414. }
  415. if (prefix->valid_until)
  416. blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
  417. blobmsg_close_table(&b, a);
  418. }
  419. }
  420. }
  421. static void
  422. interface_ip_dump_dns_server_list(struct interface_ip_settings *ip,
  423. bool enabled)
  424. {
  425. struct dns_server *dns;
  426. int buflen = 128;
  427. char *buf;
  428. vlist_simple_for_each_element(&ip->dns_servers, dns, node) {
  429. if (ip->no_dns == enabled)
  430. continue;
  431. buf = blobmsg_alloc_string_buffer(&b, NULL, buflen);
  432. inet_ntop(dns->af, &dns->addr, buf, buflen);
  433. blobmsg_add_string_buffer(&b);
  434. }
  435. }
  436. static void
  437. interface_ip_dump_dns_search_list(struct interface_ip_settings *ip,
  438. bool enabled)
  439. {
  440. struct dns_search_domain *dns;
  441. vlist_simple_for_each_element(&ip->dns_search, dns, node) {
  442. if (ip->no_dns == enabled)
  443. continue;
  444. blobmsg_add_string(&b, NULL, dns->name);
  445. }
  446. }
  447. static int
  448. netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
  449. struct ubus_request_data *req, const char *method,
  450. struct blob_attr *msg)
  451. {
  452. struct interface *iface;
  453. struct interface_data *data;
  454. struct device *dev;
  455. void *a, *inactive;
  456. iface = container_of(obj, struct interface, ubus);
  457. blob_buf_init(&b, 0);
  458. blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
  459. blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
  460. blobmsg_add_u8(&b, "available", iface->available);
  461. blobmsg_add_u8(&b, "autostart", iface->autostart);
  462. if (iface->state == IFS_UP) {
  463. time_t cur = system_get_rtime();
  464. blobmsg_add_u32(&b, "uptime", cur - iface->start_time);
  465. blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname);
  466. }
  467. if (iface->proto_handler)
  468. blobmsg_add_string(&b, "proto", iface->proto_handler->name);
  469. dev = iface->main_dev.dev;
  470. if (dev && !dev->hidden &&
  471. !(iface->proto_handler->flags & PROTO_FLAG_NODEV))
  472. blobmsg_add_string(&b, "device", dev->ifname);
  473. if (iface->state == IFS_UP) {
  474. blobmsg_add_u32(&b, "metric", iface->metric);
  475. a = blobmsg_open_array(&b, "ipv4-address");
  476. interface_ip_dump_address_list(&iface->config_ip, false, true);
  477. interface_ip_dump_address_list(&iface->proto_ip, false, true);
  478. blobmsg_close_array(&b, a);
  479. a = blobmsg_open_array(&b, "ipv6-address");
  480. interface_ip_dump_address_list(&iface->config_ip, true, true);
  481. interface_ip_dump_address_list(&iface->proto_ip, true, true);
  482. blobmsg_close_array(&b, a);
  483. a = blobmsg_open_array(&b, "ipv6-prefix");
  484. interface_ip_dump_prefix_list(&iface->config_ip);
  485. interface_ip_dump_prefix_list(&iface->proto_ip);
  486. blobmsg_close_array(&b, a);
  487. a = blobmsg_open_array(&b, "ipv6-prefix-assignment");
  488. interface_ip_dump_prefix_assignment_list(iface);
  489. blobmsg_close_array(&b, a);
  490. a = blobmsg_open_array(&b, "route");
  491. interface_ip_dump_route_list(&iface->config_ip, true);
  492. interface_ip_dump_route_list(&iface->proto_ip, true);
  493. blobmsg_close_array(&b, a);
  494. a = blobmsg_open_array(&b, "dns-server");
  495. interface_ip_dump_dns_server_list(&iface->config_ip, true);
  496. interface_ip_dump_dns_server_list(&iface->proto_ip, true);
  497. blobmsg_close_array(&b, a);
  498. a = blobmsg_open_array(&b, "dns-search");
  499. interface_ip_dump_dns_search_list(&iface->config_ip, true);
  500. interface_ip_dump_dns_search_list(&iface->proto_ip, true);
  501. blobmsg_close_array(&b, a);
  502. inactive = blobmsg_open_table(&b, "inactive");
  503. a = blobmsg_open_array(&b, "ipv4-address");
  504. interface_ip_dump_address_list(&iface->config_ip, false, false);
  505. interface_ip_dump_address_list(&iface->proto_ip, false, false);
  506. blobmsg_close_array(&b, a);
  507. a = blobmsg_open_array(&b, "ipv6-address");
  508. interface_ip_dump_address_list(&iface->config_ip, true, false);
  509. interface_ip_dump_address_list(&iface->proto_ip, true, false);
  510. blobmsg_close_array(&b, a);
  511. a = blobmsg_open_array(&b, "route");
  512. interface_ip_dump_route_list(&iface->config_ip, false);
  513. interface_ip_dump_route_list(&iface->proto_ip, false);
  514. blobmsg_close_array(&b, a);
  515. a = blobmsg_open_array(&b, "dns-server");
  516. interface_ip_dump_dns_server_list(&iface->config_ip, false);
  517. interface_ip_dump_dns_server_list(&iface->proto_ip, false);
  518. blobmsg_close_array(&b, a);
  519. a = blobmsg_open_array(&b, "dns-search");
  520. interface_ip_dump_dns_search_list(&iface->config_ip, false);
  521. interface_ip_dump_dns_search_list(&iface->proto_ip, false);
  522. blobmsg_close_array(&b, a);
  523. blobmsg_close_table(&b, inactive);
  524. }
  525. a = blobmsg_open_table(&b, "data");
  526. avl_for_each_element(&iface->data, data, node)
  527. blob_put(&b, blob_id(data->data), blob_data(data->data), blob_len(data->data));
  528. blobmsg_close_table(&b, a);
  529. if (!list_is_empty(&iface->errors))
  530. netifd_add_interface_errors(&b, iface);
  531. ubus_send_reply(ctx, req, b.head);
  532. return 0;
  533. }
  534. static int
  535. netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj,
  536. struct ubus_request_data *req, const char *method,
  537. struct blob_attr *msg)
  538. {
  539. struct blob_attr *tb[__DEV_MAX];
  540. struct interface *iface;
  541. struct device *dev;
  542. bool add = !strncmp(method, "add", 3);
  543. int ret;
  544. iface = container_of(obj, struct interface, ubus);
  545. blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
  546. if (!tb[DEV_NAME])
  547. return UBUS_STATUS_INVALID_ARGUMENT;
  548. device_lock();
  549. dev = device_get(blobmsg_data(tb[DEV_NAME]), add ? 2 : 0);
  550. if (!dev) {
  551. ret = UBUS_STATUS_NOT_FOUND;
  552. goto out;
  553. }
  554. if (add) {
  555. device_set_present(dev, true);
  556. if (iface->device_config)
  557. device_set_config(dev, &simple_device_type, iface->config);
  558. system_if_apply_settings(dev, &dev->settings);
  559. ret = interface_add_link(iface, dev);
  560. } else {
  561. ret = interface_remove_link(iface, dev);
  562. }
  563. out:
  564. device_unlock();
  565. return ret;
  566. }
  567. static int
  568. netifd_iface_notify_proto(struct ubus_context *ctx, struct ubus_object *obj,
  569. struct ubus_request_data *req, const char *method,
  570. struct blob_attr *msg)
  571. {
  572. struct interface *iface;
  573. iface = container_of(obj, struct interface, ubus);
  574. if (!iface->proto || !iface->proto->notify)
  575. return UBUS_STATUS_NOT_SUPPORTED;
  576. return iface->proto->notify(iface->proto, msg);
  577. }
  578. static void
  579. netifd_iface_do_remove(struct uloop_timeout *timeout)
  580. {
  581. struct interface *iface;
  582. iface = container_of(timeout, struct interface, remove_timer);
  583. vlist_delete(&interfaces, &iface->node);
  584. }
  585. static int
  586. netifd_iface_remove(struct ubus_context *ctx, struct ubus_object *obj,
  587. struct ubus_request_data *req, const char *method,
  588. struct blob_attr *msg)
  589. {
  590. struct interface *iface;
  591. iface = container_of(obj, struct interface, ubus);
  592. if (iface->remove_timer.cb)
  593. return UBUS_STATUS_INVALID_ARGUMENT;
  594. iface->remove_timer.cb = netifd_iface_do_remove;
  595. uloop_timeout_set(&iface->remove_timer, 100);
  596. return 0;
  597. }
  598. static int
  599. netifd_handle_iface_prepare(struct ubus_context *ctx, struct ubus_object *obj,
  600. struct ubus_request_data *req, const char *method,
  601. struct blob_attr *msg)
  602. {
  603. struct interface *iface;
  604. struct device *dev;
  605. const struct device_hotplug_ops *ops;
  606. iface = container_of(obj, struct interface, ubus);
  607. dev = iface->main_dev.dev;
  608. if (!dev)
  609. return 0;
  610. ops = dev->hotplug_ops;
  611. if (!ops)
  612. return 0;
  613. return ops->prepare(dev);
  614. }
  615. static int
  616. netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj,
  617. struct ubus_request_data *req, const char *method,
  618. struct blob_attr *msg)
  619. {
  620. struct interface *iface;
  621. struct blob_attr *cur;
  622. int rem, ret;
  623. iface = container_of(obj, struct interface, ubus);
  624. blob_for_each_attr(cur, msg, rem) {
  625. ret = interface_add_data(iface, cur);
  626. if (ret)
  627. return ret;
  628. }
  629. return 0;
  630. }
  631. static struct ubus_method iface_object_methods[] = {
  632. { .name = "up", .handler = netifd_handle_up },
  633. { .name = "down", .handler = netifd_handle_down },
  634. { .name = "status", .handler = netifd_handle_status },
  635. { .name = "prepare", .handler = netifd_handle_iface_prepare },
  636. UBUS_METHOD("add_device", netifd_iface_handle_device, dev_policy ),
  637. UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_policy ),
  638. { .name = "notify_proto", .handler = netifd_iface_notify_proto },
  639. { .name = "remove", .handler = netifd_iface_remove },
  640. { .name = "set_data", .handler = netifd_handle_set_data },
  641. };
  642. static struct ubus_object_type iface_object_type =
  643. UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
  644. static struct ubus_object iface_object = {
  645. .name = "network.interface",
  646. .type = &iface_object_type,
  647. .n_methods = ARRAY_SIZE(iface_object_methods),
  648. };
  649. static void netifd_add_object(struct ubus_object *obj)
  650. {
  651. int ret = ubus_add_object(ctx, obj);
  652. if (ret != 0)
  653. fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret));
  654. }
  655. static const struct blobmsg_policy iface_policy = {
  656. .name = "interface",
  657. .type = BLOBMSG_TYPE_STRING,
  658. };
  659. static int
  660. netifd_handle_iface(struct ubus_context *ctx, struct ubus_object *obj,
  661. struct ubus_request_data *req, const char *method,
  662. struct blob_attr *msg)
  663. {
  664. struct interface *iface;
  665. struct blob_attr *tb;
  666. int i;
  667. blobmsg_parse(&iface_policy, 1, &tb, blob_data(msg), blob_len(msg));
  668. if (!tb)
  669. return UBUS_STATUS_INVALID_ARGUMENT;
  670. iface = vlist_find(&interfaces, blobmsg_data(tb), iface, node);
  671. if (!iface)
  672. return UBUS_STATUS_NOT_FOUND;
  673. for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
  674. ubus_handler_t cb;
  675. if (strcmp(method, iface_object_methods[i].name) != 0)
  676. continue;
  677. cb = iface_object_methods[i].handler;
  678. return cb(ctx, &iface->ubus, req, method, msg);
  679. }
  680. return UBUS_STATUS_INVALID_ARGUMENT;
  681. }
  682. static void netifd_add_iface_object(void)
  683. {
  684. struct ubus_method *methods;
  685. int i;
  686. methods = calloc(1, sizeof(iface_object_methods));
  687. memcpy(methods, iface_object_methods, sizeof(iface_object_methods));
  688. iface_object.methods = methods;
  689. for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
  690. methods[i].handler = netifd_handle_iface;
  691. methods[i].policy = &iface_policy;
  692. methods[i].n_policy = 1;
  693. }
  694. netifd_add_object(&iface_object);
  695. }
  696. int
  697. netifd_ubus_init(const char *path)
  698. {
  699. uloop_init();
  700. ubus_path = path;
  701. ctx = ubus_connect(path);
  702. if (!ctx)
  703. return -EIO;
  704. DPRINTF("connected as %08x\n", ctx->local_id);
  705. ctx->connection_lost = netifd_ubus_connection_lost;
  706. netifd_ubus_add_fd();
  707. netifd_add_object(&main_object);
  708. netifd_add_object(&dev_object);
  709. netifd_add_iface_object();
  710. return 0;
  711. }
  712. void
  713. netifd_ubus_done(void)
  714. {
  715. ubus_free(ctx);
  716. }
  717. void
  718. netifd_ubus_interface_event(struct interface *iface, bool up)
  719. {
  720. blob_buf_init(&b, 0);
  721. blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown");
  722. blobmsg_add_string(&b, "interface", iface->name);
  723. ubus_send_event(ctx, "network.interface", b.head);
  724. }
  725. void
  726. netifd_ubus_add_interface(struct interface *iface)
  727. {
  728. struct ubus_object *obj = &iface->ubus;
  729. char *name = NULL;
  730. if (asprintf(&name, "%s.interface.%s", main_object.name, iface->name) == -1)
  731. return;
  732. obj->name = name;
  733. obj->type = &iface_object_type;
  734. obj->methods = iface_object_methods;
  735. obj->n_methods = ARRAY_SIZE(iface_object_methods);
  736. if (ubus_add_object(ctx, &iface->ubus)) {
  737. DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name);
  738. free(name);
  739. obj->name = NULL;
  740. }
  741. }
  742. void
  743. netifd_ubus_remove_interface(struct interface *iface)
  744. {
  745. if (!iface->ubus.name)
  746. return;
  747. ubus_remove_object(ctx, &iface->ubus);
  748. free((void *) iface->ubus.name);
  749. }