luci.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866
  1. /*
  2. * luci - LuCI core functions plugin for rpcd
  3. *
  4. * Copyright (C) 2019 Jo-Philipp Wich <jo@mein.io>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #define _GNU_SOURCE
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdint.h>
  22. #include <stdlib.h>
  23. #include <stdarg.h>
  24. #include <unistd.h>
  25. #include <ctype.h>
  26. #include <dlfcn.h>
  27. #include <time.h>
  28. #include <ifaddrs.h>
  29. #include <net/if.h>
  30. #include <arpa/inet.h>
  31. #include <sys/types.h>
  32. #include <netinet/ether.h>
  33. #include <linux/rtnetlink.h>
  34. #include <linux/if_packet.h>
  35. #include <netlink/msg.h>
  36. #include <netlink/attr.h>
  37. #include <netlink/socket.h>
  38. #include <libubus.h>
  39. #include <libubox/avl.h>
  40. #include <libubox/avl-cmp.h>
  41. #include <libubox/usock.h>
  42. #include <libubox/uloop.h>
  43. #include <uci.h>
  44. #include <iwinfo.h>
  45. #include <rpcd/plugin.h>
  46. static struct blob_buf blob;
  47. struct reply_context {
  48. struct ubus_context *context;
  49. struct ubus_request_data request;
  50. struct uloop_timeout timeout;
  51. struct blob_buf blob;
  52. struct avl_tree avl;
  53. int pending;
  54. };
  55. struct invoke_context {
  56. struct ubus_request request;
  57. struct uloop_timeout timeout;
  58. struct ubus_context *context;
  59. void (*cb)(struct ubus_request *, int, struct blob_attr *);
  60. void *priv;
  61. };
  62. static const char **iw_modenames;
  63. static struct iwinfo_ops *(*iw_backend)(const char *);
  64. static void (*iw_close)(void);
  65. static void
  66. invoke_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
  67. {
  68. struct invoke_context *ictx =
  69. container_of(req, struct invoke_context, request);
  70. if (ictx->cb != NULL)
  71. ictx->cb(req, type, msg);
  72. ictx->cb = NULL;
  73. }
  74. static void
  75. invoke_done_cb(struct ubus_request *req, int ret)
  76. {
  77. struct invoke_context *ictx =
  78. container_of(req, struct invoke_context, request);
  79. if (ictx->cb != NULL)
  80. ictx->cb(req, -1, NULL);
  81. uloop_timeout_cancel(&ictx->timeout);
  82. free(ictx);
  83. }
  84. static void
  85. invoke_timeout_cb(struct uloop_timeout *timeout)
  86. {
  87. struct invoke_context *ictx =
  88. container_of(timeout, struct invoke_context, timeout);
  89. if (ictx->cb != NULL)
  90. ictx->cb(&ictx->request, -1, NULL);
  91. ubus_abort_request(ictx->context, &ictx->request);
  92. free(ictx);
  93. }
  94. static struct reply_context *
  95. defer_request(struct ubus_context *ctx, struct ubus_request_data *req)
  96. {
  97. struct reply_context *rctx;
  98. rctx = calloc(1, sizeof(*rctx));
  99. if (!rctx)
  100. return NULL;
  101. rctx->context = ctx;
  102. blob_buf_init(&rctx->blob, 0);
  103. ubus_defer_request(ctx, req, &rctx->request);
  104. return rctx;
  105. }
  106. static int
  107. finish_request(struct reply_context *rctx, int status)
  108. {
  109. if (status == UBUS_STATUS_OK)
  110. ubus_send_reply(rctx->context, &rctx->request, rctx->blob.head);
  111. ubus_complete_deferred_request(rctx->context, &rctx->request, status);
  112. blob_buf_free(&rctx->blob);
  113. free(rctx);
  114. return status;
  115. }
  116. static bool
  117. invoke_ubus(struct ubus_context *ctx, const char *object, const char *method,
  118. struct blob_buf *req,
  119. void (*cb)(struct ubus_request *, int, struct blob_attr *),
  120. void *priv)
  121. {
  122. struct invoke_context *ictx;
  123. struct blob_buf empty = {};
  124. uint32_t id;
  125. bool rv;
  126. if (ubus_lookup_id(ctx, object, &id))
  127. return false;
  128. if (req == NULL) {
  129. blob_buf_init(&empty, 0);
  130. req = &empty;
  131. }
  132. ictx = calloc(1, sizeof(*ictx));
  133. if (ictx == NULL)
  134. return false;
  135. ictx->context = ctx;
  136. rv = !ubus_invoke_async(ctx, id, method, req->head, &ictx->request);
  137. if (rv) {
  138. ictx->cb = cb;
  139. ictx->request.priv = priv;
  140. ictx->request.data_cb = invoke_data_cb;
  141. ictx->request.complete_cb = invoke_done_cb;
  142. ubus_complete_request_async(ctx, &ictx->request);
  143. ictx->timeout.cb = invoke_timeout_cb;
  144. uloop_timeout_set(&ictx->timeout, 2000);
  145. }
  146. else {
  147. if (cb != NULL)
  148. cb(&ictx->request, -1, NULL);
  149. free(ictx);
  150. }
  151. if (req == &empty)
  152. blob_buf_free(req);
  153. return rv;
  154. }
  155. static char *
  156. readstr(const char *fmt, ...)
  157. {
  158. static char data[128];
  159. char path[128];
  160. va_list ap;
  161. size_t n;
  162. FILE *f;
  163. va_start(ap, fmt);
  164. vsnprintf(path, sizeof(path), fmt, ap);
  165. va_end(ap);
  166. data[0] = 0;
  167. f = fopen(path, "r");
  168. if (f != NULL) {
  169. n = fread(data, 1, sizeof(data) - 1, f);
  170. data[n] = 0;
  171. while (n > 0 && isspace(data[n-1]))
  172. data[--n] = 0;
  173. fclose(f);
  174. }
  175. return data;
  176. }
  177. static char *
  178. ea2str(struct ether_addr *ea)
  179. {
  180. static char mac[18];
  181. if (!ea)
  182. return NULL;
  183. snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X",
  184. ea->ether_addr_octet[0], ea->ether_addr_octet[1],
  185. ea->ether_addr_octet[2], ea->ether_addr_octet[3],
  186. ea->ether_addr_octet[4], ea->ether_addr_octet[5]);
  187. return mac;
  188. }
  189. static char *
  190. sa2str(struct sockaddr *sa)
  191. {
  192. static char buf[INET6_ADDRSTRLEN];
  193. union {
  194. struct sockaddr_in6 *in6;
  195. struct sockaddr_in *in;
  196. struct sockaddr_ll *ll;
  197. struct sockaddr *sa;
  198. } s;
  199. s.sa = sa;
  200. if (s.sa->sa_family == AF_INET)
  201. inet_ntop(sa->sa_family, &s.in->sin_addr, buf, sizeof(buf));
  202. else if (s.sa->sa_family == AF_INET6)
  203. inet_ntop(sa->sa_family, &s.in6->sin6_addr, buf, sizeof(buf));
  204. else if (s.sa->sa_family == AF_PACKET)
  205. strcpy(buf, ea2str((struct ether_addr *)s.ll->sll_addr));
  206. else
  207. buf[0] = 0;
  208. return buf;
  209. }
  210. static struct ether_addr *
  211. duid2ea(const char *duid)
  212. {
  213. static struct ether_addr ea;
  214. const char *p = NULL;
  215. size_t len;
  216. if (!duid)
  217. return NULL;
  218. for (len = 0; duid[len]; len++)
  219. if (!isxdigit(duid[len]))
  220. return NULL;
  221. #define hex(x) \
  222. (((x) <= '9') ? ((x) - '0') : \
  223. (((x) <= 'F') ? ((x) - 'A' + 10) : \
  224. ((x) - 'a' + 10)))
  225. switch (len) {
  226. case 28:
  227. if (!strncmp(duid, "00010001", 8))
  228. p = duid + 16;
  229. break;
  230. case 20:
  231. if (!strncmp(duid, "00030001", 8))
  232. p = duid + 8;
  233. break;
  234. case 12:
  235. p = duid;
  236. break;
  237. }
  238. if (!p)
  239. return NULL;
  240. ea.ether_addr_octet[0] = hex(p[0]) * 16 + hex(p[1]);
  241. ea.ether_addr_octet[1] = hex(p[2]) * 16 + hex(p[3]);
  242. ea.ether_addr_octet[2] = hex(p[4]) * 16 + hex(p[5]);
  243. ea.ether_addr_octet[3] = hex(p[6]) * 16 + hex(p[7]);
  244. ea.ether_addr_octet[4] = hex(p[8]) * 16 + hex(p[9]);
  245. ea.ether_addr_octet[5] = hex(p[10]) * 16 + hex(p[11]);
  246. return &ea;
  247. }
  248. static struct {
  249. time_t now;
  250. size_t num, off;
  251. struct {
  252. FILE *fh;
  253. bool odhcpd;
  254. } *files;
  255. } lease_state = { };
  256. struct lease_entry {
  257. int af, n_addr;
  258. char buf[512];
  259. int32_t expire;
  260. struct ether_addr mac;
  261. char *hostname;
  262. char *duid;
  263. union {
  264. struct in_addr in;
  265. struct in6_addr in6;
  266. } addr[10];
  267. };
  268. static bool
  269. add_leasefile(const char *path, bool is_odhcpd)
  270. {
  271. void *ptr;
  272. FILE *fh;
  273. fh = fopen(path, "r");
  274. if (!fh)
  275. return false;
  276. ptr = realloc(lease_state.files, sizeof(*lease_state.files) * (lease_state.num + 1));
  277. if (!ptr) {
  278. fclose(fh);
  279. return false;
  280. }
  281. lease_state.files = ptr;
  282. lease_state.files[lease_state.num].fh = fh;
  283. lease_state.files[lease_state.num].odhcpd = is_odhcpd;
  284. lease_state.num++;
  285. return true;
  286. }
  287. static bool
  288. find_leasefiles(struct uci_context *uci, bool is_odhcpd)
  289. {
  290. struct uci_ptr ptr = { .package = "dhcp" };
  291. struct uci_package *pkg = NULL;
  292. struct uci_section *s;
  293. struct uci_element *e;
  294. bool found = false;
  295. pkg = uci_lookup_package(uci, ptr.package);
  296. if (!pkg) {
  297. uci_load(uci, ptr.package, &pkg);
  298. if (!pkg)
  299. return NULL;
  300. }
  301. uci_foreach_element(&pkg->sections, e) {
  302. s = uci_to_section(e);
  303. if (strcmp(s->type, is_odhcpd ? "odhcpd" : "dnsmasq"))
  304. continue;
  305. ptr.flags = 0;
  306. ptr.section = s->e.name;
  307. ptr.s = NULL;
  308. ptr.option = "leasefile";
  309. ptr.o = NULL;
  310. if (uci_lookup_ptr(uci, &ptr, NULL, true) || ptr.o == NULL)
  311. continue;
  312. if (ptr.o->type != UCI_TYPE_STRING)
  313. continue;
  314. if (add_leasefile(ptr.o->v.string, is_odhcpd))
  315. found = true;
  316. }
  317. return found;
  318. }
  319. static void
  320. lease_close(void)
  321. {
  322. while (lease_state.num > 0)
  323. fclose(lease_state.files[--lease_state.num].fh);
  324. free(lease_state.files);
  325. lease_state.files = NULL;
  326. lease_state.num = 0;
  327. lease_state.off = 0;
  328. }
  329. static void
  330. lease_open(void)
  331. {
  332. struct uci_context *uci;
  333. lease_close();
  334. uci = uci_alloc_context();
  335. if (!uci)
  336. return;
  337. lease_state.now = time(NULL);
  338. if (!find_leasefiles(uci, false))
  339. add_leasefile("/tmp/dhcp.leases", false);
  340. if (!find_leasefiles(uci, true))
  341. add_leasefile("/tmp/hosts/odhcpd", true);
  342. uci_free_context(uci);
  343. }
  344. static struct lease_entry *
  345. lease_next(void)
  346. {
  347. static struct lease_entry e;
  348. struct ether_addr *ea;
  349. char *p;
  350. int n;
  351. memset(&e, 0, sizeof(e));
  352. while (lease_state.off < lease_state.num) {
  353. while (fgets(e.buf, sizeof(e.buf), lease_state.files[lease_state.off].fh)) {
  354. if (lease_state.files[lease_state.off].odhcpd) {
  355. strtok(e.buf, " \t\n"); /* # */
  356. strtok(NULL, " \t\n"); /* iface */
  357. e.duid = strtok(NULL, " \t\n"); /* duid */
  358. if (!e.duid)
  359. continue;
  360. p = strtok(NULL, " \t\n"); /* iaid */
  361. if (p)
  362. e.af = strcmp(p, "ipv4") ? AF_INET6 : AF_INET;
  363. else
  364. continue;
  365. e.hostname = strtok(NULL, " \t\n"); /* name */
  366. if (!e.hostname)
  367. continue;
  368. p = strtok(NULL, " \t\n"); /* ts */
  369. if (!p)
  370. continue;
  371. n = strtol(p, NULL, 10);
  372. if (n > lease_state.now)
  373. e.expire = n - lease_state.now;
  374. else if (n >= 0)
  375. e.expire = 0;
  376. else
  377. e.expire = -1;
  378. strtok(NULL, " \t\n"); /* id */
  379. strtok(NULL, " \t\n"); /* length */
  380. for (e.n_addr = 0, p = strtok(NULL, "/ \t\n");
  381. e.n_addr < ARRAY_SIZE(e.addr) && p != NULL;
  382. p = strtok(NULL, "/ \t\n")) {
  383. if (inet_pton(e.af, p, &e.addr[e.n_addr].in6))
  384. e.n_addr++;
  385. }
  386. ea = duid2ea(e.duid);
  387. if (ea)
  388. e.mac = *ea;
  389. if (!strcmp(e.hostname, "-"))
  390. e.hostname = NULL;
  391. if (!strcmp(e.duid, "-"))
  392. e.duid = NULL;
  393. }
  394. else {
  395. p = strtok(e.buf, " \t\n");
  396. if (!p)
  397. continue;
  398. n = strtol(p, NULL, 10);
  399. if (n > lease_state.now)
  400. e.expire = n - lease_state.now;
  401. else if (n > 0)
  402. e.expire = 0;
  403. else
  404. e.expire = -1;
  405. p = strtok(NULL, " \t\n");
  406. if (!p)
  407. continue;
  408. ea = ether_aton(p);
  409. p = strtok(NULL, " \t\n");
  410. if (p && inet_pton(AF_INET6, p, &e.addr[0].in6)) {
  411. e.af = AF_INET6;
  412. e.n_addr = 1;
  413. }
  414. else if (p && inet_pton(AF_INET, p, &e.addr[0].in)) {
  415. e.af = AF_INET;
  416. e.n_addr = 1;
  417. }
  418. else {
  419. continue;
  420. }
  421. if (!ea && e.af != AF_INET6)
  422. continue;
  423. e.hostname = strtok(NULL, " \t\n");
  424. e.duid = strtok(NULL, " \t\n");
  425. if (!e.hostname || !e.duid)
  426. continue;
  427. if (!strcmp(e.hostname, "*"))
  428. e.hostname = NULL;
  429. if (!strcmp(e.duid, "*"))
  430. e.duid = NULL;
  431. if (!ea && e.duid)
  432. ea = duid2ea(e.duid);
  433. if (ea)
  434. e.mac = *ea;
  435. }
  436. return &e;
  437. }
  438. lease_state.off++;
  439. }
  440. return NULL;
  441. }
  442. static void
  443. rpc_luci_parse_network_device_sys(const char *name, struct ifaddrs *ifaddr)
  444. {
  445. char link[64], buf[512], *p;
  446. unsigned int ifa_flags = 0;
  447. struct sockaddr_ll *sll;
  448. struct ifaddrs *ifa;
  449. struct dirent *e;
  450. void *o, *o2, *a;
  451. ssize_t len;
  452. uint64_t v;
  453. int n, af;
  454. DIR *d;
  455. const char *stats[] = {
  456. "rx_bytes", "tx_bytes", "tx_errors", "rx_errors", "tx_packets",
  457. "rx_packets", "multicast", "collisions", "rx_dropped", "tx_dropped"
  458. };
  459. o = blobmsg_open_table(&blob, name);
  460. blobmsg_add_string(&blob, "name", name);
  461. snprintf(buf, sizeof(buf), "/sys/class/net/%s/brif", name);
  462. d = opendir(buf);
  463. if (d) {
  464. blobmsg_add_u8(&blob, "bridge", 1);
  465. a = blobmsg_open_array(&blob, "ports");
  466. while (true) {
  467. e = readdir(d);
  468. if (e == NULL)
  469. break;
  470. if (strcmp(e->d_name, ".") && strcmp(e->d_name, ".."))
  471. blobmsg_add_string(&blob, NULL, e->d_name);
  472. }
  473. blobmsg_close_array(&blob, a);
  474. closedir(d);
  475. p = readstr("/sys/class/net/%s/bridge/bridge_id", name);
  476. blobmsg_add_string(&blob, "id", p);
  477. p = readstr("/sys/class/net/%s/bridge/stp_state", name);
  478. blobmsg_add_u8(&blob, "stp", strcmp(p, "0") ? 1 : 0);
  479. }
  480. snprintf(buf, sizeof(buf), "/sys/class/net/%s/master", name);
  481. len = readlink(buf, link, sizeof(link) - 1);
  482. if (len > 0) {
  483. link[len] = 0;
  484. blobmsg_add_string(&blob, "master", basename(link));
  485. }
  486. p = readstr("/sys/class/net/%s/phy80211/index", name);
  487. blobmsg_add_u8(&blob, "wireless", *p ? 1 : 0);
  488. p = readstr("/sys/class/net/%s/operstate", name);
  489. blobmsg_add_u8(&blob, "up", !strcmp(p, "up") || !strcmp(p, "unknown"));
  490. n = atoi(readstr("/sys/class/net/%s/mtu", name));
  491. if (n > 0)
  492. blobmsg_add_u32(&blob, "mtu", n);
  493. n = atoi(readstr("/sys/class/net/%s/tx_queue_len", name));
  494. if (n > 0)
  495. blobmsg_add_u32(&blob, "qlen", n);
  496. p = readstr("/sys/class/net/%s/master", name);
  497. if (*p)
  498. blobmsg_add_string(&blob, "master", p);
  499. p = strstr(readstr("/sys/class/net/%s/uevent", name), "DEVTYPE=");
  500. if (p) {
  501. for (n = 0, p += strlen("DEVTYPE=");; n++) {
  502. if (p[n] == '\0' || p[n] == '\n') {
  503. p[n] = 0;
  504. blobmsg_add_string(&blob, "devtype", p);
  505. break;
  506. }
  507. }
  508. }
  509. else {
  510. blobmsg_add_string(&blob, "devtype", "ethernet");
  511. }
  512. for (af = AF_INET; af != 0; af = (af == AF_INET) ? AF_INET6 : 0) {
  513. a = blobmsg_open_array(&blob,
  514. (af == AF_INET) ? "ipaddrs" : "ip6addrs");
  515. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  516. if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != af)
  517. continue;
  518. if (strcmp(ifa->ifa_name, name))
  519. continue;
  520. o2 = blobmsg_open_table(&blob, NULL);
  521. blobmsg_add_string(&blob, "address",
  522. sa2str(ifa->ifa_addr));
  523. blobmsg_add_string(&blob, "netmask",
  524. sa2str(ifa->ifa_netmask));
  525. if (ifa->ifa_dstaddr && (ifa->ifa_flags & IFF_POINTOPOINT))
  526. blobmsg_add_string(&blob, "remote",
  527. sa2str(ifa->ifa_dstaddr));
  528. else if (ifa->ifa_broadaddr && (ifa->ifa_flags & IFF_BROADCAST))
  529. blobmsg_add_string(&blob, "broadcast",
  530. sa2str(ifa->ifa_broadaddr));
  531. blobmsg_close_table(&blob, o2);
  532. ifa_flags |= ifa->ifa_flags;
  533. }
  534. blobmsg_close_array(&blob, a);
  535. }
  536. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  537. if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_PACKET)
  538. continue;
  539. if (strcmp(ifa->ifa_name, name))
  540. continue;
  541. sll = (struct sockaddr_ll *)ifa->ifa_addr;
  542. if (sll->sll_hatype == 1)
  543. blobmsg_add_string(&blob, "mac", sa2str(ifa->ifa_addr));
  544. blobmsg_add_u32(&blob, "type", sll->sll_hatype);
  545. blobmsg_add_u32(&blob, "ifindex", sll->sll_ifindex);
  546. ifa_flags |= ifa->ifa_flags;
  547. n = atoi(readstr("/sys/class/net/%s/iflink", name));
  548. if (n != sll->sll_ifindex) {
  549. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  550. if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_PACKET)
  551. continue;
  552. sll = (struct sockaddr_ll *)ifa->ifa_addr;
  553. if (sll->sll_ifindex != n)
  554. continue;
  555. blobmsg_add_string(&blob, "parent", ifa->ifa_name);
  556. break;
  557. }
  558. }
  559. break;
  560. }
  561. o2 = blobmsg_open_table(&blob, "stats");
  562. for (n = 0; n < ARRAY_SIZE(stats); n++) {
  563. v = strtoull(readstr("/sys/class/net/%s/statistics/%s",
  564. name, stats[n]), NULL, 10);
  565. blobmsg_add_u64(&blob, stats[n], v);
  566. }
  567. blobmsg_close_table(&blob, o2);
  568. o2 = blobmsg_open_table(&blob, "flags");
  569. blobmsg_add_u8(&blob, "up", ifa_flags & IFF_UP);
  570. blobmsg_add_u8(&blob, "broadcast", ifa_flags & IFF_BROADCAST);
  571. blobmsg_add_u8(&blob, "promisc", ifa_flags & IFF_PROMISC);
  572. blobmsg_add_u8(&blob, "loopback", ifa_flags & IFF_LOOPBACK);
  573. blobmsg_add_u8(&blob, "noarp", ifa_flags & IFF_NOARP);
  574. blobmsg_add_u8(&blob, "multicast", ifa_flags & IFF_MULTICAST);
  575. blobmsg_add_u8(&blob, "pointtopoint", ifa_flags & IFF_POINTOPOINT);
  576. blobmsg_close_table(&blob, o2);
  577. blobmsg_close_table(&blob, o);
  578. }
  579. static int
  580. rpc_luci_get_network_devices(struct ubus_context *ctx,
  581. struct ubus_object *obj,
  582. struct ubus_request_data *req,
  583. const char *method,
  584. struct blob_attr *msg)
  585. {
  586. struct ifaddrs *ifaddr;
  587. struct dirent *e;
  588. DIR *d;
  589. blob_buf_init(&blob, 0);
  590. d = opendir("/sys/class/net");
  591. if (d != NULL) {
  592. if (getifaddrs(&ifaddr) == 1)
  593. ifaddr = NULL;
  594. while (true) {
  595. e = readdir(d);
  596. if (e == NULL)
  597. break;
  598. if (strcmp(e->d_name, ".") && strcmp(e->d_name, ".."))
  599. rpc_luci_parse_network_device_sys(e->d_name, ifaddr);
  600. }
  601. if (ifaddr != NULL)
  602. freeifaddrs(ifaddr);
  603. closedir(d);
  604. }
  605. ubus_send_reply(ctx, req, blob.head);
  606. return 0;
  607. }
  608. static void
  609. iw_call_str(int (*method)(const char *, char *), const char *dev,
  610. struct blob_buf *blob, const char *field)
  611. {
  612. char buf[IWINFO_BUFSIZE] = {};
  613. if (method(dev, buf) == 0)
  614. blobmsg_add_string(blob, field, buf);
  615. }
  616. static void
  617. iw_call_num(int (*method)(const char *, int *), const char *dev,
  618. struct blob_buf *blob, const char *field)
  619. {
  620. int val = 0;
  621. if (method(dev, &val) == 0)
  622. blobmsg_add_u32(blob, field, val);
  623. }
  624. static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname,
  625. bool phy_only)
  626. {
  627. struct iwinfo_crypto_entry crypto = {};
  628. struct iwinfo_hardware_id ids = {};
  629. const struct iwinfo_ops *iw;
  630. void *iwlib = NULL;
  631. void *o, *o2, *a;
  632. glob_t paths;
  633. int nret, i;
  634. if (!iw_backend || !iw_close || !iw_modenames) {
  635. if (glob("/usr/lib/libiwinfo.so*", 0, NULL, &paths) != 0)
  636. return false;
  637. for (i = 0; i < paths.gl_pathc && !iwlib; i++)
  638. iwlib = dlopen(paths.gl_pathv[i], RTLD_LAZY | RTLD_LOCAL);
  639. globfree(&paths);
  640. if (!iwlib)
  641. return false;
  642. iw_backend = dlsym(iwlib, "iwinfo_backend");
  643. iw_close = dlsym(iwlib, "iwinfo_close");
  644. iw_modenames = dlsym(iwlib, "IWINFO_OPMODE_NAMES");
  645. if (!iw_backend || !iw_close || !iw_modenames)
  646. return false;
  647. }
  648. iw = iw_backend(devname);
  649. if (!iw)
  650. return false;
  651. o = blobmsg_open_table(buf, "iwinfo");
  652. iw_call_num(iw->signal, devname, buf, "signal");
  653. iw_call_num(iw->noise, devname, buf, "noise");
  654. iw_call_num(iw->channel, devname, buf, "channel");
  655. iw_call_str(iw->country, devname, buf, "country");
  656. iw_call_str(iw->phyname, devname, buf, "phy");
  657. iw_call_num(iw->txpower, devname, buf, "txpower");
  658. iw_call_num(iw->txpower_offset, devname, buf, "txpower_offset");
  659. iw_call_num(iw->frequency, devname, buf, "frequency");
  660. iw_call_num(iw->frequency_offset, devname, buf, "frequency_offset");
  661. if (!iw->hwmodelist(devname, &nret)) {
  662. a = blobmsg_open_array(buf, "hwmodes");
  663. if (nret & IWINFO_80211_AC)
  664. blobmsg_add_string(buf, NULL, "ac");
  665. if (nret & IWINFO_80211_A)
  666. blobmsg_add_string(buf, NULL, "a");
  667. if (nret & IWINFO_80211_B)
  668. blobmsg_add_string(buf, NULL, "b");
  669. if (nret & IWINFO_80211_G)
  670. blobmsg_add_string(buf, NULL, "g");
  671. if (nret & IWINFO_80211_N)
  672. blobmsg_add_string(buf, NULL, "n");
  673. blobmsg_close_array(buf, a);
  674. }
  675. if (!iw->htmodelist(devname, &nret)) {
  676. a = blobmsg_open_array(buf, "htmodes");
  677. if (nret & IWINFO_HTMODE_HT20)
  678. blobmsg_add_string(buf, NULL, "HT20");
  679. if (nret & IWINFO_HTMODE_HT40)
  680. blobmsg_add_string(buf, NULL, "HT40");
  681. if (nret & IWINFO_HTMODE_VHT20)
  682. blobmsg_add_string(buf, NULL, "VHT20");
  683. if (nret & IWINFO_HTMODE_VHT40)
  684. blobmsg_add_string(buf, NULL, "VHT40");
  685. if (nret & IWINFO_HTMODE_VHT80)
  686. blobmsg_add_string(buf, NULL, "VHT80");
  687. if (nret & IWINFO_HTMODE_VHT80_80)
  688. blobmsg_add_string(buf, NULL, "VHT80+80");
  689. if (nret & IWINFO_HTMODE_VHT160)
  690. blobmsg_add_string(buf, NULL, "VHT160");
  691. blobmsg_close_array(buf, a);
  692. }
  693. if (!iw->hardware_id(devname, (char *)&ids)) {
  694. o2 = blobmsg_open_table(buf, "hardware");
  695. a = blobmsg_open_array(buf, "id");
  696. blobmsg_add_u32(buf, NULL, ids.vendor_id);
  697. blobmsg_add_u32(buf, NULL, ids.device_id);
  698. blobmsg_add_u32(buf, NULL, ids.subsystem_vendor_id);
  699. blobmsg_add_u32(buf, NULL, ids.subsystem_device_id);
  700. blobmsg_close_array(buf, a);
  701. iw_call_str(iw->hardware_name, devname, buf, "name");
  702. blobmsg_close_table(buf, o2);
  703. }
  704. if (!phy_only) {
  705. iw_call_num(iw->quality, devname, buf, "quality");
  706. iw_call_num(iw->quality_max, devname, buf, "quality_max");
  707. iw_call_num(iw->bitrate, devname, buf, "bitrate");
  708. if (!iw->mode(devname, &nret))
  709. blobmsg_add_string(buf, "mode", iw_modenames[nret]);
  710. iw_call_str(iw->ssid, devname, buf, "ssid");
  711. iw_call_str(iw->bssid, devname, buf, "bssid");
  712. if (!iw->encryption(devname, (char *)&crypto)) {
  713. o2 = blobmsg_open_table(buf, "encryption");
  714. blobmsg_add_u8(buf, "enabled", crypto.enabled);
  715. if (crypto.enabled) {
  716. if (!crypto.wpa_version) {
  717. a = blobmsg_open_array(buf, "wep");
  718. if (crypto.auth_algs & IWINFO_AUTH_OPEN)
  719. blobmsg_add_string(buf, NULL, "open");
  720. if (crypto.auth_algs & IWINFO_AUTH_SHARED)
  721. blobmsg_add_string(buf, NULL, "shared");
  722. blobmsg_close_array(buf, a);
  723. }
  724. else {
  725. a = blobmsg_open_array(buf, "wpa");
  726. for (nret = 1; nret <= 3; nret++)
  727. if (crypto.wpa_version & (1 << (nret - 1)))
  728. blobmsg_add_u32(buf, NULL, nret);
  729. blobmsg_close_array(buf, a);
  730. a = blobmsg_open_array(buf, "authentication");
  731. if (crypto.auth_suites & IWINFO_KMGMT_PSK)
  732. blobmsg_add_string(buf, NULL, "psk");
  733. if (crypto.auth_suites & IWINFO_KMGMT_8021x)
  734. blobmsg_add_string(buf, NULL, "802.1x");
  735. if (crypto.auth_suites & IWINFO_KMGMT_SAE)
  736. blobmsg_add_string(buf, NULL, "sae");
  737. if (crypto.auth_suites & IWINFO_KMGMT_OWE)
  738. blobmsg_add_string(buf, NULL, "owe");
  739. if (!crypto.auth_suites ||
  740. (crypto.auth_suites & IWINFO_KMGMT_NONE))
  741. blobmsg_add_string(buf, NULL, "none");
  742. blobmsg_close_array(buf, a);
  743. }
  744. a = blobmsg_open_array(buf, "ciphers");
  745. nret = crypto.pair_ciphers | crypto.group_ciphers;
  746. if (nret & IWINFO_CIPHER_WEP40)
  747. blobmsg_add_string(buf, NULL, "wep-40");
  748. if (nret & IWINFO_CIPHER_WEP104)
  749. blobmsg_add_string(buf, NULL, "wep-104");
  750. if (nret & IWINFO_CIPHER_TKIP)
  751. blobmsg_add_string(buf, NULL, "tkip");
  752. if (nret & IWINFO_CIPHER_CCMP)
  753. blobmsg_add_string(buf, NULL, "ccmp");
  754. if (nret & IWINFO_CIPHER_WRAP)
  755. blobmsg_add_string(buf, NULL, "wrap");
  756. if (nret & IWINFO_CIPHER_AESOCB)
  757. blobmsg_add_string(buf, NULL, "aes-ocb");
  758. if (nret & IWINFO_CIPHER_CKIP)
  759. blobmsg_add_string(buf, NULL, "ckip");
  760. if (!nret || (nret & IWINFO_CIPHER_NONE))
  761. blobmsg_add_string(buf, NULL, "none");
  762. blobmsg_close_array(buf, a);
  763. }
  764. blobmsg_close_table(buf, o2);
  765. }
  766. }
  767. blobmsg_close_table(buf, o);
  768. iw_close();
  769. return true;
  770. }
  771. static void rpc_luci_get_wireless_devices_cb(struct ubus_request *req,
  772. int type, struct blob_attr *msg)
  773. {
  774. struct blob_attr *wifi, *cur, *iface, *cur2;
  775. struct reply_context *rctx = req->priv;
  776. const char *name, *first_ifname;
  777. int rem, rem2, rem3, rem4;
  778. void *o, *a, *o2;
  779. blob_for_each_attr(wifi, msg, rem) {
  780. if (blobmsg_type(wifi) != BLOBMSG_TYPE_TABLE ||
  781. blobmsg_name(wifi) == NULL)
  782. continue;
  783. o = blobmsg_open_table(&rctx->blob, blobmsg_name(wifi));
  784. rem2 = blobmsg_data_len(wifi);
  785. first_ifname = NULL;
  786. __blob_for_each_attr(cur, blobmsg_data(wifi), rem2) {
  787. name = blobmsg_name(cur);
  788. if (!name || !strcmp(name, "iwinfo")) {
  789. continue;
  790. }
  791. else if (!strcmp(name, "interfaces")) {
  792. if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY)
  793. continue;
  794. a = blobmsg_open_array(&rctx->blob, "interfaces");
  795. rem3 = blobmsg_data_len(cur);
  796. __blob_for_each_attr(iface, blobmsg_data(cur), rem3) {
  797. if (blobmsg_type(iface) != BLOBMSG_TYPE_TABLE)
  798. continue;
  799. o2 = blobmsg_open_table(&rctx->blob, NULL);
  800. rem4 = blobmsg_data_len(iface);
  801. name = NULL;
  802. __blob_for_each_attr(cur2, blobmsg_data(iface), rem4) {
  803. if (!strcmp(blobmsg_name(cur2), "ifname"))
  804. name = blobmsg_get_string(cur2);
  805. else if (!strcmp(blobmsg_name(cur2), "iwinfo"))
  806. continue;
  807. blobmsg_add_blob(&rctx->blob, cur2);
  808. }
  809. if (name)
  810. if (rpc_luci_get_iwinfo(&rctx->blob, name, false))
  811. first_ifname = first_ifname ? first_ifname : name;
  812. blobmsg_close_table(&rctx->blob, o2);
  813. }
  814. blobmsg_close_array(&rctx->blob, a);
  815. }
  816. else {
  817. blobmsg_add_blob(&rctx->blob, cur);
  818. }
  819. }
  820. rpc_luci_get_iwinfo(&rctx->blob,
  821. first_ifname ? first_ifname : blobmsg_name(wifi),
  822. true);
  823. blobmsg_close_table(&rctx->blob, o);
  824. }
  825. finish_request(rctx, UBUS_STATUS_OK);
  826. }
  827. static int
  828. rpc_luci_get_wireless_devices(struct ubus_context *ctx,
  829. struct ubus_object *obj,
  830. struct ubus_request_data *req,
  831. const char *method,
  832. struct blob_attr *msg)
  833. {
  834. struct reply_context *rctx = defer_request(ctx, req);
  835. if (!rctx)
  836. return UBUS_STATUS_UNKNOWN_ERROR;
  837. if (!invoke_ubus(ctx, "network.wireless", "status", NULL,
  838. rpc_luci_get_wireless_devices_cb, rctx))
  839. return finish_request(rctx, UBUS_STATUS_NOT_FOUND);
  840. return UBUS_STATUS_OK;
  841. }
  842. struct host_hint {
  843. struct avl_node avl;
  844. char *hostname;
  845. struct in_addr ip;
  846. struct in6_addr ip6;
  847. };
  848. static int
  849. nl_cb_done(struct nl_msg *msg, void *arg)
  850. {
  851. struct reply_context *rctx = arg;
  852. rctx->pending = 0;
  853. return NL_STOP;
  854. }
  855. static int
  856. nl_cb_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
  857. {
  858. struct reply_context *rctx = arg;
  859. rctx->pending = 0;
  860. return NL_STOP;
  861. }
  862. static struct host_hint *
  863. rpc_luci_get_host_hint(struct reply_context *rctx, struct ether_addr *ea)
  864. {
  865. struct host_hint *hint;
  866. char *p, *mac;
  867. if (!ea)
  868. return NULL;
  869. mac = ea2str(ea);
  870. hint = avl_find_element(&rctx->avl, mac, hint, avl);
  871. if (!hint) {
  872. hint = calloc_a(sizeof(*hint), &p, strlen(mac) + 1);
  873. if (!hint)
  874. return NULL;
  875. hint->avl.key = strcpy(p, mac);
  876. avl_insert(&rctx->avl, &hint->avl);
  877. }
  878. return hint;
  879. }
  880. static int nl_cb_dump_neigh(struct nl_msg *msg, void *arg)
  881. {
  882. struct reply_context *rctx = arg;
  883. struct ether_addr *mac;
  884. struct in6_addr *dst;
  885. struct nlmsghdr *hdr = nlmsg_hdr(msg);
  886. struct ndmsg *nd = NLMSG_DATA(hdr);
  887. struct nlattr *tb[NDA_MAX+1];
  888. struct host_hint *hint;
  889. rctx->pending = !!(hdr->nlmsg_flags & NLM_F_MULTI);
  890. if (hdr->nlmsg_type != RTM_NEWNEIGH ||
  891. (nd->ndm_family != AF_INET && nd->ndm_family != AF_INET6))
  892. return NL_SKIP;
  893. if (!(nd->ndm_state & (0xFF & ~NUD_NOARP)))
  894. return NL_SKIP;
  895. nlmsg_parse(hdr, sizeof(*nd), tb, NDA_MAX, NULL);
  896. mac = tb[NDA_LLADDR] ? RTA_DATA(tb[NDA_LLADDR]) : NULL;
  897. dst = tb[NDA_DST] ? RTA_DATA(tb[NDA_DST]) : NULL;
  898. if (!mac || !dst)
  899. return NL_SKIP;
  900. hint = rpc_luci_get_host_hint(rctx, mac);
  901. if (!hint)
  902. return NL_SKIP;
  903. if (nd->ndm_family == AF_INET)
  904. hint->ip = *(struct in_addr *)dst;
  905. else
  906. hint->ip6 = *(struct in6_addr *)dst;
  907. return NL_SKIP;
  908. }
  909. static void
  910. rpc_luci_get_host_hints_nl(struct reply_context *rctx)
  911. {
  912. struct nl_sock *sock = NULL;
  913. struct nl_msg *msg = NULL;
  914. struct nl_cb *cb = NULL;
  915. struct ndmsg ndm = {};
  916. sock = nl_socket_alloc();
  917. if (!sock)
  918. goto out;
  919. if (nl_connect(sock, NETLINK_ROUTE))
  920. goto out;
  921. cb = nl_cb_alloc(NL_CB_DEFAULT);
  922. if (!cb)
  923. goto out;
  924. msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP);
  925. if (!msg)
  926. goto out;
  927. nlmsg_append(msg, &ndm, sizeof(ndm), 0);
  928. nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl_cb_dump_neigh, rctx);
  929. nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_cb_done, rctx);
  930. nl_cb_err(cb, NL_CB_CUSTOM, nl_cb_error, rctx);
  931. avl_init(&rctx->avl, avl_strcmp, false, NULL);
  932. rctx->pending = 1;
  933. nl_send_auto_complete(sock, msg);
  934. while (rctx->pending)
  935. nl_recvmsgs(sock, cb);
  936. out:
  937. if (sock)
  938. nl_socket_free(sock);
  939. if (cb)
  940. nl_cb_put(cb);
  941. if (msg)
  942. nlmsg_free(msg);
  943. }
  944. static void
  945. rpc_luci_get_host_hints_ether(struct reply_context *rctx)
  946. {
  947. struct host_hint *hint;
  948. struct in_addr in;
  949. char buf[512], *p;
  950. FILE *f;
  951. f = fopen("/etc/ethers", "r");
  952. if (!f)
  953. return;
  954. while (fgets(buf, sizeof(buf), f)) {
  955. p = strtok(buf, " \t\n");
  956. hint = rpc_luci_get_host_hint(rctx, p ? ether_aton(p) : NULL);
  957. if (!hint)
  958. continue;
  959. p = strtok(NULL, " \t\n");
  960. if (!p)
  961. continue;
  962. if (inet_pton(AF_INET, p, &in) == 1) {
  963. if (hint->ip.s_addr == 0)
  964. hint->ip = in;
  965. }
  966. else if (*p && !hint->hostname) {
  967. hint->hostname = strdup(p);
  968. }
  969. }
  970. fclose(f);
  971. }
  972. static void
  973. rpc_luci_get_host_hints_uci(struct reply_context *rctx)
  974. {
  975. struct uci_ptr ptr = { .package = "dhcp" };
  976. struct uci_context *uci = NULL;
  977. struct uci_package *pkg = NULL;
  978. struct in6_addr empty = {};
  979. struct lease_entry *lease;
  980. struct host_hint *hint;
  981. struct uci_element *e, *l;
  982. struct uci_section *s;
  983. struct in_addr in;
  984. char *p, *n;
  985. uci = uci_alloc_context();
  986. if (!uci)
  987. goto out;
  988. uci_load(uci, ptr.package, &pkg);
  989. if (!pkg)
  990. goto out;
  991. uci_foreach_element(&pkg->sections, e)
  992. {
  993. s = uci_to_section(e);
  994. if (strcmp(s->type, "host"))
  995. continue;
  996. ptr.section = s->e.name;
  997. ptr.s = NULL;
  998. ptr.option = "ip";
  999. ptr.o = NULL;
  1000. if (!uci_lookup_ptr(uci, &ptr, NULL, true) && ptr.o != NULL &&
  1001. ptr.o->type != UCI_TYPE_STRING)
  1002. n = ptr.o->v.string;
  1003. else
  1004. n = NULL;
  1005. if (!n || inet_pton(AF_INET, n, &in) != 1)
  1006. in.s_addr = 0;
  1007. ptr.option = "name";
  1008. ptr.o = NULL;
  1009. if (!uci_lookup_ptr(uci, &ptr, NULL, true) && ptr.o != NULL &&
  1010. ptr.o->type == UCI_TYPE_STRING)
  1011. n = ptr.o->v.string;
  1012. else
  1013. n = NULL;
  1014. ptr.option = "mac";
  1015. ptr.o = NULL;
  1016. if (uci_lookup_ptr(uci, &ptr, NULL, true) || ptr.o == NULL)
  1017. continue;
  1018. if (ptr.o->type == UCI_TYPE_STRING) {
  1019. for (p = strtok(ptr.o->v.string, " \t");
  1020. p != NULL;
  1021. p = strtok(NULL, " \t")) {
  1022. hint = rpc_luci_get_host_hint(rctx, ether_aton(p));
  1023. if (!hint)
  1024. continue;
  1025. if (hint->ip.s_addr == 0 && in.s_addr != 0)
  1026. hint->ip = in;
  1027. if (n && !hint->hostname)
  1028. hint->hostname = strdup(n);
  1029. }
  1030. }
  1031. else if (ptr.o->type == UCI_TYPE_LIST) {
  1032. uci_foreach_element(&ptr.o->v.list, l) {
  1033. hint = rpc_luci_get_host_hint(rctx, ether_aton(l->name));
  1034. if (!hint)
  1035. continue;
  1036. if (hint->ip.s_addr == 0 && in.s_addr != 0)
  1037. hint->ip = in;
  1038. if (n && !hint->hostname)
  1039. hint->hostname = strdup(n);
  1040. }
  1041. }
  1042. }
  1043. lease_open();
  1044. while ((lease = lease_next()) != NULL) {
  1045. hint = rpc_luci_get_host_hint(rctx, &lease->mac);
  1046. if (!hint)
  1047. continue;
  1048. if (lease->af == AF_INET && lease->n_addr && hint->ip.s_addr == 0)
  1049. hint->ip = lease->addr[0].in;
  1050. else if (lease->af == AF_INET6 && lease->n_addr &&
  1051. !memcmp(&hint->ip6, &empty, sizeof(empty)))
  1052. hint->ip6 = lease->addr[0].in6;
  1053. if (lease->hostname && !hint->hostname)
  1054. hint->hostname = strdup(lease->hostname);
  1055. }
  1056. lease_close();
  1057. out:
  1058. if (uci)
  1059. uci_free_context(uci);
  1060. }
  1061. static void
  1062. rpc_luci_get_host_hints_ifaddrs(struct reply_context *rctx)
  1063. {
  1064. struct ether_addr empty_ea = {};
  1065. struct in6_addr empty_in6 = {};
  1066. struct ifaddrs *ifaddr, *ifa;
  1067. struct sockaddr_ll *sll;
  1068. struct avl_tree devices;
  1069. struct host_hint *hint;
  1070. struct {
  1071. struct avl_node avl;
  1072. struct ether_addr ea;
  1073. struct in6_addr in6;
  1074. struct in_addr in;
  1075. } *device, *nextdevice;
  1076. char *p;
  1077. avl_init(&devices, avl_strcmp, false, NULL);
  1078. if (getifaddrs(&ifaddr) == -1)
  1079. return;
  1080. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  1081. if (!ifa->ifa_addr)
  1082. continue;
  1083. device = avl_find_element(&devices, ifa->ifa_name, device, avl);
  1084. if (!device) {
  1085. device = calloc_a(sizeof(*device), &p, strlen(ifa->ifa_name) + 1);
  1086. if (!device)
  1087. continue;
  1088. device->avl.key = strcpy(p, ifa->ifa_name);
  1089. avl_insert(&devices, &device->avl);
  1090. }
  1091. switch (ifa->ifa_addr->sa_family) {
  1092. case AF_PACKET:
  1093. sll = (struct sockaddr_ll *)ifa->ifa_addr;
  1094. if (sll->sll_halen == 6)
  1095. memcpy(&device->ea, sll->sll_addr, 6);
  1096. break;
  1097. case AF_INET6:
  1098. device->in6 = ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
  1099. break;
  1100. case AF_INET:
  1101. device->in = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
  1102. break;
  1103. }
  1104. }
  1105. freeifaddrs(ifaddr);
  1106. avl_remove_all_elements(&devices, device, avl, nextdevice) {
  1107. if (memcmp(&device->ea, &empty_ea, sizeof(empty_ea)) &&
  1108. (memcmp(&device->in6, &empty_in6, sizeof(empty_in6)) ||
  1109. device->in.s_addr != 0)) {
  1110. hint = rpc_luci_get_host_hint(rctx, &device->ea);
  1111. if (hint) {
  1112. if (hint->ip.s_addr == 0 && device->in.s_addr != 0)
  1113. hint->ip = device->in;
  1114. if (memcmp(&hint->ip6, &empty_in6, sizeof(empty_in6)) == 0 &&
  1115. memcmp(&device->in6, &empty_in6, sizeof(empty_in6)) != 0)
  1116. hint->ip6 = device->in6;
  1117. }
  1118. }
  1119. free(device);
  1120. }
  1121. }
  1122. static int
  1123. rpc_luci_get_host_hints_finish(struct reply_context *rctx);
  1124. static void
  1125. rpc_luci_get_host_hints_rrdns_cb(struct ubus_request *req, int type,
  1126. struct blob_attr *msg)
  1127. {
  1128. struct reply_context *rctx = req->priv;
  1129. struct host_hint *hint;
  1130. struct blob_attr *cur;
  1131. struct in6_addr in6;
  1132. struct in_addr in;
  1133. int rem;
  1134. if (msg) {
  1135. blob_for_each_attr(cur, msg, rem) {
  1136. if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
  1137. continue;
  1138. if (inet_pton(AF_INET6, blobmsg_name(cur), &in6) == 1) {
  1139. avl_for_each_element(&rctx->avl, hint, avl) {
  1140. if (!memcmp(&hint->ip6, &in6, sizeof(in6))) {
  1141. if (hint->hostname)
  1142. free(hint->hostname);
  1143. hint->hostname = strdup(blobmsg_get_string(cur));
  1144. break;
  1145. }
  1146. }
  1147. }
  1148. else if (inet_pton(AF_INET, blobmsg_name(cur), &in) == 1) {
  1149. avl_for_each_element(&rctx->avl, hint, avl) {
  1150. if (!memcmp(&hint->ip, &in, sizeof(in))) {
  1151. if (hint->hostname)
  1152. free(hint->hostname);
  1153. hint->hostname = strdup(blobmsg_get_string(cur));
  1154. break;
  1155. }
  1156. }
  1157. }
  1158. }
  1159. }
  1160. rpc_luci_get_host_hints_finish(rctx);
  1161. }
  1162. static void
  1163. rpc_luci_get_host_hints_rrdns(struct reply_context *rctx)
  1164. {
  1165. struct in6_addr empty_in6 = {};
  1166. char buf[INET6_ADDRSTRLEN];
  1167. struct blob_buf req = {};
  1168. struct host_hint *hint;
  1169. int n = 0;
  1170. void *a;
  1171. blob_buf_init(&req, 0);
  1172. a = blobmsg_open_array(&req, "addrs");
  1173. avl_for_each_element(&rctx->avl, hint, avl) {
  1174. if (hint->ip.s_addr != 0) {
  1175. inet_ntop(AF_INET, &hint->ip, buf, sizeof(buf));
  1176. blobmsg_add_string(&req, NULL, buf);
  1177. n++;
  1178. }
  1179. else if (memcmp(&hint->ip6, &empty_in6, sizeof(empty_in6))) {
  1180. inet_ntop(AF_INET6, &hint->ip6, buf, sizeof(buf));
  1181. blobmsg_add_string(&req, NULL, buf);
  1182. n++;
  1183. }
  1184. }
  1185. blobmsg_close_array(&req, a);
  1186. if (n > 0) {
  1187. blobmsg_add_u32(&req, "timeout", 250);
  1188. blobmsg_add_u32(&req, "limit", n);
  1189. if (!invoke_ubus(rctx->context, "network.rrdns", "lookup", &req,
  1190. rpc_luci_get_host_hints_rrdns_cb, rctx))
  1191. rpc_luci_get_host_hints_finish(rctx);
  1192. }
  1193. else {
  1194. rpc_luci_get_host_hints_finish(rctx);
  1195. }
  1196. blob_buf_free(&req);
  1197. }
  1198. static int
  1199. rpc_luci_get_host_hints_finish(struct reply_context *rctx)
  1200. {
  1201. struct host_hint *hint, *nexthint;
  1202. char buf[INET6_ADDRSTRLEN];
  1203. struct in6_addr in6 = {};
  1204. struct in_addr in = {};
  1205. void *o;
  1206. avl_remove_all_elements(&rctx->avl, hint, avl, nexthint) {
  1207. o = blobmsg_open_table(&rctx->blob, hint->avl.key);
  1208. if (memcmp(&hint->ip, &in, sizeof(in))) {
  1209. inet_ntop(AF_INET, &hint->ip, buf, sizeof(buf));
  1210. blobmsg_add_string(&rctx->blob, "ipv4", buf);
  1211. }
  1212. if (memcmp(&hint->ip6, &in6, sizeof(in6))) {
  1213. inet_ntop(AF_INET6, &hint->ip6, buf, sizeof(buf));
  1214. blobmsg_add_string(&rctx->blob, "ipv6", buf);
  1215. }
  1216. if (hint->hostname)
  1217. blobmsg_add_string(&rctx->blob, "name", hint->hostname);
  1218. blobmsg_close_table(&rctx->blob, o);
  1219. if (hint->hostname)
  1220. free(hint->hostname);
  1221. free(hint);
  1222. }
  1223. return finish_request(rctx, UBUS_STATUS_OK);
  1224. }
  1225. static int
  1226. rpc_luci_get_host_hints(struct ubus_context *ctx, struct ubus_object *obj,
  1227. struct ubus_request_data *req, const char *method,
  1228. struct blob_attr *msg)
  1229. {
  1230. struct reply_context *rctx = defer_request(ctx, req);
  1231. if (!rctx)
  1232. return UBUS_STATUS_UNKNOWN_ERROR;
  1233. rpc_luci_get_host_hints_nl(rctx);
  1234. rpc_luci_get_host_hints_uci(rctx);
  1235. rpc_luci_get_host_hints_ether(rctx);
  1236. rpc_luci_get_host_hints_ifaddrs(rctx);
  1237. rpc_luci_get_host_hints_rrdns(rctx);
  1238. return UBUS_STATUS_OK;
  1239. }
  1240. static int
  1241. rpc_luci_get_duid_hints(struct ubus_context *ctx, struct ubus_object *obj,
  1242. struct ubus_request_data *req, const char *method,
  1243. struct blob_attr *msg)
  1244. {
  1245. struct { struct avl_node avl; } *e, *next;
  1246. char s[INET6_ADDRSTRLEN], *p;
  1247. struct ether_addr empty = {};
  1248. struct lease_entry *lease;
  1249. struct avl_tree avl;
  1250. void *o, *a;
  1251. int n;
  1252. avl_init(&avl, avl_strcmp, false, NULL);
  1253. blob_buf_init(&blob, 0);
  1254. lease_open();
  1255. while ((lease = lease_next()) != NULL) {
  1256. if (lease->af != AF_INET6 || lease->duid == NULL)
  1257. continue;
  1258. e = avl_find_element(&avl, lease->duid, e, avl);
  1259. if (e)
  1260. continue;
  1261. e = calloc_a(sizeof(*e), &p, strlen(lease->duid) + 1);
  1262. if (!e)
  1263. continue;
  1264. o = blobmsg_open_table(&blob, lease->duid);
  1265. inet_ntop(AF_INET6, &lease->addr[0].in6, s, sizeof(s));
  1266. blobmsg_add_string(&blob, "ip6addr", s);
  1267. a = blobmsg_open_array(&blob, "ip6addrs");
  1268. for (n = 0; n < lease->n_addr; n++) {
  1269. inet_ntop(AF_INET6, &lease->addr[n].in6, s, sizeof(s));
  1270. blobmsg_add_string(&blob, NULL, s);
  1271. }
  1272. blobmsg_close_array(&blob, a);
  1273. if (lease->hostname)
  1274. blobmsg_add_string(&blob, "hostname", lease->hostname);
  1275. if (memcmp(&lease->mac, &empty, sizeof(empty)))
  1276. blobmsg_add_string(&blob, "macaddr", ea2str(&lease->mac));
  1277. blobmsg_close_table(&blob, o);
  1278. e->avl.key = strcpy(p, lease->duid);
  1279. avl_insert(&avl, &e->avl);
  1280. }
  1281. lease_close();
  1282. avl_remove_all_elements(&avl, e, avl, next) {
  1283. free(e);
  1284. }
  1285. ubus_send_reply(ctx, req, blob.head);
  1286. return UBUS_STATUS_OK;
  1287. }
  1288. static int
  1289. rpc_luci_get_board_json(struct ubus_context *ctx, struct ubus_object *obj,
  1290. struct ubus_request_data *req, const char *method,
  1291. struct blob_attr *msg)
  1292. {
  1293. blob_buf_init(&blob, 0);
  1294. if (!blobmsg_add_json_from_file(&blob, "/etc/board.json"))
  1295. return UBUS_STATUS_UNKNOWN_ERROR;
  1296. ubus_send_reply(ctx, req, blob.head);
  1297. return UBUS_STATUS_OK;
  1298. }
  1299. enum {
  1300. RPC_L_FAMILY,
  1301. __RPC_L_MAX,
  1302. };
  1303. static const struct blobmsg_policy rpc_get_leases_policy[__RPC_L_MAX] = {
  1304. [RPC_L_FAMILY] = { .name = "family", .type = BLOBMSG_TYPE_INT32 }
  1305. };
  1306. static int
  1307. rpc_luci_get_dhcp_leases(struct ubus_context *ctx, struct ubus_object *obj,
  1308. struct ubus_request_data *req, const char *method,
  1309. struct blob_attr *msg)
  1310. {
  1311. struct blob_attr *tb[__RPC_L_MAX];
  1312. struct ether_addr emptymac = {};
  1313. struct lease_entry *lease;
  1314. char s[INET6_ADDRSTRLEN];
  1315. int af, family = 0;
  1316. void *a, *a2, *o;
  1317. int n;
  1318. blobmsg_parse(rpc_get_leases_policy, __RPC_L_MAX, tb,
  1319. blob_data(msg), blob_len(msg));
  1320. switch (tb[RPC_L_FAMILY] ? blobmsg_get_u32(tb[RPC_L_FAMILY]) : 0) {
  1321. case 0:
  1322. family = 0;
  1323. break;
  1324. case 4:
  1325. family = AF_INET;
  1326. break;
  1327. case 6:
  1328. family = AF_INET6;
  1329. break;
  1330. default:
  1331. return UBUS_STATUS_INVALID_ARGUMENT;
  1332. }
  1333. blob_buf_init(&blob, 0);
  1334. for (af = family ? family : AF_INET;
  1335. af != 0;
  1336. af = (family == 0) ? (af == AF_INET ? AF_INET6 : 0) : 0) {
  1337. a = blobmsg_open_array(&blob, (af == AF_INET) ? "dhcp_leases"
  1338. : "dhcp6_leases");
  1339. lease_open();
  1340. while ((lease = lease_next()) != NULL) {
  1341. if (lease->af != af)
  1342. continue;
  1343. o = blobmsg_open_table(&blob, NULL);
  1344. if (lease->expire == -1)
  1345. blobmsg_add_u8(&blob, "expires", 0);
  1346. else
  1347. blobmsg_add_u32(&blob, "expires", lease->expire);
  1348. if (lease->hostname)
  1349. blobmsg_add_string(&blob, "hostname", lease->hostname);
  1350. if (memcmp(&lease->mac, &emptymac, sizeof(emptymac)))
  1351. blobmsg_add_string(&blob, "macaddr", ea2str(&lease->mac));
  1352. if (lease->duid)
  1353. blobmsg_add_string(&blob, "duid", lease->duid);
  1354. inet_ntop(lease->af, &lease->addr[0].in6, s, sizeof(s));
  1355. blobmsg_add_string(&blob, (af == AF_INET) ? "ipaddr" : "ip6addr",
  1356. s);
  1357. if (af == AF_INET6) {
  1358. a2 = blobmsg_open_array(&blob, "ip6addrs");
  1359. for (n = 0; n < lease->n_addr; n++) {
  1360. inet_ntop(lease->af, &lease->addr[n].in6, s, sizeof(s));
  1361. blobmsg_add_string(&blob, NULL, s);
  1362. }
  1363. blobmsg_close_array(&blob, a2);
  1364. }
  1365. blobmsg_close_table(&blob, o);
  1366. }
  1367. lease_close();
  1368. blobmsg_close_array(&blob, a);
  1369. }
  1370. ubus_send_reply(ctx, req, blob.head);
  1371. return UBUS_STATUS_OK;
  1372. }
  1373. static int
  1374. rpc_luci_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
  1375. {
  1376. static const struct ubus_method luci_methods[] = {
  1377. UBUS_METHOD_NOARG("getNetworkDevices", rpc_luci_get_network_devices),
  1378. UBUS_METHOD_NOARG("getWirelessDevices", rpc_luci_get_wireless_devices),
  1379. UBUS_METHOD_NOARG("getHostHints", rpc_luci_get_host_hints),
  1380. UBUS_METHOD_NOARG("getDUIDHints", rpc_luci_get_duid_hints),
  1381. UBUS_METHOD_NOARG("getBoardJSON", rpc_luci_get_board_json),
  1382. UBUS_METHOD("getDHCPLeases", rpc_luci_get_dhcp_leases, rpc_get_leases_policy)
  1383. };
  1384. static struct ubus_object_type luci_type =
  1385. UBUS_OBJECT_TYPE("rpcd-luci", luci_methods);
  1386. static struct ubus_object obj = {
  1387. .name = "luci-rpc",
  1388. .type = &luci_type,
  1389. .methods = luci_methods,
  1390. .n_methods = ARRAY_SIZE(luci_methods),
  1391. };
  1392. return ubus_add_object(ctx, &obj);
  1393. }
  1394. struct rpc_plugin rpc_plugin = {
  1395. .init = rpc_luci_api_init
  1396. };