Implemented a hook to set reserved bits
[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/unknown_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 METHOD(listener_t, message, bool,
49 private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message,
50 bool incoming)
51 {
52 if (!incoming &&
53 message->get_request(message) == this->req &&
54 message->get_message_id(message) == this->id)
55 {
56 enumerator_t *bits, *bytes, *types, *payloads;
57 payload_type_t type;
58 payload_t *payload;
59 char *nr, *name;
60 bool *bit;
61 u_int8_t *byte, byteval;
62
63 types = conftest->test->create_section_enumerator(conftest->test,
64 "hooks.%s", this->name);
65 while (types->enumerate(types, &name))
66 {
67 type = atoi(name);
68 if (!type)
69 {
70 type = enum_from_name(payload_type_short_names, name);
71 if (type == -1)
72 {
73 DBG1(DBG_CFG, "invalid payload name '%s'", name);
74 break;
75 }
76 }
77 nr = conftest->test->get_str(conftest->test,
78 "hooks.%s.%s.bits", "", this->name, name);
79 bits = enumerator_create_token(nr, ",", " ");
80 while (bits->enumerate(bits, &nr))
81 {
82 if (type == HEADER)
83 {
84 message->set_reserved_header_bit(message, atoi(nr));
85 DBG1(DBG_CFG, "setting reserved bit %s of %N",
86 nr, payload_type_short_names, type);
87 continue;
88 }
89 payloads = message->create_payload_enumerator(message);
90 while (payloads->enumerate(payloads, &payload))
91 {
92 if (payload->get_type(payload) == type)
93 {
94 bit = payload_get_field(payload, RESERVED_BIT, atoi(nr));
95 if (bit)
96 {
97 DBG1(DBG_CFG, "setting reserved bit %s of %N",
98 nr, payload_type_short_names, type);
99 *bit = TRUE;
100 }
101 }
102 }
103 payloads->destroy(payloads);
104 }
105 bits->destroy(bits);
106
107 nr = conftest->test->get_str(conftest->test,
108 "hooks.%s.%s.bytes", "", this->name, name);
109 byteval = conftest->test->get_int(conftest->test,
110 "hooks.%s.%s.byteval", 255, this->name, name);
111 bytes = enumerator_create_token(nr, ",", " ");
112 while (bytes->enumerate(bytes, &nr))
113 {
114 payloads = message->create_payload_enumerator(message);
115 while (payloads->enumerate(payloads, &payload))
116 {
117 if (payload->get_type(payload) == type)
118 {
119 byte = payload_get_field(payload, RESERVED_BYTE, atoi(nr));
120 if (byte)
121 {
122 DBG1(DBG_CFG, "setting reserved byte %s of %N to %d",
123 nr, payload_type_short_names, type, byteval);
124 *byte = byteval;
125 }
126 }
127 }
128 payloads->destroy(payloads);
129 }
130 bytes->destroy(bytes);
131 }
132 types->destroy(types);
133 }
134 return TRUE;
135 }
136
137 METHOD(hook_t, destroy, void,
138 private_set_reserved_t *this)
139 {
140 free(this->name);
141 free(this);
142 }
143
144 /**
145 * Create the IKE_AUTH fill hook
146 */
147 hook_t *set_reserved_hook_create(char *name)
148 {
149 private_set_reserved_t *this;
150
151 INIT(this,
152 .hook = {
153 .listener = {
154 .message = _message,
155 },
156 .destroy = _destroy,
157 },
158 .req = conftest->test->get_bool(conftest->test,
159 "hooks.%s.request", TRUE, name),
160 .id = conftest->test->get_int(conftest->test,
161 "hooks.%s.id", 0, name),
162 .name = strdup(name),
163 );
164
165 return &this->hook;
166 }