Simplify signature of get_encoding_rules(), make all rules static
[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 <utils/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 return FAILED;
118 }
119 switch (this->ts_type)
120 {
121 case TS_IPV4_ADDR_RANGE:
122 {
123 if ((this->starting_address.len != 4) ||
124 (this->ending_address.len != 4))
125 {
126 /* ipv4 address must be 4 bytes long */
127 return FAILED;
128 }
129 break;
130 }
131 case TS_IPV6_ADDR_RANGE:
132 {
133 if ((this->starting_address.len != 16) ||
134 (this->ending_address.len != 16))
135 {
136 /* ipv6 address must be 16 bytes long */
137 return FAILED;
138 }
139 break;
140 }
141 default:
142 {
143 /* not supported ts type */
144 return FAILED;
145 }
146 }
147
148 return SUCCESS;
149 }
150
151 METHOD(payload_t, get_encoding_rules, int,
152 private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
153 {
154 *rules = encodings;
155 return countof(encodings);
156 }
157
158 METHOD(payload_t, get_type, payload_type_t,
159 private_traffic_selector_substructure_t *this)
160 {
161 return TRAFFIC_SELECTOR_SUBSTRUCTURE;
162 }
163
164 METHOD(payload_t, get_next_type, payload_type_t,
165 private_traffic_selector_substructure_t *this)
166 {
167 return NO_PAYLOAD;
168 }
169
170 METHOD(payload_t, set_next_type, void,
171 private_traffic_selector_substructure_t *this,payload_type_t type)
172 {
173 }
174
175 METHOD(payload_t, get_length, size_t,
176 private_traffic_selector_substructure_t *this)
177 {
178 return this->payload_length;
179 }
180
181 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
182 private_traffic_selector_substructure_t *this)
183 {
184 return traffic_selector_create_from_bytes(
185 this->ip_protocol_id, this->ts_type,
186 this->starting_address, this->start_port,
187 this->ending_address, this->end_port);
188 }
189
190 METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
191 private_traffic_selector_substructure_t *this)
192 {
193 free(this->starting_address.ptr);
194 free(this->ending_address.ptr);
195 free(this);
196 }
197
198 /*
199 * Described in header
200 */
201 traffic_selector_substructure_t *traffic_selector_substructure_create()
202 {
203 private_traffic_selector_substructure_t *this;
204
205 INIT(this,
206 .public = {
207 .payload_interface = {
208 .verify = _verify,
209 .get_encoding_rules = _get_encoding_rules,
210 .get_length = _get_length,
211 .get_next_type = _get_next_type,
212 .set_next_type = _set_next_type,
213 .get_type = _get_type,
214 .destroy = _destroy,
215 },
216 .get_traffic_selector = _get_traffic_selector,
217 .destroy = _destroy,
218 },
219 .payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
220 /* must be set to be valid */
221 .ts_type = TS_IPV4_ADDR_RANGE,
222 );
223 return &this->public;
224 }
225
226 /*
227 * Described in header
228 */
229 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
230 traffic_selector_t *ts)
231 {
232 private_traffic_selector_substructure_t *this;
233
234 this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
235 this->ts_type = ts->get_type(ts);
236 this->ip_protocol_id = ts->get_protocol(ts);
237 this->start_port = ts->get_from_port(ts);
238 this->end_port = ts->get_to_port(ts);
239 this->starting_address = chunk_clone(ts->get_from_address(ts));
240 this->ending_address = chunk_clone(ts->get_to_address(ts));
241 this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
242 this->ending_address.len + this->starting_address.len;
243
244 return &this->public;
245 }