]>
Commit | Line | Data |
---|---|---|
446a4537 MW |
1 | /* |
2 | * Copyright (C) 2010 Martin Willi | |
19ef2aec TB |
3 | * |
4 | * Copyright (C) secunet Security Networks AG | |
446a4537 MW |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
17 | #include "hook.h" | |
18 | ||
b5bbc950 | 19 | #include <encoding/payloads/sa_payload.h> |
446a4537 MW |
20 | |
21 | typedef struct private_set_reserved_t private_set_reserved_t; | |
22 | ||
23 | /** | |
24 | * Private data of an set_reserved_t object. | |
25 | */ | |
26 | struct private_set_reserved_t { | |
27 | ||
28 | /** | |
29 | * Implements the hook_t interface. | |
30 | */ | |
31 | hook_t hook; | |
32 | ||
33 | /** | |
34 | * Alter requests or responses? | |
35 | */ | |
36 | bool req; | |
37 | ||
38 | /** | |
39 | * ID of message to alter. | |
40 | */ | |
41 | int id; | |
42 | ||
43 | /** | |
44 | * Hook name | |
45 | */ | |
46 | char *name; | |
47 | }; | |
48 | ||
b5bbc950 MW |
49 | /** |
50 | * Set reserved bit of a payload | |
51 | */ | |
52 | static void set_bit(private_set_reserved_t *this, message_t *message, | |
53 | payload_type_t type, u_int nr) | |
54 | { | |
55 | enumerator_t *payloads; | |
56 | payload_t *payload; | |
57 | bool *bit; | |
58 | ||
3ecfc83c | 59 | if (type == PL_HEADER) |
b5bbc950 MW |
60 | { |
61 | message->set_reserved_header_bit(message, nr); | |
62 | DBG1(DBG_CFG, "setting reserved bit %d of %N", | |
63 | nr, payload_type_short_names, type); | |
64 | } | |
65 | else | |
66 | { | |
67 | payloads = message->create_payload_enumerator(message); | |
68 | while (payloads->enumerate(payloads, &payload)) | |
69 | { | |
70 | if (payload->get_type(payload) == type) | |
71 | { | |
72 | bit = payload_get_field(payload, RESERVED_BIT, nr); | |
73 | if (bit) | |
74 | { | |
75 | DBG1(DBG_CFG, "setting reserved bit %d of %N", | |
76 | nr, payload_type_short_names, type); | |
77 | *bit = TRUE; | |
78 | } | |
79 | } | |
80 | } | |
81 | payloads->destroy(payloads); | |
82 | } | |
83 | } | |
84 | ||
85 | /** | |
86 | * Set reserved byte of a payload | |
87 | */ | |
88 | static void set_byte(private_set_reserved_t *this, message_t *message, | |
b12c53ce | 89 | payload_type_t type, u_int nr, uint8_t byteval) |
b5bbc950 MW |
90 | { |
91 | enumerator_t *payloads; | |
92 | payload_t *payload; | |
b12c53ce | 93 | uint8_t *byte; |
b5bbc950 | 94 | |
3ecfc83c | 95 | if (type == PLV2_TRANSFORM_SUBSTRUCTURE || type == PLV2_PROPOSAL_SUBSTRUCTURE) |
b5bbc950 MW |
96 | { |
97 | enumerator_t *transforms, *proposals; | |
98 | transform_substructure_t *transform; | |
99 | proposal_substructure_t *proposal; | |
100 | sa_payload_t *sa; | |
101 | ||
102 | payloads = message->create_payload_enumerator(message); | |
103 | while (payloads->enumerate(payloads, &payload)) | |
104 | { | |
3ecfc83c | 105 | if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION) |
b5bbc950 MW |
106 | { |
107 | sa = (sa_payload_t*)payload; | |
108 | proposals = sa->create_substructure_enumerator(sa); | |
109 | while (proposals->enumerate(proposals, &proposal)) | |
110 | { | |
3ecfc83c | 111 | if (type == PLV2_PROPOSAL_SUBSTRUCTURE) |
b5bbc950 MW |
112 | { |
113 | byte = payload_get_field(&proposal->payload_interface, | |
114 | RESERVED_BYTE, nr); | |
115 | if (byte) | |
116 | { | |
117 | DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", | |
118 | nr, payload_type_short_names, type, byteval); | |
119 | *byte = byteval; | |
120 | } | |
121 | } | |
3ecfc83c | 122 | else if (type == PLV2_TRANSFORM_SUBSTRUCTURE) |
b5bbc950 MW |
123 | { |
124 | transforms = proposal->create_substructure_enumerator( | |
125 | proposal); | |
126 | while (transforms->enumerate(transforms, &transform)) | |
127 | { | |
128 | byte = payload_get_field(&transform->payload_interface, | |
129 | RESERVED_BYTE, nr); | |
130 | if (byte) | |
131 | { | |
132 | DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", | |
133 | nr, payload_type_short_names, type, byteval); | |
134 | *byte = byteval; | |
135 | } | |
136 | } | |
137 | transforms->destroy(transforms); | |
138 | } | |
139 | } | |
140 | proposals->destroy(proposals); | |
141 | } | |
142 | } | |
143 | payloads->destroy(payloads); | |
144 | } | |
145 | else | |
146 | { | |
147 | payloads = message->create_payload_enumerator(message); | |
148 | while (payloads->enumerate(payloads, &payload)) | |
149 | { | |
150 | if (payload->get_type(payload) == type) | |
151 | { | |
152 | byte = payload_get_field(payload, RESERVED_BYTE, nr); | |
153 | if (byte) | |
154 | { | |
155 | DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", | |
156 | nr, payload_type_short_names, type, byteval); | |
157 | *byte = byteval; | |
158 | } | |
159 | } | |
160 | } | |
161 | payloads->destroy(payloads); | |
162 | } | |
163 | } | |
164 | ||
446a4537 MW |
165 | METHOD(listener_t, message, bool, |
166 | private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message, | |
47b8f6ef | 167 | bool incoming, bool plain) |
446a4537 | 168 | { |
47b8f6ef | 169 | if (!incoming && plain && |
446a4537 MW |
170 | message->get_request(message) == this->req && |
171 | message->get_message_id(message) == this->id) | |
172 | { | |
5c95bf7b MW |
173 | enumerator_t *bits, *bytes, *types; |
174 | payload_type_t type; | |
175 | char *nr, *name; | |
b12c53ce | 176 | uint8_t byteval; |
5c95bf7b MW |
177 | |
178 | types = conftest->test->create_section_enumerator(conftest->test, | |
179 | "hooks.%s", this->name); | |
180 | while (types->enumerate(types, &name)) | |
446a4537 | 181 | { |
5c95bf7b MW |
182 | type = atoi(name); |
183 | if (!type) | |
446a4537 | 184 | { |
064fe9c9 | 185 | if (!enum_from_name(payload_type_short_names, name, &type)) |
5c95bf7b MW |
186 | { |
187 | DBG1(DBG_CFG, "invalid payload name '%s'", name); | |
188 | break; | |
189 | } | |
446a4537 | 190 | } |
5c95bf7b MW |
191 | nr = conftest->test->get_str(conftest->test, |
192 | "hooks.%s.%s.bits", "", this->name, name); | |
193 | bits = enumerator_create_token(nr, ",", " "); | |
194 | while (bits->enumerate(bits, &nr)) | |
446a4537 | 195 | { |
5c95bf7b | 196 | set_bit(this, message, type, atoi(nr)); |
446a4537 | 197 | } |
5c95bf7b MW |
198 | bits->destroy(bits); |
199 | ||
200 | nr = conftest->test->get_str(conftest->test, | |
201 | "hooks.%s.%s.bytes", "", this->name, name); | |
202 | byteval = conftest->test->get_int(conftest->test, | |
203 | "hooks.%s.%s.byteval", 255, this->name, name); | |
204 | bytes = enumerator_create_token(nr, ",", " "); | |
205 | while (bytes->enumerate(bytes, &nr)) | |
446a4537 | 206 | { |
5c95bf7b | 207 | set_byte(this, message, type, atoi(nr), byteval); |
446a4537 | 208 | } |
5c95bf7b | 209 | bytes->destroy(bytes); |
446a4537 | 210 | } |
5c95bf7b | 211 | types->destroy(types); |
446a4537 MW |
212 | } |
213 | return TRUE; | |
214 | } | |
215 | ||
216 | METHOD(hook_t, destroy, void, | |
217 | private_set_reserved_t *this) | |
218 | { | |
219 | free(this->name); | |
220 | free(this); | |
221 | } | |
222 | ||
223 | /** | |
224 | * Create the IKE_AUTH fill hook | |
225 | */ | |
226 | hook_t *set_reserved_hook_create(char *name) | |
227 | { | |
228 | private_set_reserved_t *this; | |
229 | ||
230 | INIT(this, | |
231 | .hook = { | |
232 | .listener = { | |
233 | .message = _message, | |
234 | }, | |
235 | .destroy = _destroy, | |
236 | }, | |
237 | .req = conftest->test->get_bool(conftest->test, | |
238 | "hooks.%s.request", TRUE, name), | |
239 | .id = conftest->test->get_int(conftest->test, | |
240 | "hooks.%s.id", 0, name), | |
241 | .name = strdup(name), | |
242 | ); | |
243 | ||
244 | return &this->hook; | |
245 | } |