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>