]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/encoding/payloads/traffic_selector_substructure.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / encoding / payloads / traffic_selector_substructure.c
1 /*
2 * Copyright (C) 2022 Tobias Brunner
3 * Copyright (C) 2005-2010 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 *
6 * Copyright (C) secunet Security Networks AG
7 *
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>.
12 *
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
16 * for more details.
17 */
18
19 #include "traffic_selector_substructure.h"
20
21 #include <encoding/payloads/encodings.h>
22 #include <bio/bio_reader.h>
23 #include <bio/bio_writer.h>
24
25 typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
26
27 /**
28 * Private data of an traffic_selector_substructure_t object.
29 */
30 struct private_traffic_selector_substructure_t {
31
32 /**
33 * Public traffic_selector_substructure_t interface.
34 */
35 traffic_selector_substructure_t public;
36
37 /**
38 * Type of traffic selector.
39 */
40 uint8_t ts_type;
41
42 /**
43 * IP Protocol ID.
44 */
45 uint8_t ip_protocol_id;
46
47 /**
48 * Length of this payload.
49 */
50 uint16_t payload_length;
51
52 /**
53 * Port/address range or security label.
54 */
55 chunk_t ts_data;
56 };
57
58 /**
59 * Encoding rules to parse or generate a TS payload.
60 *
61 * Due to the generic nature of security labels, the actual structure of regular
62 * TS is not parsed with these rules.
63 *
64 * The defined offsets are the positions in a object of type
65 * private_traffic_selector_substructure_t.
66 */
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) },
76 };
77
78 /* Regular traffic selectors for address ranges:
79 1 2 3
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 ! !
87 ~ Starting Address* ~
88 ! !
89 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 ! !
91 ~ Ending Address* ~
92 ! !
93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94
95 * Security labels:
96 1 2 3
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 +---------------+---------------+-------------------------------+
101 | |
102 ~ Security Label* ~
103 | |
104 +---------------------------------------------------------------+
105 */
106
107 /**
108 * Parse the data of a regular address range traffic selector.
109 */
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)
113 {
114 bio_reader_t *reader;
115 int addr_len;
116
117 switch (this->ts_type)
118 {
119 case TS_IPV4_ADDR_RANGE:
120 addr_len = 4;
121 break;
122 case TS_IPV6_ADDR_RANGE:
123 addr_len = 16;
124 break;
125 default:
126 return FALSE;
127 }
128
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)
135 {
136 reader->destroy(reader);
137 return FALSE;
138 }
139 reader->destroy(reader);
140 return TRUE;
141 }
142
143 METHOD(payload_t, verify, status_t,
144 private_traffic_selector_substructure_t *this)
145 {
146 switch (this->ts_type)
147 {
148 case TS_IPV4_ADDR_RANGE:
149 case TS_IPV6_ADDR_RANGE:
150 {
151 uint16_t start_port, end_port;
152 chunk_t start_addr, end_addr;
153
154 if (!parse_ts_data(this, &start_port, &end_port, &start_addr,
155 &end_addr))
156 {
157 return FAILED;
158 }
159 if (start_port > end_port)
160 {
161 /* OPAQUE ports are the only exception */
162 if (start_port != 0xffff && end_port != 0)
163 {
164 return FAILED;
165 }
166 }
167 break;
168 }
169 case TS_SECLABEL:
170 if (!this->ts_data.len)
171 {
172 return FAILED;
173 }
174 break;
175 default:
176 /* unsupported TS type, just ignored later */
177 break;
178 }
179 return SUCCESS;
180 }
181
182 METHOD(payload_t, get_encoding_rules, int,
183 private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
184 {
185 *rules = encodings;
186 return countof(encodings);
187 }
188
189 METHOD(payload_t, get_header_length, int,
190 private_traffic_selector_substructure_t *this)
191 {
192 return 4;
193 }
194
195 METHOD(payload_t, get_type, payload_type_t,
196 private_traffic_selector_substructure_t *this)
197 {
198 return PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE;
199 }
200
201 METHOD(payload_t, get_next_type, payload_type_t,
202 private_traffic_selector_substructure_t *this)
203 {
204 return PL_NONE;
205 }
206
207 METHOD(payload_t, set_next_type, void,
208 private_traffic_selector_substructure_t *this,payload_type_t type)
209 {
210 }
211
212 METHOD(payload_t, get_length, size_t,
213 private_traffic_selector_substructure_t *this)
214 {
215 return this->payload_length;
216 }
217
218 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
219 private_traffic_selector_substructure_t *this)
220 {
221 uint16_t start_port, end_port;
222 chunk_t start_addr, end_addr;
223
224 if (!parse_ts_data(this, &start_port, &end_port, &start_addr, &end_addr))
225 {
226 return NULL;
227 }
228 return traffic_selector_create_from_bytes(
229 this->ip_protocol_id, this->ts_type,
230 start_addr, start_port, end_addr, end_port);
231 }
232
233 METHOD(traffic_selector_substructure_t, get_sec_label, sec_label_t*,
234 private_traffic_selector_substructure_t *this)
235 {
236 if (this->ts_type != TS_SECLABEL)
237 {
238 return NULL;
239 }
240 return sec_label_from_encoding(this->ts_data);
241 }
242
243 METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
244 private_traffic_selector_substructure_t *this)
245 {
246 free(this->ts_data.ptr);
247 free(this);
248 }
249
250 /*
251 * Described in header
252 */
253 traffic_selector_substructure_t *traffic_selector_substructure_create()
254 {
255 private_traffic_selector_substructure_t *this;
256
257 INIT(this,
258 .public = {
259 .payload_interface = {
260 .verify = _verify,
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,
267 .destroy = _destroy,
268 },
269 .get_traffic_selector = _get_traffic_selector,
270 .get_sec_label = _get_sec_label,
271 .destroy = _destroy,
272 },
273 .payload_length = get_header_length(this),
274 /* must be set to be valid */
275 .ts_type = TS_IPV4_ADDR_RANGE,
276 );
277 return &this->public;
278 }
279
280 /*
281 * Described in header
282 */
283 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
284 traffic_selector_t *ts)
285 {
286 private_traffic_selector_substructure_t *this;
287 bio_writer_t *writer;
288
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);
292
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;
302 }
303
304 /*
305 * Described in header
306 */
307 traffic_selector_substructure_t *traffic_selector_substructure_create_from_sec_label(
308 sec_label_t *label)
309 {
310 private_traffic_selector_substructure_t *this;
311
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;
317 }