eap-radius: Increase buffer for accounting attributes to maximum attribute size
[strongswan.git] / src / libcharon / plugins / eap_radius / eap_radius_accounting.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 "eap_radius_accounting.h"
17 #include "eap_radius_plugin.h"
18
19 #include <time.h>
20
21 #include <radius_message.h>
22 #include <radius_client.h>
23 #include <daemon.h>
24 #include <collections/hashtable.h>
25 #include <threading/mutex.h>
26 #include <processing/jobs/callback_job.h>
27
28 typedef struct private_eap_radius_accounting_t private_eap_radius_accounting_t;
29
30 /**
31 * Private data of an eap_radius_accounting_t object.
32 */
33 struct private_eap_radius_accounting_t {
34
35 /**
36 * Public eap_radius_accounting_t interface.
37 */
38 eap_radius_accounting_t public;
39
40 /**
41 * Hashtable with sessions, ike_sa_id_t => entry_t
42 */
43 hashtable_t *sessions;
44
45 /**
46 * Mutex to lock sessions
47 */
48 mutex_t *mutex;
49
50 /**
51 * Session ID prefix
52 */
53 u_int32_t prefix;
54
55 /**
56 * Format string we use for Called/Calling-Station-Id for a host
57 */
58 char *station_id_fmt;
59
60 /**
61 * Disable accounting unless IKE_SA has at least one virtual IP
62 */
63 bool acct_req_vip;
64 };
65
66 /**
67 * Singleton instance of accounting
68 */
69 static private_eap_radius_accounting_t *singleton = NULL;
70
71 /**
72 * Acct-Terminate-Cause
73 */
74 typedef enum {
75 ACCT_CAUSE_USER_REQUEST = 1,
76 ACCT_CAUSE_LOST_CARRIER = 2,
77 ACCT_CAUSE_LOST_SERVICE = 3,
78 ACCT_CAUSE_IDLE_TIMEOUT = 4,
79 ACCT_CAUSE_SESSION_TIMEOUT = 5,
80 ACCT_CAUSE_ADMIN_RESET = 6,
81 ACCT_CAUSE_ADMIN_REBOOT = 7,
82 ACCT_CAUSE_PORT_ERROR = 8,
83 ACCT_CAUSE_NAS_ERROR = 9,
84 ACCT_CAUSE_NAS_REQUEST = 10,
85 ACCT_CAUSE_NAS_REBOOT = 11,
86 ACCT_CAUSE_PORT_UNNEEDED = 12,
87 ACCT_CAUSE_PORT_PREEMPTED = 13,
88 ACCT_CAUSE_PORT_SUSPENDED = 14,
89 ACCT_CAUSE_SERVICE_UNAVAILABLE = 15,
90 ACCT_CAUSE_CALLBACK = 16,
91 ACCT_CAUSE_USER_ERROR = 17,
92 ACCT_CAUSE_HOST_REQUEST = 18,
93 } radius_acct_terminate_cause_t;
94
95 /**
96 * Hashtable entry with usage stats
97 */
98 typedef struct {
99 /** IKE_SA identifier this entry is stored under */
100 ike_sa_id_t *id;
101 /** RADIUS accounting session ID */
102 char sid[16];
103 /** number of sent/received octets/packets */
104 struct {
105 u_int64_t sent;
106 u_int64_t received;
107 } bytes, packets;
108 /** session creation time */
109 time_t created;
110 /** terminate cause */
111 radius_acct_terminate_cause_t cause;
112 /* interim interval and timestamp of last update */
113 struct {
114 u_int32_t interval;
115 time_t last;
116 } interim;
117 /** did we send Accounting-Start */
118 bool start_sent;
119 } entry_t;
120
121 /**
122 * Destroy an entry_t
123 */
124 static void destroy_entry(entry_t *this)
125 {
126 this->id->destroy(this->id);
127 free(this);
128 }
129
130 /**
131 * Accounting message status types
132 */
133 typedef enum {
134 ACCT_STATUS_START = 1,
135 ACCT_STATUS_STOP = 2,
136 ACCT_STATUS_INTERIM_UPDATE = 3,
137 ACCT_STATUS_ACCOUNTING_ON = 7,
138 ACCT_STATUS_ACCOUNTING_OFF = 8,
139 } radius_acct_status_t;
140
141 /**
142 * Hashtable hash function
143 */
144 static u_int hash(ike_sa_id_t *key)
145 {
146 return key->get_responder_spi(key);
147 }
148
149 /**
150 * Hashtable equals function
151 */
152 static bool equals(ike_sa_id_t *a, ike_sa_id_t *b)
153 {
154 return a->equals(a, b);
155 }
156
157 /**
158 * Update usage counter when a CHILD_SA rekeys/goes down
159 */
160 static void update_usage(private_eap_radius_accounting_t *this,
161 ike_sa_t *ike_sa, child_sa_t *child_sa)
162 {
163 u_int64_t bytes_in, bytes_out, packets_in, packets_out;
164 entry_t *entry;
165
166 child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, &packets_out);
167 child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, &packets_in);
168
169 this->mutex->lock(this->mutex);
170 entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
171 if (entry)
172 {
173 entry->bytes.sent += bytes_out;
174 entry->bytes.received += bytes_in;
175 entry->packets.sent += packets_out;
176 entry->packets.received += packets_in;
177 }
178 this->mutex->unlock(this->mutex);
179 }
180
181 /**
182 * Send a RADIUS message, wait for response
183 */
184 static bool send_message(private_eap_radius_accounting_t *this,
185 radius_message_t *request)
186 {
187 radius_message_t *response;
188 radius_client_t *client;
189 bool ack = FALSE;
190
191 client = eap_radius_create_client();
192 if (client)
193 {
194 response = client->request(client, request);
195 if (response)
196 {
197 ack = response->get_code(response) == RMC_ACCOUNTING_RESPONSE;
198 response->destroy(response);
199 }
200 client->destroy(client);
201 }
202 return ack;
203 }
204
205 /**
206 * Add common IKE_SA parameters to RADIUS account message
207 */
208 static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
209 radius_message_t *message, ike_sa_t *ike_sa)
210 {
211 enumerator_t *enumerator;
212 host_t *vip, *host;
213 char buf[MAX_RADIUS_ATTRIBUTE_SIZE + 1];
214 chunk_t data;
215 u_int32_t value;
216
217 /* virtual NAS-Port-Type */
218 value = htonl(5);
219 message->add(message, RAT_NAS_PORT_TYPE, chunk_from_thing(value));
220 /* framed ServiceType */
221 value = htonl(2);
222 message->add(message, RAT_SERVICE_TYPE, chunk_from_thing(value));
223
224 value = htonl(ike_sa->get_unique_id(ike_sa));
225 message->add(message, RAT_NAS_PORT, chunk_from_thing(value));
226 message->add(message, RAT_NAS_PORT_ID,
227 chunk_from_str(ike_sa->get_name(ike_sa)));
228
229 host = ike_sa->get_my_host(ike_sa);
230 data = host->get_address(host);
231 switch (host->get_family(host))
232 {
233 case AF_INET:
234 message->add(message, RAT_NAS_IP_ADDRESS, data);
235 break;
236 case AF_INET6:
237 message->add(message, RAT_NAS_IPV6_ADDRESS, data);
238 default:
239 break;
240 }
241 snprintf(buf, sizeof(buf), this->station_id_fmt, host);
242 message->add(message, RAT_CALLED_STATION_ID, chunk_from_str(buf));
243 host = ike_sa->get_other_host(ike_sa);
244 snprintf(buf, sizeof(buf), this->station_id_fmt, host);
245 message->add(message, RAT_CALLING_STATION_ID, chunk_from_str(buf));
246
247 snprintf(buf, sizeof(buf), "%Y", ike_sa->get_other_eap_id(ike_sa));
248 message->add(message, RAT_USER_NAME, chunk_from_str(buf));
249
250 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
251 while (enumerator->enumerate(enumerator, &vip))
252 {
253 switch (vip->get_family(vip))
254 {
255 case AF_INET:
256 message->add(message, RAT_FRAMED_IP_ADDRESS,
257 vip->get_address(vip));
258 break;
259 case AF_INET6:
260 /* we currently assign /128 prefixes, only (reserved, length) */
261 data = chunk_from_chars(0, 128);
262 data = chunk_cata("cc", data, vip->get_address(vip));
263 message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
264 break;
265 default:
266 break;
267 }
268 }
269 enumerator->destroy(enumerator);
270 }
271
272 /**
273 * Get an existing or create a new entry from the locked session table
274 */
275 static entry_t* get_or_create_entry(private_eap_radius_accounting_t *this,
276 ike_sa_t *ike_sa)
277 {
278 ike_sa_id_t *id;
279 entry_t *entry;
280 time_t now;
281
282 entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
283 if (!entry)
284 {
285 now = time_monotonic(NULL);
286 id = ike_sa->get_id(ike_sa);
287
288 INIT(entry,
289 .id = id->clone(id),
290 .created = now,
291 .interim = {
292 .last = now,
293 },
294 /* default terminate cause, if none other catched */
295 .cause = ACCT_CAUSE_USER_REQUEST,
296 );
297 snprintf(entry->sid, sizeof(entry->sid), "%u-%u",
298 this->prefix, ike_sa->get_unique_id(ike_sa));
299 this->sessions->put(this->sessions, entry->id, entry);
300 }
301 return entry;
302 }
303
304 /* forward declaration */
305 static void schedule_interim(private_eap_radius_accounting_t *this,
306 entry_t *entry);
307
308 /**
309 * Data passed to send_interim() using callback job
310 */
311 typedef struct {
312 /** reference to radius accounting */
313 private_eap_radius_accounting_t *this;
314 /** IKE_SA identifier to send interim update to */
315 ike_sa_id_t *id;
316 } interim_data_t;
317
318 /**
319 * Clean up interim data
320 */
321 void destroy_interim_data(interim_data_t *this)
322 {
323 this->id->destroy(this->id);
324 free(this);
325 }
326
327 /**
328 * Send an interim update for entry of given IKE_SA identifier
329 */
330 static job_requeue_t send_interim(interim_data_t *data)
331 {
332 private_eap_radius_accounting_t *this = data->this;
333 u_int64_t bytes_in = 0, bytes_out = 0, packets_in = 0, packets_out = 0;
334 u_int64_t bytes, packets;
335 radius_message_t *message = NULL;
336 enumerator_t *enumerator;
337 child_sa_t *child_sa;
338 ike_sa_t *ike_sa;
339 entry_t *entry;
340 u_int32_t value;
341
342 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, data->id);
343 if (!ike_sa)
344 {
345 return JOB_REQUEUE_NONE;
346 }
347 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
348 while (enumerator->enumerate(enumerator, &child_sa))
349 {
350 child_sa->get_usestats(child_sa, FALSE, NULL, &bytes, &packets);
351 bytes_out += bytes;
352 packets_out += packets;
353 child_sa->get_usestats(child_sa, TRUE, NULL, &bytes, &packets);
354 bytes_in += bytes;
355 packets_in += packets;
356 }
357 enumerator->destroy(enumerator);
358 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
359
360 /* avoid any races by returning IKE_SA before acquiring lock */
361
362 this->mutex->lock(this->mutex);
363 entry = this->sessions->get(this->sessions, data->id);
364 if (entry)
365 {
366 entry->interim.last = time_monotonic(NULL);
367
368 bytes_in += entry->bytes.received;
369 bytes_out += entry->bytes.sent;
370 packets_in += entry->packets.received;
371 packets_out += entry->packets.sent;
372
373 message = radius_message_create(RMC_ACCOUNTING_REQUEST);
374 value = htonl(ACCT_STATUS_INTERIM_UPDATE);
375 message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
376 message->add(message, RAT_ACCT_SESSION_ID,
377 chunk_create(entry->sid, strlen(entry->sid)));
378 add_ike_sa_parameters(this, message, ike_sa);
379
380 value = htonl(bytes_out);
381 message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
382 value = htonl(bytes_out >> 32);
383 if (value)
384 {
385 message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
386 chunk_from_thing(value));
387 }
388 value = htonl(packets_out);
389 message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
390
391 value = htonl(bytes_in);
392 message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
393 value = htonl(bytes_in >> 32);
394 if (value)
395 {
396 message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
397 chunk_from_thing(value));
398 }
399 value = htonl(packets_in);
400 message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
401
402 value = htonl(entry->interim.last - entry->created);
403 message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
404
405 schedule_interim(this, entry);
406 }
407 this->mutex->unlock(this->mutex);
408
409 if (message)
410 {
411 if (!send_message(this, message))
412 {
413 if (lib->settings->get_bool(lib->settings,
414 "%s.plugins.eap-radius.accounting_close_on_timeout",
415 TRUE, lib->ns))
416 {
417 eap_radius_handle_timeout(data->id);
418 }
419 }
420 message->destroy(message);
421 }
422 return JOB_REQUEUE_NONE;
423 }
424
425 /**
426 * Schedule interim update for given entry
427 */
428 static void schedule_interim(private_eap_radius_accounting_t *this,
429 entry_t *entry)
430 {
431 if (entry->interim.interval)
432 {
433 interim_data_t *data;
434 timeval_t tv = {
435 .tv_sec = entry->interim.last + entry->interim.interval,
436 };
437
438 INIT(data,
439 .this = this,
440 .id = entry->id->clone(entry->id),
441 );
442 lib->scheduler->schedule_job_tv(lib->scheduler,
443 (job_t*)callback_job_create_with_prio(
444 (callback_job_cb_t)send_interim,
445 data, (void*)destroy_interim_data,
446 (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL), tv);
447 }
448 }
449
450 /**
451 * Check if an IKE_SA has assigned a virtual IP (to peer)
452 */
453 static bool has_vip(ike_sa_t *ike_sa)
454 {
455 enumerator_t *enumerator;
456 host_t *host;
457 bool found;
458
459 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
460 found = enumerator->enumerate(enumerator, &host);
461 enumerator->destroy(enumerator);
462
463 return found;
464 }
465
466 /**
467 * Send an accounting start message
468 */
469 static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
470 {
471 radius_message_t *message;
472 entry_t *entry;
473 u_int32_t value;
474
475 if (this->acct_req_vip && !has_vip(ike_sa))
476 {
477 return;
478 }
479
480 this->mutex->lock(this->mutex);
481
482 entry = get_or_create_entry(this, ike_sa);
483 entry->start_sent = TRUE;
484
485 message = radius_message_create(RMC_ACCOUNTING_REQUEST);
486 value = htonl(ACCT_STATUS_START);
487 message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
488 message->add(message, RAT_ACCT_SESSION_ID,
489 chunk_create(entry->sid, strlen(entry->sid)));
490
491 schedule_interim(this, entry);
492 this->mutex->unlock(this->mutex);
493
494 add_ike_sa_parameters(this, message, ike_sa);
495 if (!send_message(this, message))
496 {
497 eap_radius_handle_timeout(ike_sa->get_id(ike_sa));
498 }
499 message->destroy(message);
500 }
501
502 /**
503 * Send an account stop message
504 */
505 static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
506 {
507 radius_message_t *message;
508 entry_t *entry;
509 u_int32_t value;
510
511 this->mutex->lock(this->mutex);
512 entry = this->sessions->remove(this->sessions, ike_sa->get_id(ike_sa));
513 this->mutex->unlock(this->mutex);
514 if (entry)
515 {
516 if (!entry->start_sent)
517 { /* we tried to authenticate this peer, but never sent a start */
518 destroy_entry(entry);
519 return;
520 }
521 message = radius_message_create(RMC_ACCOUNTING_REQUEST);
522 value = htonl(ACCT_STATUS_STOP);
523 message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
524 message->add(message, RAT_ACCT_SESSION_ID,
525 chunk_create(entry->sid, strlen(entry->sid)));
526 add_ike_sa_parameters(this, message, ike_sa);
527
528 value = htonl(entry->bytes.sent);
529 message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
530 value = htonl(entry->bytes.sent >> 32);
531 if (value)
532 {
533 message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
534 chunk_from_thing(value));
535 }
536 value = htonl(entry->packets.sent);
537 message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
538
539 value = htonl(entry->bytes.received);
540 message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
541 value = htonl(entry->bytes.received >> 32);
542 if (value)
543 {
544 message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
545 chunk_from_thing(value));
546 }
547 value = htonl(entry->packets.received);
548 message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
549
550 value = htonl(time_monotonic(NULL) - entry->created);
551 message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
552
553
554 value = htonl(entry->cause);
555 message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
556
557 if (!send_message(this, message))
558 {
559 eap_radius_handle_timeout(NULL);
560 }
561 message->destroy(message);
562 destroy_entry(entry);
563 }
564 }
565
566 METHOD(listener_t, alert, bool,
567 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, alert_t alert,
568 va_list args)
569 {
570 radius_acct_terminate_cause_t cause;
571 entry_t *entry;
572
573 switch (alert)
574 {
575 case ALERT_IKE_SA_EXPIRED:
576 cause = ACCT_CAUSE_SESSION_TIMEOUT;
577 break;
578 case ALERT_RETRANSMIT_SEND_TIMEOUT:
579 cause = ACCT_CAUSE_LOST_SERVICE;
580 break;
581 default:
582 return TRUE;
583 }
584 this->mutex->lock(this->mutex);
585 entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
586 if (entry)
587 {
588 entry->cause = cause;
589 }
590 this->mutex->unlock(this->mutex);
591 return TRUE;
592 }
593
594 METHOD(listener_t, ike_updown, bool,
595 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, bool up)
596 {
597 if (!up)
598 {
599 enumerator_t *enumerator;
600 child_sa_t *child_sa;
601
602 /* update usage for all children just before sending stop */
603 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
604 while (enumerator->enumerate(enumerator, &child_sa))
605 {
606 update_usage(this, ike_sa, child_sa);
607 }
608 enumerator->destroy(enumerator);
609
610 send_stop(this, ike_sa);
611 }
612 return TRUE;
613 }
614
615 METHOD(listener_t, message_hook, bool,
616 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
617 message_t *message, bool incoming, bool plain)
618 {
619 /* start accounting here, virtual IP now is set */
620 if (plain && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
621 !incoming && !message->get_request(message))
622 {
623 if (ike_sa->get_version(ike_sa) == IKEV1 &&
624 message->get_exchange_type(message) == TRANSACTION)
625 {
626 send_start(this, ike_sa);
627 }
628 if (ike_sa->get_version(ike_sa) == IKEV2 &&
629 message->get_exchange_type(message) == IKE_AUTH)
630 {
631 send_start(this, ike_sa);
632 }
633 }
634 return TRUE;
635 }
636
637 METHOD(listener_t, ike_rekey, bool,
638 private_eap_radius_accounting_t *this, ike_sa_t *old, ike_sa_t *new)
639 {
640 entry_t *entry;
641
642 this->mutex->lock(this->mutex);
643 entry = this->sessions->remove(this->sessions, old->get_id(old));
644 if (entry)
645 {
646 /* update IKE_SA identifier */
647 entry->id->destroy(entry->id);
648 entry->id = new->get_id(new);
649 entry->id = entry->id->clone(entry->id);
650 /* fire new interim update job, old gets invalid */
651 schedule_interim(this, entry);
652
653 entry = this->sessions->put(this->sessions, entry->id, entry);
654 if (entry)
655 {
656 destroy_entry(entry);
657 }
658 }
659 this->mutex->unlock(this->mutex);
660
661 return TRUE;
662 }
663
664 METHOD(listener_t, child_rekey, bool,
665 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
666 child_sa_t *old, child_sa_t *new)
667 {
668 update_usage(this, ike_sa, old);
669
670 return TRUE;
671 }
672
673 METHOD(listener_t, child_updown, bool,
674 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
675 child_sa_t *child_sa, bool up)
676 {
677 if (!up && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
678 {
679 update_usage(this, ike_sa, child_sa);
680 }
681 return TRUE;
682 }
683
684 METHOD(eap_radius_accounting_t, destroy, void,
685 private_eap_radius_accounting_t *this)
686 {
687 charon->bus->remove_listener(charon->bus, &this->public.listener);
688 singleton = NULL;
689 this->mutex->destroy(this->mutex);
690 this->sessions->destroy(this->sessions);
691 free(this);
692 }
693
694 /**
695 * See header
696 */
697 eap_radius_accounting_t *eap_radius_accounting_create()
698 {
699 private_eap_radius_accounting_t *this;
700
701 INIT(this,
702 .public = {
703 .listener = {
704 .alert = _alert,
705 .ike_updown = _ike_updown,
706 .ike_rekey = _ike_rekey,
707 .message = _message_hook,
708 .child_updown = _child_updown,
709 .child_rekey = _child_rekey,
710 },
711 .destroy = _destroy,
712 },
713 /* use system time as Session ID prefix */
714 .prefix = (u_int32_t)time(NULL),
715 .sessions = hashtable_create((hashtable_hash_t)hash,
716 (hashtable_equals_t)equals, 32),
717 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
718 );
719 if (lib->settings->get_bool(lib->settings,
720 "%s.plugins.eap-radius.station_id_with_port", TRUE, lib->ns))
721 {
722 this->station_id_fmt = "%#H";
723 }
724 else
725 {
726 this->station_id_fmt = "%H";
727 }
728 if (lib->settings->get_bool(lib->settings,
729 "%s.plugins.eap-radius.accounting", FALSE, lib->ns))
730 {
731 singleton = this;
732 charon->bus->add_listener(charon->bus, &this->public.listener);
733 }
734 this->acct_req_vip = lib->settings->get_bool(lib->settings,
735 "%s.plugins.eap-radius.accounting_requires_vip",
736 FALSE, lib->ns);
737
738 return &this->public;
739 }
740
741 /**
742 * See header
743 */
744 void eap_radius_accounting_start_interim(ike_sa_t *ike_sa, u_int32_t interval)
745 {
746 if (singleton)
747 {
748 entry_t *entry;
749
750 DBG1(DBG_CFG, "scheduling RADIUS Interim-Updates every %us", interval);
751 singleton->mutex->lock(singleton->mutex);
752 entry = get_or_create_entry(singleton, ike_sa);
753 entry->interim.interval = interval;
754 singleton->mutex->unlock(singleton->mutex);
755 }
756 }