Separated libcharon/sa directory with ikev1 and ikev2 subfolders
[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 u_int16_t *len;
80 int i, count;
81
82 count = payload->get_encoding_rules(payload, &rules);
83 for (i = 0; i < count; i++)
84 {
85 if (rules[i].type == PAYLOAD_LENGTH)
86 {
87 len = (u_int16_t*)(((void*)payload) + rules[i].offset);
88 DBG1(DBG_CFG, "adjusting length of %N payload "
89 "from %d to %d", payload_type_short_names, type,
90 *len, *len + this->diff);
91 *len = *len + this->diff;
92 }
93 }
94 }
95 }
96 enumerator->destroy(enumerator);
97 }
98 return TRUE;
99 }
100
101 METHOD(hook_t, destroy, void,
102 private_set_length_t *this)
103 {
104 free(this);
105 }
106
107 /**
108 * Create the IKE_AUTH fill hook
109 */
110 hook_t *set_length_hook_create(char *name)
111 {
112 private_set_length_t *this;
113
114 INIT(this,
115 .hook = {
116 .listener = {
117 .message = _message,
118 },
119 .destroy = _destroy,
120 },
121 .req = conftest->test->get_bool(conftest->test,
122 "hooks.%s.request", TRUE, name),
123 .id = conftest->test->get_int(conftest->test,
124 "hooks.%s.id", 0, name),
125 .type = conftest->test->get_str(conftest->test,
126 "hooks.%s.type", "", name),
127 .diff = conftest->test->get_int(conftest->test,
128 "hooks.%s.diff", 0, name),
129 );
130
131 return &this->hook;
132 }