~yolanda.robla/ubuntu/saucy/freeradius/dep-8-tests

« back to all changes in this revision

Viewing changes to src/main/stats.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2009-11-23 03:57:37 UTC
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20091123035737-snauioz5r9tf8sdr
Tags: upstream-2.1.7+dfsg
ImportĀ upstreamĀ versionĀ 2.1.7+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * stats.c      Internal statistics handling.
 
3
 *
 
4
 * Version:     $Id$
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 *
 
20
 * Copyright 2008  The FreeRADIUS server project
 
21
 * Copyright 2008  Alan DeKok <aland@deployingradius.com>
 
22
 */
 
23
 
 
24
#include <freeradius-devel/ident.h>
 
25
RCSID("$Id$")
 
26
 
 
27
#include <freeradius-devel/radiusd.h>
 
28
#include <freeradius-devel/rad_assert.h>
 
29
 
 
30
#ifdef WITH_STATS
 
31
 
 
32
#define USEC (1000000)
 
33
#define EMA_SCALE (100)
 
34
#define PREC (USEC * EMA_SCALE)
 
35
 
 
36
#define F_EMA_SCALE (1000000)
 
37
 
 
38
static struct timeval   start_time;
 
39
static struct timeval   hup_time;
 
40
 
 
41
fr_stats_t radius_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
42
#ifdef WITH_ACCOUNTING
 
43
fr_stats_t radius_acct_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
44
#endif
 
45
 
 
46
#ifdef WITH_PROXY
 
47
fr_stats_t proxy_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
48
#ifdef WITH_ACCOUNTING
 
49
fr_stats_t proxy_acct_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
50
#endif
 
51
#endif
 
52
 
 
53
void request_stats_final(REQUEST *request)
 
54
{
 
55
        if (request->master_state == REQUEST_COUNTED) return;
 
56
 
 
57
        if ((request->listener->type != RAD_LISTEN_NONE) &&
 
58
            (request->listener->type != RAD_LISTEN_AUTH) &&
 
59
            (request->listener->type != RAD_LISTEN_ACCT)) return;
 
60
 
 
61
        /*
 
62
         *      Update the statistics.
 
63
         *
 
64
         *      Note that we do NOT do this in a child thread.
 
65
         *      Instead, we update the stats when a request is
 
66
         *      deleted, because only the main server thread calls
 
67
         *      this function, which makes it thread-safe.
 
68
         */
 
69
        switch (request->reply->code) {
 
70
        case PW_AUTHENTICATION_ACK:
 
71
                radius_auth_stats.total_responses++;
 
72
                radius_auth_stats.total_access_accepts++;
 
73
                request->listener->stats.total_responses++;
 
74
                request->listener->stats.total_access_accepts++;
 
75
                if (request->client && request->client->auth) {
 
76
                        request->client->auth->total_access_accepts++;
 
77
                        request->client->auth->total_responses++;
 
78
                }
 
79
                break;
 
80
 
 
81
        case PW_AUTHENTICATION_REJECT:
 
82
                radius_auth_stats.total_responses++;
 
83
                radius_auth_stats.total_access_rejects++;
 
84
                request->listener->stats.total_responses++;
 
85
                request->listener->stats.total_access_rejects++;
 
86
                if (request->client && request->client->auth) {
 
87
                        request->client->auth->total_access_rejects++;
 
88
                        request->client->auth->total_responses++;
 
89
                }
 
90
                break;
 
91
 
 
92
        case PW_ACCESS_CHALLENGE:
 
93
                radius_auth_stats.total_responses++;
 
94
                radius_auth_stats.total_access_challenges++;
 
95
                request->listener->stats.total_responses++;
 
96
                request->listener->stats.total_access_challenges++;
 
97
                if (request->client && request->client->auth) {
 
98
                        request->client->auth->total_access_challenges++;
 
99
                        request->client->auth->total_responses++;
 
100
                }
 
101
                break;
 
102
 
 
103
#ifdef WITH_ACCOUNTING
 
104
        case PW_ACCOUNTING_RESPONSE:
 
105
                radius_acct_stats.total_responses++;
 
106
                request->listener->stats.total_responses++;
 
107
                if (request->client && request->client->acct) {
 
108
                        request->client->acct->total_responses++;
 
109
                }
 
110
                break;
 
111
#endif
 
112
 
 
113
                /*
 
114
                 *      No response, it must have been a bad
 
115
                 *      authenticator.
 
116
                 */
 
117
        case 0:
 
118
                if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
 
119
                        radius_auth_stats.total_bad_authenticators++;
 
120
                        request->listener->stats.total_bad_authenticators++;
 
121
                        if (request->client && request->client->auth) {
 
122
                                request->client->auth->total_bad_authenticators++;
 
123
                        }
 
124
                }
 
125
                break;
 
126
 
 
127
        default:
 
128
                break;
 
129
        }
 
