Home | History | Annotate | Download | only in racoon
      1 /*	$NetBSD: evt.c,v 1.10 2010/10/21 06:15:28 tteras Exp $	*/
      2 
      3 /* Id: evt.c,v 1.5 2006/06/22 20:11:35 manubsd Exp */
      4 
      5 /*
      6  * Copyright (C) 2004 Emmanuel Dreyfus
      7  * Copyright (C) 2008 Timo Teras
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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.
     21  *
     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
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include "config.h"
     36 
     37 #include <errno.h>
     38 #include <string.h>
     39 #include <stdio.h>
     40 #include <time.h>
     41 #include <unistd.h>
     42 #include <stdlib.h>
     43 #include <sys/queue.h>
     44 #include <sys/socket.h>
     45 
     46 #include "vmbuf.h"
     47 #include "plog.h"
     48 #include "misc.h"
     49 #include "admin.h"
     50 #include "handler.h"
     51 #include "session.h"
     52 #include "gcmalloc.h"
     53 #include "evt.h"
     54 #include "var.h"
     55 
     56 #ifdef ENABLE_ADMINPORT
     57 
     58 static EVT_LISTENER_LIST(evt_listeners);
     59 
     60 struct evt_message {
     61 	struct admin_com adm;
     62 	struct evt_async evt;
     63 };
     64 
     65 struct evt {
     66 	struct evtdump *dump;
     67 	TAILQ_ENTRY(evt) next;
     68 };
     69 
     70 TAILQ_HEAD(evtlist, evt);
     71 
     72 #define EVTLIST_MAX	32
     73 
     74 static struct evtlist evtlist = TAILQ_HEAD_INITIALIZER(evtlist);
     75 static int evtlist_len = 0;
     76 static int evtlist_inuse = 0;
     77 
     78 static struct {
     79 	int newtype, oldtype;
     80 } evttype_map[] = {
     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 },
     96 };
     97 
     98 static void
     99 evt_push(src, dst, type, optdata)
    100 	struct sockaddr *src;
    101 	struct sockaddr *dst;
    102 	int type;
    103 	vchar_t *optdata;
    104 {
    105 	struct evtdump *evtdump;
    106 	struct evt *evt;
    107 	size_t len;
    108 	int i;
    109 
    110 	/* If admin socket is disabled, silently discard anything */
    111 	if (adminsock_path == NULL || !evtlist_inuse)
    112 		return;
    113 
    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)
    117 			break;
    118 	if (i >= sizeof(evttype_map) / sizeof(evttype_map[0]))
    119 		return;
    120 
    121 	type = evttype_map[i].oldtype;
    122 	if (type < 0)
    123 		return;
    124 
    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");
    129 		return;
    130 	}
    131 
    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");
    136 		src = NULL;
    137 		dst = NULL;
    138 		type = EVTT_OVERFLOW;
    139 		optdata = NULL;
    140 	}
    141 
    142 	len = sizeof(*evtdump);
    143 	if (optdata)
    144 		len += optdata->l;
    145 
    146 	if ((evtdump = racoon_malloc(len)) == NULL) {
    147 		plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
    148 		    strerror(errno));
    149 		return;
    150 	}
    151 
    152 	if ((evt = racoon_malloc(sizeof(*evt))) == NULL) {
    153 		plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
    154 		    strerror(errno));
    155 		racoon_free(evtdump);
    156 		return;
    157 	}
    158 
    159 	if (src)
    160 		memcpy(&evtdump->src, src, sysdep_sa_len(src));
    161 	if (dst)
    162 		memcpy(&evtdump->dst, dst, sysdep_sa_len(dst));
    163 	evtdump->len = len;
    164 	evtdump->type = type;
    165 	time(&evtdump->timestamp);
    166 
    167 	if (optdata)
    168 		memcpy(evtdump + 1, optdata->v, optdata->l);
    169 
    170 	evt->dump = evtdump;
    171 	TAILQ_INSERT_TAIL(&evtlist, evt, next);
    172 
    173 	evtlist_len++;
    174 
    175 	return;
    176 }
    177 
    178 static struct evtdump *
    179 evt_pop(void) {
    180 	struct evtdump *evtdump;
    181 	struct evt *evt;
    182 
    183 	if ((evt = TAILQ_FIRST(&evtlist)) == NULL)
    184 		return NULL;
    185 
    186 	evtdump = evt->dump;
    187 	TAILQ_REMOVE(&evtlist, evt, next);
    188 	racoon_free(evt);
    189 	evtlist_len--;
    190 
    191 	return evtdump;
    192 }
    193 
    194 vchar_t *
    195 evt_dump(void) {
    196 	struct evtdump *evtdump;
    197 	vchar_t *buf = NULL;
    198 
    199 	if (!evtlist_inuse) {
    200 		evtlist_inuse = 1;
    201 		plog(LLV_ERROR, LOCATION, NULL,
    202 		     "evt_dump: deprecated event polling used\n");
    203 	}
    204 
    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));
    209 			return NULL;
    210 		}
    211 		memcpy(buf->v, evtdump, evtdump->len);
    212 		racoon_free(evtdump);
    213 	}
    214 
    215 	return buf;
    216 }
    217 
    218 static struct evt_message *
    219 evtmsg_create(type, optdata)
    220 	int type;
    221 	vchar_t *optdata;
    222 {
    223 	struct evt_message *e;
    224 	size_t len;
    225 
    226 	len = sizeof(struct evt_message);
    227 	if (optdata != NULL)
    228 		len += optdata->l;
    229 
    230 	if ((e = racoon_malloc(len)) == NULL) {
    231 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate event: %s\n",
    232 		     strerror(errno));
    233 		return NULL;
    234 	}
    235 
    236 	memset(e, 0, sizeof(struct evt_message));
    237 	e->adm.ac_len = len;
    238 	e->adm.ac_cmd = ADMIN_SHOW_EVT;
    239 	e->adm.ac_errno = 0;
    240 	e->adm.ac_proto = 0;
    241 	e->evt.ec_type = type;
    242 	time(&e->evt.ec_timestamp);
    243 	if (optdata != NULL)
    244 		memcpy(e + 1, optdata->v, optdata->l);
    245 
    246 	return e;
    247 }
    248 
    249 static void
    250 evt_unsubscribe(l)
    251 	struct evt_listener *l;
    252 {
    253 	plog(LLV_DEBUG, LOCATION, NULL,
    254 	     "[%d] admin connection released\n", l->fd);
    255 
    256 	LIST_REMOVE(l, ll_chain);
    257 	unmonitor_fd(l->fd);
    258 	close(l->fd);
    259 	racoon_free(l);
    260 }
    261 
    262 static int
    263 evt_unsubscribe_cb(ctx, fd)
    264 	void *ctx;
    265 	int fd;
    266 {
    267 	evt_unsubscribe((struct evt_listener *) ctx);
    268 	return 0;
    269 }
    270 
    271 static void
    272 evtmsg_broadcast(ll, e)
    273 	const struct evt_listener_list *ll;
    274 	struct evt_message *e;
    275 {
    276 	struct evt_listener *l, *nl;
    277 
    278 	for (l = LIST_FIRST(ll); l != NULL; l = nl) {
    279 		nl = LIST_NEXT(l, ll_chain);
    280 
    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",
    283 				strerror(errno));
    284 			evt_unsubscribe(l);
    285 		}
    286 	}
    287 }
    288 
    289 void
    290 evt_generic(type, optdata)
    291 	int type;
    292 	vchar_t *optdata;
    293 {
    294 	struct evt_message *e;
    295 
    296 	if ((e = evtmsg_create(type, optdata)) == NULL)
    297 		return;
    298 
    299 	evtmsg_broadcast(&evt_listeners, e);
    300 	evt_push(&e->evt.ec_ph1src, &e->evt.ec_ph1dst, type, optdata);
    301 
    302 	racoon_free(e);
    303 }
    304 
    305 void
    306 evt_phase1(ph1, type, optdata)
    307 	const struct ph1handle *ph1;
    308 	int type;
    309 	vchar_t *optdata;
    310 {
    311 	struct evt_message *e;
    312 
    313 	if ((e = evtmsg_create(type, optdata)) == NULL)
    314 		return;
    315 
    316 	if (ph1->local)
    317 		memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local));
    318 	if (ph1->remote)
    319 		memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote));
    320 
    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);
    324 
    325 	racoon_free(e);
    326 }
    327 
    328 void
    329 evt_phase2(ph2, type, optdata)
    330 	const struct ph2handle *ph2;
    331 	int type;
    332 	vchar_t *optdata;
    333 {
    334 	struct evt_message *e;
    335 	struct ph1handle *ph1 = ph2->ph1;
    336 
    337 	if ((e = evtmsg_create(type, optdata)) == NULL)
    338 		return;
    339 
    340 	if (ph1) {
    341 		if (ph1->local)
    342 			memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local));
    343 		if (ph1->remote)
    344 			memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote));
    345 	}
    346 	e->evt.ec_ph2msgid = ph2->msgid;
    347 
    348 	evtmsg_broadcast(&ph2->evt_listeners, e);
    349 	if (ph1)
    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);
    353 
    354 	racoon_free(e);
    355 }
    356 
    357 int
    358 evt_subscribe(list, fd)
    359 	struct evt_listener_list *list;
    360 	int fd;
    361 {
    362 	struct evt_listener *l;
    363 
    364 	if ((l = racoon_malloc(sizeof(*l))) == NULL) {
    365 		plog(LLV_ERROR, LOCATION, NULL,
    366 		     "Cannot allocate event listener: %s\n",
    367 		     strerror(errno));
    368 		return errno;
    369 	}
    370 
    371 	if (list == NULL)
    372 		list = &evt_listeners;
    373 
    374 	LIST_INSERT_HEAD(list, l, ll_chain);
    375 	l->fd = fd;
    376 	monitor_fd(l->fd, evt_unsubscribe_cb, l, 0);
    377 
    378 	plog(LLV_DEBUG, LOCATION, NULL,
    379 	     "[%d] admin connection is polling events\n", fd);
    380 
    381 	return -2;
    382 }
    383 
    384 void
    385 evt_list_init(list)
    386 	struct evt_listener_list *list;
    387 {
    388 	LIST_INIT(list);
    389 }
    390 
    391 void
    392 evt_list_cleanup(list)
    393 	struct evt_listener_list *list;
    394 {
    395 	while (!LIST_EMPTY(list))
    396 		evt_unsubscribe(LIST_FIRST(list));
    397 }
    398 
    399 #endif /* ENABLE_ADMINPORT */
    400