Version bump to 5.9.0
[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, bool plain)
54 {
55 if (!incoming && plain &&
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 if (!enum_from_name(payload_type_short_names, this->type, &type))
67 {
68 DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
69 return TRUE;
70 }
71 }
72 enumerator = message->create_payload_enumerator(message);
73 while (enumerator->enumerate(enumerator, &payload))
74 {
75 if (type == payload->get_type(payload))
76 {
77 encoding_rule_t *rules;
78 uint16_t *len;
79 int i, count;
80
81 count = payload->get_encoding_rules(payload, &rules);
82 for (i = 0; i < count; i++)
83 {
84 if (rules[i].type == PAYLOAD_LENGTH)
85 {
86 len = (uint16_t*)(((void*)payload) + rules[i].offset);
87 DBG1(DBG_CFG, "adjusting length of %N payload "
88 "from %d to %d", payload_type_short_names, type,
89 *len, *len + this->diff);
90 *len = *len + this->diff;
91 }
92 }
93 }
94 }
95 enumerator->destroy(enumerator);
96 }
97 return TRUE;
98 }
99
100 METHOD(hook_t, destroy, void,
101 private_set_length_t *this)
102 {
103 free(this);
104 }
105
106 /**
107 * Create the IKE_AUTH fill hook
108 */
109 hook_t *set_length_hook_create(char *name)
110 {
111 private_set_length_t *this;
112
113 INIT(this,
114 .hook = {
115 .listener = {
116 .message = _message,
117 },
118 .destroy = _destroy,
119 },
120 .req = conftest->test->get_bool(conftest->test,
121 "hooks.%s.request", TRUE, name),
122 .id = conftest->test->get_int(conftest->test,
123 "hooks.%s.id", 0, name),
124 .type = conftest->test->get_str(conftest->test,
125 "hooks.%s.type", "", name),
126 .diff = conftest->test->get_int(conftest->test,
127 "hooks.%s.diff", 0, name),
128 );
129
130 return &this->hook;
131 }