Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/endpoint_notify.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2007 Tobias Brunner
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 "endpoint_notify.h"
17:
18: #include <math.h>
19:
20: #include <daemon.h>
21:
22: typedef struct private_endpoint_notify_t private_endpoint_notify_t;
23:
24: /**
25: * Private data of an notify_payload_t object.
26: */
27: struct private_endpoint_notify_t {
28: /**
29: * Public endpoint_notify_t interface.
30: */
31: endpoint_notify_t public;
32:
33: /**
34: * Priority
35: */
36: uint32_t priority;
37:
38: /**
39: * Family
40: */
41: me_endpoint_family_t family;
42:
43: /**
44: * Endpoint type
45: */
46: me_endpoint_type_t type;
47:
48: /**
49: * Endpoint
50: */
51: host_t *endpoint;
52:
53: /**
54: * Base (used for server reflexive endpoints)
55: */
56: host_t *base;
57: };
58:
59: /* Notification data:
60: 1 2 3
61: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
62: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63: ! Priority !
64: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65: ! Family ! Type ! Port !
66: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67: ! IP Address (variable) !
68: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69: */
70:
71: ENUM(me_endpoint_type_names, HOST, RELAYED,
72: "HOST",
73: "PEER_REFLEXIVE",
74: "SERVER_REFLEXIVE",
75: "RELAYED"
76: );
77:
78: /**
79: * Forward declaration
80: */
81: static private_endpoint_notify_t *endpoint_notify_create();
82:
83: /**
84: * Helper functions to parse integer values
85: */
86: static status_t parse_uint8(uint8_t **cur, uint8_t *top, uint8_t *val)
87: {
88: if (*cur + sizeof(uint8_t) > top)
89: {
90: return FAILED;
91: }
92: *val = *(uint8_t*)*cur;
93: *cur += sizeof(uint8_t);
94: return SUCCESS;
95: }
96:
97: static status_t parse_uint16(uint8_t **cur, uint8_t *top, uint16_t *val)
98: {
99: if (*cur + sizeof(uint16_t) > top)
100: {
101: return FAILED;
102: }
103: *val = ntohs(*(uint16_t*)*cur);
104: *cur += sizeof(uint16_t);
105: return SUCCESS;
106: }
107:
108: static status_t parse_uint32(uint8_t **cur, uint8_t *top, uint32_t *val)
109: {
110: if (*cur + sizeof(uint32_t) > top)
111: {
112: return FAILED;
113: }
114: *val = ntohl(*(uint32_t*)*cur);
115: *cur += sizeof(uint32_t);
116: return SUCCESS;
117: }
118:
119: /**
120: * Parses the notification data of a ME_ENDPOINT notify
121: */
122: static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
123: {
124: uint8_t family, type, addr_family;
125: uint16_t port;
126: chunk_t addr;
127: uint8_t *cur = data.ptr;
128: uint8_t *top = data.ptr + data.len;
129:
130: DBG3(DBG_IKE, "me_endpoint_data %B", &data);
131:
132: if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
133: {
134: DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority");
135: return FAILED;
136: }
137:
138: if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
139: {
140: DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family");
141: return FAILED;
142: }
143: this->family = (me_endpoint_family_t)family;
144:
145: if (parse_uint8(&cur, top, &type) != SUCCESS ||
146: type == NO_TYPE || type >= MAX_TYPE)
147: {
148: DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type");
149: return FAILED;
150: }
151: this->type = (me_endpoint_type_t)type;
152:
153: addr_family = AF_INET;
154: addr.len = 4;
155:
156: switch(this->family)
157: {
158: case IPv6:
159: addr_family = AF_INET6;
160: addr.len = 16;
161: /* fall-through */
162: case IPv4:
163: if (parse_uint16(&cur, top, &port) != SUCCESS)
164: {
165: DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port");
166: return FAILED;
167: }
168:
169: if (cur + addr.len > top)
170: {
171: DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address");
172: return FAILED;
173: }
174:
175: addr.ptr = cur;
176: this->endpoint = host_create_from_chunk(addr_family, addr, port);
177: break;
178: case NO_FAMILY:
179: default:
180: this->endpoint = NULL;
181: break;
182: }
183: return SUCCESS;
184: }
185:
186:
187: /**
188: * Generates the notification data of a ME_ENDPOINT notify
189: */
190: static chunk_t build_notification_data(private_endpoint_notify_t *this)
191: {
192: chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
193: chunk_t data;
194: uint32_t prio;
195: uint16_t port;
196: uint8_t family, type;
197:
198: prio = htonl(this->priority);
199: prio_chunk = chunk_from_thing(prio);
200: family = this->family;
201: family_chunk = chunk_from_thing(family);
202: type = this->type;
203: type_chunk = chunk_from_thing(type);
204:
205: if (this->endpoint)
206: {
207: port = htons(this->endpoint->get_port(this->endpoint));
208: addr_chunk = this->endpoint->get_address(this->endpoint);
209: }
210: else
211: {
212: port = 0;
213: addr_chunk = chunk_empty;
214: }
215: port_chunk = chunk_from_thing(port);
216:
217: /* data = prio | family | type | port | addr */
218: data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
219: port_chunk, addr_chunk);
220: DBG3(DBG_IKE, "me_endpoint_data %B", &data);
221: return data;
222: }
223:
224: METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
225: private_endpoint_notify_t *this)
226: {
227: chunk_t data;
228: notify_payload_t *notify;
229:
230: notify = notify_payload_create(PLV2_NOTIFY);
231: notify->set_notify_type(notify, ME_ENDPOINT);
232: data = build_notification_data(this);
233: notify->set_notification_data(notify, data);
234: chunk_free(&data);
235:
236: return notify;
237: }
238:
239:
240: METHOD(endpoint_notify_t, get_priority, uint32_t,
241: private_endpoint_notify_t *this)
242: {
243: return this->priority;
244: }
245:
246: METHOD(endpoint_notify_t, set_priority, void,
247: private_endpoint_notify_t *this, uint32_t priority)
248: {
249: this->priority = priority;
250: }
251:
252: METHOD(endpoint_notify_t, get_type, me_endpoint_type_t,
253: private_endpoint_notify_t *this)
254: {
255: return this->type;
256: }
257:
258: METHOD(endpoint_notify_t, get_family, me_endpoint_family_t,
259: private_endpoint_notify_t *this)
260: {
261: return this->family;
262: }
263:
264: METHOD(endpoint_notify_t, get_host, host_t*,
265: private_endpoint_notify_t *this)
266: {
267: return this->endpoint;
268: }
269:
270: METHOD(endpoint_notify_t, get_base, host_t*,
271: private_endpoint_notify_t *this)
272: {
273: return (!this->base) ? this->endpoint : this->base;
274: }
275:
276: METHOD(endpoint_notify_t, clone_, endpoint_notify_t*,
277: private_endpoint_notify_t *this)
278: {
279: private_endpoint_notify_t *clone;
280:
281: clone = endpoint_notify_create();
282: clone->priority = this->priority;
283: clone->type = this->type;
284: clone->family = this->family;
285:
286: if (this->endpoint)
287: {
288: clone->endpoint = this->endpoint->clone(this->endpoint);
289: }
290:
291: if (this->base)
292: {
293: clone->base = this->base->clone(this->base);
294: }
295:
296: return &clone->public;
297: }
298:
299: METHOD(endpoint_notify_t, destroy, void,
300: private_endpoint_notify_t *this)
301: {
302: DESTROY_IF(this->endpoint);
303: DESTROY_IF(this->base);
304: free(this);
305: }
306:
307: /**
308: * Creates an empty endpoint notify
309: */
310: static private_endpoint_notify_t *endpoint_notify_create()
311: {
312: private_endpoint_notify_t *this;
313:
314: INIT(this,
315: .public = {
316: .get_priority = _get_priority,
317: .set_priority = _set_priority,
318: .get_type = _get_type,
319: .get_family = _get_family,
320: .get_host = _get_host,
321: .get_base = _get_base,
322: .build_notify = _build_notify,
323: .clone = _clone_,
324: .destroy = _destroy,
325: },
326: .family = NO_FAMILY,
327: .type = NO_TYPE,
328: );
329:
330: return this;
331: }
332:
333: /**
334: * Described in header
335: */
336: endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type,
337: host_t *host, host_t *base)
338: {
339: private_endpoint_notify_t *this = endpoint_notify_create();
340: this->type = type;
341:
342: switch(type)
343: {
344: case HOST:
345: this->priority = pow(2, 16) * ME_PRIO_HOST;
346: break;
347: case PEER_REFLEXIVE:
348: this->priority = pow(2, 16) * ME_PRIO_PEER;
349: break;
350: case SERVER_REFLEXIVE:
351: this->priority = pow(2, 16) * ME_PRIO_SERVER;
352: break;
353: case RELAYED:
354: default:
355: this->priority = pow(2, 16) * ME_PRIO_RELAY;
356: break;
357: }
358:
359: /* FIXME: if there is more than one ip address we should vary this priority */
360: this->priority += 65535;
361:
362: if (!host)
363: {
364: return &this->public;
365: }
366:
367: switch(host->get_family(host))
368: {
369: case AF_INET:
370: this->family = IPv4;
371: break;
372: case AF_INET6:
373: this->family = IPv6;
374: break;
375: default:
376: /* unsupported family type, we do not set the host
377: * (family is set to NO_FAMILY) */
378: return &this->public;
379: }
380:
381: this->endpoint = host->clone(host);
382:
383: if (base)
384: {
385: this->base = base->clone(base);
386: }
387:
388: return &this->public;
389: }
390:
391: /**
392: * Described in header
393: */
394: endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
395: {
396: private_endpoint_notify_t *this;
397: chunk_t data;
398:
399: if (notify->get_notify_type(notify) != ME_ENDPOINT)
400: {
401: return NULL;
402: }
403:
404: this = endpoint_notify_create();
405: data = notify->get_notification_data(notify);
406:
407: if (parse_notification_data(this, data) != SUCCESS)
408: {
409: destroy(this);
410: return NULL;
411: }
412: return &this->public;
413: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>