Return to gateway.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / manager |
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: