2 * Copyright (C) 2022 Tobias Brunner
3 * Copyright (C) 2005-2010 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
6 * Copyright (C) secunet Security Networks AG
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "traffic_selector_substructure.h"
21 #include <encoding/payloads/encodings.h>
22 #include <bio/bio_reader.h>
23 #include <bio/bio_writer.h>
25 typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t
;
28 * Private data of an traffic_selector_substructure_t object.
30 struct private_traffic_selector_substructure_t
{
33 * Public traffic_selector_substructure_t interface.
35 traffic_selector_substructure_t
public;
38 * Type of traffic selector.
45 uint8_t ip_protocol_id
;
48 * Length of this payload.
50 uint16_t payload_length
;
53 * Port/address range or security label.
59 * Encoding rules to parse or generate a TS payload.
61 * Due to the generic nature of security labels, the actual structure of regular
62 * TS is not parsed with these rules.
64 * The defined offsets are the positions in a object of type
65 * private_traffic_selector_substructure_t.
67 static encoding_rule_t encodings
[] = {
68 /* 1 Byte next ts type*/
69 { U_INT_8
, offsetof(private_traffic_selector_substructure_t
, ts_type
) },
70 /* 1 Byte IP protocol id*/
71 { U_INT_8
, offsetof(private_traffic_selector_substructure_t
, ip_protocol_id
) },
72 /* Length of the whole payload*/
73 { PAYLOAD_LENGTH
,offsetof(private_traffic_selector_substructure_t
, payload_length
) },
74 /* traffic selector data, length is defined in PAYLOAD_LENGTH */
75 { CHUNK_DATA
, offsetof(private_traffic_selector_substructure_t
, ts_data
) },
78 /* Regular traffic selectors for address ranges:
80 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
81 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 ! TS Type !IP Protocol ID*| Selector Length |
83 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 | Start Port* | End Port* |
85 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 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
98 +---------------+---------------+-------------------------------+
99 | TS Type | Reserved | Selector Length |
100 +---------------+---------------+-------------------------------+
104 +---------------------------------------------------------------+
108 * Parse the data of a regular address range traffic selector.
110 static bool parse_ts_data(private_traffic_selector_substructure_t
*this,
111 uint16_t *start_port
, uint16_t *end_port
,
112 chunk_t
*start_addr
, chunk_t
*end_addr
)
114 bio_reader_t
*reader
;
117 switch (this->ts_type
)
119 case TS_IPV4_ADDR_RANGE
:
122 case TS_IPV6_ADDR_RANGE
:
129 reader
= bio_reader_create(this->ts_data
);
130 if (!reader
->read_uint16(reader
, start_port
) ||
131 !reader
->read_uint16(reader
, end_port
) ||
132 !reader
->read_data(reader
, addr_len
, start_addr
) ||
133 !reader
->read_data(reader
, addr_len
, end_addr
) ||
134 reader
->remaining(reader
) > 0)
136 reader
->destroy(reader
);
139 reader
->destroy(reader
);
143 METHOD(payload_t
, verify
, status_t
,
144 private_traffic_selector_substructure_t
*this)
146 switch (this->ts_type
)
148 case TS_IPV4_ADDR_RANGE
:
149 case TS_IPV6_ADDR_RANGE
:
151 uint16_t start_port
, end_port
;
152 chunk_t start_addr
, end_addr
;
154 if (!parse_ts_data(this, &start_port
, &end_port
, &start_addr
,
159 if (start_port
> end_port
)
161 /* OPAQUE ports are the only exception */
162 if (start_port
!= 0xffff && end_port
!= 0)
170 if (!this->ts_data
.len
)
176 /* unsupported TS type, just ignored later */
182 METHOD(payload_t
, get_encoding_rules
, int,
183 private_traffic_selector_substructure_t
*this, encoding_rule_t
**rules
)
186 return countof(encodings
);
189 METHOD(payload_t
, get_header_length
, int,
190 private_traffic_selector_substructure_t
*this)
195 METHOD(payload_t
, get_type
, payload_type_t
,
196 private_traffic_selector_substructure_t
*this)
198 return PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE
;
201 METHOD(payload_t
, get_next_type
, payload_type_t
,
202 private_traffic_selector_substructure_t
*this)
207 METHOD(payload_t
, set_next_type
, void,
208 private_traffic_selector_substructure_t
*this,payload_type_t type
)
212 METHOD(payload_t
, get_length
, size_t,
213 private_traffic_selector_substructure_t
*this)
215 return this->payload_length
;
218 METHOD(traffic_selector_substructure_t
, get_traffic_selector
, traffic_selector_t
*,
219 private_traffic_selector_substructure_t
*this)
221 uint16_t start_port
, end_port
;
222 chunk_t start_addr
, end_addr
;
224 if (!parse_ts_data(this, &start_port
, &end_port
, &start_addr
, &end_addr
))
228 return traffic_selector_create_from_bytes(
229 this->ip_protocol_id
, this->ts_type
,
230 start_addr
, start_port
, end_addr
, end_port
);
233 METHOD(traffic_selector_substructure_t
, get_sec_label
, sec_label_t
*,
234 private_traffic_selector_substructure_t
*this)
236 if (this->ts_type
!= TS_SECLABEL
)
240 return sec_label_from_encoding(this->ts_data
);
243 METHOD2(payload_t
, traffic_selector_substructure_t
, destroy
, void,
244 private_traffic_selector_substructure_t
*this)
246 free(this->ts_data
.ptr
);
251 * Described in header
253 traffic_selector_substructure_t
*traffic_selector_substructure_create()
255 private_traffic_selector_substructure_t
*this;
259 .payload_interface
= {
261 .get_encoding_rules
= _get_encoding_rules
,
262 .get_header_length
= _get_header_length
,
263 .get_length
= _get_length
,
264 .get_next_type
= _get_next_type
,
265 .set_next_type
= _set_next_type
,
266 .get_type
= _get_type
,
269 .get_traffic_selector
= _get_traffic_selector
,
270 .get_sec_label
= _get_sec_label
,
273 .payload_length
= get_header_length(this),
274 /* must be set to be valid */
275 .ts_type
= TS_IPV4_ADDR_RANGE
,
277 return &this->public;
281 * Described in header
283 traffic_selector_substructure_t
*traffic_selector_substructure_create_from_traffic_selector(
284 traffic_selector_t
*ts
)
286 private_traffic_selector_substructure_t
*this;
287 bio_writer_t
*writer
;
289 this = (private_traffic_selector_substructure_t
*)traffic_selector_substructure_create();
290 this->ts_type
= ts
->get_type(ts
);
291 this->ip_protocol_id
= ts
->get_protocol(ts
);
293 writer
= bio_writer_create(this->ts_type
== TS_IPV4_ADDR_RANGE
? 12 : 36);
294 writer
->write_uint16(writer
, ts
->get_from_port(ts
));
295 writer
->write_uint16(writer
, ts
->get_to_port(ts
));
296 writer
->write_data(writer
, ts
->get_from_address(ts
));
297 writer
->write_data(writer
, ts
->get_to_address(ts
));
298 this->ts_data
= writer
->extract_buf(writer
);
299 this->payload_length
+= this->ts_data
.len
;
300 writer
->destroy(writer
);
301 return &this->public;
305 * Described in header
307 traffic_selector_substructure_t
*traffic_selector_substructure_create_from_sec_label(
310 private_traffic_selector_substructure_t
*this;
312 this = (private_traffic_selector_substructure_t
*)traffic_selector_substructure_create();
313 this->ts_type
= TS_SECLABEL
;
314 this->ts_data
= chunk_clone(label
->get_encoding(label
));
315 this->payload_length
+= this->ts_data
.len
;
316 return &this->public;