payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / encoding / payloads / fragment_payload.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "fragment_payload.h"
17
18 #include <encoding/payloads/encodings.h>
19
20 /** Flag that is set in case the given fragment is the last for the message */
21 #define LAST_FRAGMENT 0x01
22
23 typedef struct private_fragment_payload_t private_fragment_payload_t;
24
25 /**
26 * Private data of an fragment_payload_t object.
27 */
28 struct private_fragment_payload_t {
29
30 /**
31 * Public fragment_payload_t interface.
32 */
33 fragment_payload_t public;
34
35 /**
36 * Next payload type.
37 */
38 u_int8_t next_payload;
39
40 /**
41 * Reserved byte
42 */
43 u_int8_t reserved;
44
45 /**
46 * Length of this payload.
47 */
48 u_int16_t payload_length;
49
50 /**
51 * Fragment ID.
52 */
53 u_int16_t fragment_id;
54
55 /**
56 * Fragment number.
57 */
58 u_int8_t fragment_number;
59
60 /**
61 * Flags
62 */
63 u_int8_t flags;
64
65 /**
66 * The contained fragment data.
67 */
68 chunk_t data;
69 };
70
71 /**
72 * Encoding rules for an IKEv1 fragment payload
73 */
74 static encoding_rule_t encodings[] = {
75 /* 1 Byte next payload type, stored in the field next_payload */
76 { U_INT_8, offsetof(private_fragment_payload_t, next_payload) },
77 { RESERVED_BYTE, offsetof(private_fragment_payload_t, reserved) },
78 /* Length of the whole payload*/
79 { PAYLOAD_LENGTH, offsetof(private_fragment_payload_t, payload_length) },
80 { U_INT_16, offsetof(private_fragment_payload_t, fragment_id) },
81 { U_INT_8, offsetof(private_fragment_payload_t, fragment_number) },
82 { U_INT_8, offsetof(private_fragment_payload_t, flags) },
83 /* Fragment data is of variable size */
84 { CHUNK_DATA, offsetof(private_fragment_payload_t, data) },
85 };
86
87 /*
88 1 2 3
89 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
90 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 ! Next Payload ! RESERVED ! Payload Length !
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 ! Fragment ID ! Fragment Num ! Flags !
94 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 ! !
96 ~ Fragment Data ~
97 ! !
98 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 */
100
101 METHOD(payload_t, verify, status_t,
102 private_fragment_payload_t *this)
103 {
104 if (this->fragment_number == 0)
105 {
106 return FAILED;
107 }
108 return SUCCESS;
109 }
110
111 METHOD(payload_t, get_encoding_rules, int,
112 private_fragment_payload_t *this, encoding_rule_t **rules)
113 {
114 *rules = encodings;
115 return countof(encodings);
116 }
117
118 METHOD(payload_t, get_header_length, int,
119 private_fragment_payload_t *this)
120 {
121 return 8;
122 }
123
124 METHOD(payload_t, get_type, payload_type_t,
125 private_fragment_payload_t *this)
126 {
127 return PLV1_FRAGMENT;
128 }
129
130 METHOD(payload_t, get_next_type, payload_type_t,
131 private_fragment_payload_t *this)
132 {
133 return this->next_payload;
134 }
135
136 METHOD(payload_t, set_next_type, void,
137 private_fragment_payload_t *this, payload_type_t type)
138 {
139 this->next_payload = type;
140 }
141
142 METHOD(payload_t, get_length, size_t,
143 private_fragment_payload_t *this)
144 {
145 return this->payload_length;
146 }
147
148 METHOD(fragment_payload_t, get_id, u_int16_t,
149 private_fragment_payload_t *this)
150 {
151 return this->fragment_id;
152 }
153
154 METHOD(fragment_payload_t, get_number, u_int8_t,
155 private_fragment_payload_t *this)
156 {
157 return this->fragment_number;
158 }
159
160 METHOD(fragment_payload_t, is_last, bool,
161 private_fragment_payload_t *this)
162 {
163 return (this->flags & LAST_FRAGMENT) == LAST_FRAGMENT;
164 }
165
166 METHOD(fragment_payload_t, get_data, chunk_t,
167 private_fragment_payload_t *this)
168 {
169 return this->data;
170 }
171
172 METHOD2(payload_t, fragment_payload_t, destroy, void,
173 private_fragment_payload_t *this)
174 {
175 free(this->data.ptr);
176 free(this);
177 }
178
179 /*
180 * Described in header
181 */
182 fragment_payload_t *fragment_payload_create()
183 {
184 private_fragment_payload_t *this;
185
186 INIT(this,
187 .public = {
188 .payload_interface = {
189 .verify = _verify,
190 .get_encoding_rules = _get_encoding_rules,
191 .get_header_length = _get_header_length,
192 .get_length = _get_length,
193 .get_next_type = _get_next_type,
194 .set_next_type = _set_next_type,
195 .get_type = _get_type,
196 .destroy = _destroy,
197 },
198 .get_id = _get_id,
199 .get_number = _get_number,
200 .is_last = _is_last,
201 .get_data = _get_data,
202 .destroy = _destroy,
203 },
204 .next_payload = PL_NONE,
205 );
206 this->payload_length = get_header_length(this);
207 return &this->public;
208 }
209
210 /*
211 * Described in header
212 */
213 fragment_payload_t *fragment_payload_create_from_data(u_int8_t num, bool last,
214 chunk_t data)
215 {
216 private_fragment_payload_t *this;
217
218 this = (private_fragment_payload_t*)fragment_payload_create();
219 this->fragment_id = 1;
220 this->fragment_number = num;
221 this->flags |= (last ? LAST_FRAGMENT : 0);
222 this->data = chunk_clone(data);
223 this->payload_length = get_header_length(this) + data.len;
224 return &this->public;
225 }