SNMP code that doesn't work.
#ifndef _RADIUS_SNMP_H
#define _RADIUS_SNMP_H
+
+#include <freeradius-devel/stats.h>
+
/*
* Version: $Id$
*/
#ifdef WITH_SNMP
+#ifndef WITH_STATS
+#error WITH_SNMP needs WITH_STATS
+#endif
+
typedef enum smux_event_t {
SMUX_NONE, SMUX_CONNECT, SMUX_READ
} smux_event_t;
time_t last_reset_time;
int32_t reset_time;
int32_t config_reset;
- int32_t total_requests;
- int32_t total_invalid_requests;
- int32_t total_dup_requests;
- int32_t total_responses;
- int32_t total_access_accepts;
- int32_t total_access_rejects;
- int32_t total_access_challenges;
- int32_t total_malformed_requests;
- int32_t total_bad_authenticators;
- int32_t total_packets_dropped;
- int32_t total_no_records;
- int32_t total_unknown_types;
+ fr_stats_t stats;
} rad_snmp_server_t;
typedef struct rad_snmp_t {
int smux_max_failures;
} rad_snmp_t;
-/*
- * Taken from RFC 2619 and RFC 2621
- */
-struct rad_snmp_client_entry_t {
- int index;
- /* IP address */
- /* Client ID (string ) */
- uint32_t requests;
- uint32_t dup_requests;
- uint32_t responses;
- uint32_t accepts;
- uint32_t rejects;
- uint32_t challenges;
- uint32_t malformed_requests;
- uint32_t bad_authenticators;
- uint32_t packets_dropped;
- uint32_t unknown_types;
-};
-
extern rad_snmp_t rad_snmp;
#define RAD_SNMP_INC(_x) if (mainconfig.do_snmp) _x++
#ifdef WITH_ACCOUNTING
#define RAD_SNMP_TYPE_INC(_listener, _x) if (mainconfig.do_snmp) { \
if (_listener->type == RAD_LISTEN_AUTH) { \
- rad_snmp.auth._x++; \
+ rad_snmp.auth.stats._x++; \
} else { if (_listener->type == RAD_LISTEN_ACCT) \
- rad_snmp.acct._x++; } }
+ rad_snmp.acct.stats._x++; } }
#define RAD_SNMP_CLIENT_INC(_listener, _client, _x) if (mainconfig.do_snmp) { \
if (_listener->type == RAD_LISTEN_AUTH) { \
#else /* WITH_ACCOUNTING */
#define RAD_SNMP_TYPE_INC(_listener, _x) if (mainconfig.do_snmp) { \
- rad_snmp.auth._x++; }
+ rad_snmp.auth.stats._x++; }
#define RAD_SNMP_CLIENT_INC(_listener, _client, _x) if (mainconfig.do_snmp) { \
_client->auth->_x++; }
#define WITH_DYNAMIC_CLIENTS (1)
#endif
+#ifndef WITHOUT_STATS
+#define WITH_STATS
+#endif
+#include <freeradius-devel/stats.h>
+
+
/*
* See util.c
*/
typedef struct request_data_t request_data_t;
-typedef struct rad_snmp_client_entry_t rad_snmp_client_entry_t;
-
typedef struct radclient {
fr_ipaddr_t ipaddr;
int prefix;
char *server;
int number; /* internal use only */
const CONF_SECTION *cs;
-#ifdef WITH_SNMP
- rad_snmp_client_entry_t *auth;
+#ifdef WITH_STATS
+ fr_client_stats_t *auth;
#ifdef WITH_ACCOUNTING
- rad_snmp_client_entry_t *acct;
+ fr_client_stats_t *acct;
#endif
#endif
--- /dev/null
+#ifndef FR_STATS_H
+#define FR_STATS_H
+
+/*
+ * stats.h Structures and functions for statistics.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2005,2006,2007,2008 The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(stats_h, "$Id$")
+
+#ifdef WITH_STATS_64BIT
+typedef uint64_t fr_uint_t;
+#else
+typedef uint32_t fr_uint_t;
+#endif
+
+#ifdef WITH_STATS
+typedef struct fr_stats_t {
+ fr_uint_t total_requests;
+ fr_uint_t total_invalid_requests;
+ fr_uint_t total_dup_requests;
+ fr_uint_t total_responses;
+ fr_uint_t total_access_accepts;
+ fr_uint_t total_access_rejects;
+ fr_uint_t total_access_challenges;
+ fr_uint_t total_malformed_requests;
+ fr_uint_t total_bad_authenticators;
+ fr_uint_t total_packets_dropped;
+ fr_uint_t total_no_records;
+ fr_uint_t total_unknown_types;
+} fr_stats_t;
+
+/*
+ * Taken from RFC 2619 and RFC 2621
+ */
+typedef struct fr_client_stats_t {
+ /* IP address */
+ /* Client ID (string ) */
+ fr_uint_t requests;
+ fr_uint_t dup_requests;
+ fr_uint_t responses;
+ fr_uint_t accepts;
+ fr_uint_t rejects;
+ fr_uint_t challenges;
+ fr_uint_t malformed_requests;
+ fr_uint_t bad_authenticators;
+ fr_uint_t packets_dropped;
+ fr_uint_t unknown_types;
+} fr_client_stats_t;
+
+
+void request_stats_final(REQUEST *request);
+
+
+#else
+#define request_stats_final(_x)
+#endif
+
+#endif /* FR_STATS_H */
}
}
-#ifdef WITH_SNMP
-static void snmp_inc_counters(REQUEST *request)
-{
- if (!request->root->do_snmp) return;
-
- if (request->master_state == REQUEST_COUNTED) return;
-
- if ((request->listener->type != RAD_LISTEN_AUTH) &&
- (request->listener->type != RAD_LISTEN_ACCT)) return;
-
- /*
- * Update the SNMP statistics.
- *
- * Note that we do NOT do this in a child thread.
- * Instead, we update the stats when a request is
- * deleted, because only the main server thread calls
- * this function, which makes it thread-safe.
- */
- switch (request->reply->code) {
- case PW_AUTHENTICATION_ACK:
- rad_snmp.auth.total_responses++;
- rad_snmp.auth.total_access_accepts++;
- if (request->client && request->client->auth) {
- request->client->auth->accepts++;
- }
- break;
-
- case PW_AUTHENTICATION_REJECT:
- rad_snmp.auth.total_responses++;
- rad_snmp.auth.total_access_rejects++;
- if (request->client && request->client->auth) {
- request->client->auth->rejects++;
- }
- break;
-
- case PW_ACCESS_CHALLENGE:
- rad_snmp.auth.total_responses++;
- rad_snmp.auth.total_access_challenges++;
- if (request->client && request->client->auth) {
- request->client->auth->challenges++;
- }
- break;
-
-#ifdef WITH_ACCOUNTING
- case PW_ACCOUNTING_RESPONSE:
- rad_snmp.acct.total_responses++;
- if (request->client && request->client->acct) {
- request->client->acct->responses++;
- }
- break;
-#endif
-
- /*
- * No response, it must have been a bad
- * authenticator.
- */
- case 0:
- if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
- rad_snmp.auth.total_bad_authenticators++;
- if (request->client && request->client->auth) {
- request->client->auth->bad_authenticators++;
- }
- }
- break;
-
- default:
- break;
- }
-
- request->master_state = REQUEST_COUNTED;
-}
-#else
-#define snmp_inc_counters(_x)
-#endif
-
-
static void remove_from_request_hash(REQUEST *request)
{
if (!request->in_request_hash) return;
fr_packet_list_yank(pl, request->packet);
request->in_request_hash = FALSE;
- snmp_inc_counters(request);
+ request_stats_final(request);
}
#ifdef HAVE_PTHREAD_H
request->child_pid = NO_SUCH_CHILD_PID;
#endif
- snmp_inc_counters(request);
+ request_stats_final(request);
cleanup_delay(request);
return;
#ifdef HAVE_PTHREAD_H
request->child_pid = NO_SUCH_CHILD_PID;
#endif
- snmp_inc_counters(request);
+ request_stats_final(request);
case REQUEST_PROXIED:
rad_assert(request->next_callback != NULL);
case RADIUSACCSERVTOTALREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_requests;
+ return (u_char *) &rad_snmp.acct.stats.total_requests;
case RADIUSACCSERVTOTALINVALIDREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_invalid_requests;
+ return (u_char *) &rad_snmp.acct.stats.total_invalid_requests;
case RADIUSACCSERVTOTALDUPREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_dup_requests;
+ return (u_char *) &rad_snmp.acct.stats.total_dup_requests;
case RADIUSACCSERVTOTALRESPONSES:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_responses;
+ return (u_char *) &rad_snmp.acct.stats.total_responses;
case RADIUSACCSERVTOTALMALFORMEDREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_malformed_requests;
+ return (u_char *) &rad_snmp.acct.stats.total_malformed_requests;
case RADIUSACCSERVTOTALBADAUTHENTICATORS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_bad_authenticators;
+ return (u_char *) &rad_snmp.acct.stats.total_bad_authenticators;
case RADIUSACCSERVTOTALPACKETSDROPPED:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_packets_dropped;
+ return (u_char *) &rad_snmp.acct.stats.total_packets_dropped;
case RADIUSACCSERVTOTALNORECORDS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_no_records;
+ return (u_char *) &rad_snmp.acct.stats.total_no_records;
case RADIUSACCSERVTOTALUNKNOWNTYPES:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.acct.total_unknown_types;
+ return (u_char *) &rad_snmp.acct.stats.total_unknown_types;
}
case RADIUSAUTHSERVTOTALACCESSREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_requests;
+ return (u_char *) &rad_snmp.auth.stats.total_requests;
case RADIUSAUTHSERVTOTALINVALIDREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_invalid_requests;
+ return (u_char *) &rad_snmp.auth.stats.total_invalid_requests;
case RADIUSAUTHSERVTOTALDUPACCESSREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_dup_requests;
+ return (u_char *) &rad_snmp.auth.stats.total_dup_requests;
case RADIUSAUTHSERVTOTALACCESSACCEPTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_access_accepts;
+ return (u_char *) &rad_snmp.auth.stats.total_access_accepts;
case RADIUSAUTHSERVTOTALACCESSREJECTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_access_rejects;
+ return (u_char *) &rad_snmp.auth.stats.total_access_rejects;
case RADIUSAUTHSERVTOTALACCESSCHALLENGES:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_access_challenges;
+ return (u_char *) &rad_snmp.auth.stats.total_access_challenges;
case RADIUSAUTHSERVTOTALMALFORMEDACCESSREQUESTS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_malformed_requests;
+ return (u_char *) &rad_snmp.auth.stats.total_malformed_requests;
case RADIUSAUTHSERVTOTALBADAUTHENTICATORS:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_bad_authenticators;
+ return (u_char *) &rad_snmp.auth.stats.total_bad_authenticators;
case RADIUSAUTHSERVTOTALPACKETSDROPPED:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_packets_dropped;
+ return (u_char *) &rad_snmp.auth.stats.total_packets_dropped;
case RADIUSAUTHSERVTOTALUNKNOWNTYPES:
*var_len = sizeof(int32_t);
- return (u_char *) &rad_snmp.auth.total_unknown_types;
+ return (u_char *) &rad_snmp.auth.stats.total_unknown_types;
}
--- /dev/null
+/*
+ * stats.c Internal statistics handling.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2008 The FreeRADIUS server project
+ * Copyright 2008 Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/radius_snmp.h>
+
+#ifdef WITH_STATS
+
+#ifdef WITH_PROXY
+fr_stats_t proxy_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+fr_stats_t proxy_acct_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+void request_stats_final(REQUEST *request)
+{
+ if (request->master_state == REQUEST_COUNTED) return;
+
+ if ((request->listener->type != RAD_LISTEN_AUTH) &&
+ (request->listener->type != RAD_LISTEN_ACCT)) return;
+
+ /*
+ * Update the statistics.
+ *
+ * Note that we do NOT do this in a child thread.
+ * Instead, we update the stats when a request is
+ * deleted, because only the main server thread calls
+ * this function, which makes it thread-safe.
+ */
+ switch (request->reply->code) {
+ case PW_AUTHENTICATION_ACK:
+ rad_snmp.auth.stats.total_responses++;
+ rad_snmp.auth.stats.total_access_accepts++;
+ if (request->client && request->client->auth) {
+ request->client->auth->accepts++;
+ }
+ break;
+
+ case PW_AUTHENTICATION_REJECT:
+ rad_snmp.auth.stats.total_responses++;
+ rad_snmp.auth.stats.total_access_rejects++;
+ if (request->client && request->client->auth) {
+ request->client->auth->rejects++;
+ }
+ break;
+
+ case PW_ACCESS_CHALLENGE:
+ rad_snmp.auth.stats.total_responses++;
+ rad_snmp.auth.stats.total_access_challenges++;
+ if (request->client && request->client->auth) {
+ request->client->auth->challenges++;
+ }
+ break;
+
+#ifdef WITH_ACCOUNTINGxu
+ case PW_ACCOUNTING_RESPONSE:
+ rad_snmp.acct.stats.total_responses++;
+ if (request->client && request->client->acct) {
+ request->client->acct->responses++;
+ }
+ break;
+#endif
+
+ /*
+ * No response, it must have been a bad
+ * authenticator.
+ */
+ case 0:
+ if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
+ rad_snmp.auth.stats.total_bad_authenticators++;
+ if (request->client && request->client->auth) {
+ request->client->auth->bad_authenticators++;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#ifdef WITH_PROXY
+ if (!request->proxy) goto done; /* simplifies formatting */
+
+ switch (request->proxy_reply->code) {
+ case PW_AUTHENTICATION_REQUEST:
+ proxy_auth_stats.total_requests += request->num_proxied_requests;
+ break;
+
+#ifdef WITH_ACCOUNTING
+ case PW_ACCOUNTING_REQUEST:
+ proxy_acct_stats.total_requests++;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ if (!request->proxy_reply) goto done; /* simplifies formatting */
+
+ switch (request->proxy_reply->code) {
+ case PW_AUTHENTICATION_ACK:
+ proxy_auth_stats.total_responses += request->num_proxied_responses;
+ proxy_auth_stats.total_access_accepts += request->num_proxied_responses;
+ break;
+
+ case PW_AUTHENTICATION_REJECT:
+ proxy_auth_stats.total_responses += request->num_proxied_responses;
+ proxy_auth_stats.total_access_rejects += request->num_proxied_responses;
+ break;
+
+ case PW_ACCESS_CHALLENGE:
+ proxy_auth_stats.total_responses += request->num_proxied_responses;
+ proxy_auth_stats.total_access_challenges += request->num_proxied_responses;
+ break;
+
+#ifdef WITH_ACCOUNTING
+ case PW_ACCOUNTING_RESPONSE:
+ rad_snmp.acct.stats.total_responses++;
+ break;
+#endif
+
+ default:
+ proxy_auth_stats.total_unknown_types++;
+ break;
+ }
+
+ done:
+#endif /* WITH_PROXY */
+
+ request->master_state = REQUEST_COUNTED;
+}
+
+typedef struct fr_stats2vp {
+ int attribute;
+ size_t offset;
+} fr_stats2vp;
+
+/*
+ * Authentication
+ */
+static fr_stats2vp authvp[] = {
+ { 128, offsetof(fr_stats_t, total_requests) },
+ { 129, offsetof(fr_stats_t, total_access_accepts) },
+ { 130, offsetof(fr_stats_t, total_access_rejects) },
+ { 131, offsetof(fr_stats_t, total_access_challenges) },
+ { 132, offsetof(fr_stats_t, total_responses) },
+ { 133, offsetof(fr_stats_t, total_dup_requests) },
+ { 134, offsetof(fr_stats_t, total_malformed_requests) },
+ { 135, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 136, offsetof(fr_stats_t, total_packets_dropped) },
+ { 137, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+
+#ifdef WITH_PROXY
+/*
+ * Proxied authentication requests.
+ */
+static fr_stats2vp proxy_authvp[] = {
+ { 138, offsetof(fr_stats_t, total_requests) },
+ { 139, offsetof(fr_stats_t, total_access_accepts) },
+ { 140, offsetof(fr_stats_t, total_access_rejects) },
+ { 141, offsetof(fr_stats_t, total_access_challenges) },
+ { 142, offsetof(fr_stats_t, total_responses) },
+ { 143, offsetof(fr_stats_t, total_dup_requests) },
+ { 144, offsetof(fr_stats_t, total_malformed_requests) },
+ { 145, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 146, offsetof(fr_stats_t, total_packets_dropped) },
+ { 147, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+#endif
+
+#define FR2ATTR(x) ((11344 << 16) | (x))
+
+void request_stats_reply(REQUEST *request)
+{
+ int i;
+ VALUE_PAIR *vp;
+
+ if (request->packet->code != PW_STATUS_SERVER) return;
+
+ if ((request->packet->src_ipaddr.af != AF_INET) ||
+ (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_LOOPBACK))) return;
+
+#if 0
+ vp = pairfind(request->packet->vps, PW_CLASS);
+ if (!vp || (strcmp(vp->vp_strvalue, "Statistics") != 0)) return;
+#endif
+
+ for (i = 0; authvp[i].attribute != 0; i++) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(authvp[i].attribute),
+ PW_TYPE_INTEGER);
+ if (!vp) continue;
+
+ vp->vp_integer = *(int *)(((char *) &rad_snmp.auth.stats) +
+ authvp[i].offset);
+ }
+
+#ifdef WITH_PROXY
+ for (i = 0; proxy_authvp[i].attribute != 0; i++) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(proxy_authvp[i].attribute),
+ PW_TYPE_INTEGER);
+ if (!vp) continue;
+
+ vp->vp_integer = *(int *)(((char *) &proxy_auth_stats) +
+ proxy_authvp[i].offset);
+ }
+#endif
+}
+
+#endif /* WITH_STATS */