130
 
 
131
#ifdef WITH_PROXY
 
132
        if (!request->proxy || !request->proxy_listener) goto done;     /* simplifies formatting */
 
133
 
 
134
        switch (request->proxy->code) {
 
135
        case PW_AUTHENTICATION_REQUEST:
 
136
                proxy_auth_stats.total_requests += request->num_proxied_requests;
 
137
                request->proxy_listener->stats.total_requests += request->num_proxied_requests;
 
138
                request->home_server->stats.total_requests += request->num_proxied_requests;
 
139
                break;
 
140
 
 
141
#ifdef WITH_ACCOUNTING
 
142
        case PW_ACCOUNTING_REQUEST:
 
143
                proxy_acct_stats.total_requests++;
 
144
                request->proxy_listener->stats.total_requests += request->num_proxied_requests;
 
145
                request->home_server->stats.total_requests += request->num_proxied_requests;
 
146
                break;
 
147
#endif
 
148
 
 
149
        default:
 
150
                break;
 
151
        }
 
152
 
 
153
        if (!request->proxy_reply) goto done;   /* simplifies formatting */
 
154
 
 
155
#undef INC
 
156
#define INC(_x) proxy_auth_stats._x += request->num_proxied_responses; request->proxy_listener->stats._x += request->num_proxied_responses; request->home_server->stats._x += request->num_proxied_responses;
 
157
 
 
158
        switch (request->proxy_reply->code) {
 
159
        case PW_AUTHENTICATION_ACK:
 
160
                INC(total_responses);
 
161
                INC(total_access_accepts);
 
162
                break;
 
163
 
 
164
        case PW_AUTHENTICATION_REJECT:
 
165
                INC(total_responses);
 
166
                INC(total_access_rejects);
 
167
                break;
 
168
 
 
169
        case PW_ACCESS_CHALLENGE:
 
170
                INC(total_responses);
 
171
                INC(total_access_challenges);
 
172
                break;
 
173
 
 
174
#ifdef WITH_ACCOUNTING
 
175
        case PW_ACCOUNTING_RESPONSE:
 
176
                radius_acct_stats.total_responses++;
 
177
                request->proxy_listener->stats.total_responses++;
 
178
                request->home_server->stats.total_responses++;
 
179
                break;
 
180
#endif
 
181
 
 
182
        default:
 
183
                proxy_auth_stats.total_unknown_types++;
 
184
                request->proxy_listener->stats.total_unknown_types++;
 
185
                request->home_server->stats.total_unknown_types++;
 
186
                break;
 
187
        }
 
188
 
 
189
 done:
 
190
#endif /* WITH_PROXY */
 
191
 
 
192
        request->master_state = REQUEST_COUNTED;
 
193
}
 
194
 
 
195
typedef struct fr_stats2vp {
 
196
        int     attribute;
 
197
        size_t  offset;
 
198
} fr_stats2vp;
 
199
 
 
200
/*
 
201
 *      Authentication
 
202
 */
 
203
static fr_stats2vp authvp[] = {
 
204
        { 128, offsetof(fr_stats_t, total_requests) },
 
205
        { 129, offsetof(fr_stats_t, total_access_accepts) },
 
206
        { 130, offsetof(fr_stats_t, total_access_rejects) },
 
207
        { 131, offsetof(fr_stats_t, total_access_challenges) },
 
208
        { 132, offsetof(fr_stats_t, total_responses) },
 
209
        { 133, offsetof(fr_stats_t, total_dup_requests) },
 
210
        { 134, offsetof(fr_stats_t, total_malformed_requests) },
 
211
        { 135, offsetof(fr_stats_t, total_bad_authenticators) },
 
212
        { 136, offsetof(fr_stats_t, total_packets_dropped) },
 
213
        { 137, offsetof(fr_stats_t, total_unknown_types) },
 
214
        { 0, 0 }
 
215
};
 
