Annotation of embedaddon/strongswan/src/libcharon/plugins/uci/uci_control.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008 Thomas Kallenberg
        !             3:  * Copyright (C) 2008 Martin Willi
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #define _GNU_SOURCE
        !            18: #include <string.h>
        !            19: #include <stdio.h>
        !            20: #include <unistd.h>
        !            21: #include <sys/types.h>
        !            22: #include <sys/stat.h>
        !            23: #include <errno.h>
        !            24: 
        !            25: #include "uci_control.h"
        !            26: 
        !            27: #include <daemon.h>
        !            28: #include <threading/thread.h>
        !            29: #include <processing/jobs/callback_job.h>
        !            30: 
        !            31: #define FIFO_FILE "/var/run/charon.fifo"
        !            32: 
        !            33: 
        !            34: typedef struct private_uci_control_t private_uci_control_t;
        !            35: 
        !            36: /**
        !            37:  * private data of uci_control_t
        !            38:  */
        !            39: struct private_uci_control_t {
        !            40: 
        !            41:        /**
        !            42:         * Public part
        !            43:         */
        !            44:        uci_control_t public;
        !            45: };
        !            46: 
        !            47: /**
        !            48:  * write answer to fifo
        !            49:  */
        !            50: static void write_fifo(private_uci_control_t *this, char *format, ...)
        !            51: {
        !            52:        va_list args;
        !            53:        FILE *out;
        !            54: 
        !            55:        out = fopen(FIFO_FILE, "w");
        !            56:        if (out)
        !            57:        {
        !            58:                va_start(args, format);
        !            59:                vfprintf(out, format, args);
        !            60:                va_end(args);
        !            61:                fclose(out);
        !            62:        }
        !            63:        else
        !            64:        {
        !            65:                DBG1(DBG_CFG, "writing to UCI fifo failed: %s", strerror(errno));
        !            66:        }
        !            67: }
        !            68: 
        !            69: /**
        !            70:  * print IKE_SA status information
        !            71:  */
        !            72: static void status(private_uci_control_t *this, char *name)
        !            73: {
        !            74:        enumerator_t *configs, *sas, *children;
        !            75:        linked_list_t *list;
        !            76:        ike_sa_t *ike_sa;
        !            77:        child_sa_t *child_sa;
        !            78:        peer_cfg_t *peer_cfg;
        !            79:        char buf[2048];
        !            80:        FILE *out = NULL;
        !            81: 
        !            82:        configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
        !            83:                                                                                        NULL, NULL, NULL, NULL, IKE_ANY);
        !            84:        while (configs->enumerate(configs, &peer_cfg))
        !            85:        {
        !            86:                if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
        !            87:                {
        !            88:                        continue;
        !            89:                }
        !            90:                sas = charon->controller->create_ike_sa_enumerator(
        !            91:                                                                                                        charon->controller, TRUE);
        !            92:                while (sas->enumerate(sas, &ike_sa))
        !            93:                {
        !            94:                        if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg)))
        !            95:                        {
        !            96:                                continue;
        !            97:                        }
        !            98:                        if (!out)
        !            99:                        {
        !           100:                                out = fmemopen(buf, sizeof(buf), "w");
        !           101:                                if (!out)
        !           102:                                {
        !           103:                                        continue;
        !           104:                                }
        !           105:                        }
        !           106:                        fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
        !           107:                                ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
        !           108: 
        !           109:                        children = ike_sa->create_child_sa_enumerator(ike_sa);
        !           110:                        while (children->enumerate(children, (void**)&child_sa))
        !           111:                        {
        !           112:                                list = linked_list_create_from_enumerator(
        !           113:                                                        child_sa->create_ts_enumerator(child_sa, FALSE));
        !           114:                                fprintf(out, "%#R", list);
        !           115:                                list->destroy(list);
        !           116:                        }
        !           117:                        children->destroy(children);
        !           118:                        fprintf(out, "\n");
        !           119:                }
        !           120:                sas->destroy(sas);
        !           121:        }
        !           122:        configs->destroy(configs);
        !           123:        if (out)
        !           124:        {
        !           125:                fclose(out);
        !           126:                write_fifo(this, "%s", buf);
        !           127:        }
        !           128:        else
        !           129:        {
        !           130:                write_fifo(this, "");
        !           131:        }
        !           132: }
        !           133: 
        !           134: /**
        !           135:  * Initiate an IKE_SA
        !           136:  */
        !           137: static void initiate(private_uci_control_t *this, char *name)
        !           138: {
        !           139:        peer_cfg_t *peer_cfg;
        !           140:        child_cfg_t *child_cfg;
        !           141:        enumerator_t *enumerator;
        !           142: 
        !           143:        peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
        !           144:        if (peer_cfg)
        !           145:        {
        !           146:                enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
        !           147:                if (enumerator->enumerate(enumerator, &child_cfg) &&
        !           148:                        charon->controller->initiate(charon->controller, peer_cfg,
        !           149:                                                                child_cfg->get_ref(child_cfg),
        !           150:                                                                controller_cb_empty, NULL, 0, FALSE) == SUCCESS)
        !           151:                {
        !           152:                        write_fifo(this, "connection '%s' established\n", name);
        !           153:                }
        !           154:                else
        !           155:                {
        !           156:                        write_fifo(this, "establishing connection '%s' failed\n", name);
        !           157:                }
        !           158:                enumerator->destroy(enumerator);
        !           159:        }
        !           160:        else
        !           161:        {
        !           162:                write_fifo(this, "no connection named '%s' found\n", name);
        !           163:        }
        !           164: }
        !           165: 
        !           166: /**
        !           167:  * terminate an IKE_SA
        !           168:  */
        !           169: static void terminate(private_uci_control_t *this, char *name)
        !           170: {
        !           171:        enumerator_t *enumerator;
        !           172:        ike_sa_t *ike_sa;
        !           173:        u_int id;
        !           174: 
        !           175:        enumerator = charon->controller->create_ike_sa_enumerator(
        !           176:                                                                                                        charon->controller, TRUE);
        !           177:        while (enumerator->enumerate(enumerator, &ike_sa))
        !           178:        {
        !           179:                if (streq(name, ike_sa->get_name(ike_sa)))
        !           180:                {
        !           181:                        id = ike_sa->get_unique_id(ike_sa);
        !           182:                        enumerator->destroy(enumerator);
        !           183:                        charon->controller->terminate_ike(charon->controller, id, FALSE,
        !           184:                                                                                          controller_cb_empty, NULL, 0);
        !           185:                        write_fifo(this, "connection '%s' terminated\n", name);
        !           186:                        return;
        !           187:                }
        !           188:        }
        !           189:        enumerator->destroy(enumerator);
        !           190:        write_fifo(this, "no active connection named '%s'\n", name);
        !           191: }
        !           192: 
        !           193: /**
        !           194:  * dispatch control request
        !           195:  */
        !           196: static void process(private_uci_control_t *this, char *message)
        !           197: {
        !           198:        enumerator_t* enumerator;
        !           199: 
        !           200:        enumerator = enumerator_create_token(message, " \n", "");
        !           201:        if (enumerator->enumerate(enumerator, &message))
        !           202:        {
        !           203:                if (streq(message, "status"))
        !           204:                {
        !           205:                        if (enumerator->enumerate(enumerator, &message))
        !           206:                        {
        !           207:                                status(this, message);
        !           208:                        }
        !           209:                        else
        !           210:                        {
        !           211:                                status(this, NULL);
        !           212:                        }
        !           213:                }
        !           214:                else if (streq(message, "up") &&
        !           215:                                 enumerator->enumerate(enumerator, &message))
        !           216:                {
        !           217:                        initiate(this, message);
        !           218:                }
        !           219:                else if (streq(message, "down") &&
        !           220:                                 enumerator->enumerate(enumerator, &message))
        !           221:                {
        !           222:                        terminate(this, message);
        !           223:                }
        !           224:                else
        !           225:                {
        !           226:                        write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
        !           227:                                           "  status format: name peer-id peer-addr tunnel(s)\n");
        !           228:                }
        !           229:        }
        !           230:        enumerator->destroy(enumerator);
        !           231: }
        !           232: 
        !           233: /**
        !           234:  * read from fifo
        !           235:  */
        !           236: static job_requeue_t receive(private_uci_control_t *this)
        !           237: {
        !           238:        char message[128];
        !           239:        int len;
        !           240:        bool oldstate;
        !           241:        FILE *in;
        !           242: 
        !           243:        memset(message, 0, sizeof(message));
        !           244:        oldstate = thread_cancelability(TRUE);
        !           245:        in = fopen(FIFO_FILE, "r");
        !           246:        thread_cancelability(oldstate);
        !           247:        if (in)
        !           248:        {
        !           249:                len = fread(message, 1, sizeof(message) - 1, in);
        !           250:                fclose(in);
        !           251:                if (len > 0)
        !           252:                {
        !           253:                        process(this, message);
        !           254:                }
        !           255:                else
        !           256:                {
        !           257:                        DBG1(DBG_DMN, "reading from UCI fifo failed: %s", strerror(errno));
        !           258:                }
        !           259:        }
        !           260:        else
        !           261:        {
        !           262:                DBG1(DBG_DMN, "opening UCI fifo failed: %s", strerror(errno));
        !           263:        }
        !           264:        return JOB_REQUEUE_FAIR;
        !           265: }
        !           266: 
        !           267: METHOD(uci_control_t, destroy, void,
        !           268:        private_uci_control_t *this)
        !           269: {
        !           270:        unlink(FIFO_FILE);
        !           271:        free(this);
        !           272: }
        !           273: 
        !           274: /**
        !           275:  * Described in header.
        !           276:  */
        !           277: uci_control_t *uci_control_create()
        !           278: {
        !           279:        private_uci_control_t *this;
        !           280: 
        !           281:        INIT(this,
        !           282:                .public = {
        !           283:                        .destroy = _destroy,
        !           284:                },
        !           285:        );
        !           286: 
        !           287:        unlink(FIFO_FILE);
        !           288:        if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
        !           289:        {
        !           290:                DBG1(DBG_CFG, "creating UCI control fifo '%s' failed: %s",
        !           291:                         FIFO_FILE, strerror(errno));
        !           292:        }
        !           293:        else
        !           294:        {
        !           295:                lib->processor->queue_job(lib->processor,
        !           296:                        (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive,
        !           297:                                                        this, NULL, (callback_job_cancel_t)return_false,
        !           298:                                                        JOB_PRIO_CRITICAL));
        !           299:        }
        !           300:        return &this->public;
        !           301: }

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