Add stroke message type counters
[strongswan.git] / src / libcharon / plugins / stroke / stroke_counter.c
1 /*
2 * Copyright (C) 2012 Martin Willi
3 * Copyright (C) 2012 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 "stroke_counter.h"
17
18 #include <threading/spinlock.h>
19
20 ENUM(stroke_counter_type_names,
21 COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
22 "ikeInitRekey",
23 "ikeRspRekey",
24 "ikeChildSaRekey",
25 "ikeInInvalid",
26 "ikeInInvalidSpi",
27 "ikeInInitReq",
28 "ikeInInitRsp",
29 "ikeOutInitReq",
30 "ikeOutInitRsp",
31 "ikeInAuthReq",
32 "ikeInAuthRsp",
33 "ikeOutAuthReq",
34 "ikeOutAuthRsp",
35 "ikeInCrChildReq",
36 "ikeInCrChildRsp",
37 "ikeOutCrChildReq",
38 "ikeOutCrChildRsp",
39 "ikeInInfoReq",
40 "ikeInInfoRsp",
41 "ikeOutInfoReq",
42 "ikeOutInfoRsp",
43 );
44
45 typedef struct private_stroke_counter_t private_stroke_counter_t;
46
47 /**
48 * Private data of an stroke_counter_t object.
49 */
50 struct private_stroke_counter_t {
51
52 /**
53 * Public stroke_counter_t interface.
54 */
55 stroke_counter_t public;
56
57 /**
58 * Counter values
59 */
60 u_int64_t counter[COUNTER_MAX];
61
62 /**
63 * Lock for counter values
64 */
65 spinlock_t *lock;
66 };
67
68 METHOD(listener_t, alert, bool,
69 private_stroke_counter_t *this, ike_sa_t *ike_sa,
70 alert_t alert, va_list args)
71 {
72 stroke_counter_type_t type;
73
74 switch (alert)
75 {
76 case ALERT_INVALID_IKE_SPI:
77 type = COUNTER_IN_INVALID_IKE_SPI;
78 break;
79 case ALERT_PARSE_ERROR_HEADER:
80 case ALERT_PARSE_ERROR_BODY:
81 type = COUNTER_IN_INVALID;
82 break;
83 default:
84 return TRUE;
85 }
86
87 this->lock->lock(this->lock);
88 this->counter[type]++;
89 this->lock->unlock(this->lock);
90
91 return TRUE;
92 }
93
94 METHOD(listener_t, ike_rekey, bool,
95 private_stroke_counter_t *this, ike_sa_t *old, ike_sa_t *new)
96 {
97 stroke_counter_type_t type;
98 ike_sa_id_t *id;
99
100 id = new->get_id(new);
101 if (id->is_initiator(id))
102 {
103 type = COUNTER_INIT_IKE_SA_REKEY;
104 }
105 else
106 {
107 type = COUNTER_RESP_IKE_SA_REKEY;
108 }
109
110 this->lock->lock(this->lock);
111 this->counter[type]++;
112 this->lock->unlock(this->lock);
113
114 return TRUE;
115 }
116
117 METHOD(listener_t, child_rekey, bool,
118 private_stroke_counter_t *this, ike_sa_t *ike_sa,
119 child_sa_t *old, child_sa_t *new)
120 {
121 this->lock->lock(this->lock);
122 this->counter[COUNTER_CHILD_SA_REKEY]++;
123 this->lock->unlock(this->lock);
124
125 return TRUE;
126 }
127
128 METHOD(listener_t, message_hook, bool,
129 private_stroke_counter_t *this, ike_sa_t *ike_sa, message_t *message,
130 bool incoming, bool plain)
131 {
132 stroke_counter_type_t type;
133 bool request;
134
135 if ((incoming && !plain) || (!incoming && !plain))
136 { /* handle each message only once */
137 return TRUE;
138 }
139
140 request = message->get_request(message);
141 switch (message->get_exchange_type(message))
142 {
143 case IKE_SA_INIT:
144 if (incoming)
145 {
146 type = request ? COUNTER_IN_IKE_SA_INIT_REQ
147 : COUNTER_IN_IKE_SA_INIT_RSP;
148 }
149 else
150 {
151 type = request ? COUNTER_OUT_IKE_SA_INIT_REQ
152 : COUNTER_OUT_IKE_SA_INIT_RES;
153 }
154 break;
155 case IKE_AUTH:
156 if (incoming)
157 {
158 type = request ? COUNTER_IN_IKE_AUTH_REQ
159 : COUNTER_IN_IKE_AUTH_RSP;
160 }
161 else
162 {
163 type = request ? COUNTER_OUT_IKE_AUTH_REQ
164 : COUNTER_OUT_IKE_AUTH_RSP;
165 }
166 break;
167 case CREATE_CHILD_SA:
168 if (incoming)
169 {
170 type = request ? COUNTER_IN_CREATE_CHILD_SA_REQ
171 : COUNTER_IN_CREATE_CHILD_SA_RSP;
172 }
173 else
174 {
175 type = request ? COUNTER_OUT_CREATE_CHILD_SA_REQ
176 : COUNTER_OUT_CREATE_CHILD_SA_RSP;
177 }
178 break;
179 case INFORMATIONAL:
180 if (incoming)
181 {
182 type = request ? COUNTER_IN_INFORMATIONAL_REQ
183 : COUNTER_IN_INFORMATIONAL_RSP;
184 }
185 else
186 {
187 type = request ? COUNTER_OUT_INFORMATIONAL_REQ
188 : COUNTER_OUT_INFORMATIONAL_RSP;
189 }
190 break;
191 default:
192 return TRUE;
193 }
194
195 this->lock->lock(this->lock);
196 this->counter[type]++;
197 this->lock->unlock(this->lock);
198
199 return TRUE;
200 }
201
202 METHOD(stroke_counter_t, destroy, void,
203 private_stroke_counter_t *this)
204 {
205 this->lock->destroy(this->lock);
206 free(this);
207 }
208
209 /**
210 * See header
211 */
212 stroke_counter_t *stroke_counter_create()
213 {
214 private_stroke_counter_t *this;
215
216 INIT(this,
217 .public = {
218 .listener = {
219 .alert = _alert,
220 .ike_rekey = _ike_rekey,
221 .child_rekey = _child_rekey,
222 .message = _message_hook,
223 },
224 .destroy = _destroy,
225 },
226 .lock = spinlock_create(),
227 );
228
229 return &this->public;
230 }