2 * stats.c Internal statistics handling.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2008 The FreeRADIUS server project
21 * Copyright 2008 Alan DeKok <aland@deployingradius.com>
24 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/rad_assert.h>
32 fr_stats_t radius_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
33 #ifdef WITH_ACCOUNTING
34 fr_stats_t radius_acct_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
38 fr_stats_t proxy_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
39 #ifdef WITH_ACCOUNTING
40 fr_stats_t proxy_acct_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
44 void request_stats_final(REQUEST *request)
46 if (request->master_state == REQUEST_COUNTED) return;
48 if ((request->listener->type != RAD_LISTEN_AUTH) &&
49 (request->listener->type != RAD_LISTEN_ACCT)) return;
52 * Update the statistics.
54 * Note that we do NOT do this in a child thread.
55 * Instead, we update the stats when a request is
56 * deleted, because only the main server thread calls
57 * this function, which makes it thread-safe.
59 switch (request->reply->code) {
60 case PW_AUTHENTICATION_ACK:
61 radius_auth_stats.total_responses++;
62 radius_auth_stats.total_access_accepts++;
63 if (request->client && request->client->auth) {
64 request->client->auth->accepts++;
68 case PW_AUTHENTICATION_REJECT:
69 radius_auth_stats.total_responses++;
70 radius_auth_stats.total_access_rejects++;
71 if (request->client && request->client->auth) {
72 request->client->auth->rejects++;
76 case PW_ACCESS_CHALLENGE:
77 radius_auth_stats.total_responses++;
78 radius_auth_stats.total_access_challenges++;
79 if (request->client && request->client->auth) {
80 request->client->auth->challenges++;
84 #ifdef WITH_ACCOUNTING
85 case PW_ACCOUNTING_RESPONSE:
86 radius_acct_stats.total_responses++;
87 if (request->client && request->client->acct) {
88 request->client->acct->responses++;
94 * No response, it must have been a bad
98 if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
99 radius_auth_stats.total_bad_authenticators++;
100 if (request->client && request->client->auth) {
101 request->client->auth->bad_authenticators++;
111 if (!request->proxy) goto done; /* simplifies formatting */
113 switch (request->proxy_reply->code) {
114 case PW_AUTHENTICATION_REQUEST:
115 proxy_auth_stats.total_requests += request->num_proxied_requests;
118 #ifdef WITH_ACCOUNTING
119 case PW_ACCOUNTING_REQUEST:
120 proxy_acct_stats.total_requests++;
128 if (!request->proxy_reply) goto done; /* simplifies formatting */
130 switch (request->proxy_reply->code) {
131 case PW_AUTHENTICATION_ACK:
132 proxy_auth_stats.total_responses += request->num_proxied_responses;
133 proxy_auth_stats.total_access_accepts += request->num_proxied_responses;
136 case PW_AUTHENTICATION_REJECT:
137 proxy_auth_stats.total_responses += request->num_proxied_responses;
138 proxy_auth_stats.total_access_rejects += request->num_proxied_responses;
141 case PW_ACCESS_CHALLENGE:
142 proxy_auth_stats.total_responses += request->num_proxied_responses;
143 proxy_auth_stats.total_access_challenges += request->num_proxied_responses;
146 #ifdef WITH_ACCOUNTING
147 case PW_ACCOUNTING_RESPONSE:
148 radius_acct_stats.total_responses++;
153 proxy_auth_stats.total_unknown_types++;
158 #endif /* WITH_PROXY */
160 request->master_state = REQUEST_COUNTED;
163 typedef struct fr_stats2vp {
171 static fr_stats2vp authvp[] = {
172 { 128, offsetof(fr_stats_t, total_requests) },
173 { 129, offsetof(fr_stats_t, total_access_accepts) },
174 { 130, offsetof(fr_stats_t, total_access_rejects) },
175 { 131, offsetof(fr_stats_t, total_access_challenges) },
176 { 132, offsetof(fr_stats_t, total_responses) },
177 { 133, offsetof(fr_stats_t, total_dup_requests) },
178 { 134, offsetof(fr_stats_t, total_malformed_requests) },
179 { 135, offsetof(fr_stats_t, total_bad_authenticators) },
180 { 136, offsetof(fr_stats_t, total_packets_dropped) },
181 { 137, offsetof(fr_stats_t, total_unknown_types) },
187 * Proxied authentication requests.
189 static fr_stats2vp proxy_authvp[] = {
190 { 138, offsetof(fr_stats_t, total_requests) },
191 { 139, offsetof(fr_stats_t, total_access_accepts) },
192 { 140, offsetof(fr_stats_t, total_access_rejects) },
193 { 141, offsetof(fr_stats_t, total_access_challenges) },
194 { 142, offsetof(fr_stats_t, total_responses) },
195 { 143, offsetof(fr_stats_t, total_dup_requests) },
196 { 144, offsetof(fr_stats_t, total_malformed_requests) },
197 { 145, offsetof(fr_stats_t, total_bad_authenticators) },
198 { 146, offsetof(fr_stats_t, total_packets_dropped) },
199 { 147, offsetof(fr_stats_t, total_unknown_types) },
204 #define FR2ATTR(x) ((11344 << 16) | (x))
206 void request_stats_reply(REQUEST *request)
211 if (request->packet->code != PW_STATUS_SERVER) return;
213 if ((request->packet->src_ipaddr.af != AF_INET) ||
214 (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_LOOPBACK))) return;
216 vp = pairfind(request->packet->vps, PW_CONFIGURATION_TOKEN);
217 if (!vp || (strcmp(vp->vp_strvalue, "Statistics") != 0)) return;
219 for (i = 0; authvp[i].attribute != 0; i++) {
220 vp = radius_paircreate(request, &request->reply->vps,
221 FR2ATTR(authvp[i].attribute),
225 vp->vp_integer = *(int *)(((char *) &radius_auth_stats) +
230 for (i = 0; proxy_authvp[i].attribute != 0; i++) {
231 vp = radius_paircreate(request, &request->reply->vps,
232 FR2ATTR(proxy_authvp[i].attribute),
236 vp->vp_integer = *(int *)(((char *) &proxy_auth_stats) +
237 proxy_authvp[i].offset);
242 #endif /* WITH_STATS */