]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/nhrp_event.c
*: fix source file headers & includes for errcodes
[mirror_frr.git] / nhrpd / nhrp_event.c
CommitLineData
2fb975da
TT
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;
996c9314 27 uint8_t ibuf_data[4 * 1024];
2fb975da
TT
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)
ffa2c898
QY
43 thread_add_timer_msec(master, evmgr_reconnect, evmgr, 10,
44 &evmgr->t_reconnect);
2fb975da
TT
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;
996c9314 56 if (len >= sizeof(buf) - 1)
2fb975da
TT
57 continue;
58 memcpy(buf, zbuf_pulln(&zl, len), len);
59 buf[len] = 0;
60
61 debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
0651460e 62 if (sscanf(buf, "eventid=%" SCNu32, &eventid) != 1)
6c8ca260
JB
63 continue;
64 if (sscanf(buf, "result=%63s", result) != 1)
65 continue;
2fb975da 66 }
996c9314
LB
67 debugf(NHRP_DEBUG_EVENT, "evmgr: received: eventid=%d result=%s",
68 eventid, result);
2fb975da 69 if (eventid && result[0]) {
996c9314
LB
70 struct nhrp_reqid *r =
71 nhrp_reqid_lookup(&nhrp_event_reqid, eventid);
72 if (r)
73 r->cb(r, result);
2fb975da
TT
74 }
75}
76
77static int evmgr_read(struct thread *t)
78{
79 struct event_manager *evmgr = THREAD_ARG(t);
80 struct zbuf *ibuf = &evmgr->ibuf;
81 struct zbuf msg;
82
83 evmgr->t_read = NULL;
996c9314 84 if (zbuf_read(ibuf, evmgr->fd, (size_t)-1) < 0) {
2fb975da
TT
85 evmgr_connection_error(evmgr);
86 return 0;
87 }
88
89 /* Process all messages in buffer */
90 while (zbuf_may_pull_until(ibuf, "\n\n", &msg))
91 evmgr_recv_message(evmgr, &msg);
92
ffa2c898 93 thread_add_read(master, evmgr_read, evmgr, evmgr->fd, &evmgr->t_read);
2fb975da
TT
94 return 0;
95}
96
97static int evmgr_write(struct thread *t)
98{
99 struct event_manager *evmgr = THREAD_ARG(t);
100 int r;
101
102 evmgr->t_write = NULL;
103 r = zbufq_write(&evmgr->obuf, evmgr->fd);
104 if (r > 0) {
ffa2c898
QY
105 thread_add_write(master, evmgr_write, evmgr, evmgr->fd,
106 &evmgr->t_write);
2fb975da
TT
107 } else if (r < 0) {
108 evmgr_connection_error(evmgr);
109 }
110
111 return 0;
112}
113
114static void evmgr_hexdump(struct zbuf *zb, const uint8_t *val, size_t vallen)
115{
116 static const char xd[] = "0123456789abcdef";
117 size_t i;
118 char *ptr;
119
996c9314
LB
120 ptr = zbuf_pushn(zb, 2 * vallen);
121 if (!ptr)
122 return;
2fb975da
TT
123
124 for (i = 0; i < vallen; i++) {
125 uint8_t b = val[i];
126 *(ptr++) = xd[b >> 4];
127 *(ptr++) = xd[b & 0xf];
128 }
129}
130
131static void evmgr_put(struct zbuf *zb, const char *fmt, ...)
132{
133 const char *pos, *nxt, *str;
134 const uint8_t *bin;
135 const union sockunion *su;
136 int len;
137 va_list va;
138
139 va_start(va, fmt);
140 for (pos = fmt; (nxt = strchr(pos, '%')) != NULL; pos = nxt + 2) {
996c9314 141 zbuf_put(zb, pos, nxt - pos);
2fb975da
TT
142 switch (nxt[1]) {
143 case '%':
144 zbuf_put8(zb, '%');
145 break;
146 case 'u':
996c9314
LB
147 zb->tail +=
148 snprintf((char *)zb->tail, zbuf_tailroom(zb),
149 "%u", va_arg(va, uint32_t));
2fb975da
TT
150 break;
151 case 's':
152 str = va_arg(va, const char *);
153 zbuf_put(zb, str, strlen(str));
154 break;
155 case 'U':
156 su = va_arg(va, const union sockunion *);
996c9314
LB
157 if (sockunion2str(su, (char *)zb->tail,
158 zbuf_tailroom(zb)))
159 zb->tail += strlen((char *)zb->tail);
2fb975da
TT
160 else
161 zbuf_set_werror(zb);
162 break;
163 case 'H':
164 bin = va_arg(va, const uint8_t *);
165 len = va_arg(va, int);
166 evmgr_hexdump(zb, bin, len);
167 break;
168 }
169 }
170 va_end(va);
171 zbuf_put(zb, pos, strlen(pos));
172}
173
174static void evmgr_submit(struct event_manager *evmgr, struct zbuf *obuf)
175{
176 if (obuf->error) {
177 zbuf_free(obuf);
178 return;
179 }
180 zbuf_put(obuf, "\n", 1);
181 zbufq_queue(&evmgr->obuf, obuf);
182 if (evmgr->fd >= 0)
ffa2c898
QY
183 thread_add_write(master, evmgr_write, evmgr, evmgr->fd,
184 &evmgr->t_write);
2fb975da
TT
185}
186
187static int evmgr_reconnect(struct thread *t)
188{
189 struct event_manager *evmgr = THREAD_ARG(t);
190 int fd;
191
192 evmgr->t_reconnect = NULL;
996c9314
LB
193 if (evmgr->fd >= 0 || !nhrp_event_socket_path)
194 return 0;
2fb975da
TT
195
196 fd = sock_open_unix(nhrp_event_socket_path);
197 if (fd < 0) {
198 zlog_warn("%s: failure connecting nhrp-event socket: %s",
996c9314 199 __PRETTY_FUNCTION__, strerror(errno));
2fb975da 200 zbufq_reset(&evmgr->obuf);
ffa2c898
QY
201 thread_add_timer(master, evmgr_reconnect, evmgr, 10,
202 &evmgr->t_reconnect);
2fb975da
TT
203 return 0;
204 }
205
206 zlog_info("Connected to Event Manager");
207 evmgr->fd = fd;
ffa2c898 208 thread_add_read(master, evmgr_read, evmgr, evmgr->fd, &evmgr->t_read);
2fb975da
TT
209
210 return 0;
211}
212
213static struct event_manager evmgr_connection;
214
215void evmgr_init(void)
216{
217 struct event_manager *evmgr = &evmgr_connection;
218
219 evmgr->fd = -1;
220 zbuf_init(&evmgr->ibuf, evmgr->ibuf_data, sizeof(evmgr->ibuf_data), 0);
221 zbufq_init(&evmgr->obuf);
ffa2c898
QY
222 thread_add_timer_msec(master, evmgr_reconnect, evmgr, 10,
223 &evmgr->t_reconnect);
2fb975da
TT
224}
225
226void evmgr_set_socket(const char *socket)
227{
d258c885 228 if (nhrp_event_socket_path) {
996c9314 229 free((char *)nhrp_event_socket_path);
d258c885
DS
230 nhrp_event_socket_path = NULL;
231 }
232 if (socket)
233 nhrp_event_socket_path = strdup(socket);
2fb975da
TT
234 evmgr_connection_error(&evmgr_connection);
235}
236
237void evmgr_terminate(void)
238{
239}
240
996c9314
LB
241void evmgr_notify(const char *name, struct nhrp_cache *c,
242 void (*cb)(struct nhrp_reqid *, void *))
2fb975da
TT
243{
244 struct event_manager *evmgr = &evmgr_connection;
245 struct nhrp_vc *vc;
246 struct nhrp_interface *nifp = c->ifp->info;
247 struct zbuf *zb;
248 afi_t afi = family2afi(sockunion_family(&c->remote_addr));
249
250 if (!nhrp_event_socket_path) {
996c9314 251 cb(&c->eventid, (void *)"accept");
2fb975da
TT
252 return;
253 }
254
255 debugf(NHRP_DEBUG_EVENT, "evmgr: sending event %s", name);
256
257 vc = c->new.peer ? c->new.peer->vc : NULL;
996c9314
LB
258 zb = zbuf_alloc(
259 1024 + (vc ? (vc->local.certlen + vc->remote.certlen) * 2 : 0));
2fb975da
TT
260
261 if (cb) {
262 nhrp_reqid_free(&nhrp_event_reqid, &c->eventid);
996c9314
LB
263 evmgr_put(zb, "eventid=%u\n",
264 nhrp_reqid_alloc(&nhrp_event_reqid, &c->eventid, cb));
2fb975da
TT
265 }
266
267 evmgr_put(zb,
996c9314
LB
268 "event=%s\n"
269 "type=%s\n"
270 "old_type=%s\n"
271 "num_nhs=%u\n"
272 "interface=%s\n"
273 "local_addr=%U\n",
274 name, nhrp_cache_type_str[c->new.type],
275 nhrp_cache_type_str[c->cur.type],
276 (unsigned int)nhrp_cache_counts[NHRP_CACHE_NHS], c->ifp->name,
277 &nifp->afi[afi].addr);
2fb975da
TT
278
279 if (vc) {
280 evmgr_put(zb,
996c9314
LB
281 "vc_initiated=%s\n"
282 "local_nbma=%U\n"
283 "local_cert=%H\n"
284 "remote_addr=%U\n"
285 "remote_nbma=%U\n"
286 "remote_cert=%H\n",
287 c->new.peer->requested ? "yes" : "no",
288 &vc->local.nbma, vc->local.cert, vc->local.certlen,
289 &c->remote_addr, &vc->remote.nbma, vc->remote.cert,
290 vc->remote.certlen);
2fb975da
TT
291 }
292
293 evmgr_submit(evmgr, zb);
294}