File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / evt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    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 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>