source: src/router/quagga/nhrpd/nhrp_event.c @ 31640

Last change on this file since 31640 was 31640, checked in by brainslayer, 5 months ago

update quagga

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