payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / encoding / payloads / traffic_selector_substructure.c
1 /*
2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "traffic_selector_substructure.h"
19
20 #include <encoding/payloads/encodings.h>
21 #include <collections/linked_list.h>
22
23 typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
24
25 /**
26 * Private data of an traffic_selector_substructure_t object.
27 */
28 struct private_traffic_selector_substructure_t {
29
30 /**
31 * Public traffic_selector_substructure_t interface.
32 */
33 traffic_selector_substructure_t public;
34
35 /**
36 * Type of traffic selector.
37 */
38 u_int8_t ts_type;
39
40 /**
41 * IP Protocol ID.
42 */
43 u_int8_t ip_protocol_id;
44
45 /**
46 * Length of this payload.
47 */
48 u_int16_t payload_length;
49
50 /**
51 * Start port number.
52 */
53 u_int16_t start_port;
54
55 /**
56 * End port number.
57 */
58 u_int16_t end_port;
59
60 /**
61 * Starting address.
62 */
63 chunk_t starting_address;
64
65 /**
66 * Ending address.
67 */
68 chunk_t ending_address;
69 };
70
71 /**
72 * Encoding rules to parse or generate a TS payload
73 *
74 * The defined offsets are the positions in a object of type
75 * private_traffic_selector_substructure_t.
76 */
77 static encoding_rule_t encodings[] = {
78 /* 1 Byte next ts type*/
79 { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
80 /* 1 Byte IP protocol id*/
81 { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
82 /* Length of the whole payload*/
83 { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) },
84 /* 2 Byte start port*/
85 { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
86 /* 2 Byte end port*/
87 { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
88 /* starting address is either 4 or 16 byte */
89 { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
90 /* ending address is either 4 or 16 byte */
91 { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
92 };
93
94 /*
95 1 2 3
96 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
97 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 ! TS Type !IP Protocol ID*| Selector Length |
99 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 | Start Port* | End Port* |
101 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 ! !
103 ~ Starting Address* ~
104 ! !
105 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 ! !
107 ~ Ending Address* ~
108 ! !
109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 */
111
112 METHOD(payload_t, verify, status_t,
113 private_traffic_selector_substructure_t *this)
114 {
115 if (this->start_port > this->end_port)
116 {
117 /* OPAQUE ports are the only exception */
118 if (this->start_port != 0xffff && this->end_port != 0)
119 {
120 return FAILED;
121 }
122 }
123 switch (this->ts_type)
124 {
125 case TS_IPV4_ADDR_RANGE:
126 {
127 if ((this->starting_address.len != 4) ||
128 (this->ending_address.len != 4))
129 {
130 /* ipv4 address must be 4 bytes long */
131 return FAILED;
132 }
133 break;
134 }
135 case TS_IPV6_ADDR_RANGE:
136 {
137 if ((this->starting_address.len != 16) ||
138 (this->ending_address.len != 16))
139 {
140 /* ipv6 address must be 16 bytes long */
141 return FAILED;
142 }
143 break;
144 }
145 default:
146 {
147 /* not supported ts type */
148 return FAILED;
149 }
150 }
151
152 return SUCCESS;
153 }
154
155 METHOD(payload_t, get_encoding_rules, int,
156 private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
157 {
158 *rules = encodings;
159 return countof(encodings);
160 }
161
162 METHOD(payload_t, get_header_length, int,
163 private_traffic_selector_substructure_t *this)
164 {
165 return 8;
166 }
167
168 METHOD(payload_t, get_type, payload_type_t,
169 private_traffic_selector_substructure_t *this)
170 {
171 return PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE;
172 }
173
174 METHOD(payload_t, get_next_type, payload_type_t,
175 private_traffic_selector_substructure_t *this)
176 {
177 return PL_NONE;
178 }
179
180 METHOD(payload_t, set_next_type, void,
181 private_traffic_selector_substructure_t *this,payload_type_t type)
182 {
183 }
184
185 METHOD(payload_t, get_length, size_t,
186 private_traffic_selector_substructure_t *this)
187 {
188 return this->payload_length;
189 }
190
191 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
192 private_traffic_selector_substructure_t *this)
193 {
194 return traffic_selector_create_from_bytes(
195 this->ip_protocol_id, this->ts_type,
196 this->starting_address, this->start_port,
197 this->ending_address, this->end_port);
198 }
199
200 METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
201 private_traffic_selector_substructure_t *this)
202 {
203 free(this->starting_address.ptr);
204 free(this->ending_address.ptr);
205 free(this);
206 }
207
208 /*
209 * Described in header
210 */
211 traffic_selector_substructure_t *traffic_selector_substructure_create()
212 {
213 private_traffic_selector_substructure_t *this;
214
215 INIT(this,
216 .public = {
217 .payload_interface = {
218 .verify = _verify,
219 .get_encoding_rules = _get_encoding_rules,
220 .get_header_length = _get_header_length,
221 .get_length = _get_length,
222 .get_next_type = _get_next_type,
223 .set_next_type = _set_next_type,
224 .get_type = _get_type,
225 .destroy = _destroy,
226 },
227 .get_traffic_selector = _get_traffic_selector,
228 .destroy = _destroy,
229 },
230 .payload_length = get_header_length(this),
231 /* must be set to be valid */
232 .ts_type = TS_IPV4_ADDR_RANGE,
233 );
234 return &this->public;
235 }
236
237 /*
238 * Described in header
239 */
240 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
241 traffic_selector_t *ts)
242 {
243 private_traffic_selector_substructure_t *this;
244
245 this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
246 this->ts_type = ts->get_type(ts);
247 this->ip_protocol_id = ts->get_protocol(ts);
248 this->start_port = ts->get_from_port(ts);
249 this->end_port = ts->get_to_port(ts);
250 this->starting_address = chunk_clone(ts->get_from_address(ts));
251 this->ending_address = chunk_clone(ts->get_to_address(ts));
252 this->payload_length = get_header_length(this) +
253 this->ending_address.len + this->starting_address.len;
254
255 return &this->public;
256 }