Annotation of embedaddon/ipsec-tools/src/racoon/evt.c, revision 1.1
1.1 ! misho 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>