Migrated traffic_selector_substructre to INIT/METHOD macros
[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 encoding_rule_t traffic_selector_substructure_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, void,
152 private_traffic_selector_substructure_t *this, encoding_rule_t **rules,
153 size_t *rule_count)
154 {
155 *rules = traffic_selector_substructure_encodings;
156 *rule_count = countof(traffic_selector_substructure_encodings);
157 }
158
159 METHOD(payload_t, get_type, payload_type_t,
160 private_traffic_selector_substructure_t *this)
161 {
162 return TRAFFIC_SELECTOR_SUBSTRUCTURE;
163 }
164
165 METHOD(payload_t, get_next_type, payload_type_t,
166 private_traffic_selector_substructure_t *this)
167 {
168 return NO_PAYLOAD;
169 }
170
171 METHOD(payload_t, set_next_type, void,
172 private_traffic_selector_substructure_t *this,payload_type_t type)
173 {
174 }
175
176 METHOD(payload_t, get_length, size_t,
177 private_traffic_selector_substructure_t *this)
178 {
179 return this->payload_length;
180 }
181
182 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
183 private_traffic_selector_substructure_t *this)
184 {
185 return traffic_selector_create_from_bytes(
186 this->ip_protocol_id, this->ts_type,
187 this->starting_address, this->start_port,
188 this->ending_address, this->end_port);
189 }
190
191 METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
192 private_traffic_selector_substructure_t *this)
193 {
194 free(this->starting_address.ptr);
195 free(this->ending_address.ptr);
196 free(this);
197 }
198
199 /*
200 * Described in header
201 */
202 traffic_selector_substructure_t *traffic_selector_substructure_create()
203 {
204 private_traffic_selector_substructure_t *this;
205
206 INIT(this,
207 .public = {
208 .payload_interface = {
209 .verify = _verify,
210 .get_encoding_rules = _get_encoding_rules,
211 .get_length = _get_length,
212 .get_next_type = _get_next_type,
213 .set_next_type = _set_next_type,
214 .get_type = _get_type,
215 .destroy = _destroy,
216 },
217 .get_traffic_selector = _get_traffic_selector,
218 .destroy = _destroy,
219 },
220 .payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
221 /* must be set to be valid */
222 .ts_type = TS_IPV4_ADDR_RANGE,
223 );
224 return &this->public;
225 }
226
227 /*
228 * Described in header
229 */
230 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
231 traffic_selector_t *ts)
232 {
233 private_traffic_selector_substructure_t *this;
234
235 this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
236 this->ts_type = ts->get_type(ts);
237 this->ip_protocol_id = ts->get_protocol(ts);
238 this->start_port = ts->get_from_port(ts);
239 this->end_port = ts->get_to_port(ts);
240 this->starting_address = chunk_clone(ts->get_from_address(ts));
241 this->ending_address = chunk_clone(ts->get_to_address(ts));
242 this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
243 this->ending_address.len + this->starting_address.len;
244
245 return &this->public;
246 }