Annotation of embedaddon/strongswan/src/libcharon/plugins/uci/uci_control.c, revision 1.1.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>