Implemented a hook to set reserved bits
[strongswan.git] / src / conftest / hooks / set_length.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 typedef struct private_set_length_t private_set_length_t;
19
20 /**
21 * Private data of an set_length_t object.
22 */
23 struct private_set_length_t {
24
25 /**
26 * Implements the hook_t interface.
27 */
28 hook_t hook;
29
30 /**
31 * Alter requests or responses?
32 */
33 bool req;
34
35 /**
36 * ID of message to alter.
37 */
38 int id;
39
40 /**
41 * Payload type
42 */
43 char *type;
44
45 /**
46 * Difference to correct length
47 */
48 int diff;
49 };
50
51 METHOD(listener_t, message, bool,
52 private_set_length_t *this, ike_sa_t *ike_sa, message_t *message,
53 bool incoming)
54 {
55 if (!incoming &&
56 message->get_request(message) == this->req &&
57 message->get_message_id(message) == this->id)
58 {
59 payload_t *payload;
60 enumerator_t *enumerator;
61 payload_type_t type;
62
63 type = atoi(this->type);
64 if (!type)
65 {
66 type = enum_from_name(payload_type_short_names, this->type);
67 if (type == -1)
68 {
69 DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
70 return TRUE;
71 }
72 }
73 enumerator = message->create_payload_enumerator(message);
74 while (enumerator->enumerate(enumerator, &payload))
75 {
76 if (type == payload->get_type(payload))
77 {
78 encoding_rule_t *rules;
79 size_t count;
80 u_int16_t *len;
81 int i;
82
83 payload->get_encoding_rules(payload, &rules, &count);
84 for (i = 0; i < count; i++)
85 {
86 if (rules[i].type == PAYLOAD_LENGTH)
87 {
88 len = (u_int16_t*)(((void*)payload) + rules[i].offset);
89 DBG1(DBG_CFG, "adjusting length of %N payload "
90 "from %d to %d", payload_type_short_names, type,
91 *len, *len + this->diff);
92 *len = *len + this->diff;
93 }
94 }
95 }
96 }
97 enumerator->destroy(enumerator);
98 }
99 return TRUE;
100 }
101
102 METHOD(hook_t, destroy, void,
103 private_set_length_t *this)
104 {
105 free(this);
106 }
107
108 /**
109 * Create the IKE_AUTH fill hook
110 */
111 hook_t *set_length_hook_create(char *name)
112 {
113 private_set_length_t *this;
114
115 INIT(this,
116 .hook = {
117 .listener = {
118 .message = _message,
119 },
120 .destroy = _destroy,
121 },
122 .req = conftest->test->get_bool(conftest->test,
123 "hooks.%s.request", TRUE, name),
124 .id = conftest->test->get_int(conftest->test,
125 "hooks.%s.id", 0, name),
126 .type = conftest->test->get_str(conftest->test,
127 "hooks.%s.type", "", name),
128 .diff = conftest->test->get_int(conftest->test,
129 "hooks.%s.diff", 0, name),
130 );
131
132 return &this->hook;
133 }