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>