Return to evt.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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 */