123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /* NHRP event manager
- * Copyright (c) 2014-2015 Timo Teräs
- *
- * This file is free software: you may copy, redistribute and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- */
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include "thread.h"
- #include "zbuf.h"
- #include "log.h"
- #include "nhrpd.h"
- const char *nhrp_event_socket_path;
- struct nhrp_reqid_pool nhrp_event_reqid;
- struct event_manager {
- struct thread *t_reconnect, *t_read, *t_write;
- struct zbuf ibuf;
- struct zbuf_queue obuf;
- int fd;
- uint8_t ibuf_data[4*1024];
- };
- static int evmgr_reconnect(struct thread *t);
- static void evmgr_connection_error(struct event_manager *evmgr)
- {
- THREAD_OFF(evmgr->t_read);
- THREAD_OFF(evmgr->t_write);
- zbuf_reset(&evmgr->ibuf);
- zbufq_reset(&evmgr->obuf);
- if (evmgr->fd >= 0)
- close(evmgr->fd);
- evmgr->fd = -1;
- if (nhrp_event_socket_path)
- THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect,
- evmgr, 10);
- }
- static void evmgr_recv_message(struct event_manager *evmgr, struct zbuf *zb)
- {
- struct zbuf zl;
- uint32_t eventid = 0;
- size_t len;
- char buf[256], result[64] = "";
- while (zbuf_may_pull_until(zb, "\n", &zl)) {
- len = zbuf_used(&zl) - 1;
- if (len >= sizeof(buf)-1)
- continue;
- memcpy(buf, zbuf_pulln(&zl, len), len);
- buf[len] = 0;
- debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
- sscanf(buf, "eventid=%d", &eventid);
- sscanf(buf, "result=%63s", result);
- }
- debugf(NHRP_DEBUG_EVENT, "evmgr: received: eventid=%d result=%s", eventid, result);
- if (eventid && result[0]) {
- struct nhrp_reqid *r = nhrp_reqid_lookup(&nhrp_event_reqid, eventid);
- if (r) r->cb(r, result);
- }
- }
- static int evmgr_read(struct thread *t)
- {
- struct event_manager *evmgr = THREAD_ARG(t);
- struct zbuf *ibuf = &evmgr->ibuf;
- struct zbuf msg;
- evmgr->t_read = NULL;
- if (zbuf_read(ibuf, evmgr->fd, (size_t) -1) < 0) {
- evmgr_connection_error(evmgr);
- return 0;
- }
- /* Process all messages in buffer */
- while (zbuf_may_pull_until(ibuf, "\n\n", &msg))
- evmgr_recv_message(evmgr, &msg);
- THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
- return 0;
- }
- static int evmgr_write(struct thread *t)
- {
- struct event_manager *evmgr = THREAD_ARG(t);
- int r;
- evmgr->t_write = NULL;
- r = zbufq_write(&evmgr->obuf, evmgr->fd);
- if (r > 0) {
- THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
- } else if (r < 0) {
- evmgr_connection_error(evmgr);
- }
- return 0;
- }
- static void evmgr_hexdump(struct zbuf *zb, const uint8_t *val, size_t vallen)
- {
- static const char xd[] = "0123456789abcdef";
- size_t i;
- char *ptr;
- ptr = zbuf_pushn(zb, 2*vallen);
- if (!ptr) return;
- for (i = 0; i < vallen; i++) {
- uint8_t b = val[i];
- *(ptr++) = xd[b >> 4];
- *(ptr++) = xd[b & 0xf];
- }
- }
- static void evmgr_put(struct zbuf *zb, const char *fmt, ...)
- {
- const char *pos, *nxt, *str;
- const uint8_t *bin;
- const union sockunion *su;
- int len;
- va_list va;
- va_start(va, fmt);
- for (pos = fmt; (nxt = strchr(pos, '%')) != NULL; pos = nxt + 2) {
- zbuf_put(zb, pos, nxt-pos);
- switch (nxt[1]) {
- case '%':
- zbuf_put8(zb, '%');
- break;
- case 'u':
- zb->tail += snprintf((char *) zb->tail, zbuf_tailroom(zb), "%u", va_arg(va, uint32_t));
- break;
- case 's':
- str = va_arg(va, const char *);
- zbuf_put(zb, str, strlen(str));
- break;
- case 'U':
- su = va_arg(va, const union sockunion *);
- if (sockunion2str(su, (char *) zb->tail, zbuf_tailroom(zb)))
- zb->tail += strlen((char *) zb->tail);
- else
- zbuf_set_werror(zb);
- break;
- case 'H':
- bin = va_arg(va, const uint8_t *);
- len = va_arg(va, int);
- evmgr_hexdump(zb, bin, len);
- break;
- }
- }
- va_end(va);
- zbuf_put(zb, pos, strlen(pos));
- }
- static void evmgr_submit(struct event_manager *evmgr, struct zbuf *obuf)
- {
- if (obuf->error) {
- zbuf_free(obuf);
- return;
- }
- zbuf_put(obuf, "\n", 1);
- zbufq_queue(&evmgr->obuf, obuf);
- if (evmgr->fd >= 0)
- THREAD_WRITE_ON(master, evmgr->t_write, evmgr_write, evmgr, evmgr->fd);
- }
- static int evmgr_reconnect(struct thread *t)
- {
- struct event_manager *evmgr = THREAD_ARG(t);
- int fd;
- evmgr->t_reconnect = NULL;
- if (evmgr->fd >= 0 || !nhrp_event_socket_path) return 0;
- fd = sock_open_unix(nhrp_event_socket_path);
- if (fd < 0) {
- zlog_warn("%s: failure connecting nhrp-event socket: %s",
- __PRETTY_FUNCTION__, strerror(errno));
- zbufq_reset(&evmgr->obuf);
- THREAD_TIMER_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
- return 0;
- }
- zlog_info("Connected to Event Manager");
- evmgr->fd = fd;
- THREAD_READ_ON(master, evmgr->t_read, evmgr_read, evmgr, evmgr->fd);
- return 0;
- }
- static struct event_manager evmgr_connection;
- void evmgr_init(void)
- {
- struct event_manager *evmgr = &evmgr_connection;
- evmgr->fd = -1;
- zbuf_init(&evmgr->ibuf, evmgr->ibuf_data, sizeof(evmgr->ibuf_data), 0);
- zbufq_init(&evmgr->obuf);
- THREAD_TIMER_MSEC_ON(master, evmgr->t_reconnect, evmgr_reconnect, evmgr, 10);
- }
- void evmgr_set_socket(const char *socket)
- {
- if (nhrp_event_socket_path)
- free((char *) nhrp_event_socket_path);
- nhrp_event_socket_path = strdup(socket);
- evmgr_connection_error(&evmgr_connection);
- }
- void evmgr_terminate(void)
- {
- }
- void evmgr_notify(const char *name, struct nhrp_cache *c, void (*cb)(struct nhrp_reqid *, void *))
- {
- struct event_manager *evmgr = &evmgr_connection;
- struct nhrp_vc *vc;
- struct nhrp_interface *nifp = c->ifp->info;
- struct zbuf *zb;
- afi_t afi = family2afi(sockunion_family(&c->remote_addr));
- if (!nhrp_event_socket_path) {
- cb(&c->eventid, (void*) "accept");
- return;
- }
- debugf(NHRP_DEBUG_EVENT, "evmgr: sending event %s", name);
- vc = c->new.peer ? c->new.peer->vc : NULL;
- zb = zbuf_alloc(1024 + (vc ? (vc->local.certlen + vc->remote.certlen) * 2 : 0));
- if (cb) {
- nhrp_reqid_free(&nhrp_event_reqid, &c->eventid);
- evmgr_put(zb,
- "eventid=%u\n",
- nhrp_reqid_alloc(&nhrp_event_reqid, &c->eventid, cb));
- }
- evmgr_put(zb,
- "event=%s\n"
- "type=%s\n"
- "old_type=%s\n"
- "num_nhs=%u\n"
- "interface=%s\n"
- "local_addr=%U\n",
- name,
- nhrp_cache_type_str[c->new.type],
- nhrp_cache_type_str[c->cur.type],
- (unsigned int) nhrp_cache_counts[NHRP_CACHE_NHS],
- c->ifp->name,
- &nifp->afi[afi].addr);
- if (vc) {
- evmgr_put(zb,
- "vc_initiated=%s\n"
- "local_nbma=%U\n"
- "local_cert=%H\n"
- "remote_addr=%U\n"
- "remote_nbma=%U\n"
- "remote_cert=%H\n",
- c->new.peer->requested ? "yes" : "no",
- &vc->local.nbma,
- vc->local.cert, vc->local.certlen,
- &c->remote_addr, &vc->remote.nbma,
- vc->remote.cert, vc->remote.certlen);
- }
- evmgr_submit(evmgr, zb);
- }
|