nhrp_event.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /* NHRP event manager
  2. * Copyright (c) 2014-2015 Timo Teräs
  3. *
  4. * This file is free software: you may copy, redistribute and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. */
  9. #include <string.h>
  10. #include <sys/socket.h>
  11. #include <sys/un.h>
  12. #include "thread.h"
  13. #include "zbuf.h"
  14. #include "log.h"
  15. #include "nhrpd.h"
  16. const char *nhrp_event_socket_path;
  17. struct nhrp_reqid_pool nhrp_event_reqid;
  18. struct event_manager {
  19. struct thread *t_reconnect, *t_read, *t_write;
  20. struct zbuf ibuf;
  21. struct zbuf_queue obuf;
  22. int fd;
  23. uint8_t ibuf_data[4*1024];
  24. };
  25. static int evmgr_reconnect(struct thread *t);
  26. static void evmgr_connection_error(struct event_manager *evmgr)
  27. {
  28. THREAD_OFF(evmgr->t_read);
  29. THREAD_OFF(evmgr->t_write);
  30. zbuf_reset(&evmgr->ibuf);
  31. zbufq_reset(&evmgr->obuf);
  32. if (evmgr->fd >= 0)
  33. close(evmgr->fd);
  34. evmgr->fd = -1;
  35. if (nhrp_event_socket_path)
  36. THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect,
  37. evmgr, 10);
  38. }
  39. static void evmgr_recv_message(struct event_manager *evmgr, struct zbuf *zb)
  40. {
  41. struct zbuf zl;
  42. uint32_t eventid = 0;
  43. size_t len;
  44. char buf[256], result[64] = "";
  45. while (zbuf_may_pull_until(zb, "\n", &zl)) {
  46. len = zbuf_used(&zl) - 1;
  47. if (len >= sizeof(buf)-1)
  48. continue;
  49. memcpy(buf, zbuf_pulln(&zl, len), len);
  50. buf[len] = 0;
  51. debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
  52. sscanf(buf, "eventid=%d", &eventid);
  53. sscanf(buf, "result=%63s", result);
  54. }
  55. debugf(NHRP_DEBUG_EVENT, "evmgr: received: eventid=%d result=%s", eventid, result);
  56. if (eventid && result[0]) {
  57. struct nhrp_reqid *r = nhrp_reqid_lookup(&nhrp_event_reqid, eventid);
  58. if (r) r->cb(r, result);
  59. }
  60. }
  61. static int evmgr_read(struct thread *t)
  62. {
  63. struct event_manager *evmgr = THREAD_ARG(t);
  64. struct zbuf *ibuf = &evmgr->ibuf;
  65. struct zbuf msg;
  66. evmgr->t_read = NULL;
  67. if (zbuf_read(ibuf, evmgr->fd, (size_t) -1) < 0) {
  68. evmgr_connection_error(evmgr);
  69. return 0;
  70. }
  71. /* Process all messages in buffer */
  72. while (zbuf_may_pull_until(ibuf, "\n\n", &msg))
  73. evmgr_recv_message(evmgr, &msg);
  74. THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
  75. return 0;
  76. }
  77. static int evmgr_write(struct thread *t)
  78. {
  79. struct event_manager *evmgr = THREAD_ARG(t);
  80. int r;
  81. evmgr->t_write = NULL;
  82. r = zbufq_write(&evmgr->obuf, evmgr->fd);
  83. if (r > 0) {
  84. THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
  85. } else if (r < 0) {
  86. evmgr_connection_error(evmgr);
  87. }
  88. return 0;
  89. }
  90. static void evmgr_hexdump(struct zbuf *zb, const uint8_t *val, size_t vallen)
  91. {
  92. static const char xd[] = "0123456789abcdef";
  93. size_t i;
  94. char *ptr;
  95. ptr = zbuf_pushn(zb, 2*vallen);
  96. if (!ptr) return;
  97. for (i = 0; i < vallen; i++) {
  98. uint8_t b = val[i];
  99. *(ptr++) = xd[b >> 4];
  100. *(ptr++) = xd[b & 0xf];
  101. }
  102. }
  103. static void evmgr_put(struct zbuf *zb, const char *fmt, ...)
  104. {
  105. const char *pos, *nxt, *str;
  106. const uint8_t *bin;
  107. const union sockunion *su;
  108. int len;
  109. va_list va;
  110. va_start(va, fmt);
  111. for (pos = fmt; (nxt = strchr(pos, '%')) != NULL; pos = nxt + 2) {
  112. zbuf_put(zb, pos, nxt-pos);
  113. switch (nxt[1]) {
  114. case '%':
  115. zbuf_put8(zb, '%');
  116. break;
  117. case 'u':
  118. zb->tail += snprintf((char *) zb->tail, zbuf_tailroom(zb), "%u", va_arg(va, uint32_t));
  119. break;
  120. case 's':
  121. str = va_arg(va, const char *);
  122. zbuf_put(zb, str, strlen(str));
  123. break;
  124. case 'U':
  125. su = va_arg(va, const union sockunion *);
  126. if (sockunion2str(su, (char *) zb->tail, zbuf_tailroom(zb)))
  127. zb->tail += strlen((char *) zb->tail);
  128. else
  129. zbuf_set_werror(zb);
  130. break;
  131. case 'H':
  132. bin = va_arg(va, const uint8_t *);
  133. len = va_arg(va, int);
  134. evmgr_hexdump(zb, bin, len);
  135. break;
  136. }
  137. }
  138. va_end(va);
  139. zbuf_put(zb, pos, strlen(pos));
  140. }
  141. static void evmgr_submit(struct event_manager *evmgr, struct zbuf *obuf)
  142. {
  143. if (obuf->error) {
  144. zbuf_free(obuf);
  145. return;
  146. }
  147. zbuf_put(obuf, "\n", 1);
  148. zbufq_queue(&evmgr->obuf, obuf);
  149. if (evmgr->fd >= 0)
  150. THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
  151. }
  152. static int evmgr_reconnect(struct thread *t)
  153. {
  154. struct event_manager *evmgr = THREAD_ARG(t);
  155. int fd;
  156. evmgr->t_reconnect = NULL;
  157. if (evmgr->fd >= 0 || !nhrp_event_socket_path) return 0;
  158. fd = sock_open_unix(nhrp_event_socket_path);
  159. if (fd < 0) {
  160. zlog_warn("%s: failure connecting nhrp-event socket: %s",
  161. __PRETTY_FUNCTION__, strerror(errno));
  162. zbufq_reset(&evmgr->obuf);
  163. THREAD_TIMER_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
  164. return 0;
  165. }
  166. zlog_info("Connected to Event Manager");
  167. evmgr->fd = fd;
  168. THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
  169. return 0;
  170. }
  171. static struct event_manager evmgr_connection;
  172. void evmgr_init(void)
  173. {
  174. struct event_manager *evmgr = &evmgr_connection;
  175. evmgr->fd = -1;
  176. zbuf_init(&evmgr->ibuf, evmgr->ibuf_data, sizeof(evmgr->ibuf_data), 0);
  177. zbufq_init(&evmgr->obuf);
  178. THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
  179. }
  180. void evmgr_set_socket(const char *socket)
  181. {
  182. if (nhrp_event_socket_path)
  183. free((char *) nhrp_event_socket_path);
  184. nhrp_event_socket_path = strdup(socket);
  185. evmgr_connection_error(&evmgr_connection);
  186. }
  187. void evmgr_terminate(void)
  188. {
  189. }
  190. void evmgr_notify(const char *name, struct nhrp_cache *c, void (*cb)(struct nhrp_reqid *, void *))
  191. {
  192. struct event_manager *evmgr = &evmgr_connection;
  193. struct nhrp_vc *vc;
  194. struct nhrp_interface *nifp = c->ifp->info;
  195. struct zbuf *zb;
  196. afi_t afi = family2afi(sockunion_family(&c->remote_addr));
  197. if (!nhrp_event_socket_path) {
  198. cb(&c->eventid, (void*) "accept");
  199. return;
  200. }
  201. debugf(NHRP_DEBUG_EVENT, "evmgr: sending event %s", name);
  202. vc = c->new.peer ? c->new.peer->vc : NULL;
  203. zb = zbuf_alloc(1024 + (vc ? (vc->local.certlen + vc->remote.certlen) * 2 : 0));
  204. if (cb) {
  205. nhrp_reqid_free(&nhrp_event_reqid, &c->eventid);
  206. evmgr_put(zb,
  207. "eventid=%u\n",
  208. nhrp_reqid_alloc(&nhrp_event_reqid, &c->eventid, cb));
  209. }
  210. evmgr_put(zb,
  211. "event=%s\n"
  212. "type=%s\n"
  213. "old_type=%s\n"
  214. "num_nhs=%u\n"
  215. "interface=%s\n"
  216. "local_addr=%U\n",
  217. name,
  218. nhrp_cache_type_str[c->new.type],
  219. nhrp_cache_type_str[c->cur.type],
  220. (unsigned int) nhrp_cache_counts[NHRP_CACHE_NHS],
  221. c->ifp->name,
  222. &nifp->afi[afi].addr);
  223. if (vc) {
  224. evmgr_put(zb,
  225. "vc_initiated=%s\n"
  226. "local_nbma=%U\n"
  227. "local_cert=%H\n"
  228. "remote_addr=%U\n"
  229. "remote_nbma=%U\n"
  230. "remote_cert=%H\n",
  231. c->new.peer->requested ? "yes" : "no",
  232. &vc->local.nbma,
  233. vc->local.cert, vc->local.certlen,
  234. &c->remote_addr, &vc->remote.nbma,
  235. vc->remote.cert, vc->remote.certlen);
  236. }
  237. evmgr_submit(evmgr, zb);
  238. }