2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2007 Tobias Brunner
5 * Copyright (C) 2005 Jan Hutter
7 * Hochschule fuer Technik Rapperswil
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 #include "id_payload.h"
25 #include <encoding/payloads/encodings.h>
27 typedef struct private_id_payload_t private_id_payload_t
;
30 * Private data of an id_payload_t object.
32 struct private_id_payload_t
{
35 * Public id_payload_t interface.
42 u_int8_t next_payload
;
57 u_int8_t reserved_byte
[3];
60 * Length of this payload.
62 u_int16_t payload_length
;
65 * Type of the ID Data.
70 * The contained id data value.
75 * Tunneled protocol ID for IKEv1 quick modes.
80 * Tunneled port for IKEv1 quick modes.
85 * one of ID_INITIATOR, ID_RESPONDER and IDv1
91 * Encoding rules for an IKEv2 ID payload
93 static encoding_rule_t encodings_v2
[] = {
94 /* 1 Byte next payload type, stored in the field next_payload */
95 { U_INT_8
, offsetof(private_id_payload_t
, next_payload
) },
96 /* the critical bit */
97 { FLAG
, offsetof(private_id_payload_t
, critical
) },
98 /* 7 Bit reserved bits */
99 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[0]) },
100 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[1]) },
101 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[2]) },
102 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[3]) },
103 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[4]) },
104 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[5]) },
105 { RESERVED_BIT
, offsetof(private_id_payload_t
, reserved_bit
[6]) },
106 /* Length of the whole payload*/
107 { PAYLOAD_LENGTH
, offsetof(private_id_payload_t
, payload_length
) },
109 { U_INT_8
, offsetof(private_id_payload_t
, id_type
) },
110 /* 3 reserved bytes */
111 { RESERVED_BYTE
, offsetof(private_id_payload_t
, reserved_byte
[0])},
112 { RESERVED_BYTE
, offsetof(private_id_payload_t
, reserved_byte
[1])},
113 { RESERVED_BYTE
, offsetof(private_id_payload_t
, reserved_byte
[2])},
114 /* some id data bytes, length is defined in PAYLOAD_LENGTH */
115 { CHUNK_DATA
, offsetof(private_id_payload_t
, id_data
) },
120 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
121 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 ! Next Payload !C! RESERVED ! Payload Length !
123 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 ! ID Type ! RESERVED |
125 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 ~ Identification Data ~
129 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 * Encoding rules for an IKEv1 ID payload
135 static encoding_rule_t encodings_v1
[] = {
136 /* 1 Byte next payload type, stored in the field next_payload */
137 { U_INT_8
, offsetof(private_id_payload_t
, next_payload
) },
138 /* Reserved Byte is skipped */
139 { RESERVED_BYTE
, offsetof(private_id_payload_t
, reserved_byte
[0])},
140 /* Length of the whole payload*/
141 { PAYLOAD_LENGTH
, offsetof(private_id_payload_t
, payload_length
) },
143 { U_INT_8
, offsetof(private_id_payload_t
, id_type
) },
144 { U_INT_8
, offsetof(private_id_payload_t
, protocol_id
) },
145 { U_INT_16
, offsetof(private_id_payload_t
, port
) },
146 /* some id data bytes, length is defined in PAYLOAD_LENGTH */
147 { CHUNK_DATA
, offsetof(private_id_payload_t
, id_data
) },
152 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
153 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 ! Next Payload ! RESERVED ! Payload Length !
155 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 ! ID Type ! Protocol ID ! Port |
157 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 ~ Identification Data ~
161 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 METHOD(payload_t
, verify
, status_t
,
165 private_id_payload_t
*this)
167 bool bad_length
= FALSE
;
169 switch (this->id_type
)
171 case ID_IPV4_ADDR_RANGE
:
172 case ID_IPV4_ADDR_SUBNET
:
173 bad_length
= this->id_data
.len
!= 8;
175 case ID_IPV6_ADDR_RANGE
:
176 case ID_IPV6_ADDR_SUBNET
:
177 bad_length
= this->id_data
.len
!= 32;
182 DBG1(DBG_ENC
, "invalid %N length (%d bytes)",
183 id_type_names
, this->id_type
, this->id_data
.len
);
189 METHOD(payload_t
, get_encoding_rules
, int,
190 private_id_payload_t
*this, encoding_rule_t
**rules
)
192 if (this->type
== ID_V1
)
194 *rules
= encodings_v1
;
195 return countof(encodings_v1
);
197 *rules
= encodings_v2
;
198 return countof(encodings_v2
);
201 METHOD(payload_t
, get_header_length
, int,
202 private_id_payload_t
*this)
207 METHOD(payload_t
, get_type
, payload_type_t
,
208 private_id_payload_t
*this)
213 METHOD(payload_t
, get_next_type
, payload_type_t
,
214 private_id_payload_t
*this)
216 return this->next_payload
;
219 METHOD(payload_t
, set_next_type
, void,
220 private_id_payload_t
*this, payload_type_t type
)
222 this->next_payload
= type
;
225 METHOD(payload_t
, get_length
, size_t,
226 private_id_payload_t
*this)
228 return this->payload_length
;
231 METHOD(id_payload_t
, get_identification
, identification_t
*,
232 private_id_payload_t
*this)
234 return identification_create_from_encoding(this->id_type
, this->id_data
);
238 * Create a traffic selector from an range ID
240 static traffic_selector_t
*get_ts_from_range(private_id_payload_t
*this,
243 return traffic_selector_create_from_bytes(this->protocol_id
, type
,
244 chunk_create(this->id_data
.ptr
, this->id_data
.len
/ 2), this->port
,
245 chunk_skip(this->id_data
, this->id_data
.len
/ 2), this->port ?
: 65535);
249 * Create a traffic selector from an subnet ID
251 static traffic_selector_t
*get_ts_from_subnet(private_id_payload_t
*this,
254 chunk_t net
, netmask
;
257 net
= chunk_create(this->id_data
.ptr
, this->id_data
.len
/ 2);
258 netmask
= chunk_skip(this->id_data
, this->id_data
.len
/ 2);
259 for (i
= 0; i
< net
.len
; i
++)
261 netmask
.ptr
[i
] = (netmask
.ptr
[i
] ^ 0xFF) | net
.ptr
[i
];
263 return traffic_selector_create_from_bytes(this->protocol_id
, type
,
264 net
, this->port
, netmask
, this->port ?
: 65535);
267 METHOD(id_payload_t
, get_ts
, traffic_selector_t
*,
268 private_id_payload_t
*this)
270 switch (this->id_type
)
272 case ID_IPV4_ADDR_SUBNET
:
273 if (this->id_data
.len
== 8)
275 return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE
);
278 case ID_IPV6_ADDR_SUBNET
:
279 if (this->id_data
.len
== 32)
281 return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE
);
284 case ID_IPV4_ADDR_RANGE
:
285 if (this->id_data
.len
== 8)
287 return get_ts_from_range(this, TS_IPV4_ADDR_RANGE
);
290 case ID_IPV6_ADDR_RANGE
:
291 if (this->id_data
.len
== 32)
293 return get_ts_from_range(this, TS_IPV6_ADDR_RANGE
);
302 METHOD2(payload_t
, id_payload_t
, destroy
, void,
303 private_id_payload_t
*this)
305 free(this->id_data
.ptr
);
310 * Described in header.
312 id_payload_t
*id_payload_create(payload_type_t type
)
314 private_id_payload_t
*this;
318 .payload_interface
= {
320 .get_encoding_rules
= _get_encoding_rules
,
321 .get_header_length
= _get_header_length
,
322 .get_length
= _get_length
,
323 .get_next_type
= _get_next_type
,
324 .set_next_type
= _set_next_type
,
325 .get_type
= _get_type
,
328 .get_identification
= _get_identification
,
332 .next_payload
= NO_PAYLOAD
,
333 .payload_length
= get_header_length(this),
336 return &this->public;
340 * Described in header.
342 id_payload_t
*id_payload_create_from_identification(payload_type_t type
,
343 identification_t
*id
)
345 private_id_payload_t
*this;
347 this = (private_id_payload_t
*)id_payload_create(type
);
348 this->id_data
= chunk_clone(id
->get_encoding(id
));
349 this->id_type
= id
->get_type(id
);
350 this->payload_length
+= this->id_data
.len
;
352 return &this->public;
356 * Described in header.
358 id_payload_t
*id_payload_create_from_ts(traffic_selector_t
*ts
)
360 private_id_payload_t
*this;
364 this = (private_id_payload_t
*)id_payload_create(ID_V1
);
366 if (ts
->to_subnet(ts
, &net
, &mask
))
368 u_int8_t netmask
[16], len
, byte
;
370 if (ts
->get_type(ts
) == TS_IPV4_ADDR_RANGE
)
372 this->id_type
= ID_IPV4_ADDR_SUBNET
;
377 this->id_type
= ID_IPV6_ADDR_SUBNET
;
380 memset(netmask
, 0, sizeof(netmask
));
381 for (byte
= 0; byte
< sizeof(netmask
); byte
++)
385 netmask
[byte
] = 0xFF << (8 - mask
);
388 netmask
[byte
] = 0xFF;
391 this->id_data
= chunk_cat("cc", net
->get_address(net
),
392 chunk_create(netmask
, len
));
396 if (ts
->get_type(ts
) == TS_IPV4_ADDR_RANGE
)
398 this->id_type
= ID_IPV4_ADDR_RANGE
;
402 this->id_type
= ID_IPV6_ADDR_RANGE
;
404 this->id_data
= chunk_cat("cc",
405 ts
->get_from_address(ts
), ts
->get_to_address(ts
));
407 this->port
= ts
->get_from_port(ts
);
408 this->protocol_id
= ts
->get_protocol(ts
);
412 return &this->public;