216
 
 
217
 
 
218
#ifdef WITH_PROXY
 
219
/*
 
220
 *      Proxied authentication requests.
 
221
 */
 
222
static fr_stats2vp proxy_authvp[] = {
 
223
        { 138, offsetof(fr_stats_t, total_requests) },
 
224
        { 139, offsetof(fr_stats_t, total_access_accepts) },
 
225
        { 140, offsetof(fr_stats_t, total_access_rejects) },
 
226
        { 141, offsetof(fr_stats_t, total_access_challenges) },
 
227
        { 142, offsetof(fr_stats_t, total_responses) },
 
228
        { 143, offsetof(fr_stats_t, total_dup_requests) },
 
229
        { 144, offsetof(fr_stats_t, total_malformed_requests) },
 
230
        { 145, offsetof(fr_stats_t, total_bad_authenticators) },
 
231
        { 146, offsetof(fr_stats_t, total_packets_dropped) },
 
232
        { 147, offsetof(fr_stats_t, total_unknown_types) },
 
233
        { 0, 0 }
 
234
};
 
235
#endif
 
236
 
 
237
 
 
238
#ifdef WITH_ACCOUNTING
 
239
/*
 
240
 *      Accounting
 
241
 */
 
242
static fr_stats2vp acctvp[] = {
 
243
        { 148, offsetof(fr_stats_t, total_requests) },
 
244
        { 149, offsetof(fr_stats_t, total_responses) },
 
245
        { 150, offsetof(fr_stats_t, total_dup_requests) },
 
246
        { 151, offsetof(fr_stats_t, total_malformed_requests) },
 
247
        { 152, offsetof(fr_stats_t, total_bad_authenticators) },
 
248
        { 153, offsetof(fr_stats_t, total_packets_dropped) },
 
249
        { 154, offsetof(fr_stats_t, total_unknown_types) },
 
250
        { 0, 0 }
 
251
};
 
252
 
 
253
#ifdef WITH_PROXY
 
254
static fr_stats2vp proxy_acctvp[] = {
 
255
        { 155, offsetof(fr_stats_t, total_requests) },
 
256
        { 156, offsetof(fr_stats_t, total_responses) },
 
257
        { 157, offsetof(fr_stats_t, total_dup_requests) },
 
258
        { 158, offsetof(fr_stats_t, total_malformed_requests) },
 
259
        { 159, offsetof(fr_stats_t, total_bad_authenticators) },
 
260
        { 160, offsetof(fr_stats_t, total_packets_dropped) },
 
261
        { 161, offsetof(fr_stats_t, total_unknown_types) },
 
262
        { 0, 0 }
 
263
};
 
264
#endif
 
265
#endif
 
266
 
 
267
static fr_stats2vp client_authvp[] = {
 
268
        { 128, offsetof(fr_stats_t, total_requests) },
 
269
        { 129, offsetof(fr_stats_t, total_access_accepts) },
 
270
        { 130, offsetof(fr_stats_t, total_access_rejects) },
 
271
        { 131, offsetof(fr_stats_t, total_access_challenges) },
 
272
        { 132, offsetof(fr_stats_t, total_responses) },
 
273
        { 133, offsetof(fr_stats_t, total_dup_requests) },
 
274
        { 134, offsetof(fr_stats_t, total_malformed_requests) },
 
275
        { 135, offsetof(fr_stats_t, total_bad_authenticators) },
 
276
        { 136, offsetof(fr_stats_t, total_packets_dropped) },
 
277
        { 137, offsetof(fr_stats_t, total_unknown_types) },
 
278
        { 0, 0 }
 
279
};
 
280
 
 
281
#ifdef WITH_ACCOUNTING
 
282
static fr_stats2vp client_acctvp[] = {
 
283
        { 148, offsetof(fr_stats_t, total_requests) },
 
284
        { 149, offsetof(fr_stats_t, total_responses) },
 
285
        { 150, offsetof(fr_stats_t, total_dup_requests) },
 
286
        { 151, offsetof(fr_stats_t, total_malformed_requests) },
 
287
        { 152, offsetof(fr_stats_t, total_bad_authenticators) },
 
288
        { 153, offsetof(fr_stats_t, total_packets_dropped) },
 
289
        { 154, offsetof(fr_stats_t, total_unknown_types) },
 
290
        { 0, 0 }
 
291
};
 
