File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / manager / gateway.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 1 month ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2007 Martin Willi
    3:  * HSR Hochschule fuer Technik Rapperswil
    4:  *
    5:  * This program is free software; you can redistribute it and/or modify it
    6:  * under the terms of the GNU General Public License as published by the
    7:  * Free Software Foundation; either version 2 of the License, or (at your
    8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
    9:  *
   10:  * This program is distributed in the hope that it will be useful, but
   11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13:  * for more details.
   14:  */
   15: 
   16: #include "gateway.h"
   17: 
   18: #include <sys/types.h>
   19: #include <sys/socket.h>
   20: #include <unistd.h>
   21: #include <string.h>
   22: #include <sys/socket.h>
   23: #include <sys/un.h>
   24: 
   25: #include <xml.h>
   26: 
   27: typedef struct private_gateway_t private_gateway_t;
   28: 
   29: /**
   30:  * private data of gateway
   31:  */
   32: struct private_gateway_t {
   33: 
   34: 	/**
   35: 	 * public functions
   36: 	 */
   37: 	gateway_t public;
   38: 
   39: 	/**
   40: 	 * name of the gateway
   41: 	 */
   42: 	char *name;
   43: 
   44: 	/**
   45: 	 * host to connect using tcp
   46: 	 */
   47: 	host_t *host;
   48: 
   49: 	/**
   50: 	 * socket file descriptor, > 0 if connected
   51: 	 */
   52: 	int fd;
   53: 
   54: 	/**
   55: 	 * unique id assigned to each xml message
   56: 	 */
   57: 	int xmlid;
   58: };
   59: 
   60: struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
   61: 
   62: /**
   63:  * establish connection to gateway
   64:  */
   65: static bool connect_(private_gateway_t *this)
   66: {
   67: 	int family, len;
   68: 	struct sockaddr *addr;
   69: 
   70: 	if (this->fd >= 0)
   71: 	{
   72: 		close(this->fd);
   73: 	}
   74: 	if (this->host)
   75: 	{
   76: 		family = AF_INET;
   77: 		addr = this->host->get_sockaddr(this->host);
   78: 		len = *this->host->get_sockaddr_len(this->host);
   79: 	}
   80: 	else
   81: 	{
   82: 		family = AF_UNIX;
   83: 		addr = (struct sockaddr*)&unix_addr;
   84: 		len = sizeof(unix_addr);
   85: 	}
   86: 
   87: 	this->fd = socket(family, SOCK_STREAM, 0);
   88: 	if (this->fd < 0)
   89: 	{
   90: 		return FALSE;
   91: 	}
   92: 	if (connect(this->fd, addr, len) != 0)
   93: 	{
   94: 		close(this->fd);
   95: 		this->fd = -1;
   96: 		return FALSE;
   97: 	}
   98: 	return TRUE;
   99: }
  100: 
  101: METHOD(gateway_t, request, char*,
  102: 	private_gateway_t *this, char *xml, ...)
  103: {
  104: 	if (this->fd < 0)
  105: 	{
  106: 		if (!connect_(this))
  107: 		{
  108: 			return NULL;
  109: 		}
  110: 	}
  111: 	while (TRUE)
  112: 	{
  113: 		char buf[8096];
  114: 		ssize_t len;
  115: 		va_list args;
  116: 
  117: 		va_start(args, xml);
  118: 		len = vsnprintf(buf, sizeof(buf), xml, args);
  119: 		va_end(args);
  120: 		if (len < 0 || len >= sizeof(buf))
  121: 		{
  122: 			return NULL;
  123: 		}
  124: 		if (send(this->fd, buf, len, 0) != len)
  125: 		{
  126: 			if (!connect_(this))
  127: 			{
  128: 				return NULL;
  129: 			}
  130: 			continue;
  131: 		}
  132: 		len = recv(this->fd, buf, sizeof(buf) - 1, 0);
  133: 		if (len <= 0)
  134: 		{
  135: 			if (!connect_(this))
  136: 			{
  137: 				return NULL;
  138: 			}
  139: 			continue;
  140: 		}
  141: 		buf[len] = 0;
  142: 		return strdup(buf);
  143: 	}
  144: }
  145: 
  146: METHOD(gateway_t, query_ikesalist, enumerator_t*,
  147: 	private_gateway_t *this)
  148: {
  149: 	char *str, *name, *value;
  150: 	xml_t *xml;
  151: 	enumerator_t *e1, *e2, *e3, *e4 = NULL;
  152: 
  153: 	str = request(this,	"<message type=\"request\" id=\"%d\">"
  154: 							"<query>"
  155: 								"<ikesalist/>"
  156: 							"</query>"
  157: 						"</message>", this->xmlid++);
  158: 	if (str == NULL)
  159: 	{
  160: 		return NULL;
  161: 	}
  162: 	xml = xml_create(str);
  163: 	if (xml == NULL)
  164: 	{
  165: 		return NULL;
  166: 	}
  167: 
  168: 	e1 = xml->children(xml);
  169: 	free(str);
  170: 	while (e1->enumerate(e1, &xml, &name, &value))
  171: 	{
  172: 		if (streq(name, "message"))
  173: 		{
  174: 			e2 = xml->children(xml);
  175: 			while (e2->enumerate(e2, &xml, &name, &value))
  176: 			{
  177: 				if (streq(name, "query"))
  178: 				{
  179: 					e3 = xml->children(xml);
  180: 					while (e3->enumerate(e3, &xml, &name, &value))
  181: 					{
  182: 						if (streq(name, "ikesalist"))
  183: 						{
  184: 							e4 = xml->children(xml);
  185: 							e1->destroy(e1);
  186: 							e2->destroy(e2);
  187: 							e3->destroy(e3);
  188: 							return e4;
  189: 						}
  190: 					}
  191: 					e3->destroy(e3);
  192: 				}
  193: 			}
  194: 			e2->destroy(e2);
  195: 		}
  196: 	}
  197: 	e1->destroy(e1);
  198: 	return NULL;
  199: }
  200: 
  201: METHOD(gateway_t, query_configlist, enumerator_t*,
  202: 	private_gateway_t *this)
  203: {
  204: 	char *str, *name, *value;
  205: 	xml_t *xml;
  206: 	enumerator_t *e1, *e2, *e3, *e4 = NULL;
  207: 
  208: 	str = request(this,	"<message type=\"request\" id=\"%d\">"
  209: 							"<query>"
  210: 								"<configlist/>"
  211: 							"</query>"
  212: 						"</message>", this->xmlid++);
  213: 	if (str == NULL)
  214: 	{
  215: 		return NULL;
  216: 	}
  217: 	xml = xml_create(str);
  218: 	if (xml == NULL)
  219: 	{
  220: 		return NULL;
  221: 	}
  222: 
  223: 	e1 = xml->children(xml);
  224: 	free(str);
  225: 	while (e1->enumerate(e1, &xml, &name, &value))
  226: 	{
  227: 		if (streq(name, "message"))
  228: 		{
  229: 			e2 = xml->children(xml);
  230: 			while (e2->enumerate(e2, &xml, &name, &value))
  231: 			{
  232: 				if (streq(name, "query"))
  233: 				{
  234: 					e3 = xml->children(xml);
  235: 					while (e3->enumerate(e3, &xml, &name, &value))
  236: 					{
  237: 						if (streq(name, "configlist"))
  238: 						{
  239: 							e4 = xml->children(xml);
  240: 							e1->destroy(e1);
  241: 							e2->destroy(e2);
  242: 							e3->destroy(e3);
  243: 							return e4;
  244: 						}
  245: 					}
  246: 					e3->destroy(e3);
  247: 				}
  248: 			}
  249: 			e2->destroy(e2);
  250: 		}
  251: 	}
  252: 	e1->destroy(e1);
  253: 	return NULL;
  254: }
  255: 
  256: /**
  257:  * create enumerator over control elements children of a control response
  258:  */
  259: static enumerator_t* read_result(private_gateway_t *this, char *res)
  260: {
  261: 	char *name, *value;
  262: 	xml_t *xml;
  263: 	enumerator_t *e1, *e2, *e3;
  264: 
  265: 	if (res == NULL)
  266: 	{
  267: 		return NULL;
  268: 	}
  269: 	xml = xml_create(res);
  270: 	if (xml == NULL)
  271: 	{
  272: 		return NULL;
  273: 	}
  274: 	e1 = xml->children(xml);
  275: 	free(res);
  276: 	while (e1->enumerate(e1, &xml, &name, &value))
  277: 	{
  278: 		if (streq(name, "message"))
  279: 		{
  280: 			e2 = xml->children(xml);
  281: 			while (e2->enumerate(e2, &xml, &name, &value))
  282: 			{
  283: 				if (streq(name, "control"))
  284: 				{
  285: 					e3 = xml->children(xml);
  286: 					e1->destroy(e1);
  287: 					e2->destroy(e2);
  288: 					return e3;
  289: 				}
  290: 			}
  291: 			e2->destroy(e2);
  292: 		}
  293: 	}
  294: 	e1->destroy(e1);
  295: 	return NULL;
  296: }
  297: 
  298: METHOD(gateway_t, initiate, enumerator_t*,
  299: 	private_gateway_t *this, bool ike, char *name)
  300: {
  301: 	char *str, *kind;
  302: 
  303: 	if (ike)
  304: 	{
  305: 		kind = "ike";
  306: 	}
  307: 	else
  308: 	{
  309: 		kind = "child";
  310: 	}
  311: 	str = request(this,	"<message type=\"request\" id=\"%d\">"
  312: 							"<control>"
  313: 								"<%ssainitiate>%s</%ssainitiate>"
  314: 							"</control>"
  315: 						"</message>", this->xmlid++, kind, name, kind);
  316: 	return read_result(this, str);
  317: }
  318: 
  319: METHOD(gateway_t, terminate, enumerator_t*,
  320: 	private_gateway_t *this, bool ike, uint32_t id)
  321: {
  322: 	char *str, *kind;
  323: 
  324: 	if (ike)
  325: 	{
  326: 		kind = "ike";
  327: 	}
  328: 	else
  329: 	{
  330: 		kind = "child";
  331: 	}
  332: 	str = request(this,	"<message type=\"request\" id=\"%d\">"
  333: 							"<control>"
  334: 								"<%ssaterminate>%d</%ssaterminate>"
  335: 							"</control>"
  336: 						"</message>", this->xmlid++, kind, id, kind);
  337: 	return read_result(this, str);
  338: }
  339: 
  340: METHOD(gateway_t, destroy, void,
  341: 	private_gateway_t *this)
  342: {
  343: 	if (this->fd >= 0)
  344: 	{
  345: 		close(this->fd);
  346: 	}
  347: 	if (this->host) this->host->destroy(this->host);
  348: 	free(this->name);
  349: 	free(this);
  350: }
  351: 
  352: /**
  353:  * generic constructor
  354:  */
  355: static private_gateway_t *gateway_create(char *name)
  356: {
  357: 	private_gateway_t *this;
  358: 
  359: 	INIT(this,
  360: 		.public = {
  361: 			.request = _request,
  362: 			.query_ikesalist = _query_ikesalist,
  363: 			.query_configlist = _query_configlist,
  364: 			.initiate = _initiate,
  365: 			.terminate = _terminate,
  366: 			.destroy = _destroy,
  367: 		},
  368: 		.name = strdup(name),
  369: 		.fd = -1,
  370: 		.xmlid = 1,
  371: 	);
  372: 
  373: 	return this;
  374: }
  375: 
  376: /**
  377:  * see header
  378:  */
  379: gateway_t *gateway_create_tcp(char *name, host_t *host)
  380: {
  381: 	private_gateway_t *this = gateway_create(name);
  382: 
  383: 	this->host = host;
  384: 
  385: 	return &this->public;
  386: }
  387: 
  388: /**
  389:  * see header
  390:  */
  391: gateway_t *gateway_create_unix(char *name)
  392: {
  393: 	private_gateway_t *this = gateway_create(name);
  394: 
  395: 	return &this->public;
  396: }
  397: 

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