ubus.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  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. #include "wireless.h"
  24. struct ubus_context *ubus_ctx = NULL;
  25. static struct blob_buf b;
  26. static const char *ubus_path;
  27. /* global object */
  28. static int
  29. netifd_handle_restart(struct ubus_context *ctx, struct ubus_object *obj,
  30. struct ubus_request_data *req, const char *method,
  31. struct blob_attr *msg)
  32. {
  33. netifd_restart();
  34. return 0;
  35. }
  36. static int
  37. netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj,
  38. struct ubus_request_data *req, const char *method,
  39. struct blob_attr *msg)
  40. {
  41. if (netifd_reload())
  42. return UBUS_STATUS_NOT_FOUND;
  43. return UBUS_STATUS_OK;
  44. }
  45. enum {
  46. HR_TARGET,
  47. HR_V6,
  48. HR_INTERFACE,
  49. __HR_MAX
  50. };
  51. static const struct blobmsg_policy route_policy[__HR_MAX] = {
  52. [HR_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
  53. [HR_V6] = { .name = "v6", .type = BLOBMSG_TYPE_BOOL },
  54. [HR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
  55. };
  56. static int
  57. netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
  58. struct ubus_request_data *req, const char *method,
  59. struct blob_attr *msg)
  60. {
  61. struct blob_attr *tb[__HR_MAX];
  62. struct interface *iface = NULL;
  63. union if_addr a;
  64. bool v6 = false;
  65. blobmsg_parse(route_policy, __HR_MAX, tb, blob_data(msg), blob_len(msg));
  66. if (!tb[HR_TARGET])
  67. return UBUS_STATUS_INVALID_ARGUMENT;
  68. if (tb[HR_V6])
  69. v6 = blobmsg_get_bool(tb[HR_V6]);
  70. if (tb[HR_INTERFACE])
  71. iface = vlist_find(&interfaces, blobmsg_data(tb[HR_INTERFACE]), iface, node);
  72. memset(&a, 0, sizeof(a));
  73. if (!inet_pton(v6 ? AF_INET6 : AF_INET, blobmsg_data(tb[HR_TARGET]), &a))
  74. return UBUS_STATUS_INVALID_ARGUMENT;
  75. iface = interface_ip_add_target_route(&a, v6, iface);
  76. if (!iface)
  77. return UBUS_STATUS_NOT_FOUND;
  78. blob_buf_init(&b, 0);
  79. blobmsg_add_string(&b, "interface", iface->name);
  80. ubus_send_reply(ctx, req, b.head);
  81. return 0;
  82. }
  83. static int
  84. netifd_get_proto_handlers(struct ubus_context *ctx, struct ubus_object *obj,
  85. struct ubus_request_data *req, const char *method,
  86. struct blob_attr *msg)
  87. {
  88. blob_buf_init(&b, 0);
  89. proto_dump_handlers(&b);
  90. ubus_send_reply(ctx, req, b.head);
  91. return 0;
  92. }
  93. enum {
  94. DI_NAME,
  95. __DI_MAX
  96. };
  97. static const struct blobmsg_policy dynamic_policy[__DI_MAX] = {
  98. [DI_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  99. };
  100. static int
  101. netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj,
  102. struct ubus_request_data *req, const char *method,
  103. struct blob_attr *msg)
  104. {
  105. struct blob_attr *tb[__DI_MAX];
  106. struct interface *iface;
  107. struct blob_attr *config;
  108. blobmsg_parse(dynamic_policy, __DI_MAX, tb, blob_data(msg), blob_len(msg));
  109. if (!tb[DI_NAME])
  110. return UBUS_STATUS_INVALID_ARGUMENT;
  111. const char *name = blobmsg_get_string(tb[DI_NAME]);
  112. iface = interface_alloc(name, msg, true);
  113. if (!iface)
  114. return UBUS_STATUS_UNKNOWN_ERROR;
  115. config = blob_memdup(msg);
  116. if (!config)
  117. goto error;
  118. if (!interface_add(iface, config))
  119. goto error_free_config;
  120. return UBUS_STATUS_OK;
  121. error_free_config:
  122. free(config);
  123. error:
  124. free(iface);
  125. return UBUS_STATUS_UNKNOWN_ERROR;
  126. }
  127. static struct ubus_method main_object_methods[] = {
  128. { .name = "restart", .handler = netifd_handle_restart },
  129. { .name = "reload", .handler = netifd_handle_reload },
  130. UBUS_METHOD("add_host_route", netifd_add_host_route, route_policy),
  131. { .name = "get_proto_handlers", .handler = netifd_get_proto_handlers },
  132. UBUS_METHOD("add_dynamic", netifd_add_dynamic, dynamic_policy),
  133. };
  134. static struct ubus_object_type main_object_type =
  135. UBUS_OBJECT_TYPE("netifd", main_object_methods);
  136. static struct ubus_object main_object = {
  137. .name = "network",
  138. .type = &main_object_type,
  139. .methods = main_object_methods,
  140. .n_methods = ARRAY_SIZE(main_object_methods),
  141. };
  142. enum {
  143. DEV_NAME,
  144. __DEV_MAX,
  145. };
  146. static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
  147. [DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  148. };
  149. static int
  150. netifd_dev_status(struct ubus_context *ctx, struct ubus_object *obj,
  151. struct ubus_request_data *req, const char *method,
  152. struct blob_attr *msg)
  153. {
  154. struct device *dev = NULL;
  155. struct blob_attr *tb[__DEV_MAX];
  156. blobmsg_parse(dev_policy, __DEV_MAX, tb, blob_data(msg), blob_len(msg));
  157. if (tb[DEV_NAME]) {
  158. dev = device_find(blobmsg_data(tb[DEV_NAME]));
  159. if (!dev)
  160. return UBUS_STATUS_INVALID_ARGUMENT;
  161. }
  162. blob_buf_init(&b, 0);
  163. device_dump_status(&b, dev);
  164. ubus_send_reply(ctx, req, b.head);
  165. return 0;
  166. }
  167. enum {
  168. ALIAS_ATTR_ALIAS,
  169. ALIAS_ATTR_DEV,
  170. __ALIAS_ATTR_MAX,
  171. };
  172. static const struct blobmsg_policy alias_attrs[__ALIAS_ATTR_MAX] = {
  173. [ALIAS_ATTR_ALIAS] = { "alias", BLOBMSG_TYPE_ARRAY },
  174. [ALIAS_ATTR_DEV] = { "device", BLOBMSG_TYPE_STRING },
  175. };
  176. static int
  177. netifd_handle_alias(struct ubus_context *ctx, struct ubus_object *obj,
  178. struct ubus_request_data *req, const char *method,
  179. struct blob_attr *msg)
  180. {
  181. struct device *dev = NULL;
  182. struct blob_attr *tb[__ALIAS_ATTR_MAX];
  183. struct blob_attr *cur;
  184. int rem;
  185. blobmsg_parse(alias_attrs, __ALIAS_ATTR_MAX, tb, blob_data(msg), blob_len(msg));
  186. if (!tb[ALIAS_ATTR_ALIAS])
  187. return UBUS_STATUS_INVALID_ARGUMENT;
  188. if ((cur = tb[ALIAS_ATTR_DEV]) != NULL) {
  189. dev = device_get(blobmsg_data(cur), true);
  190. if (!dev)
  191. return UBUS_STATUS_NOT_FOUND;
  192. }
  193. blobmsg_for_each_attr(cur, tb[ALIAS_ATTR_ALIAS], rem) {
  194. if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
  195. goto error;
  196. if (!blobmsg_check_attr(cur, false))
  197. goto error;
  198. alias_notify_device(blobmsg_data(cur), dev);
  199. }
  200. return 0;
  201. error:
  202. device_free_unused(dev);
  203. return UBUS_STATUS_INVALID_ARGUMENT;
  204. }
  205. enum {
  206. DEV_STATE_NAME,
  207. DEV_STATE_DEFER,
  208. __DEV_STATE_MAX,
  209. };
  210. static const struct blobmsg_policy dev_state_policy[__DEV_STATE_MAX] = {
  211. [DEV_STATE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  212. [DEV_STATE_DEFER] = { .name = "defer", .type = BLOBMSG_TYPE_BOOL },
  213. };
  214. static int
  215. netifd_handle_set_state(struct ubus_context *ctx, struct ubus_object *obj,
  216. struct ubus_request_data *req, const char *method,
  217. struct blob_attr *msg)
  218. {
  219. struct device *dev = NULL;
  220. struct blob_attr *tb[__DEV_STATE_MAX];
  221. struct blob_attr *cur;
  222. blobmsg_parse(dev_state_policy, __DEV_STATE_MAX, tb, blob_data(msg), blob_len(msg));
  223. cur = tb[DEV_STATE_NAME];
  224. if (!cur)
  225. return UBUS_STATUS_INVALID_ARGUMENT;
  226. dev = device_find(blobmsg_data(cur));
  227. if (!dev)
  228. return UBUS_STATUS_NOT_FOUND;
  229. cur = tb[DEV_STATE_DEFER];
  230. if (cur)
  231. device_set_deferred(dev, !!blobmsg_get_u8(cur));
  232. return 0;
  233. }
  234. static struct ubus_method dev_object_methods[] = {
  235. UBUS_METHOD("status", netifd_dev_status, dev_policy),
  236. UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
  237. UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
  238. };
  239. static struct ubus_object_type dev_object_type =
  240. UBUS_OBJECT_TYPE("device", dev_object_methods);
  241. static struct ubus_object dev_object = {
  242. .name = "network.device",
  243. .type = &dev_object_type,
  244. .methods = dev_object_methods,
  245. .n_methods = ARRAY_SIZE(dev_object_methods),
  246. };
  247. static void
  248. netifd_ubus_add_fd(void)
  249. {
  250. ubus_add_uloop(ubus_ctx);
  251. system_fd_set_cloexec(ubus_ctx->sock.fd);
  252. }
  253. static void
  254. netifd_ubus_reconnect_timer(struct uloop_timeout *timeout)
  255. {
  256. static struct uloop_timeout retry = {
  257. .cb = netifd_ubus_reconnect_timer,
  258. };
  259. int t = 2;
  260. if (ubus_reconnect(ubus_ctx, ubus_path) != 0) {
  261. DPRINTF("failed to reconnect, trying again in %d seconds\n", t);
  262. uloop_timeout_set(&retry, t * 1000);
  263. return;
  264. }
  265. DPRINTF("reconnected to ubus, new id: %08x\n", ubus_ctx->local_id);
  266. netifd_ubus_add_fd();
  267. }
  268. static void
  269. netifd_ubus_connection_lost(struct ubus_context *ctx)
  270. {
  271. netifd_ubus_reconnect_timer(NULL);
  272. }
  273. /* per-interface object */
  274. static int
  275. netifd_handle_up(struct ubus_context *ctx, struct ubus_object *obj,
  276. struct ubus_request_data *req, const char *method,
  277. struct blob_attr *msg)
  278. {
  279. struct interface *iface;
  280. iface = container_of(obj, struct interface, ubus);
  281. interface_set_up(iface);
  282. return 0;
  283. }
  284. static int
  285. netifd_handle_down(struct ubus_context *ctx, struct ubus_object *obj,
  286. struct ubus_request_data *req, const char *method,
  287. struct blob_attr *msg)
  288. {
  289. struct interface *iface;
  290. iface = container_of(obj, struct interface, ubus);
  291. interface_set_down(iface);
  292. return 0;
  293. }
  294. static int
  295. netifd_handle_renew(struct ubus_context *ctx, struct ubus_object *obj,
  296. struct ubus_request_data *req, const char *method,
  297. struct blob_attr *msg)
  298. {
  299. struct interface *iface;
  300. iface = container_of(obj, struct interface, ubus);
  301. interface_renew(iface);
  302. return 0;
  303. }
  304. static void
  305. netifd_add_interface_errors(struct blob_buf *b, struct interface *iface)
  306. {
  307. struct interface_error *error;
  308. void *e, *e2, *e3;
  309. int i;
  310. e = blobmsg_open_array(b, "errors");
  311. list_for_each_entry(error, &iface->errors, list) {
  312. e2 = blobmsg_open_table(b, NULL);
  313. blobmsg_add_string(b, "subsystem", error->subsystem);
  314. blobmsg_add_string(b, "code", error->code);
  315. if (error->data[0]) {
  316. e3 = blobmsg_open_array(b, "data");
  317. for (i = 0; error->data[i]; i++)
  318. blobmsg_add_string(b, NULL, error->data[i]);
  319. blobmsg_close_array(b, e3);
  320. }
  321. blobmsg_close_table(b, e2);
  322. }
  323. blobmsg_close_array(b, e);
  324. }
  325. static void
  326. interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, bool enabled)
  327. {
  328. struct device_addr *addr;
  329. char *buf;
  330. void *a;
  331. int buflen = 128;
  332. int af;
  333. time_t now = system_get_rtime();
  334. vlist_for_each_element(&ip->addr, addr, node) {
  335. if (addr->enabled != enabled)
  336. continue;
  337. if ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
  338. af = AF_INET;
  339. else
  340. af = AF_INET6;
  341. if (af != (v6 ? AF_INET6 : AF_INET))
  342. continue;
  343. a = blobmsg_open_table(&b, NULL);
  344. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  345. inet_ntop(af, &addr->addr, buf, buflen);
  346. blobmsg_add_string_buffer(&b);
  347. blobmsg_add_u32(&b, "mask", addr->mask);
  348. if (addr->point_to_point) {
  349. buf = blobmsg_alloc_string_buffer(&b, "ptpaddress", buflen);
  350. inet_ntop(af, &addr->point_to_point, buf, buflen);
  351. blobmsg_add_string_buffer(&b);
  352. }
  353. if (addr->preferred_until) {
  354. int preferred = addr->preferred_until - now;
  355. if (preferred < 0)
  356. preferred = 0;
  357. blobmsg_add_u32(&b, "preferred", preferred);
  358. }
  359. if (addr->valid_until)
  360. blobmsg_add_u32(&b, "valid", addr->valid_until - now);
  361. if (addr->pclass)
  362. blobmsg_add_string(&b, "class", addr->pclass);
  363. blobmsg_close_table(&b, a);
  364. }
  365. }
  366. static void
  367. interface_ip_dump_neighbor_list(struct interface_ip_settings *ip, bool enabled)
  368. {
  369. struct device_neighbor *neighbor;
  370. int buflen = 128;
  371. char *buf;
  372. void *r;
  373. int af;
  374. vlist_for_each_element(&ip->neighbor, neighbor, node) {
  375. if (neighbor->enabled != enabled)
  376. continue;
  377. if ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
  378. af = AF_INET;
  379. else
  380. af = AF_INET6;
  381. r = blobmsg_open_table(&b, NULL);
  382. if (neighbor->flags & DEVNEIGH_MAC)
  383. blobmsg_add_string(&b, "mac", format_macaddr(neighbor->macaddr));
  384. buf = blobmsg_alloc_string_buffer(&b , "address", buflen);
  385. inet_ntop(af, &neighbor->addr, buf, buflen);
  386. blobmsg_add_string_buffer(&b);
  387. if (neighbor->proxy)
  388. blobmsg_add_u32(&b, "proxy", neighbor->proxy);
  389. if (neighbor->router)
  390. blobmsg_add_u32(&b, "router", neighbor->router);
  391. blobmsg_close_table(&b, r);
  392. }
  393. }
  394. static void
  395. interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
  396. {
  397. struct device_route *route;
  398. int buflen = 128;
  399. char *buf;
  400. void *r;
  401. int af;
  402. time_t now = system_get_rtime();
  403. vlist_for_each_element(&ip->route, route, node) {
  404. if (route->enabled != enabled)
  405. continue;
  406. if ((ip->no_defaultroute == enabled) && !route->mask)
  407. continue;
  408. if ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
  409. af = AF_INET;
  410. else
  411. af = AF_INET6;
  412. r = blobmsg_open_table(&b, NULL);
  413. buf = blobmsg_alloc_string_buffer(&b, "target", buflen);
  414. inet_ntop(af, &route->addr, buf, buflen);
  415. blobmsg_add_string_buffer(&b);
  416. blobmsg_add_u32(&b, "mask", route->mask);
  417. buf = blobmsg_alloc_string_buffer(&b, "nexthop", buflen);
  418. inet_ntop(af, &route->nexthop, buf, buflen);
  419. blobmsg_add_string_buffer(&b);
  420. if (route->flags & DEVROUTE_TYPE)
  421. blobmsg_add_u32(&b, "type", route->type);
  422. if (route->flags & DEVROUTE_PROTO)
  423. blobmsg_add_u32(&b, "proto", route->proto);
  424. if (route->flags & DEVROUTE_MTU)
  425. blobmsg_add_u32(&b, "mtu", route->mtu);
  426. if (route->flags & DEVROUTE_METRIC)
  427. blobmsg_add_u32(&b, "metric", route->metric);
  428. if (route->flags & DEVROUTE_TABLE)
  429. blobmsg_add_u32(&b, "table", route->table);
  430. if (route->valid_until)
  431. blobmsg_add_u32(&b, "valid", route->valid_until - now);
  432. buf = blobmsg_alloc_string_buffer(&b, "source", buflen);
  433. inet_ntop(af, &route->source, buf, buflen);
  434. snprintf(buf + strlen(buf), buflen - strlen(buf), "/%u", route->sourcemask);
  435. blobmsg_add_string_buffer(&b);
  436. blobmsg_close_table(&b, r);
  437. }
  438. }
  439. static void
  440. interface_ip_dump_prefix_list(struct interface_ip_settings *ip)
  441. {
  442. struct device_prefix *prefix;
  443. char *buf;
  444. void *a, *c;
  445. const int buflen = INET6_ADDRSTRLEN;
  446. time_t now = system_get_rtime();
  447. vlist_for_each_element(&ip->prefix, prefix, node) {
  448. a = blobmsg_open_table(&b, NULL);
  449. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  450. inet_ntop(AF_INET6, &prefix->addr, buf, buflen);
  451. blobmsg_add_string_buffer(&b);
  452. blobmsg_add_u32(&b, "mask", prefix->length);
  453. if (prefix->preferred_until) {
  454. int preferred = prefix->preferred_until - now;
  455. if (preferred < 0)
  456. preferred = 0;
  457. blobmsg_add_u32(&b, "preferred", preferred);
  458. }
  459. if (prefix->valid_until)
  460. blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
  461. blobmsg_add_string(&b, "class", prefix->pclass);
  462. c = blobmsg_open_table(&b, "assigned");
  463. struct device_prefix_assignment *assign;
  464. list_for_each_entry(assign, &prefix->assignments, head) {
  465. if (!assign->name[0])
  466. continue;
  467. struct in6_addr addr = prefix->addr;
  468. addr.s6_addr32[1] |= htonl(assign->assigned);
  469. void *d = blobmsg_open_table(&b, assign->name);
  470. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  471. inet_ntop(AF_INET6, &addr, buf, buflen);
  472. blobmsg_add_string_buffer(&b);
  473. blobmsg_add_u32(&b, "mask", assign->length);
  474. blobmsg_close_table(&b, d);
  475. }
  476. blobmsg_close_table(&b, c);
  477. blobmsg_close_table(&b, a);
  478. }
  479. }
  480. static void
  481. interface_ip_dump_prefix_assignment_list(struct interface *iface)
  482. {
  483. void *a;
  484. char *buf;
  485. const int buflen = INET6_ADDRSTRLEN;
  486. time_t now = system_get_rtime();
  487. struct device_prefix *prefix;
  488. list_for_each_entry(prefix, &prefixes, head) {
  489. struct device_prefix_assignment *assign;
  490. list_for_each_entry(assign, &prefix->assignments, head) {
  491. if (strcmp(assign->name, iface->name))
  492. continue;
  493. struct in6_addr addr = prefix->addr;
  494. addr.s6_addr32[1] |= htonl(assign->assigned);
  495. a = blobmsg_open_table(&b, NULL);
  496. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  497. inet_ntop(AF_INET6, &addr, buf, buflen);
  498. blobmsg_add_string_buffer(&b);
  499. blobmsg_add_u32(&b, "mask", assign->length);
  500. if (prefix->preferred_until) {
  501. int preferred = prefix->preferred_until - now;
  502. if (preferred < 0)
  503. preferred = 0;
  504. blobmsg_add_u32(&b, "preferred", preferred);
  505. }
  506. if (prefix->valid_until)
  507. blobmsg_add_u32(&b, "valid", prefix->valid_until - now);
  508. void *c = blobmsg_open_table(&b, "local-address");
  509. if (assign->enabled) {
  510. buf = blobmsg_alloc_string_buffer(&b, "address", buflen);
  511. inet_ntop(AF_INET6, &assign->addr, buf, buflen);
  512. blobmsg_add_string_buffer(&b);
  513. blobmsg_add_u32(&b, "mask", assign->length);
  514. }
  515. blobmsg_close_table(&b, c);
  516. blobmsg_close_table(&b, a);
  517. }
  518. }
  519. }
  520. static void
  521. interface_ip_dump_dns_server_list(struct interface_ip_settings *ip, bool enabled)
  522. {
  523. struct dns_server *dns;
  524. int buflen = 128;
  525. char *buf;
  526. vlist_simple_for_each_element(&ip->dns_servers, dns, node) {
  527. if (ip->no_dns == enabled)
  528. continue;
  529. buf = blobmsg_alloc_string_buffer(&b, NULL, buflen);
  530. inet_ntop(dns->af, &dns->addr, buf, buflen);
  531. blobmsg_add_string_buffer(&b);
  532. }
  533. }
  534. static void
  535. interface_ip_dump_dns_search_list(struct interface_ip_settings *ip, bool enabled)
  536. {
  537. struct dns_search_domain *dns;
  538. vlist_simple_for_each_element(&ip->dns_search, dns, node) {
  539. if (ip->no_dns == enabled)
  540. continue;
  541. blobmsg_add_string(&b, NULL, dns->name);
  542. }
  543. }
  544. static void
  545. netifd_dump_status(struct interface *iface)
  546. {
  547. struct interface_data *data;
  548. struct device *dev;
  549. void *a, *inactive;
  550. blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
  551. blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
  552. blobmsg_add_u8(&b, "available", iface->available);
  553. blobmsg_add_u8(&b, "autostart", iface->autostart);
  554. blobmsg_add_u8(&b, "dynamic", iface->dynamic);
  555. if (iface->state == IFS_UP) {
  556. time_t cur = system_get_rtime();
  557. blobmsg_add_u32(&b, "uptime", cur - iface->start_time);
  558. if (iface->l3_dev.dev)
  559. blobmsg_add_string(&b, "l3_device", iface->l3_dev.dev->ifname);
  560. }
  561. if (iface->proto_handler)
  562. blobmsg_add_string(&b, "proto", iface->proto_handler->name);
  563. dev = iface->main_dev.dev;
  564. if (dev && !dev->hidden && iface->proto_handler &&
  565. !(iface->proto_handler->flags & PROTO_FLAG_NODEV))
  566. blobmsg_add_string(&b, "device", dev->ifname);
  567. if (iface->state == IFS_UP) {
  568. if (iface->updated) {
  569. a = blobmsg_open_array(&b, "updated");
  570. if (iface->updated & IUF_ADDRESS)
  571. blobmsg_add_string(&b, NULL, "addresses");
  572. if (iface->updated & IUF_ROUTE)
  573. blobmsg_add_string(&b, NULL, "routes");
  574. if (iface->updated & IUF_PREFIX)
  575. blobmsg_add_string(&b, NULL, "prefixes");
  576. if (iface->updated & IUF_DATA)
  577. blobmsg_add_string(&b, NULL, "data");
  578. blobmsg_close_array(&b, a);
  579. }
  580. if (iface->ip4table)
  581. blobmsg_add_u32(&b, "ip4table", iface->ip4table);
  582. if (iface->ip6table)
  583. blobmsg_add_u32(&b, "ip6table", iface->ip6table);
  584. blobmsg_add_u32(&b, "metric", iface->metric);
  585. blobmsg_add_u32(&b, "dns_metric", iface->dns_metric);
  586. blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation);
  587. if (iface->assignment_weight)
  588. blobmsg_add_u32(&b, "ip6weight", iface->assignment_weight);
  589. a = blobmsg_open_array(&b, "ipv4-address");
  590. interface_ip_dump_address_list(&iface->config_ip, false, true);
  591. interface_ip_dump_address_list(&iface->proto_ip, false, true);
  592. blobmsg_close_array(&b, a);
  593. a = blobmsg_open_array(&b, "ipv6-address");
  594. interface_ip_dump_address_list(&iface->config_ip, true, true);
  595. interface_ip_dump_address_list(&iface->proto_ip, true, true);
  596. blobmsg_close_array(&b, a);
  597. a = blobmsg_open_array(&b, "ipv6-prefix");
  598. interface_ip_dump_prefix_list(&iface->config_ip);
  599. interface_ip_dump_prefix_list(&iface->proto_ip);
  600. blobmsg_close_array(&b, a);
  601. a = blobmsg_open_array(&b, "ipv6-prefix-assignment");
  602. interface_ip_dump_prefix_assignment_list(iface);
  603. blobmsg_close_array(&b, a);
  604. a = blobmsg_open_array(&b, "route");
  605. interface_ip_dump_route_list(&iface->config_ip, true);
  606. interface_ip_dump_route_list(&iface->proto_ip, true);
  607. blobmsg_close_array(&b, a);
  608. a = blobmsg_open_array(&b, "dns-server");
  609. interface_ip_dump_dns_server_list(&iface->config_ip, true);
  610. interface_ip_dump_dns_server_list(&iface->proto_ip, true);
  611. blobmsg_close_array(&b, a);
  612. a = blobmsg_open_array(&b, "dns-search");
  613. interface_ip_dump_dns_search_list(&iface->config_ip, true);
  614. interface_ip_dump_dns_search_list(&iface->proto_ip, true);
  615. blobmsg_close_array(&b, a);
  616. a = blobmsg_open_array(&b, "neighbors");
  617. interface_ip_dump_neighbor_list(&iface->config_ip, true);
  618. interface_ip_dump_neighbor_list(&iface->proto_ip, true);
  619. blobmsg_close_array(&b, a);
  620. inactive = blobmsg_open_table(&b, "inactive");
  621. a = blobmsg_open_array(&b, "ipv4-address");
  622. interface_ip_dump_address_list(&iface->config_ip, false, false);
  623. interface_ip_dump_address_list(&iface->proto_ip, false, false);
  624. blobmsg_close_array(&b, a);
  625. a = blobmsg_open_array(&b, "ipv6-address");
  626. interface_ip_dump_address_list(&iface->config_ip, true, false);
  627. interface_ip_dump_address_list(&iface->proto_ip, true, false);
  628. blobmsg_close_array(&b, a);
  629. a = blobmsg_open_array(&b, "route");
  630. interface_ip_dump_route_list(&iface->config_ip, false);
  631. interface_ip_dump_route_list(&iface->proto_ip, false);
  632. blobmsg_close_array(&b, a);
  633. a = blobmsg_open_array(&b, "dns-server");
  634. interface_ip_dump_dns_server_list(&iface->config_ip, false);
  635. interface_ip_dump_dns_server_list(&iface->proto_ip, false);
  636. blobmsg_close_array(&b, a);
  637. a = blobmsg_open_array(&b, "dns-search");
  638. interface_ip_dump_dns_search_list(&iface->config_ip, false);
  639. interface_ip_dump_dns_search_list(&iface->proto_ip, false);
  640. blobmsg_close_array(&b, a);
  641. a = blobmsg_open_array(&b, "neighbors");
  642. interface_ip_dump_neighbor_list(&iface->config_ip, false);
  643. interface_ip_dump_neighbor_list(&iface->proto_ip, false);
  644. blobmsg_close_array(&b, a);
  645. blobmsg_close_table(&b, inactive);
  646. }
  647. a = blobmsg_open_table(&b, "data");
  648. avl_for_each_element(&iface->data, data, node)
  649. blobmsg_add_blob(&b, data->data);
  650. blobmsg_close_table(&b, a);
  651. if (!list_empty(&iface->errors))
  652. netifd_add_interface_errors(&b, iface);
  653. }
  654. static int
  655. netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj,
  656. struct ubus_request_data *req, const char *method,
  657. struct blob_attr *msg)
  658. {
  659. struct interface *iface = container_of(obj, struct interface, ubus);
  660. blob_buf_init(&b, 0);
  661. netifd_dump_status(iface);
  662. ubus_send_reply(ctx, req, b.head);
  663. return 0;
  664. }
  665. static int
  666. netifd_handle_dump(struct ubus_context *ctx, struct ubus_object *obj,
  667. struct ubus_request_data *req, const char *method,
  668. struct blob_attr *msg)
  669. {
  670. blob_buf_init(&b, 0);
  671. void *a = blobmsg_open_array(&b, "interface");
  672. struct interface *iface;
  673. vlist_for_each_element(&interfaces, iface, node) {
  674. void *i = blobmsg_open_table(&b, NULL);
  675. blobmsg_add_string(&b, "interface", iface->name);
  676. netifd_dump_status(iface);
  677. blobmsg_close_table(&b, i);
  678. }
  679. blobmsg_close_array(&b, a);
  680. ubus_send_reply(ctx, req, b.head);
  681. return 0;
  682. }
  683. enum {
  684. DEV_LINK_NAME,
  685. DEV_LINK_EXT,
  686. __DEV_LINK_MAX,
  687. };
  688. static const struct blobmsg_policy dev_link_policy[__DEV_LINK_MAX] = {
  689. [DEV_LINK_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
  690. [DEV_LINK_EXT] = { .name = "link-ext", .type = BLOBMSG_TYPE_BOOL },
  691. };
  692. static int
  693. netifd_iface_handle_device(struct ubus_context *ctx, struct ubus_object *obj,
  694. struct ubus_request_data *req, const char *method,
  695. struct blob_attr *msg)
  696. {
  697. struct blob_attr *tb[__DEV_LINK_MAX];
  698. struct blob_attr *cur;
  699. struct interface *iface;
  700. bool add = !strncmp(method, "add", 3);
  701. bool link_ext = true;
  702. iface = container_of(obj, struct interface, ubus);
  703. blobmsg_parse(dev_link_policy, __DEV_LINK_MAX, tb, blob_data(msg), blob_len(msg));
  704. if (!tb[DEV_LINK_NAME])
  705. return UBUS_STATUS_INVALID_ARGUMENT;
  706. cur = tb[DEV_LINK_EXT];
  707. if (cur)
  708. link_ext = blobmsg_get_bool(cur);
  709. return interface_handle_link(iface, blobmsg_data(tb[DEV_LINK_NAME]), add, link_ext);
  710. }
  711. static int
  712. netifd_iface_notify_proto(struct ubus_context *ctx, struct ubus_object *obj,
  713. struct ubus_request_data *req, const char *method,
  714. struct blob_attr *msg)
  715. {
  716. struct interface *iface;
  717. iface = container_of(obj, struct interface, ubus);
  718. if (!iface->proto || !iface->proto->notify)
  719. return UBUS_STATUS_NOT_SUPPORTED;
  720. return iface->proto->notify(iface->proto, msg);
  721. }
  722. static void
  723. netifd_iface_do_remove(struct uloop_timeout *timeout)
  724. {
  725. struct interface *iface;
  726. iface = container_of(timeout, struct interface, remove_timer);
  727. vlist_delete(&interfaces, &iface->node);
  728. }
  729. static int
  730. netifd_iface_remove(struct ubus_context *ctx, struct ubus_object *obj,
  731. struct ubus_request_data *req, const char *method,
  732. struct blob_attr *msg)
  733. {
  734. struct interface *iface;
  735. iface = container_of(obj, struct interface, ubus);
  736. if (iface->remove_timer.cb)
  737. return UBUS_STATUS_INVALID_ARGUMENT;
  738. iface->remove_timer.cb = netifd_iface_do_remove;
  739. uloop_timeout_set(&iface->remove_timer, 100);
  740. return 0;
  741. }
  742. static int
  743. netifd_handle_iface_prepare(struct ubus_context *ctx, struct ubus_object *obj,
  744. struct ubus_request_data *req, const char *method,
  745. struct blob_attr *msg)
  746. {
  747. struct interface *iface;
  748. struct device *dev;
  749. const struct device_hotplug_ops *ops;
  750. iface = container_of(obj, struct interface, ubus);
  751. dev = iface->main_dev.dev;
  752. if (!dev)
  753. return 0;
  754. ops = dev->hotplug_ops;
  755. if (!ops)
  756. return 0;
  757. return ops->prepare(dev);
  758. }
  759. static int
  760. netifd_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj,
  761. struct ubus_request_data *req, const char *method,
  762. struct blob_attr *msg)
  763. {
  764. struct interface *iface;
  765. iface = container_of(obj, struct interface, ubus);
  766. return interface_parse_data(iface, msg);
  767. }
  768. static struct ubus_method iface_object_methods[] = {
  769. { .name = "up", .handler = netifd_handle_up },
  770. { .name = "down", .handler = netifd_handle_down },
  771. { .name = "renew", .handler = netifd_handle_renew },
  772. { .name = "status", .handler = netifd_handle_status },
  773. { .name = "prepare", .handler = netifd_handle_iface_prepare },
  774. { .name = "dump", .handler = netifd_handle_dump },
  775. UBUS_METHOD("add_device", netifd_iface_handle_device, dev_link_policy ),
  776. UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_link_policy ),
  777. { .name = "notify_proto", .handler = netifd_iface_notify_proto },
  778. { .name = "remove", .handler = netifd_iface_remove },
  779. { .name = "set_data", .handler = netifd_handle_set_data },
  780. };
  781. static struct ubus_object_type iface_object_type =
  782. UBUS_OBJECT_TYPE("netifd_iface", iface_object_methods);
  783. static struct ubus_object iface_object = {
  784. .name = "network.interface",
  785. .type = &iface_object_type,
  786. .n_methods = ARRAY_SIZE(iface_object_methods),
  787. };
  788. static void netifd_add_object(struct ubus_object *obj)
  789. {
  790. int ret = ubus_add_object(ubus_ctx, obj);
  791. if (ret != 0)
  792. fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret));
  793. }
  794. static const struct blobmsg_policy iface_policy = {
  795. .name = "interface",
  796. .type = BLOBMSG_TYPE_STRING,
  797. };
  798. static int
  799. netifd_handle_iface(struct ubus_context *ctx, struct ubus_object *obj,
  800. struct ubus_request_data *req, const char *method,
  801. struct blob_attr *msg)
  802. {
  803. struct interface *iface;
  804. struct blob_attr *tb;
  805. int i;
  806. blobmsg_parse(&iface_policy, 1, &tb, blob_data(msg), blob_len(msg));
  807. if (!tb)
  808. return UBUS_STATUS_INVALID_ARGUMENT;
  809. iface = vlist_find(&interfaces, blobmsg_data(tb), iface, node);
  810. if (!iface)
  811. return UBUS_STATUS_NOT_FOUND;
  812. for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
  813. ubus_handler_t cb;
  814. if (strcmp(method, iface_object_methods[i].name) != 0)
  815. continue;
  816. cb = iface_object_methods[i].handler;
  817. return cb(ctx, &iface->ubus, req, method, msg);
  818. }
  819. return UBUS_STATUS_INVALID_ARGUMENT;
  820. }
  821. static void netifd_add_iface_object(void)
  822. {
  823. struct ubus_method *methods;
  824. int i;
  825. methods = calloc(1, sizeof(iface_object_methods));
  826. if (!methods)
  827. return;
  828. memcpy(methods, iface_object_methods, sizeof(iface_object_methods));
  829. iface_object.methods = methods;
  830. for (i = 0; i < ARRAY_SIZE(iface_object_methods); i++) {
  831. if (methods[i].handler == netifd_handle_dump)
  832. continue;
  833. methods[i].handler = netifd_handle_iface;
  834. methods[i].policy = &iface_policy;
  835. methods[i].n_policy = 1;
  836. }
  837. netifd_add_object(&iface_object);
  838. }
  839. static struct wireless_device *
  840. get_wdev(struct blob_attr *msg, int *ret)
  841. {
  842. struct blobmsg_policy wdev_policy = {
  843. .name = "device",
  844. .type = BLOBMSG_TYPE_STRING,
  845. };
  846. struct blob_attr *dev_attr;
  847. struct wireless_device *wdev = NULL;
  848. blobmsg_parse(&wdev_policy, 1, &dev_attr, blob_data(msg), blob_len(msg));
  849. if (!dev_attr) {
  850. *ret = UBUS_STATUS_INVALID_ARGUMENT;
  851. return NULL;
  852. }
  853. wdev = vlist_find(&wireless_devices, blobmsg_data(dev_attr), wdev, node);
  854. if (!wdev) {
  855. *ret = UBUS_STATUS_NOT_FOUND;
  856. return NULL;
  857. }
  858. *ret = 0;
  859. return wdev;
  860. }
  861. static int
  862. netifd_handle_wdev_reconf(struct ubus_context *ctx, struct ubus_object *obj,
  863. struct ubus_request_data *req, const char *method,
  864. struct blob_attr *msg)
  865. {
  866. struct wireless_device *wdev;
  867. int ret;
  868. wdev = get_wdev(msg, &ret);
  869. if (ret == UBUS_STATUS_NOT_FOUND)
  870. return ret;
  871. if (wdev) {
  872. wireless_device_reconf(wdev);
  873. } else {
  874. vlist_for_each_element(&wireless_devices, wdev, node)
  875. wireless_device_reconf(wdev);
  876. }
  877. return 0;
  878. }
  879. static int
  880. netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj,
  881. struct ubus_request_data *req, const char *method,
  882. struct blob_attr *msg)
  883. {
  884. struct wireless_device *wdev;
  885. int ret;
  886. wdev = get_wdev(msg, &ret);
  887. if (ret == UBUS_STATUS_NOT_FOUND)
  888. return ret;
  889. if (wdev) {
  890. wireless_device_set_up(wdev);
  891. } else {
  892. vlist_for_each_element(&wireless_devices, wdev, node)
  893. wireless_device_set_up(wdev);
  894. }
  895. return 0;
  896. }
  897. static int
  898. netifd_handle_wdev_down(struct ubus_context *ctx, struct ubus_object *obj,
  899. struct ubus_request_data *req, const char *method,
  900. struct blob_attr *msg)
  901. {
  902. struct wireless_device *wdev;
  903. int ret;
  904. wdev = get_wdev(msg, &ret);
  905. if (ret == UBUS_STATUS_NOT_FOUND)
  906. return ret;
  907. if (wdev) {
  908. wireless_device_set_down(wdev);
  909. } else {
  910. vlist_for_each_element(&wireless_devices, wdev, node)
  911. wireless_device_set_down(wdev);
  912. }
  913. return 0;
  914. }
  915. static int
  916. netifd_handle_wdev_status(struct ubus_context *ctx, struct ubus_object *obj,
  917. struct ubus_request_data *req, const char *method,
  918. struct blob_attr *msg)
  919. {
  920. struct wireless_device *wdev;
  921. int ret;
  922. wdev = get_wdev(msg, &ret);
  923. if (ret == UBUS_STATUS_NOT_FOUND)
  924. return ret;
  925. blob_buf_init(&b, 0);
  926. if (wdev) {
  927. wireless_device_status(wdev, &b);
  928. } else {
  929. vlist_for_each_element(&wireless_devices, wdev, node)
  930. wireless_device_status(wdev, &b);
  931. }
  932. ubus_send_reply(ctx, req, b.head);
  933. return 0;
  934. }
  935. static int
  936. netifd_handle_wdev_get_validate(struct ubus_context *ctx, struct ubus_object *obj,
  937. struct ubus_request_data *req, const char *method,
  938. struct blob_attr *msg)
  939. {
  940. struct wireless_device *wdev;
  941. int ret;
  942. wdev = get_wdev(msg, &ret);
  943. if (ret == UBUS_STATUS_NOT_FOUND)
  944. return ret;
  945. blob_buf_init(&b, 0);
  946. if (wdev) {
  947. wireless_device_get_validate(wdev, &b);
  948. } else {
  949. vlist_for_each_element(&wireless_devices, wdev, node)
  950. wireless_device_get_validate(wdev, &b);
  951. }
  952. ubus_send_reply(ctx, req, b.head);
  953. return 0;
  954. }
  955. static int
  956. netifd_handle_wdev_notify(struct ubus_context *ctx, struct ubus_object *obj,
  957. struct ubus_request_data *req, const char *method,
  958. struct blob_attr *msg)
  959. {
  960. struct wireless_device *wdev;
  961. int ret;
  962. wdev = get_wdev(msg, &ret);
  963. if (!wdev)
  964. return ret;
  965. return wireless_device_notify(wdev, msg, req);
  966. }
  967. static struct ubus_method wireless_object_methods[] = {
  968. { .name = "up", .handler = netifd_handle_wdev_up },
  969. { .name = "down", .handler = netifd_handle_wdev_down },
  970. { .name = "reconf", .handler = netifd_handle_wdev_reconf },
  971. { .name = "status", .handler = netifd_handle_wdev_status },
  972. { .name = "notify", .handler = netifd_handle_wdev_notify },
  973. { .name = "get_validate", .handler = netifd_handle_wdev_get_validate },
  974. };
  975. static struct ubus_object_type wireless_object_type =
  976. UBUS_OBJECT_TYPE("netifd_iface", wireless_object_methods);
  977. static struct ubus_object wireless_object = {
  978. .name = "network.wireless",
  979. .type = &wireless_object_type,
  980. .methods = wireless_object_methods,
  981. .n_methods = ARRAY_SIZE(wireless_object_methods),
  982. };
  983. int
  984. netifd_ubus_init(const char *path)
  985. {
  986. uloop_init();
  987. ubus_path = path;
  988. ubus_ctx = ubus_connect(path);
  989. if (!ubus_ctx)
  990. return -EIO;
  991. DPRINTF("connected as %08x\n", ubus_ctx->local_id);
  992. ubus_ctx->connection_lost = netifd_ubus_connection_lost;
  993. netifd_ubus_add_fd();
  994. netifd_add_object(&main_object);
  995. netifd_add_object(&dev_object);
  996. netifd_add_object(&wireless_object);
  997. netifd_add_iface_object();
  998. return 0;
  999. }
  1000. void
  1001. netifd_ubus_done(void)
  1002. {
  1003. ubus_free(ubus_ctx);
  1004. }
  1005. void
  1006. netifd_ubus_interface_event(struct interface *iface, bool up)
  1007. {
  1008. blob_buf_init(&b, 0);
  1009. blobmsg_add_string(&b, "action", up ? "ifup" : "ifdown");
  1010. blobmsg_add_string(&b, "interface", iface->name);
  1011. ubus_send_event(ubus_ctx, "network.interface", b.head);
  1012. }
  1013. void
  1014. netifd_ubus_interface_notify(struct interface *iface, bool up)
  1015. {
  1016. const char *event = (up) ? "interface.update" : "interface.down";
  1017. blob_buf_init(&b, 0);
  1018. blobmsg_add_string(&b, "interface", iface->name);
  1019. netifd_dump_status(iface);
  1020. ubus_notify(ubus_ctx, &iface_object, event, b.head, -1);
  1021. ubus_notify(ubus_ctx, &iface->ubus, event, b.head, -1);
  1022. }
  1023. void
  1024. netifd_ubus_add_interface(struct interface *iface)
  1025. {
  1026. struct ubus_object *obj = &iface->ubus;
  1027. char *name = NULL;
  1028. if (asprintf(&name, "%s.interface.%s", main_object.name, iface->name) == -1)
  1029. return;
  1030. obj->name = name;
  1031. obj->type = &iface_object_type;
  1032. obj->methods = iface_object_methods;
  1033. obj->n_methods = ARRAY_SIZE(iface_object_methods);
  1034. if (ubus_add_object(ubus_ctx, &iface->ubus)) {
  1035. DPRINTF("failed to publish ubus object for interface '%s'\n", iface->name);
  1036. free(name);
  1037. obj->name = NULL;
  1038. }
  1039. }
  1040. void
  1041. netifd_ubus_remove_interface(struct interface *iface)
  1042. {
  1043. if (!iface->ubus.name)
  1044. return;
  1045. ubus_remove_object(ubus_ctx, &iface->ubus);
  1046. free((void *) iface->ubus.name);
  1047. }