neighbours-batadv.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <json-c/json.h>
  5. #include <net/if.h>
  6. #include <batadv-genl.h>
  7. #define STR(x) #x
  8. #define XSTR(x) STR(x)
  9. struct neigh_netlink_opts {
  10. struct json_object *obj;
  11. struct batadv_nlquery_opts query_opts;
  12. };
  13. static const enum batadv_nl_attrs parse_orig_list_mandatory[] = {
  14. BATADV_ATTR_ORIG_ADDRESS,
  15. BATADV_ATTR_NEIGH_ADDRESS,
  16. BATADV_ATTR_TQ,
  17. BATADV_ATTR_HARD_IFINDEX,
  18. BATADV_ATTR_LAST_SEEN_MSECS,
  19. };
  20. static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg)
  21. {
  22. struct nlattr *attrs[BATADV_ATTR_MAX+1];
  23. struct nlmsghdr *nlh = nlmsg_hdr(msg);
  24. struct batadv_nlquery_opts *query_opts = arg;
  25. struct genlmsghdr *ghdr;
  26. uint8_t *orig;
  27. uint8_t *dest;
  28. uint8_t tq;
  29. uint32_t hardif;
  30. uint32_t lastseen;
  31. char ifname_buf[IF_NAMESIZE], *ifname;
  32. struct neigh_netlink_opts *opts;
  33. char mac1[18];
  34. opts = batadv_container_of(query_opts, struct neigh_netlink_opts, query_opts);
  35. if (!genlmsg_valid_hdr(nlh, 0))
  36. return NL_OK;
  37. ghdr = nlmsg_data(nlh);
  38. if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
  39. return NL_OK;
  40. if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
  41. genlmsg_len(ghdr), batadv_genl_policy))
  42. return NL_OK;
  43. if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory,
  44. BATADV_ARRAY_SIZE(parse_orig_list_mandatory)))
  45. return NL_OK;
  46. if (!attrs[BATADV_ATTR_FLAG_BEST])
  47. return NL_OK;
  48. orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
  49. dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
  50. tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
  51. hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]);
  52. lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
  53. if (memcmp(orig, dest, 6) != 0)
  54. return NL_OK;
  55. ifname = if_indextoname(hardif, ifname_buf);
  56. if (!ifname)
  57. return NL_OK;
  58. sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x",
  59. orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
  60. struct json_object *neigh = json_object_new_object();
  61. if (!neigh)
  62. return NL_OK;
  63. json_object_object_add(neigh, "tq", json_object_new_int(tq));
  64. json_object_object_add(neigh, "lastseen", json_object_new_double(lastseen / 1000.));
  65. json_object_object_add(neigh, "ifname", json_object_new_string(ifname));
  66. json_object_object_add(opts->obj, mac1, neigh);
  67. return NL_OK;
  68. }
  69. static json_object *neighbours(void) {
  70. struct neigh_netlink_opts opts = {
  71. .query_opts = {
  72. .err = 0,
  73. },
  74. };
  75. int ret;
  76. opts.obj = json_object_new_object();
  77. if (!opts.obj)
  78. return NULL;
  79. ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS,
  80. parse_orig_list_netlink_cb, NLM_F_DUMP,
  81. &opts.query_opts);
  82. if (ret < 0) {
  83. json_object_put(opts.obj);
  84. return NULL;
  85. }
  86. return opts.obj;
  87. }
  88. int main(void) {
  89. struct json_object *obj;
  90. printf("Content-type: text/event-stream\n\n");
  91. fflush(stdout);
  92. while (1) {
  93. obj = neighbours();
  94. if (obj) {
  95. printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
  96. fflush(stdout);
  97. json_object_put(obj);
  98. }
  99. sleep(10);
  100. }
  101. return 0;
  102. }