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