payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / conftest / hooks / set_reserved.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "hook.h"
17
18 #include <encoding/payloads/sa_payload.h>
19
20 typedef struct private_set_reserved_t private_set_reserved_t;
21
22 /**
23 * Private data of an set_reserved_t object.
24 */
25 struct private_set_reserved_t {
26
27 /**
28 * Implements the hook_t interface.
29 */
30 hook_t hook;
31
32 /**
33 * Alter requests or responses?
34 */
35 bool req;
36
37 /**
38 * ID of message to alter.
39 */
40 int id;
41
42 /**
43 * Hook name
44 */
45 char *name;
46 };
47
48 /**
49 * Set reserved bit of a payload
50 */
51 static void set_bit(private_set_reserved_t *this, message_t *message,
52 payload_type_t type, u_int nr)
53 {
54 enumerator_t *payloads;
55 payload_t *payload;
56 bool *bit;
57
58 if (type == PL_HEADER)
59 {
60 message->set_reserved_header_bit(message, nr);
61 DBG1(DBG_CFG, "setting reserved bit %d of %N",
62 nr, payload_type_short_names, type);
63 }
64 else
65 {
66 payloads = message->create_payload_enumerator(message);
67 while (payloads->enumerate(payloads, &payload))
68 {
69 if (payload->get_type(payload) == type)
70 {
71 bit = payload_get_field(payload, RESERVED_BIT, nr);
72 if (bit)
73 {
74 DBG1(DBG_CFG, "setting reserved bit %d of %N",
75 nr, payload_type_short_names, type);
76 *bit = TRUE;
77 }
78 }
79 }
80 payloads->destroy(payloads);
81 }
82 }
83
84 /**
85 * Set reserved byte of a payload
86 */
87 static void set_byte(private_set_reserved_t *this, message_t *message,
88 payload_type_t type, u_int nr, u_int8_t byteval)
89 {
90 enumerator_t *payloads;
91 payload_t *payload;
92 u_int8_t *byte;
93
94 if (type == PLV2_TRANSFORM_SUBSTRUCTURE || type == PLV2_PROPOSAL_SUBSTRUCTURE)
95 {
96 enumerator_t *transforms, *proposals;
97 transform_substructure_t *transform;
98 proposal_substructure_t *proposal;
99 sa_payload_t *sa;
100
101 payloads = message->create_payload_enumerator(message);
102 while (payloads->enumerate(payloads, &payload))
103 {
104 if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION)
105 {
106 sa = (sa_payload_t*)payload;
107 proposals = sa->create_substructure_enumerator(sa);
108 while (proposals->enumerate(proposals, &proposal))
109 {
110 if (type == PLV2_PROPOSAL_SUBSTRUCTURE)
111 {
112 byte = payload_get_field(&proposal->payload_interface,
113 RESERVED_BYTE, nr);
114 if (byte)
115 {
116 DBG1(DBG_CFG, "setting reserved byte %d of %N to %d",
117 nr, payload_type_short_names, type, byteval);
118 *byte = byteval;
119 }
120 }
121 else if (type == PLV2_TRANSFORM_SUBSTRUCTURE)
122 {
123 transforms = proposal->create_substructure_enumerator(
124 proposal);
125 while (transforms->enumerate(transforms, &transform))
126 {
127 byte = payload_get_field(&transform->payload_interface,
128 RESERVED_BYTE, nr);
129 if (byte)
130 {
131 DBG1(DBG_CFG, "setting reserved byte %d of %N to %d",
132 nr, payload_type_short_names, type, byteval);
133 *byte = byteval;
134 }
135 }
136 transforms->destroy(transforms);
137 }
138 }
139 proposals->destroy(proposals);
140 }
141 }
142 payloads->destroy(payloads);
143 }
144 else
145 {
146 payloads = message->create_payload_enumerator(message);
147 while (payloads->enumerate(payloads, &payload))
148 {
149 if (payload->get_type(payload) == type)
150 {
151 byte = payload_get_field(payload, RESERVED_BYTE, nr);
152 if (byte)
153 {
154 DBG1(DBG_CFG, "setting reserved byte %d of %N to %d",
155 nr, payload_type_short_names, type, byteval);
156 *byte = byteval;
157 }
158 }
159 }
160 payloads->destroy(payloads);
161 }
162 }
163
164 METHOD(listener_t, message, bool,
165 private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message,
166 bool incoming, bool plain)
167 {
168 if (!incoming && plain &&
169 message->get_request(message) == this->req &&
170 message->get_message_id(message) == this->id)
171 {
172 enumerator_t *bits, *bytes, *types;
173 payload_type_t type;
174 char *nr, *name;
175 u_int8_t byteval;
176
177 types = conftest->test->create_section_enumerator(conftest->test,
178 "hooks.%s", this->name);
179 while (types->enumerate(types, &name))
180 {
181 type = atoi(name);
182 if (!type)
183 {
184 if (!enum_from_name(payload_type_short_names, name, &type))
185 {
186 DBG1(DBG_CFG, "invalid payload name '%s'", name);
187 break;
188 }
189 }
190 nr = conftest->test->get_str(conftest->test,
191 "hooks.%s.%s.bits", "", this->name, name);
192 bits = enumerator_create_token(nr, ",", " ");
193 while (bits->enumerate(bits, &nr))
194 {
195 set_bit(this, message, type, atoi(nr));
196 }
197 bits->destroy(bits);
198
199 nr = conftest->test->get_str(conftest->test,
200 "hooks.%s.%s.bytes", "", this->name, name);
201 byteval = conftest->test->get_int(conftest->test,
202 "hooks.%s.%s.byteval", 255, this->name, name);
203 bytes = enumerator_create_token(nr, ",", " ");
204 while (bytes->enumerate(bytes, &nr))
205 {
206 set_byte(this, message, type, atoi(nr), byteval);
207 }
208 bytes->destroy(bytes);
209 }
210 types->destroy(types);
211 }
212 return TRUE;
213 }
214
215 METHOD(hook_t, destroy, void,
216 private_set_reserved_t *this)
217 {
218 free(this->name);
219 free(this);
220 }
221
222 /**
223 * Create the IKE_AUTH fill hook
224 */
225 hook_t *set_reserved_hook_create(char *name)
226 {
227 private_set_reserved_t *this;
228
229 INIT(this,
230 .hook = {
231 .listener = {
232 .message = _message,
233 },
234 .destroy = _destroy,
235 },
236 .req = conftest->test->get_bool(conftest->test,
237 "hooks.%s.request", TRUE, name),
238 .id = conftest->test->get_int(conftest->test,
239 "hooks.%s.id", 0, name),
240 .name = strdup(name),
241 );
242
243 return &this->hook;
244 }