Removed strayed code fragment
[strongswan.git] / src / charon / encoding / payloads / endpoint_notify.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * 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 u_int32_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 * Helper functions to parse integer values
80 */
81 static status_t parse_uint8(u_int8_t **cur, u_int8_t *top, u_int8_t *val)
82 {
83 if (*cur + sizeof(u_int8_t) > top)
84 {
85 return FAILED;
86 }
87 *val = *(u_int8_t*)*cur;
88 *cur += sizeof(u_int8_t);
89 return SUCCESS;
90 }
91
92 static status_t parse_uint16(u_int8_t **cur, u_int8_t *top, u_int16_t *val)
93 {
94 if (*cur + sizeof(u_int16_t) > top)
95 {
96 return FAILED;
97 }
98 *val = ntohs(*(u_int16_t*)*cur);
99 *cur += sizeof(u_int16_t);
100 return SUCCESS;
101 }
102
103 static status_t parse_uint32(u_int8_t **cur, u_int8_t *top, u_int32_t *val)
104 {
105 if (*cur + sizeof(u_int32_t) > top)
106 {
107 return FAILED;
108 }
109 *val = ntohl(*(u_int32_t*)*cur);
110 *cur += sizeof(u_int32_t);
111 return SUCCESS;
112 }
113
114 /**
115 * Parses the notification data of a ME_ENDPOINT notify
116 */
117 static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
118 {
119 u_int8_t family, type, addr_family;
120 u_int16_t port;
121 chunk_t addr;
122 u_int8_t *cur = data.ptr;
123 u_int8_t *top = data.ptr + data.len;
124
125 DBG3(DBG_IKE, "me_endpoint_data %B", &data);
126
127 if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
128 {
129 DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority");
130 return FAILED;
131 }
132
133 if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
134 {
135 DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family");
136 return FAILED;
137 }
138 this->family = (me_endpoint_family_t)family;
139
140 if (parse_uint8(&cur, top, &type) != SUCCESS ||
141 type == NO_TYPE || type >= MAX_TYPE)
142 {
143 DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type");
144 return FAILED;
145 }
146 this->type = (me_endpoint_type_t)type;
147
148 addr_family = AF_INET;
149 addr.len = 4;
150
151 switch(this->family)
152 {
153 case IPv6:
154 addr_family = AF_INET6;
155 addr.len = 16;
156 /* fall-through */
157 case IPv4:
158 if (parse_uint16(&cur, top, &port) != SUCCESS)
159 {
160 DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port");
161 return FAILED;
162 }
163
164 if (cur + addr.len > top)
165 {
166 DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address");
167 return FAILED;
168 }
169
170 addr.ptr = cur;
171 this->endpoint = host_create_from_chunk(addr_family, addr, port);
172 break;
173 case NO_FAMILY:
174 default:
175 this->endpoint = NULL;
176 break;
177 }
178 return SUCCESS;
179 }
180
181
182 /**
183 * Generates the notification data of a ME_ENDPOINT notify
184 */
185 static chunk_t build_notification_data(private_endpoint_notify_t *this)
186 {
187 chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
188 chunk_t data;
189 u_int32_t prio;
190 u_int16_t port;
191 u_int8_t family, type;
192
193 prio = htonl(this->priority);
194 prio_chunk = chunk_from_thing(prio);
195 family = this->family;
196 family_chunk = chunk_from_thing(family);
197 type = this->type;
198 type_chunk = chunk_from_thing(type);
199
200 if (this->endpoint)
201 {
202 port = htons(this->endpoint->get_port(this->endpoint));
203 addr_chunk = this->endpoint->get_address(this->endpoint);
204 }
205 else
206 {
207 port = 0;
208 addr_chunk = chunk_empty;
209 }
210 port_chunk = chunk_from_thing(port);
211
212 /* data = prio | family | type | port | addr */
213 data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
214 port_chunk, addr_chunk);
215 DBG3(DBG_IKE, "me_endpoint_data %B", &data);
216 return data;
217 }
218
219 /**
220 * Implementation of endpoint_notify_t.build_notify
221 */
222 static notify_payload_t *build_notify(private_endpoint_notify_t *this)
223 {
224 chunk_t data;
225 notify_payload_t *notify;
226
227 notify = notify_payload_create();
228 notify->set_notify_type(notify, ME_ENDPOINT);
229 data = build_notification_data(this);
230 notify->set_notification_data(notify, data);
231 chunk_free(&data);
232
233 return notify;
234 }
235
236 /**
237 * Implementation of endpoint_notify_t.get_priority.
238 */
239 static u_int32_t get_priority(private_endpoint_notify_t *this)
240 {
241 return this->priority;
242 }
243
244 /**
245 * Implementation of endpoint_notify_t.set_priority.
246 */
247 static void set_priority(private_endpoint_notify_t *this, u_int32_t priority)
248 {
249 this->priority = priority;
250 }
251
252 /**
253 * Implementation of endpoint_notify_t.get_type.
254 */
255 static me_endpoint_type_t get_type(private_endpoint_notify_t *this)
256 {
257 return this->type;
258 }
259
260 /**
261 * Implementation of endpoint_notify_t.get_family.
262 */
263 static me_endpoint_family_t get_family(private_endpoint_notify_t *this)
264 {
265 return this->family;
266 }
267
268 /**
269 * Implementation of endpoint_notify_t.get_host.
270 */
271 static host_t *get_host(private_endpoint_notify_t *this)
272 {
273 return this->endpoint;
274 }
275
276 /**
277 * Implementation of endpoint_notify_t.get_base.
278 */
279 static host_t *get_base(private_endpoint_notify_t *this)
280 {
281 return (!this->base) ? this->endpoint : this->base;
282 }
283
284 /**
285 * Implementation of endpoint_notify_t.clone.
286 */
287 static endpoint_notify_t *_clone(private_endpoint_notify_t *this)
288 {
289 private_endpoint_notify_t *clone = (private_endpoint_notify_t*)endpoint_notify_create();
290
291 clone->priority = this->priority;
292 clone->type = this->type;
293 clone->family = this->family;
294 if (this->endpoint)
295 {
296 clone->endpoint = this->endpoint->clone(this->endpoint);
297 }
298
299 if (this->base)
300 {
301 clone->base = this->base->clone(this->base);
302 }
303
304 return &clone->public;
305 }
306
307 /**
308 * Implementation of endpoint_notify_t.destroy.
309 */
310 static status_t destroy(private_endpoint_notify_t *this)
311 {
312 DESTROY_IF(this->endpoint);
313 DESTROY_IF(this->base);
314 free(this);
315 return SUCCESS;
316 }
317
318 /*
319 * Described in header
320 */
321 endpoint_notify_t *endpoint_notify_create()
322 {
323 private_endpoint_notify_t *this = malloc_thing(private_endpoint_notify_t);
324
325 /* public functions */
326 this->public.get_priority = (u_int32_t (*) (endpoint_notify_t *)) get_priority;
327 this->public.set_priority = (void (*) (endpoint_notify_t *, u_int32_t)) set_priority;
328 this->public.get_type = (me_endpoint_type_t (*) (endpoint_notify_t *)) get_type;
329 this->public.get_family = (me_endpoint_family_t (*) (endpoint_notify_t *)) get_family;
330 this->public.get_host = (host_t *(*) (endpoint_notify_t *)) get_host;
331 this->public.get_base = (host_t *(*) (endpoint_notify_t *)) get_base;
332 this->public.build_notify = (notify_payload_t *(*) (endpoint_notify_t *)) build_notify;
333 this->public.clone = (endpoint_notify_t *(*) (endpoint_notify_t *)) _clone;
334 this->public.destroy = (void (*) (endpoint_notify_t *)) destroy;
335
336 /* set default values of the fields */
337 this->priority = 0;
338 this->family = NO_FAMILY;
339 this->type = NO_TYPE;
340 this->endpoint = NULL;
341 this->base = NULL;
342
343 return &this->public;
344 }
345
346 /**
347 * Described in header
348 */
349 endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type, host_t *host, host_t *base)
350 {
351 private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
352
353 this->type = type;
354
355 switch(type)
356 {
357 case HOST:
358 this->priority = pow(2, 16) * ME_PRIO_HOST;
359 break;
360 case PEER_REFLEXIVE:
361 this->priority = pow(2, 16) * ME_PRIO_PEER;
362 break;
363 case SERVER_REFLEXIVE:
364 this->priority = pow(2, 16) * ME_PRIO_SERVER;
365 break;
366 case RELAYED:
367 default:
368 this->priority = pow(2, 16) * ME_PRIO_RELAY;
369 break;
370 }
371
372 /* FIXME: if there is more than one ip address we should vary this priority */
373 this->priority += 65535;
374
375 if (!host)
376 {
377 return &this->public;
378 }
379
380 switch(host->get_family(host))
381 {
382 case AF_INET:
383 this->family = IPv4;
384 break;
385 case AF_INET6:
386 this->family = IPv6;
387 break;
388 default:
389 /* unsupported family type, we do not set the host
390 * (family is set to NO_FAMILY) */
391 return &this->public;
392 }
393
394 this->endpoint = host->clone(host);
395
396 if (base)
397 {
398 this->base = base->clone(base);
399 }
400
401 return &this->public;
402 }
403
404 /**
405 * Described in header
406 */
407 endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
408 {
409 if (notify->get_notify_type(notify) != ME_ENDPOINT)
410 {
411 return NULL;
412 }
413
414 private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
415 chunk_t data = notify->get_notification_data(notify);
416 if (parse_notification_data(this, data) != SUCCESS)
417 {
418 destroy(this);
419 return NULL;
420 }
421 return &this->public;
422 }