traffic-selector: Store ICMP[v6] message type and code properly
[strongswan.git] / src / libstrongswan / selectors / traffic_selector.h
1 /*
2 * Copyright (C) 2007-2013 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
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 /**
19 * @defgroup traffic_selector traffic_selector
20 * @{ @ingroup selectors
21 */
22
23 #ifndef TRAFFIC_SELECTOR_H_
24 #define TRAFFIC_SELECTOR_H_
25
26 typedef enum ts_type_t ts_type_t;
27 typedef struct traffic_selector_t traffic_selector_t;
28
29 #include <library.h>
30 #include <networking/host.h>
31
32 /**
33 * Traffic selector types.
34 */
35 enum ts_type_t {
36
37 /**
38 * A range of IPv4 addresses, represented by two four (4) octet
39 * values. The first value is the beginning IPv4 address
40 * (inclusive) and the second value is the ending IPv4 address
41 * (inclusive). All addresses falling between the two specified
42 * addresses are considered to be within the list.
43 */
44 TS_IPV4_ADDR_RANGE = 7,
45
46 /**
47 * A range of IPv6 addresses, represented by two sixteen (16)
48 * octet values. The first value is the beginning IPv6 address
49 * (inclusive) and the second value is the ending IPv6 address
50 * (inclusive). All addresses falling between the two specified
51 * addresses are considered to be within the list.
52 */
53 TS_IPV6_ADDR_RANGE = 8
54 };
55
56 /**
57 * enum names for ts_type_t
58 */
59 extern enum_name_t *ts_type_name;
60
61 /**
62 * Object representing a traffic selector entry.
63 *
64 * A traffic selector defines an range of addresses
65 * and a range of ports.
66 *
67 * If the protocol is ICMP or ICMPv6 the ICMP type and code are stored in the
68 * port field as follows: The message type is placed in the most significant
69 * 8 bits and the code in the least significant 8 bits. Utility functions are
70 * provided to extract the individual values.
71 */
72 struct traffic_selector_t {
73
74 /**
75 * Compare two traffic selectors, and create a new one
76 * which is the largest subset of both (subnet & port).
77 *
78 * Resulting traffic_selector is newly created and must be destroyed.
79 *
80 * @param other traffic selector to compare
81 * @return
82 * - created subset of them
83 * - or NULL if no match between this and other
84 */
85 traffic_selector_t *(*get_subset) (traffic_selector_t *this,
86 traffic_selector_t *other);
87
88 /**
89 * Clone a traffic selector.
90 *
91 * @return clone of it
92 */
93 traffic_selector_t *(*clone) (traffic_selector_t *this);
94
95 /**
96 * Get starting address of this ts as a chunk.
97 *
98 * Chunk is in network order and points to internal data.
99 *
100 * @return chunk containing the address
101 */
102 chunk_t (*get_from_address) (traffic_selector_t *this);
103
104 /**
105 * Get ending address of this ts as a chunk.
106 *
107 * Chunk is in network order and points to internal data.
108 *
109 * @return chunk containing the address
110 */
111 chunk_t (*get_to_address) (traffic_selector_t *this);
112
113 /**
114 * Get starting port of this ts.
115 *
116 * Port is in host order, since the parser converts it.
117 *
118 * If the protocol is ICMP/ICMPv6 the ICMP type and code are stored in this
119 * field as follows: The message type is placed in the most significant
120 * 8 bits and the code in the least significant 8 bits. Use the utility
121 * functions to extract them.
122 *
123 * @return port
124 */
125 u_int16_t (*get_from_port) (traffic_selector_t *this);
126
127 /**
128 * Get ending port of this ts.
129 *
130 * Port is in host order, since the parser converts it.
131 *
132 * If the protocol is ICMP/ICMPv6 the ICMP type and code are stored in this
133 * field as follows: The message type is placed in the most significant
134 * 8 bits and the code in the least significant 8 bits. Use the utility
135 * functions to extract them.
136 *
137 * @return port
138 */
139 u_int16_t (*get_to_port) (traffic_selector_t *this);
140
141 /**
142 * Get the type of the traffic selector.
143 *
144 * @return ts_type_t specifying the type
145 */
146 ts_type_t (*get_type) (traffic_selector_t *this);
147
148 /**
149 * Get the protocol id of this ts.
150 *
151 * @return protocol id
152 */
153 u_int8_t (*get_protocol) (traffic_selector_t *this);
154
155 /**
156 * Check if the traffic selector is for a single host.
157 *
158 * Traffic selector may describe the end of *-to-host tunnel. In this
159 * case, the address range is a single address equal to the hosts
160 * peer address.
161 * If host is NULL, the traffic selector is checked if it is a single host,
162 * but not a specific one.
163 *
164 * @param host host_t specifying the address range
165 */
166 bool (*is_host) (traffic_selector_t *this, host_t* host);
167
168 /**
169 * Check if a traffic selector has been created by create_dynamic().
170 *
171 * @return TRUE if TS is dynamic
172 */
173 bool (*is_dynamic)(traffic_selector_t *this);
174
175 /**
176 * Update the address of a traffic selector.
177 *
178 * Update the address range of a traffic selector, if it is
179 * constructed with the traffic_selector_create_dynamic().
180 *
181 * @param host host_t specifying the address
182 */
183 void (*set_address) (traffic_selector_t *this, host_t* host);
184
185 /**
186 * Compare two traffic selectors for equality.
187 *
188 * @param other ts to compare with this
189 * @return TRUE if equal, FALSE otherwise
190 */
191 bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
192
193 /**
194 * Check if a traffic selector is contained completly in another.
195 *
196 * contains() allows to check if multiple traffic selectors are redundant.
197 *
198 * @param other ts that contains this
199 * @return TRUE if other contains this completly, FALSE otherwise
200 */
201 bool (*is_contained_in) (traffic_selector_t *this, traffic_selector_t *other);
202
203 /**
204 * Check if a specific host is included in the address range of
205 * this traffic selector.
206 *
207 * @param host the host to check
208 */
209 bool (*includes) (traffic_selector_t *this, host_t *host);
210
211 /**
212 * Convert a traffic selector address range to a subnet
213 * and its net mask.
214 * If from and to ports of this traffic selector are equal,
215 * the port of the returned host_t is set to that port.
216 *
217 * @param net converted subnet (has to be freed)
218 * @param mask converted net mask
219 * @return TRUE if traffic selector matches exactly to the subnet
220 */
221 bool (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
222
223 /**
224 * Destroys the ts object
225 */
226 void (*destroy) (traffic_selector_t *this);
227 };
228
229 /**
230 * Extract the ICMP/ICMPv6 message type from a port in host order
231 *
232 * @param port port number in host order
233 * @return ICMP/ICMPv6 message type
234 */
235 static inline u_int8_t traffic_selector_icmp_type(u_int16_t port)
236 {
237 return port >> 8;
238 }
239
240 /**
241 * Extract the ICMP/ICMPv6 message code from a port in host order
242 *
243 * @param port port number in host order
244 * @return ICMP/ICMPv6 message code
245 */
246 static inline u_int8_t traffic_selector_icmp_code(u_int16_t port)
247 {
248 return port & 0xff;
249 }
250
251 /**
252 * Create a new traffic selector using human readable params.
253 *
254 * If protocol is ICMP or ICMPv6 the ports are interpreted as follows: If they
255 * are less than 256 the value is assumed to be a message type, if they are
256 * greater or equal to 256 they are assumed to be type and code as defined
257 * for traffic_selector_t.
258 *
259 * @param protocol protocol for this ts, such as TCP or UDP
260 * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
261 * @param from_addr start of address range as string
262 * @param from_port port number in host order
263 * @param to_addr end of address range as string
264 * @param to_port port number in host order
265 * @return
266 * - traffic_selector_t object
267 * - NULL if invalid address strings/protocol
268 */
269 traffic_selector_t *traffic_selector_create_from_string(
270 u_int8_t protocol, ts_type_t type,
271 char *from_addr, u_int16_t from_port,
272 char *to_addr, u_int16_t to_port);
273
274
275
276 /**
277 * Create a traffic selector from a CIDR string.
278 *
279 * If protocol is ICMP or ICMPv6 the ports are interpreted as follows: If they
280 * are less than 256 the value is assumed to be a message type, if they are
281 * greater or equal to 256 they are assumed to be type and code as defined
282 * for traffic_selector_t.
283 *
284 * @param string CIDR string, such as 10.1.0.0/16
285 * @param protocol protocol for this ts, such as TCP or UDP
286 * @param from_port start of allowed port range
287 * @param to_port end of port range
288 * @return traffic selector, NULL if string invalid
289 */
290 traffic_selector_t *traffic_selector_create_from_cidr(
291 char *string, u_int8_t protocol,
292 u_int16_t from_port, u_int16_t to_port);
293
294 /**
295 * Create a new traffic selector using data read from the net.
296 *
297 * There exists a mix of network and host order in the params.
298 * But the parser gives us this data in this format, so we
299 * don't have to convert twice.
300 *
301 * If protocol is ICMP or ICMPv6 the ports are interpreted as follows: If they
302 * are less than 256 the value is assumed to be a message type, if they are
303 * greater or equal to 256 they are assumed to be type and code as defined
304 * for traffic_selector_t.
305 *
306 * @param protocol protocol for this ts, such as TCP or UDP
307 * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
308 * @param from_address start of address range, network order
309 * @param from_port port number, host order
310 * @param to_address end of address range, network order
311 * @param to_port port number, host order
312 * @return traffic_selector_t object
313 */
314 traffic_selector_t *traffic_selector_create_from_bytes(
315 u_int8_t protocol, ts_type_t type,
316 chunk_t from_address, u_int16_t from_port,
317 chunk_t to_address, u_int16_t to_port);
318
319 /**
320 * Create a new traffic selector using the RFC 3779 ASN.1 min/max address format
321 *
322 * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
323 * @param from_addr start of address range in RFC 3779 ASN.1 BIT STRING format
324 * @param to_addr end of address range in RFC 3779 ASN.1 BIT STRING format
325 * @return traffic_selector_t object
326 */
327 traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
328 chunk_t from_addr, chunk_t to_addr);
329
330 /**
331 * Create a new traffic selector defining a whole subnet.
332 *
333 * In most cases, definition of a traffic selector for full subnets
334 * is sufficient. This constructor creates a traffic selector for
335 * all protocols, all ports and the address range specified by the
336 * subnet.
337 * Additionally, a protocol and ports may be specified.
338 *
339 * If protocol is ICMP or ICMPv6 the ports are interpreted as follows: If they
340 * are less than 256 the value is assumed to be a message type, if they are
341 * greater or equal to 256 they are assumed to be type and code as defined
342 * for traffic_selector_t.
343 *
344 * @param net subnet to use
345 * @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation
346 * @param protocol protocol for this ts, such as TCP or UDP
347 * @param from_port start of allowed port range
348 * @param to_port end of port range
349 * @return
350 * - traffic_selector_t object
351 * - NULL if address family of net not supported
352 */
353 traffic_selector_t *traffic_selector_create_from_subnet(
354 host_t *net, u_int8_t netbits, u_int8_t protocol,
355 u_int16_t from_port, u_int16_t to_port);
356
357 /**
358 * Create a traffic selector for host-to-host cases.
359 *
360 * For host2host or virtual IP setups, the traffic selectors gets
361 * created at runtime using the external/virtual IP. Using this constructor,
362 * a call to set_address() sets this traffic selector to the supplied host.
363 *
364 * If protocol is ICMP or ICMPv6 the ports are interpreted as follows: If they
365 * are less than 256 the value is assumed to be a message type, if they are
366 * greater or equal to 256 they are assumed to be type and code as defined
367 * for traffic_selector_t.
368 *
369 * @param protocol upper layer protocl to allow
370 * @param from_port start of allowed port range
371 * @param to_port end of range
372 * @return
373 * - traffic_selector_t object
374 * - NULL if type not supported
375 */
376 traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
377 u_int16_t from_port, u_int16_t to_port);
378
379 /**
380 * printf hook function for traffic_selector_t.
381 *
382 * Arguments are:
383 * traffic_selector_t *ts
384 * With the #-specifier, arguments are:
385 * linked_list_t *list containing traffic_selector_t*
386 */
387 int traffic_selector_printf_hook(printf_hook_data_t *data,
388 printf_hook_spec_t *spec, const void *const *args);
389
390 #endif /** TRAFFIC_SELECTOR_H_ @}*/