libcharon: Use lib->ns instead of charon->name
[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[128];
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 eap_radius_handle_timeout(data->id);
414 }
415 message->destroy(message);
416 }
417 return JOB_REQUEUE_NONE;
418 }
419
420 /**
421 * Schedule interim update for given entry
422 */
423 static void schedule_interim(private_eap_radius_accounting_t *this,
424 entry_t *entry)
425 {
426 if (entry->interim.interval)
427 {
428 interim_data_t *data;
429 timeval_t tv = {
430 .tv_sec = entry->interim.last + entry->interim.interval,
431 };
432
433 INIT(data,
434 .this = this,
435 .id = entry->id->clone(entry->id),
436 );
437 lib->scheduler->schedule_job_tv(lib->scheduler,
438 (job_t*)callback_job_create_with_prio(
439 (callback_job_cb_t)send_interim,
440 data, (void*)destroy_interim_data,
441 (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL), tv);
442 }
443 }
444
445 /**
446 * Check if an IKE_SA has assigned a virtual IP (to peer)
447 */
448 static bool has_vip(ike_sa_t *ike_sa)
449 {
450 enumerator_t *enumerator;
451 host_t *host;
452 bool found;
453
454 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
455 found = enumerator->enumerate(enumerator, &host);
456 enumerator->destroy(enumerator);
457
458 return found;
459 }
460
461 /**
462 * Send an accounting start message
463 */
464 static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
465 {
466 radius_message_t *message;
467 entry_t *entry;
468 u_int32_t value;
469
470 if (this->acct_req_vip && !has_vip(ike_sa))
471 {
472 return;
473 }
474
475 this->mutex->lock(this->mutex);
476
477 entry = get_or_create_entry(this, ike_sa);
478 entry->start_sent = TRUE;
479
480 message = radius_message_create(RMC_ACCOUNTING_REQUEST);
481 value = htonl(ACCT_STATUS_START);
482 message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
483 message->add(message, RAT_ACCT_SESSION_ID,
484 chunk_create(entry->sid, strlen(entry->sid)));
485
486 schedule_interim(this, entry);
487 this->mutex->unlock(this->mutex);
488
489 add_ike_sa_parameters(this, message, ike_sa);
490 if (!send_message(this, message))
491 {
492 eap_radius_handle_timeout(ike_sa->get_id(ike_sa));
493 }
494 message->destroy(message);
495 }
496
497 /**
498 * Send an account stop message
499 */
500 static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
501 {
502 radius_message_t *message;
503 entry_t *entry;
504 u_int32_t value;
505
506 this->mutex->lock(this->mutex);
507 entry = this->sessions->remove(this->sessions, ike_sa->get_id(ike_sa));
508 this->mutex->unlock(this->mutex);
509 if (entry)
510 {
511 if (!entry->start_sent)
512 { /* we tried to authenticate this peer, but never sent a start */
513 destroy_entry(entry);
514 return;
515 }
516 message = radius_message_create(RMC_ACCOUNTING_REQUEST);
517 value = htonl(ACCT_STATUS_STOP);
518 message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
519 message->add(message, RAT_ACCT_SESSION_ID,
520 chunk_create(entry->sid, strlen(entry->sid)));
521 add_ike_sa_parameters(this, message, ike_sa);
522
523 value = htonl(entry->bytes.sent);
524 message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
525 value = htonl(entry->bytes.sent >> 32);
526 if (value)
527 {
528 message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
529 chunk_from_thing(value));
530 }
531 value = htonl(entry->packets.sent);
532 message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
533
534 value = htonl(entry->bytes.received);
535 message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
536 value = htonl(entry->bytes.received >> 32);
537 if (value)
538 {
539 message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
540 chunk_from_thing(value));
541 }
542 value = htonl(entry->packets.received);
543 message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
544
545 value = htonl(time_monotonic(NULL) - entry->created);
546 message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
547
548
549 value = htonl(entry->cause);
550 message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
551
552 if (!send_message(this, message))
553 {
554 eap_radius_handle_timeout(NULL);
555 }
556 message->destroy(message);
557 destroy_entry(entry);
558 }
559 }
560
561 METHOD(listener_t, alert, bool,
562 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, alert_t alert,
563 va_list args)
564 {
565 radius_acct_terminate_cause_t cause;
566 entry_t *entry;
567
568 switch (alert)
569 {
570 case ALERT_IKE_SA_EXPIRED:
571 cause = ACCT_CAUSE_SESSION_TIMEOUT;
572 break;
573 case ALERT_RETRANSMIT_SEND_TIMEOUT:
574 cause = ACCT_CAUSE_LOST_SERVICE;
575 break;
576 default:
577 return TRUE;
578 }
579 this->mutex->lock(this->mutex);
580 entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
581 if (entry)
582 {
583 entry->cause = cause;
584 }
585 this->mutex->unlock(this->mutex);
586 return TRUE;
587 }
588
589 METHOD(listener_t, ike_updown, bool,
590 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, bool up)
591 {
592 if (!up)
593 {
594 enumerator_t *enumerator;
595 child_sa_t *child_sa;
596
597 /* update usage for all children just before sending stop */
598 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
599 while (enumerator->enumerate(enumerator, &child_sa))
600 {
601 update_usage(this, ike_sa, child_sa);
602 }
603 enumerator->destroy(enumerator);
604
605 send_stop(this, ike_sa);
606 }
607 return TRUE;
608 }
609
610 METHOD(listener_t, message_hook, bool,
611 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
612 message_t *message, bool incoming, bool plain)
613 {
614 /* start accounting here, virtual IP now is set */
615 if (plain && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
616 !incoming && !message->get_request(message))
617 {
618 if (ike_sa->get_version(ike_sa) == IKEV1 &&
619 message->get_exchange_type(message) == TRANSACTION)
620 {
621 send_start(this, ike_sa);
622 }
623 if (ike_sa->get_version(ike_sa) == IKEV2 &&
624 message->get_exchange_type(message) == IKE_AUTH)
625 {
626 send_start(this, ike_sa);
627 }
628 }
629 return TRUE;
630 }
631
632 METHOD(listener_t, ike_rekey, bool,
633 private_eap_radius_accounting_t *this, ike_sa_t *old, ike_sa_t *new)
634 {
635 entry_t *entry;
636
637 this->mutex->lock(this->mutex);
638 entry = this->sessions->remove(this->sessions, old->get_id(old));
639 if (entry)
640 {
641 /* update IKE_SA identifier */
642 entry->id->destroy(entry->id);
643 entry->id = new->get_id(new);
644 entry->id = entry->id->clone(entry->id);
645 /* fire new interim update job, old gets invalid */
646 schedule_interim(this, entry);
647
648 entry = this->sessions->put(this->sessions, entry->id, entry);
649 if (entry)
650 {
651 destroy_entry(entry);
652 }
653 }
654 this->mutex->unlock(this->mutex);
655
656 return TRUE;
657 }
658
659 METHOD(listener_t, child_rekey, bool,
660 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
661 child_sa_t *old, child_sa_t *new)
662 {
663 update_usage(this, ike_sa, old);
664
665 return TRUE;
666 }
667
668 METHOD(listener_t, child_updown, bool,
669 private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
670 child_sa_t *child_sa, bool up)
671 {
672 if (!up && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
673 {
674 update_usage(this, ike_sa, child_sa);
675 }
676 return TRUE;
677 }
678
679 METHOD(eap_radius_accounting_t, destroy, void,
680 private_eap_radius_accounting_t *this)
681 {
682 charon->bus->remove_listener(charon->bus, &this->public.listener);
683 singleton = NULL;
684 this->mutex->destroy(this->mutex);
685 this->sessions->destroy(this->sessions);
686 free(this);
687 }
688
689 /**
690 * See header
691 */
692 eap_radius_accounting_t *eap_radius_accounting_create()
693 {
694 private_eap_radius_accounting_t *this;
695
696 INIT(this,
697 .public = {
698 .listener = {
699 .alert = _alert,
700 .ike_updown = _ike_updown,
701 .ike_rekey = _ike_rekey,
702 .message = _message_hook,
703 .child_updown = _child_updown,
704 .child_rekey = _child_rekey,
705 },
706 .destroy = _destroy,
707 },
708 /* use system time as Session ID prefix */
709 .prefix = (u_int32_t)time(NULL),
710 .sessions = hashtable_create((hashtable_hash_t)hash,
711 (hashtable_equals_t)equals, 32),
712 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
713 );
714 if (lib->settings->get_bool(lib->settings,
715 "%s.plugins.eap-radius.station_id_with_port", TRUE, lib->ns))
716 {
717 this->station_id_fmt = "%#H";
718 }
719 else
720 {
721 this->station_id_fmt = "%H";
722 }
723 if (lib->settings->get_bool(lib->settings,
724 "%s.plugins.eap-radius.accounting", FALSE, lib->ns))
725 {
726 singleton = this;
727 charon->bus->add_listener(charon->bus, &this->public.listener);
728 }
729 this->acct_req_vip = lib->settings->get_bool(lib->settings,
730 "%s.plugins.eap-radius.accounting_requires_vip",
731 FALSE, lib->ns);
732
733 return &this->public;
734 }
735
736 /**
737 * See header
738 */
739 void eap_radius_accounting_start_interim(ike_sa_t *ike_sa, u_int32_t interval)
740 {
741 if (singleton)
742 {
743 entry_t *entry;
744
745 DBG1(DBG_CFG, "scheduling RADIUS Interim-Updates every %us", interval);
746 singleton->mutex->lock(singleton->mutex);
747 entry = get_or_create_entry(singleton, ike_sa);
748 entry->interim.interval = interval;
749 singleton->mutex->unlock(singleton->mutex);
750 }
751 }