1 /* $NetBSD: evt.c,v 1.8 2008/12/23 14:03:12 tteras Exp $ */
3 /* Id: evt.c,v 1.5 2006/06/22 20:11:35 manubsd Exp */
6 * Copyright (C) 2004 Emmanuel Dreyfus
7 * Copyright (C) 2008 Timo Teras
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the project nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 #include <sys/queue.h>
44 #include <sys/socket.h>
56 #ifdef ENABLE_ADMINPORT
58 static EVT_LISTENER_LIST(evt_listeners
);
67 TAILQ_ENTRY(evt
) next
;
70 TAILQ_HEAD(evtlist
, evt
);
72 #define EVTLIST_MAX 32
74 static struct evtlist evtlist
= TAILQ_HEAD_INITIALIZER(evtlist
);
75 static int evtlist_len
= 0;
76 static int evtlist_inuse
= 0;
81 { EVT_RACOON_QUIT
, EVTT_RACOON_QUIT
},
82 { EVT_PHASE1_UP
, EVTT_PHASE1_UP
},
83 { EVT_PHASE1_DOWN
, EVTT_PHASE1_DOWN
},
84 { EVT_PHASE1_NO_RESPONSE
, EVTT_PEER_NO_RESPONSE
},
85 { EVT_PHASE1_NO_PROPOSAL
, EVTT_PEERPH1_NOPROP
},
86 { EVT_PHASE1_AUTH_FAILED
, EVTT_PEERPH1AUTH_FAILED
},
87 { EVT_PHASE1_DPD_TIMEOUT
, EVTT_DPD_TIMEOUT
},
88 { EVT_PHASE1_PEER_DELETED
, EVTT_PEER_DELETE
},
89 { EVT_PHASE1_MODE_CFG
, EVTT_ISAKMP_CFG_DONE
},
90 { EVT_PHASE1_XAUTH_SUCCESS
, EVTT_XAUTH_SUCCESS
},
91 { EVT_PHASE1_XAUTH_FAILED
, EVTT_XAUTH_FAILED
},
92 { EVT_PHASE2_NO_PHASE1
, -1 },
93 { EVT_PHASE2_UP
, EVTT_PHASE2_UP
},
94 { EVT_PHASE2_DOWN
, EVTT_PHASE2_DOWN
},
95 { EVT_PHASE2_NO_RESPONSE
, EVTT_PEER_NO_RESPONSE
},
99 evt_push(src
, dst
, type
, optdata
)
100 struct sockaddr
*src
;
101 struct sockaddr
*dst
;
105 struct evtdump
*evtdump
;
110 /* If admin socket is disabled, silently discard anything */
111 if (adminsock_path
== NULL
|| !evtlist_inuse
)
114 /* Map the event type to old */
115 for (i
= 0; i
< sizeof(evttype_map
) / sizeof(evttype_map
[0]); i
++)
116 if (evttype_map
[i
].newtype
== type
)
118 if (i
>= sizeof(evttype_map
) / sizeof(evttype_map
[0]))
121 type
= evttype_map
[i
].oldtype
;
125 /* If we are above the limit, don't record anything */
126 if (evtlist_len
> EVTLIST_MAX
) {
127 plog(LLV_DEBUG
, LOCATION
, NULL
,
128 "Cannot record event: event queue overflowed\n");
132 /* If we hit the limit, record an overflow event instead */
133 if (evtlist_len
== EVTLIST_MAX
) {
134 plog(LLV_ERROR
, LOCATION
, NULL
,
135 "Cannot record event: event queue overflow\n");
138 type
= EVTT_OVERFLOW
;
142 len
= sizeof(*evtdump
);
146 if ((evtdump
= racoon_malloc(len
)) == NULL
) {
147 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot record event: %s\n",
152 if ((evt
= racoon_malloc(sizeof(*evt
))) == NULL
) {
153 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot record event: %s\n",
155 racoon_free(evtdump
);
160 memcpy(&evtdump
->src
, src
, sysdep_sa_len(src
));
162 memcpy(&evtdump
->dst
, dst
, sysdep_sa_len(dst
));
164 evtdump
->type
= type
;
165 time(&evtdump
->timestamp
);
168 memcpy(evtdump
+ 1, optdata
->v
, optdata
->l
);
171 TAILQ_INSERT_TAIL(&evtlist
, evt
, next
);
178 static struct evtdump
*
180 struct evtdump
*evtdump
;
183 if ((evt
= TAILQ_FIRST(&evtlist
)) == NULL
)
187 TAILQ_REMOVE(&evtlist
, evt
, next
);
196 struct evtdump
*evtdump
;
199 if (!evtlist_inuse
) {
201 plog(LLV_ERROR
, LOCATION
, NULL
,
202 "evt_dump: deprecated event polling used\n");
205 if ((evtdump
= evt_pop()) != NULL
) {
206 if ((buf
= vmalloc(evtdump
->len
)) == NULL
) {
207 plog(LLV_ERROR
, LOCATION
, NULL
,
208 "evt_dump failed: %s\n", strerror(errno
));
211 memcpy(buf
->v
, evtdump
, evtdump
->len
);
212 racoon_free(evtdump
);
218 static struct evt_message
*
219 evtmsg_create(type
, optdata
)
223 struct evt_message
*e
;
226 len
= sizeof(struct evt_message
);
230 if ((e
= racoon_malloc(len
)) == NULL
) {
231 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate event: %s\n",
236 memset(e
, 0, sizeof(struct evt_message
));
238 e
->adm
.ac_cmd
= ADMIN_SHOW_EVT
;
241 e
->evt
.ec_type
= type
;
242 time(&e
->evt
.ec_timestamp
);
244 memcpy(e
+ 1, optdata
->v
, optdata
->l
);
251 struct evt_listener
*l
;
253 plog(LLV_DEBUG
, LOCATION
, NULL
,
254 "[%d] admin connection released\n", l
->fd
);
256 LIST_REMOVE(l
, ll_chain
);
263 evt_unsubscribe_cb(ctx
, fd
)
267 evt_unsubscribe((struct evt_listener
*) ctx
);
272 evtmsg_broadcast(ll
, e
)
273 const struct evt_listener_list
*ll
;
274 struct evt_message
*e
;
276 struct evt_listener
*l
, *nl
;
278 for (l
= LIST_FIRST(ll
); l
!= NULL
; l
= nl
) {
279 nl
= LIST_NEXT(l
, ll_chain
);
281 if (send(l
->fd
, e
, e
->adm
.ac_len
, MSG_DONTWAIT
) < 0) {
282 plog(LLV_DEBUG
, LOCATION
, NULL
, "Cannot send event to fd: %s\n",
290 evt_generic(type
, optdata
)
294 struct evt_message
*e
;
296 if ((e
= evtmsg_create(type
, optdata
)) == NULL
)
299 evtmsg_broadcast(&evt_listeners
, e
);
300 evt_push(&e
->evt
.ec_ph1src
, &e
->evt
.ec_ph1dst
, type
, optdata
);
306 evt_phase1(ph1
, type
, optdata
)
307 const struct ph1handle
*ph1
;
311 struct evt_message
*e
;
313 if ((e
= evtmsg_create(type
, optdata
)) == NULL
)
317 memcpy(&e
->evt
.ec_ph1src
, ph1
->local
, sysdep_sa_len(ph1
->local
));
319 memcpy(&e
->evt
.ec_ph1dst
, ph1
->remote
, sysdep_sa_len(ph1
->remote
));
321 evtmsg_broadcast(&ph1
->evt_listeners
, e
);
322 evtmsg_broadcast(&evt_listeners
, e
);
323 evt_push(&e
->evt
.ec_ph1src
, &e
->evt
.ec_ph1dst
, type
, optdata
);
329 evt_phase2(ph2
, type
, optdata
)
330 const struct ph2handle
*ph2
;
334 struct evt_message
*e
;
335 struct ph1handle
*ph1
= ph2
->ph1
;
337 if ((e
= evtmsg_create(type
, optdata
)) == NULL
)
342 memcpy(&e
->evt
.ec_ph1src
, ph1
->local
, sysdep_sa_len(ph1
->local
));
344 memcpy(&e
->evt
.ec_ph1dst
, ph1
->remote
, sysdep_sa_len(ph1
->remote
));
346 e
->evt
.ec_ph2msgid
= ph2
->msgid
;
348 evtmsg_broadcast(&ph2
->evt_listeners
, e
);
350 evtmsg_broadcast(&ph1
->evt_listeners
, e
);
351 evtmsg_broadcast(&evt_listeners
, e
);
352 evt_push(&e
->evt
.ec_ph1src
, &e
->evt
.ec_ph1dst
, type
, optdata
);
358 evt_subscribe(list
, fd
)
359 struct evt_listener_list
*list
;
362 struct evt_listener
*l
;
364 if ((l
= racoon_malloc(sizeof(*l
))) == NULL
) {
365 plog(LLV_ERROR
, LOCATION
, NULL
,
366 "Cannot allocate event listener: %s\n",
372 list
= &evt_listeners
;
374 LIST_INSERT_HEAD(list
, l
, ll_chain
);
376 monitor_fd(l
->fd
, evt_unsubscribe_cb
, l
);
378 plog(LLV_DEBUG
, LOCATION
, NULL
,
379 "[%d] admin connection is polling events\n", fd
);
386 struct evt_listener_list
*list
;
392 evt_list_cleanup(list
)
393 struct evt_listener_list
*list
;
395 while (!LIST_EMPTY(list
))
396 evt_unsubscribe(LIST_FIRST(list
));
399 #endif /* ENABLE_ADMINPORT */