292
#endif
 
293
 
 
294
#define FR2ATTR(x) ((11344 << 16) | (x))
 
295
 
 
296
static void request_stats_addvp(REQUEST *request,
 
297
                                fr_stats2vp *table, fr_stats_t *stats)
 
298
{
 
299
        int i;
 
300
        VALUE_PAIR *vp;
 
301
 
 
302
        for (i = 0; table[i].attribute != 0; i++) {
 
303
                vp = radius_paircreate(request, &request->reply->vps,
 
304
                                       FR2ATTR(table[i].attribute),
 
305
                                       PW_TYPE_INTEGER);
 
306
                if (!vp) continue;
 
307
 
 
308
                vp->vp_integer = *(int *)(((char *) stats) + table[i].offset);
 
309
        }
 
310
}
 
311
 
 
312
 
 
313
void request_stats_reply(REQUEST *request)
 
314
{
 
315
        VALUE_PAIR *flag, *vp;
 
316
 
 
317
        /*
 
318
         *      Statistics are available ONLY on a "status" port.
 
319
         */
 
320
        rad_assert(request->packet->code == PW_STATUS_SERVER);
 
321
        rad_assert(request->listener->type == RAD_LISTEN_NONE);
 
322
                
 
323
        flag = pairfind(request->packet->vps, FR2ATTR(127));
 
324
        if (!flag || (flag->vp_integer == 0)) return;
 
325
 
 
326
        /*
 
327
         *      Authentication.
 
328
         */
 
329
        if (((flag->vp_integer & 0x01) != 0) &&
 
330
            ((flag->vp_integer & 0xc0) == 0)) {
 
331
                request_stats_addvp(request, authvp, &radius_auth_stats);
 
332
        }
 
333
                
 
334
#ifdef WITH_ACCOUNTING
 
335
        /*
 
336
         *      Accounting
 
337
         */
 
338
        if (((flag->vp_integer & 0x02) != 0) &&
 
339
            ((flag->vp_integer & 0xc0) == 0)) {
 
340
                request_stats_addvp(request, acctvp, &radius_acct_stats);
 
341
        }
 
342
#endif
 
343
 
 
344
#ifdef WITH_PROXY
 
345
        /*
 
346
         *      Proxied authentication requests.
 
347
         */
 
348
        if (((flag->vp_integer & 0x04) != 0) &&
 
349
            ((flag->vp_integer & 0x20) == 0)) {
 
350
                request_stats_addvp(request, proxy_authvp, &proxy_auth_stats);
 
351
        }
 
352
 
 
353
#ifdef WITH_ACCOUNTING
 
354
        /*
 
355
         *      Proxied accounting requests.
 
356
         */
 
357
        if (((flag->vp_integer & 0x08) != 0) &&
 
358
            ((flag->vp_integer & 0x20) == 0)) {
 
359
                request_stats_addvp(request, proxy_acctvp, &proxy_acct_stats);
 
360
        }
 
361
#endif
 
362
#endif
 
363
 
 
364
        /*
 
365
         *      Internal server statistics
 
366
         */
 
367
        if ((flag->vp_integer & 0x10) != 0) {
 
368
                vp = radius_paircreate(request, &request->reply->vps,
 
369
                                       FR2ATTR(176), PW_TYPE_DATE);
 
370
                if (vp) vp->vp_date = start_time.tv_sec;
 
371
                vp = radius_paircreate(request, &request->reply->vps,
 
372
                                       FR2ATTR(177), PW_TYPE_DATE);
 
373
                if (vp) vp->vp_date = hup_time.tv_sec;
 
374
                
 
375
#ifdef HAVE_PTHREAD_H
 
376
                int i, array[RAD_LISTEN_MAX];
 
377
 
 
378
                thread_pool_queue_stats(array);
 
379
 
 
380
                for (i = 0; i <= RAD_LISTEN_DETAIL; i++) {
 
381
                        vp = radius_paircreate(request, &request->reply->vps,
 
382
                                               FR2ATTR(162 + i),
 
383
                                               PW_TYPE_INTEGER);
 
384
                        
 
385
                        if (!vp) continue;
 
386
                        vp->vp_integer = array[i];
 
387
                }
 
388
#endif
 
389
        }
 
390
 
 
391
        /*
 
392
         *      For a particular client.
 
393
         */
 
394
        if ((flag->vp_integer & 0x20) != 0) {
 
395
                fr_ipaddr_t ipaddr;
 
396
                VALUE_PAIR *server_ip, *server_port = NULL;
 
397
                RADCLIENT *client = NULL;
 
398
                RADCLIENT_LIST *cl = NULL;
 
399
 
 
400
                /*
 
401
                 *      See if we need to look up the client by server
 
402
                 *      socket.
 
403
                 */
 
404
                server_ip = pairfind(request->packet->vps, FR2ATTR(170));
 
405
                if (server_ip) {
 
406
                        server_port = pairfind(request->packet->vps,
 
407
                                               FR2ATTR(171));
 
408
 
 
409
                        if (server_port) {
 
410
                                ipaddr.af = AF_INET;
 
411
                                ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
 
412
                                cl = listener_find_client_list(&ipaddr, server_port->vp_integer);
 
413
                                                               
 
414
                                /*
 
415
                                 *      Not found: don't do anything
 
416
                                 */
 
417
                                if (!cl) return;
 
418
                        }
 
419
                }
 
420
 
 
421
 
 
422
                vp = pairfind(request->packet->vps, FR2ATTR(167));
 
423
                if (vp) {
 
424
                        ipaddr.af = AF_INET;
 
425
                        ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
 
426
                        client = client_find(cl, &ipaddr);
 
427
 
 
428
                        /*
 
429
                         *      Else look it up by number.
 
430
                         */
 
431
                } else if ((vp = pairfind(request->packet->vps,
 
432
                                           FR2ATTR(168))) != NULL) {
 
433
                        client = client_findbynumber(cl, vp->vp_integer);
 
434
                }
 
435
 
 
436
                if (client) {
 
437
                        /*
 
438
                         *      If found, echo it back, along with
 
439
                         *      the requested statistics.
 
440
                         */
 
441
                        pairadd(&request->reply->vps, paircopyvp(vp));
 
442
 
 
443
                        /*
 
444
                         *      When retrieving client by number, also
 
445
                         *      echo back it's IP address.
 
446
                         */
 
447
                        if ((vp->type == PW_TYPE_INTEGER) &&
 
448
                            (client->ipaddr.af == AF_INET)) {
 
449
                                vp = radius_paircreate(request,
 
450
                                                       &request->reply->vps,
 
451
                                                       FR2ATTR(167),
 
452
                                                       PW_TYPE_IPADDR);
 
453
                                if (vp) {
 
454
                                        vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
 
455
                                }
 
456
 
 
457
                                if (client->prefix != 32) {
 
458
                                        vp = radius_paircreate(request,
 
459
                                                               &request->reply->vps,
 
460
                                                               FR2ATTR(169),
 
461
                                                               PW_TYPE_INTEGER);
 
462
                                        if (vp) {
 
463
                                                vp->vp_integer = client->prefix;
 
464
                                        }
 
465
                                }
 
466
                        }
 
467
                        
 
468
                        if (server_ip) {
 
469
                                pairadd(&request->reply->vps,
 
470
                                        paircopyvp(server_ip));
 
471
                                pairadd(&request->reply->vps,
 
472
                                        paircopyvp(server_port));
 
473
                        }
 
474
 
 
475
                        if (client->auth &&
 
476
                            ((flag->vp_integer & 0x01) != 0)) {
 
477
                                request_stats_addvp(request, client_authvp,
 
478
                                                    client->auth);
 
479
                        }
 
480
#ifdef WITH_ACCOUNTING
 
481
                        if (client->acct &&
 
482
                            ((flag->vp_integer & 0x01) != 0)) {
 
483
                                request_stats_addvp(request, client_acctvp,
 
484
                                                    client->acct);
 
485
                        }
 
486
#endif
 
487
                } /* else client wasn't found, don't echo it back */
 
488
        }
 
489
 
 
490
        /*
 
491
         *      For a particular "listen" socket.
 
492
         */
 
493
        if (((flag->vp_integer & 0x40) != 0) &&
 
494
            ((flag->vp_integer & 0x03) != 0)) {
 
495
                rad_listen_t *this;
 
496
                VALUE_PAIR *server_ip, *server_port;
 
497
                fr_ipaddr_t ipaddr;
 
498
 
 
499
                /*
 
500
                 *      See if we need to look up the server by socket
 
501
                 *      socket.
 
502
                 */
 
503
                server_ip = pairfind(request->packet->vps, FR2ATTR(170));
 
504
                if (!server_ip) return;
 
505
 
 
506
                server_port = pairfind(request->packet->vps,
 
507
                                       FR2ATTR(171));
 
508
                if (!server_port) return;
 
509
                
 
510
                ipaddr.af = AF_INET;
 
511
                ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
 
512
                this = listener_find_byipaddr(&ipaddr,
 
513
                                              server_port->vp_integer);
 
514
                
 
515
                /*
 
516
                 *      Not found: don't do anything
 
517
                 */
 
518
                if (!this) return;
 
519
                
 
520
                pairadd(&request->reply->vps,
 
521
                        paircopyvp(server_ip));
 
522
                pairadd(&request->reply->vps,
 
523
                        paircopyvp(server_port));
 
524
 
 
525
                if (((flag->vp_integer & 0x01) != 0) &&
 
526
                    ((request->listener->type == RAD_LISTEN_AUTH) ||
 
527
                     (request->listener->type == RAD_LISTEN_NONE))) {
 
528
                        request_stats_addvp(request, authvp, &this->stats);
 
529
                }
 
530
                
 
531
#ifdef WITH_ACCOUNTING
 
532
                if (((flag->vp_integer & 0x02) != 0) &&
 
533
                    ((request->listener->type == RAD_LISTEN_ACCT) ||
 
534
                     (request->listener->type == RAD_LISTEN_NONE))) {
 
535
                        request_stats_addvp(request, acctvp, &this->stats);
 
536
                }
 
537
#endif
 
538
        }
 
539
 
 
540
        /*
 
541
         *      Home servers.
 
542
         */
 
543
        if (((flag->vp_integer & 0x80) != 0) &&
 
544
            ((flag->vp_integer & 0x03) != 0)) {
 
545
                home_server *home;
 
546
                VALUE_PAIR *server_ip, *server_port;
 
547
                fr_ipaddr_t ipaddr;
 
548
 
 
549
                /*
 
550
                 *      See if we need to look up the server by socket
 
551
                 *      socket.
 
552
                 */
 
553
                server_ip = pairfind(request->packet->vps, FR2ATTR(170));
 
554
                if (!server_ip) return;
 
555
 
 
556
                server_port = pairfind(request->packet->vps,
 
557
                                       FR2ATTR(171));
 
558
                if (!server_port) return;
 
559
                
 
560
                ipaddr.af = AF_INET;
 
561
                ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
 
562
                home = home_server_find(&ipaddr, server_port->vp_integer);
 
563
 
 
564
                /*
 
565
                 *      Not found: don't do anything
 
566
                 */
 
567
                if (!home) return;
 
568
                
 
569
                pairadd(&request->reply->vps,
 
570
                        paircopyvp(server_ip));
 
571
                pairadd(&request->reply->vps,
 
572
                        paircopyvp(server_port));
 
573
 
 
574
                vp = radius_paircreate(request, &request->reply->vps,
 
575
                                       FR2ATTR(172), PW_TYPE_INTEGER);
 
576
                if (vp) vp->vp_integer = home->currently_outstanding;
 
577
 
 
578
                vp = radius_paircreate(request, &request->reply->vps,
 
579
                                       FR2ATTR(173), PW_TYPE_INTEGER);
 
580
                if (vp) vp->vp_integer = home->state;
 
581
 
 
582
                if ((home->state == HOME_STATE_ALIVE) &&
 
583
                    (home->revive_time.tv_sec != 0)) {
 
584
                        vp = radius_paircreate(request, &request->reply->vps,
 
585
                                               FR2ATTR(175), PW_TYPE_DATE);
 
586
                        if (vp) vp->vp_date = home->revive_time.tv_sec;
 
587
                }
 
588
 
 
589
                if ((home->state == HOME_STATE_ALIVE) &&
 
590
                    (home->ema.window > 0)) {
 
591
                                vp = radius_paircreate(request,
 
592
                                                       &request->reply->vps,
 
593
                                                       FR2ATTR(178),
 
594
                                                       PW_TYPE_INTEGER);
 
595
                                if (vp) vp->vp_integer = home->ema.window;
 
596
                                vp = radius_paircreate(request,
 
597
                                                       &request->reply->vps,
 
598
                                                       FR2ATTR(179),
 
599
                                                       PW_TYPE_INTEGER);
 
600
                                if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
 
601
                                vp = radius_paircreate(request,
 
602
                                                       &request->reply->vps,
 
603
                                                       FR2ATTR(180),
 
604
                                                       PW_TYPE_INTEGER);
 
605
                                if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
 
606
 
 
607
                }
 
608
 
 
609
                if (home->state == HOME_STATE_IS_DEAD) {
 
610
                        vp = radius_paircreate(request, &request->reply->vps,
 
611
                                               FR2ATTR(174), PW_TYPE_DATE);
 
612
                        if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
 
613
                }
 
614
 
 
615
                if (((flag->vp_integer & 0x01) != 0) &&
 
616
                    (home->type == HOME_TYPE_AUTH)) {
 
617
                        request_stats_addvp(request, proxy_authvp,
 
618
                                            &home->stats);
 
619
                }
 
620
 
 
621
#ifdef WITH_ACCOUNTING
 
622
                if (((flag->vp_integer & 0x02) != 0) &&
 
623
                    (home->type == HOME_TYPE_ACCT)) {
 
624
                        request_stats_addvp(request, proxy_acctvp,
 
625
                                            &home->stats);
 
626
                }
 
627
#endif
 
628
        }
 
629
}
 
