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>