Annotation of embedaddon/strongswan/src/manager/gateway.c, revision 1.1.1.1

1.1       misho       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>