630
 
 
631
void radius_stats_init(int flag)
 
632
{
 
633
        if (!flag) {
 
634
                gettimeofday(&start_time, NULL);
 
635
                hup_time = start_time; /* it's just nicer this way */
 
636
        } else {
 
637
                gettimeofday(&hup_time, NULL);
 
638
        }
 
639
}
 
640
 
 
641
void radius_stats_ema(fr_stats_ema_t *ema,
 
642
                      struct timeval *start, struct timeval *end)
 
643
{
 
644
        int micro;
 
645
        time_t tdiff;
 
646
#ifdef WITH_STATS_DEBUG
 
647
        static int n = 0;
 
648
#endif
 
649
        if (ema->window == 0) return;
 
650
 
 
651
        rad_assert(start->tv_sec >= end->tv_sec);
 
652
 
 
653
        /*
 
654
         *      Initialize it.
 
655
         */
 
656
        if (ema->f1 == 0) {
 
657
                if (ema->window > 10000) ema->window = 10000;
 
658
                
 
659
                ema->f1 =  (2 * F_EMA_SCALE) / (ema->window + 1);
 
660
                ema->f10 = (2 * F_EMA_SCALE) / ((10 * ema->window) + 1);
 
661
        }
 
662
 
 
663
 
 
664
        tdiff = start->tv_sec;
 
665
        tdiff -= end->tv_sec;
 
666
        
 
667
        micro = (int) tdiff;
 
668
        if (micro > 40) micro = 40; /* don't overflow 32-bit ints */
 
669
        micro *= USEC;
 
670
        micro += start->tv_usec;
 
671
        micro -= end->tv_usec;
 
672
        
 
673
        micro *= EMA_SCALE;
 
674
 
 
675
        if (ema->ema1 == 0) {
 
676
                ema->ema1 = micro;
 
677
                ema->ema10 = micro;
 
678
        } else {
 
679
                int diff;
 
680
                
 
681
                diff = ema->f1 * (micro - ema->ema1);
 
682
                ema->ema1 += (diff / 1000000);
 
683
                
 
684
                diff = ema->f10 * (micro - ema->ema10);
 
685
                ema->ema10 += (diff / 1000000);
 
686
        }
 
687
        
 
688
        
 
689
#ifdef WITH_STATS_DEBUG
 
690
        DEBUG("time %d %d.%06d\t%d.%06d\t%d.%06d\n",
 
691
              n, micro / PREC, (micro / EMA_SCALE) % USEC,
 
692
              ema->ema1 / PREC, (ema->ema1 / EMA_SCALE) % USEC,
 
693
              ema->ema10 / PREC, (ema->ema10 / EMA_SCALE) % USEC);
 
694
        n++;
 
695
#endif  
 
696
}
 
697
 
 
698
#endif /* WITH_STATS */