Add support for logging CDR recrods to a radius server (issue #6639, phsultan)
- with contributions from miconda, jcollie, and sb - branch maintained by oej Thanks everyone! git-svn-id: http://svn.digium.com/svn/asterisk/trunk@29094 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
eb4fd3a539
commit
e0162250d9
5
CREDITS
5
CREDITS
|
@ -92,8 +92,9 @@ Brian M. Clapper - poll.c emulation
|
|||
Music provided by www.freeplaymusic.com
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
Asterisk uses libedit, the lightweight readline replacement from
|
||||
NetBSD. It is BSD-licensed and requires the following statement:
|
||||
Asterisk uses libedit, the lightweight readline replacement from NetBSD.
|
||||
The cdr_radius module uses libradiusclient-ng, which is also from NetBSD.
|
||||
They are BSD-licensed and require the following statement:
|
||||
|
||||
This product includes software developed by the NetBSD
|
||||
Foundation, Inc. and its contributors.
|
||||
|
|
46
acinclude.m4
46
acinclude.m4
|
@ -5,35 +5,35 @@ AC_DEFUN([AST_EXT_LIB],
|
|||
AC_ARG_WITH([$1], AC_HELP_STRING([--with-$1=PATH],[use $5 files in PATH]),[
|
||||
case ${withval} in
|
||||
n|no)
|
||||
USE_$1=no
|
||||
USE_$4=no
|
||||
;;
|
||||
y|ye|yes)
|
||||
$1_MANDATORY="yes"
|
||||
$4_MANDATORY="yes"
|
||||
;;
|
||||
*)
|
||||
$1_DIR="${withval}"
|
||||
$1_MANDATORY="yes"
|
||||
$4_DIR="${withval}"
|
||||
$4_MANDATORY="yes"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
PBX_LIB$1=0
|
||||
PBX_LIB$4=0
|
||||
|
||||
if test "${USE_$1}" != "no"; then
|
||||
if test "${USE_$4}" != "no"; then
|
||||
pbxlibdir=""
|
||||
if test "x${$1_DIR}" != "x"; then
|
||||
if test "x${$4_DIR}" != "x"; then
|
||||
pbxlibdir="-L${$1_DIR}/lib"
|
||||
fi
|
||||
AC_CHECK_LIB([$1], [$2], [:], [], ${pbxlibdir} $6)
|
||||
AC_CHECK_LIB([$1], [$2], [AST_$4_FOUND=yes], [AST_$4_FOUND=no], ${pbxlibdir} $6)
|
||||
|
||||
if test "${ac_cv_lib_$1_$2}" = "yes"; then
|
||||
$1_LIB="-l$1 $6"
|
||||
if test "${AST_$4_FOUND}" = "yes"; then
|
||||
$4_LIB="-l$1 $6"
|
||||
$4_HEADER_FOUND="1"
|
||||
if test "x${$1_DIR}" != "x"; then
|
||||
$1_LIB="${pbxlibdir} ${$1_LIB}"
|
||||
$1_INCLUDE="-I${$1_DIR}/include"
|
||||
if test "x${$4_DIR}" != "x"; then
|
||||
$4_LIB="${pbxlibdir} ${$4_LIB}"
|
||||
$4_INCLUDE="-I${$4_DIR}/include"
|
||||
if test "x$3" != "x" ; then
|
||||
AC_CHECK_HEADER([${$1_DIR}/include/$3], [$4_HEADER_FOUND=1], [$4_HEADER_FOUND=0] )
|
||||
AC_CHECK_HEADER([${$4_DIR}/include/$3], [$4_HEADER_FOUND=1], [$4_HEADER_FOUND=0] )
|
||||
fi
|
||||
else
|
||||
if test "x$3" != "x" ; then
|
||||
|
@ -41,7 +41,7 @@ if test "${USE_$1}" != "no"; then
|
|||
fi
|
||||
fi
|
||||
if test "x${$4_HEADER_FOUND}" = "x0" ; then
|
||||
if test ! -z "${$1_MANDATORY}" ;
|
||||
if test ! -z "${$4_MANDATORY}" ;
|
||||
then
|
||||
echo " ***"
|
||||
echo " *** It appears that you do not have the $1 development package installed."
|
||||
|
@ -49,14 +49,14 @@ if test "${USE_$1}" != "no"; then
|
|||
echo " *** without explicitly specifying --with-$1"
|
||||
exit 1
|
||||
fi
|
||||
$1_LIB=""
|
||||
$1_INCLUDE=""
|
||||
PBX_LIB$1=0
|
||||
$4_LIB=""
|
||||
$4_INCLUDE=""
|
||||
PBX_LIB$4=0
|
||||
else
|
||||
PBX_LIB$1=1
|
||||
PBX_LIB$4=1
|
||||
AC_DEFINE_UNQUOTED([HAVE_$4], 1, [Define to indicate the $5 library])
|
||||
fi
|
||||
elif test ! -z "${$1_MANDATORY}";
|
||||
elif test ! -z "${$4_MANDATORY}";
|
||||
then
|
||||
echo "***"
|
||||
echo "*** The $5 installation on this system appears to be broken."
|
||||
|
@ -65,9 +65,9 @@ if test "${USE_$1}" != "no"; then
|
|||
exit 1
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([$1_LIB])
|
||||
AC_SUBST([$1_INCLUDE])
|
||||
AC_SUBST([PBX_LIB$1])
|
||||
AC_SUBST([$4_LIB])
|
||||
AC_SUBST([$4_INCLUDE])
|
||||
AC_SUBST([PBX_LIB$4])
|
||||
])
|
||||
|
||||
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
ASOUND=@PBX_LIBasound@
|
||||
ASOUND=@PBX_LIBALSA@
|
||||
CURL=@PBX_CURL@
|
||||
FREETDS=@PBX_LIBtds@
|
||||
FREETDS=@PBX_LIBFREETDS@
|
||||
GTK=@PBX_GTK@
|
||||
H323=@PBX_H323@
|
||||
KDE=@PBX_KDE@
|
||||
LIBNEWT=@PBX_LIBnewt@
|
||||
LIBOSPTK=@PBX_LIBosptk@
|
||||
LIBPOPT=@PBX_LIBpopt@
|
||||
LIBPRI=@PBX_LIBpri@
|
||||
LIBSPEEX=@PBX_LIBspeex@
|
||||
LIBVORBIS=@PBX_LIBvorbis@
|
||||
NBS=@PBX_LIBnbs@
|
||||
OGG=@PBX_LIBogg@
|
||||
OSSAUDIO=@PBX_LIBossaudio@
|
||||
LIBNEWT=@PBX_LIBNEWT@
|
||||
LIBOSPTK=@PBX_LIBOSPTK@
|
||||
LIBPOPT=@PBX_LIBPOPT@
|
||||
LIBPRI=@PBX_LIBLIBPRI@
|
||||
LIBSPEEX=@PBX_LIBSPEEX@
|
||||
LIBVORBIS=@PBX_LIBVORBIS@
|
||||
NBS=@PBX_LIBNBS@
|
||||
OGG=@PBX_LIBOGG@
|
||||
OSSAUDIO=@PBX_LIBOSS@
|
||||
PGSQL=@PBX_LIBpq@
|
||||
QT=@PBX_QT@
|
||||
SQLITE=@PBX_LIBsqlite@
|
||||
SSL=@PBX_LIBssl@
|
||||
UNIXODBC=@PBX_LIBodbc@
|
||||
RADIUSCLIENT=@PBX_LIBRADIUSCLIENT@
|
||||
SQLITE=@PBX_LIBSQLITE@
|
||||
SSL=@PBX_LIBOPENSSL@
|
||||
UNIXODBC=@PBX_LIBUNIXODBC@
|
||||
VPBAPI=@PBX_LIBvpb@
|
||||
WIN32=@OSISWIN32@
|
||||
ZLIB=@PBX_LIBz@
|
||||
ZAPTEL=@PBX_LIBtonezone@
|
||||
ZLIB=@PBX_LIBZLIB@
|
||||
ZAPTEL=@PBX_LIBZAPTEL@
|
||||
LIBGSM=@PBX_LIBgsm@
|
||||
IXJUSER=@PBX_IXJUSER@
|
||||
|
|
|
@ -75,6 +75,13 @@ cdr_sqlite.so: cdr_sqlite.o
|
|||
cdr_sqlite.o: cdr_sqlite.c
|
||||
$(CC) -c -o $@ $(CFLAGS) $(SQLITE_INCLUDE) $<
|
||||
|
||||
cdr_radius.so: cdr_radius.o
|
||||
$(CC) $(SOLINK) -o $@ $< $(RADIUSCLIENT_LIB)
|
||||
|
||||
cdr_radius.o: cdr_radius.c
|
||||
$(CC) -c -o $@ $(CFLAGS) $(RADIUSCLIENT_INCLUDE) $<
|
||||
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief RADIUS CDR Support
|
||||
* \author Philippe Sultan
|
||||
*
|
||||
* \arg See also \ref AstCDR
|
||||
* \ingroup cdr_drivers
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>radiusclient</depend>
|
||||
***/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <radiusclient-ng.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Rev$")
|
||||
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/cdr.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
/*! ISO 8601 standard format */
|
||||
#define DATE_FORMAT "%Y-%m-%d %T %z"
|
||||
|
||||
#define VENDOR_CODE 22736
|
||||
|
||||
enum {
|
||||
PW_AST_ACCT_CODE = 101,
|
||||
PW_AST_SRC = 102,
|
||||
PW_AST_DST = 103,
|
||||
PW_AST_DST_CTX = 104,
|
||||
PW_AST_CLID = 105,
|
||||
PW_AST_CHAN = 106,
|
||||
PW_AST_DST_CHAN = 107,
|
||||
PW_AST_LAST_APP = 108,
|
||||
PW_AST_LAST_DATA = 109,
|
||||
PW_AST_START_TIME = 110,
|
||||
PW_AST_ANSWER_TIME = 111,
|
||||
PW_AST_END_TIME = 112,
|
||||
PW_AST_DURATION = 113,
|
||||
PW_AST_BILL_SEC = 114,
|
||||
PW_AST_DISPOSITION = 115,
|
||||
PW_AST_AMA_FLAGS = 116,
|
||||
PW_AST_UNIQUE_ID = 117,
|
||||
PW_AST_USER_FIELD = 118
|
||||
};
|
||||
|
||||
enum {
|
||||
/*! Log dates and times in UTC */
|
||||
RADIUS_FLAG_USEGMTIME = (1 << 0),
|
||||
/*! Log Unique ID */
|
||||
RADIUS_FLAG_LOGUNIQUEID = (1 << 1),
|
||||
/*! Log User Field */
|
||||
RADIUS_FLAG_LOGUSERFIELD = (1 << 2)
|
||||
};
|
||||
|
||||
static char *desc = "RADIUS CDR Backend";
|
||||
static char *name = "radius";
|
||||
static char *cdr_config = "cdr.conf";
|
||||
|
||||
static char radiuscfg[AST_CONFIG_MAX_PATH] = "/etc/radiusclient-ng/radiusclient.conf";
|
||||
|
||||
static struct ast_flags global_flags = { RADIUS_FLAG_USEGMTIME | RADIUS_FLAG_LOGUNIQUEID | RADIUS_FLAG_LOGUSERFIELD };
|
||||
|
||||
static rc_handle *rh = NULL;
|
||||
|
||||
static int build_radius_record(VALUE_PAIR **send, struct ast_cdr *cdr)
|
||||
{
|
||||
int recordtype = PW_STATUS_STOP;
|
||||
struct tm tm;
|
||||
char timestr[128];
|
||||
char *tmp;
|
||||
|
||||
if (!rc_avpair_add(rh, send, PW_ACCT_STATUS_TYPE, &recordtype, 0, 0)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Account code */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_ACCT_CODE, &cdr->accountcode, strlen(cdr->accountcode), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Source */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_SRC, &cdr->src, strlen(cdr->src), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Destination */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_DST, &cdr->dst, strlen(cdr->dst), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Destination context */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_DST_CTX, &cdr->dcontext, strlen(cdr->dcontext), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Caller ID */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_CLID, &cdr->clid, strlen(cdr->clid), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Channel */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_CHAN, &cdr->channel, strlen(cdr->channel), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Destination Channel */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_DST_CHAN, &cdr->dstchannel, strlen(cdr->dstchannel), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Last Application */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_LAST_APP, &cdr->lastapp, strlen(cdr->lastapp), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Last Data */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_LAST_DATA, &cdr->lastdata, strlen(cdr->lastdata), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Start Time */
|
||||
if (ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME))
|
||||
gmtime_r(&(cdr->start.tv_sec), &tm);
|
||||
else
|
||||
localtime_r(&(cdr->start.tv_sec), &tm);
|
||||
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
|
||||
if (!rc_avpair_add(rh, send, PW_AST_START_TIME, timestr, strlen(timestr), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer Time */
|
||||
if (ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME))
|
||||
gmtime_r(&(cdr->answer.tv_sec), &tm);
|
||||
else
|
||||
localtime_r(&(cdr->answer.tv_sec), &tm);
|
||||
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
|
||||
if (!rc_avpair_add(rh, send, PW_AST_ANSWER_TIME, timestr, strlen(timestr), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* End Time */
|
||||
if (ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME))
|
||||
gmtime_r(&(cdr->end.tv_sec), &tm);
|
||||
else
|
||||
localtime_r(&(cdr->end.tv_sec), &tm);
|
||||
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
|
||||
if (!rc_avpair_add(rh, send, PW_AST_END_TIME, timestr, strlen(timestr), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Duration */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_DURATION, &cdr->duration, 0, VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Billable seconds */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_BILL_SEC, &cdr->billsec, 0, VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Disposition */
|
||||
tmp = ast_cdr_disp2str(cdr->disposition);
|
||||
if (!rc_avpair_add(rh, send, PW_AST_DISPOSITION, tmp, strlen(tmp), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* AMA Flags */
|
||||
tmp = ast_cdr_flags2str(cdr->amaflags);
|
||||
if (!rc_avpair_add(rh, send, PW_AST_AMA_FLAGS, tmp, strlen(tmp), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_test_flag(&global_flags, RADIUS_FLAG_LOGUNIQUEID)) {
|
||||
/* Unique ID */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_UNIQUE_ID, &cdr->uniqueid, strlen(cdr->uniqueid), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag(&global_flags, RADIUS_FLAG_LOGUSERFIELD)) {
|
||||
/* append the user field */
|
||||
if (!rc_avpair_add(rh, send, PW_AST_USER_FIELD, &cdr->userfield, strlen(cdr->userfield), VENDOR_CODE)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting Acct-Session-Id & User-Name attributes for proper generation
|
||||
of Acct-Unique-Session-Id on server side */
|
||||
/* Channel */
|
||||
if (!rc_avpair_add(rh, send, PW_USER_NAME, &cdr->channel, strlen(cdr->channel), 0)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
/* Unique ID */
|
||||
if (!rc_avpair_add(rh, send, PW_ACCT_SESSION_ID, &cdr->uniqueid, strlen(cdr->uniqueid), 0)) {
|
||||
ast_log(LOG_WARNING, "Failed to add VALUE PAIR. RADIUS CDR not recorded!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radius_log(struct ast_cdr *cdr)
|
||||
{
|
||||
int result = ERROR_RC;
|
||||
VALUE_PAIR *send = NULL;
|
||||
|
||||
if (build_radius_record(&send, cdr)) {
|
||||
ast_log(LOG_WARNING, "Unable to create RADIUS record. CDR not recorded!\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
result = rc_acct(rh, 0, send);
|
||||
if (result != OK_RC)
|
||||
ast_log(LOG_ERROR, "Failed to record Radius CDR record!\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *description(void)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
static int unload_module(void *mod)
|
||||
{
|
||||
ast_cdr_unregister(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_module(void *mod)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *tmp;
|
||||
|
||||
if ((cfg = ast_config_load(cdr_config))) {
|
||||
ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "usegmtime")), RADIUS_FLAG_USEGMTIME);
|
||||
ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguniqueid")), RADIUS_FLAG_LOGUNIQUEID);
|
||||
ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguserfield")), RADIUS_FLAG_LOGUSERFIELD);
|
||||
if ((tmp = ast_variable_retrieve(cfg, "radius", "radiuscfg")))
|
||||
ast_copy_string(radiuscfg, tmp, sizeof(radiuscfg));
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
|
||||
/* start logging */
|
||||
rc_openlog("asterisk");
|
||||
|
||||
/* read radiusclient-ng config file */
|
||||
if (!(rh = rc_read_config(radiuscfg))) {
|
||||
ast_log(LOG_NOTICE, "Cannot load radiusclient-ng configuration file %s.\n", radiuscfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read radiusclient-ng dictionaries */
|
||||
if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))) {
|
||||
ast_log(LOG_NOTICE, "Cannot load radiusclient-ng dictionary file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ast_cdr_register(name, desc, radius_log);
|
||||
}
|
||||
|
||||
static const char *key(void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
STD_MOD(MOD_0, NULL, NULL, NULL);
|
|
@ -61,3 +61,11 @@
|
|||
;loguniqueid=yes ;log uniqueid
|
||||
;loguserfield=yes ;log user field
|
||||
|
||||
;[radius]
|
||||
;usegmtime=yes ;log date/time in GMT
|
||||
;loguniqueid=yes ;log uniqueid
|
||||
;loguserfield=yes ;log user field
|
||||
; Set this to the location of the radiusclient-ng configuration file
|
||||
; The default is /etc/radiusclient-ng/radiusclient.conf
|
||||
;radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf
|
||||
|
||||
|
|
27
configure.ac
27
configure.ac
|
@ -198,6 +198,7 @@ AST_EXT_LIB([ogg], [ogg_sync_init], [], [OGG], [OGG])
|
|||
AST_EXT_LIB([osptk], [OSPPCryptoDecrypt], [osp/osp.h], [OSPTK], [OSP Toolkit], [-lcrypto -lssl])
|
||||
AST_EXT_LIB([popt], [poptStrerror], [popt.h], [POPT], [popt])
|
||||
AST_EXT_LIB([pri], [pri_call], [libpri.h], [LIBPRI], [ISDN PRI])
|
||||
AST_EXT_LIB([radiusclient-ng], [rc_read_config], [radiusclient-ng.h], [RADIUSCLIENT], [Radius Client])
|
||||
AST_EXT_LIB([speex], [speex_encode], [speex/speex.h], [SPEEX], [Speex], [-lm])
|
||||
AST_EXT_LIB([sqlite], [sqlite_exec], [sqlite.h], [SQLITE], [SQLite])
|
||||
AST_EXT_LIB([ssl], [ssl2_connect], [openssl/ssl.h], [OPENSSL], [OpenSSL], [-lcrypto])
|
||||
|
@ -208,38 +209,38 @@ AST_EXT_LIB([vorbis], [vorbis_info_init], [vorbis/codec.h], [VORBIS], [Vorbis],
|
|||
AST_EXT_LIB([z], [compress], [zlib.h], [ZLIB], [zlib])
|
||||
|
||||
EDITLINE_LIBS=""
|
||||
if test "x$termcap_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$termcap_LIB"
|
||||
elif test "x$tinfo_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$tinfo_LIB"
|
||||
elif test "x$curses_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$curses_LIB"
|
||||
elif test "x$ncurses_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$ncurses_LIB"
|
||||
if test "x$TERMCAP_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$TERMCAP_LIB"
|
||||
elif test "x$TINFO_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$TINFO_LIB"
|
||||
elif test "x$CURSES_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$CURSES_LIB"
|
||||
elif test "x$NCURSES_LIB" != "x" ; then
|
||||
EDITLINE_LIBS="$NCURSES_LIB"
|
||||
else
|
||||
echo "*** termcap support not found"
|
||||
exit 1
|
||||
fi
|
||||
AC_SUBST(EDITLINE_LIBS)
|
||||
|
||||
PBX_LIBossaudio=0
|
||||
PBX_LIBOSS=0
|
||||
AC_CHECK_HEADER([linux/soundcard.h],
|
||||
[
|
||||
PBX_LIBossaudio=1
|
||||
PBX_LIBOSS=1
|
||||
AC_DEFINE_UNQUOTED([HAVE_OSS], 1, [Define to indicate the Open Sound System library])
|
||||
])
|
||||
if test "$PBX_LIBossaudio" = "0"; then
|
||||
if test "$PBX_LIBOSS" = "0"; then
|
||||
AC_CHECK_HEADER([sys/soundcard.h],
|
||||
[
|
||||
PBX_LIBossaudio=1
|
||||
AC_DEFINE_UNQUOTED([HAVE_OSS], 1, [Define to indicate the Open Sound System library])
|
||||
])
|
||||
fi
|
||||
if test "$PBX_LIBossaudio" = "0"; then
|
||||
if test "$PBX_LIBOSS" = "0"; then
|
||||
AST_EXT_LIB([ossaudio], [oss_ioctl_mixer], [soundcard.h], [OSS], [Open Sound System])
|
||||
fi
|
||||
|
||||
AC_SUBST([PBX_LIBossaudio])
|
||||
AC_SUBST([PBX_LIBOSS])
|
||||
|
||||
if test "${PBX_OSTYPE}" = "Linux" ; then
|
||||
AST_EXT_LIB([tonezone], [tone_zone_find], [linux/zaptel.h], [ZAPTEL], [Zaptel])
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Digium's Asterisk specific radius attributes
|
||||
# markster@digium.com
|
||||
#
|
||||
#
|
||||
|
||||
VENDOR Digium 22736
|
||||
|
||||
BEGIN-VENDOR Digium
|
||||
|
||||
ATTRIBUTE Asterisk-Acc-Code 101 string Digium
|
||||
ATTRIBUTE Asterisk-Src 102 string Digium
|
||||
ATTRIBUTE Asterisk-Dst 103 string Digium
|
||||
ATTRIBUTE Asterisk-Dst-Ctx 104 string Digium
|
||||
ATTRIBUTE Asterisk-Clid 105 string Digium
|
||||
ATTRIBUTE Asterisk-Chan 106 string Digium
|
||||
ATTRIBUTE Asterisk-Dst-Chan 107 string Digium
|
||||
ATTRIBUTE Asterisk-Last-App 108 string Digium
|
||||
ATTRIBUTE Asterisk-Last-Data 109 string Digium
|
||||
ATTRIBUTE Asterisk-Start-Time 110 string Digium
|
||||
ATTRIBUTE Asterisk-Answer-Time 111 string Digium
|
||||
ATTRIBUTE Asterisk-End-Time 112 string Digium
|
||||
ATTRIBUTE Asterisk-Duration 113 integer Digium
|
||||
ATTRIBUTE Asterisk-Bill-Sec 114 integer Digium
|
||||
ATTRIBUTE Asterisk-Disposition 115 string Digium
|
||||
ATTRIBUTE Asterisk-AMA-Flags 116 string Digium
|
||||
ATTRIBUTE Asterisk-Unique-ID 117 string Digium
|
||||
ATTRIBUTE Asterisk-User-Field 118 string Digium
|
||||
|
||||
END-VENDOR Digium
|
||||
|
|
@ -166,6 +166,4 @@ PGSQL:
|
|||
|
||||
SQLLITE:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
08/02/2004 : Duane Cox <dcox@illicom.net> - added mssql information
|
||||
RADIUS: See doc/radius.txt for more information on cdr_radius
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
Call Detail Recording to RADIUS Server
|
||||
======================================
|
||||
|
||||
|
||||
Configuration of Asterisk to send CDRs to (Free)RADIUS servers.
|
||||
|
||||
|
||||
A. What is needed :
|
||||
* FreeRADIUS server
|
||||
* Radiusclient-ng library
|
||||
* Asterisk PBX
|
||||
|
||||
|
||||
+--------------------+
|
||||
| Asterisk PBX |
|
||||
| |
|
||||
|********************|
|
||||
| | +---------------+
|
||||
| RADIUS client |------->| RADIUS server |
|
||||
| |<-------| (FreeRADIUS) |
|
||||
+--------------------+ +---------------+
|
||||
|
||||
|
||||
|
||||
|
||||
B. Steps to follow in order to have RADIUS support:
|
||||
|
||||
1.Radiusclient library
|
||||
1.a Installation
|
||||
|
||||
Download the sources from:
|
||||
|
||||
http://developer.berlios.de/projects/radiusclient-ng/
|
||||
|
||||
Untar the source tarball.
|
||||
root@localhost:/usr/local/src# tar xvfz radiusclient-ng-0.5.2.tar.gz
|
||||
|
||||
Compile and install the library.
|
||||
root@localhost:/usr/local/src# cd radiusclient-ng-0.5.2
|
||||
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# ./configure
|
||||
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# make
|
||||
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# make install
|
||||
|
||||
1.b Configuration
|
||||
|
||||
By default all the configuration files of the radiusclient library will
|
||||
be in /usr/local/etc/radiusclient-ng directory.
|
||||
|
||||
File "radiusclient.conf"
|
||||
Open the file and find lines containing the following:
|
||||
|
||||
authserver localhost
|
||||
|
||||
This is the hostname or IP address of the RADIUS server used for
|
||||
authentication. You will have to change this unless the server is
|
||||
running on the same host as your Asterisk PBX.
|
||||
|
||||
acctserver localhost
|
||||
|
||||
This is the hostname or IP address of the RADIUS server used for
|
||||
accounting. You will have to change this unless the server is running
|
||||
on the same host as your Asterisk PBX.
|
||||
|
||||
File "servers"
|
||||
|
||||
RADIUS protocol uses simple access control mechanism based on shared
|
||||
secrets that allows RADIUS servers to limit access from RADIUS clients.
|
||||
|
||||
A RADIUS server is configured with a secret string and only RADIUS
|
||||
clients that have the same secret will be accepted.
|
||||
|
||||
You need to configure a shared secret for each server you have
|
||||
configured in radiusclient.conf file in the previous step. The shared
|
||||
secrets are stored in /usr/local/etc/radiusclient-ng/servers file.
|
||||
|
||||
Each line contains hostname of a RADIUS server and shared secret
|
||||
used in communication with that server. The two values are separated
|
||||
by white spaces. Configure shared secrets for every RADIUS server you
|
||||
are going to use.
|
||||
|
||||
File "dictionary"
|
||||
|
||||
Asterisk uses some attributes that are not included in the
|
||||
dictionary of radiusclient library, therefore it is necesarry to add
|
||||
them. A file called dictionary.asterisk was created to list all new
|
||||
attributes used by Asterisk. Add into file
|
||||
/usr/local/etc/radiusclient-ng/dictionary
|
||||
the line:
|
||||
|
||||
$INCLUDE /path/to/dictionary.asterisk
|
||||
|
||||
2.FreeRADIUS Server
|
||||
2.a Installation
|
||||
|
||||
Download sources tarball from:
|
||||
|
||||
http://freeradius.org/
|
||||
|
||||
Untar, configure, build, and install the server:
|
||||
|
||||
root@localhost:/usr/local/src# tar xvfz freeradius-1.1.1.tar.gz
|
||||
root@localhost:/usr/local/src# cd freeradius-1.1.1
|
||||
root@localhost"/usr/local/src/freeradius-1.1.1# ./configure
|
||||
root@localhost"/usr/local/src/freeradius-1.1.1# make
|
||||
root@localhost"/usr/local/src/freeradius-1.1.1# make install
|
||||
|
||||
All the configuration files of FreeRADIUS server will be in
|
||||
/usr/local/etc/raddb directory.
|
||||
|
||||
|
||||
2.b Configuration
|
||||
|
||||
There are several file that have to be modified to configure the
|
||||
RADIUS server. These are presented next.
|
||||
|
||||
File "clients.conf"
|
||||
|
||||
File /usr/local/etc/raddb/clients.conf contains description of
|
||||
RADIUS clients that are allowed to use the server. For each of the
|
||||
clients you need to specify its hostname or IP address and also a
|
||||
shared secret. The shared secret must be the same string you configured
|
||||
in radiusclient library.
|
||||
|
||||
Example:
|
||||
client myhost {
|
||||
secret = mysecret
|
||||
shortname = foo
|
||||
}
|
||||
|
||||
This fragment allows access from RADIUS clients on "myhost" if they use
|
||||
"mysecret" as the shared secret.
|
||||
The file already contains an entry for localhost (127.0.0.1), so if you
|
||||
are running the RADIUS server on the same host as your Asterisk server,
|
||||
then modify the existing entry instead, replacing the default password.
|
||||
|
||||
File "dictionary"
|
||||
|
||||
File /usr/local/etc/raddb/dictionary contains the dictionary of
|
||||
FreeRADIUS server. You have to add the same dictionary file
|
||||
(dictionary.asterisk), which you added to the dictionary of radiusclient-ng
|
||||
library. You can include it into the main file, adding the following line at the
|
||||
end of file '/usr/local/etc/raddb/dictionary':
|
||||
|
||||
$INCLUDE /path/to/dictionary.digium
|
||||
|
||||
That will include the same new attribute definitions that are used
|
||||
in radiusclient-ng library so the client and server will understand each
|
||||
other.
|
||||
|
||||
|
||||
3. Asterisk Accounting Configuration
|
||||
|
||||
Compilation and installation:
|
||||
The module will be compiled as long as the radiusclient-ng
|
||||
library has been detected on your system.
|
||||
|
||||
By default FreeRADIUS server will log all accounting requests into
|
||||
/usr/local/var/log/radius/radacct directory in form of plain text files.
|
||||
The server will create one file for each hostname in the directory. The
|
||||
following example shows how the log files look like.
|
||||
|
||||
Asterisk now generates Call Detail Records. See /include/asterisk/cdr.h
|
||||
for all the fields which are recorded. By default, records in comma
|
||||
separated values will be created in /var/log/asterisk/cdr-csv.
|
||||
|
||||
The configuration file for cdr_radius.so module is :
|
||||
|
||||
/etc/asterisk/cdr.conf
|
||||
This is where you can set CDR related parameters as well as the path to
|
||||
the radiusclient-ng library configuration file.
|
||||
|
||||
|
||||
4. Logged Values
|
||||
|
||||
"Asterisk-Acc-Code", The account name of detail records
|
||||
"Asterisk-Src",
|
||||
"Asterisk-Dst",
|
||||
"Asterisk-Dst-Ctx", The destination context
|
||||
"Asterisk-Clid",
|
||||
"Asterisk-Chan", The channel
|
||||
"Asterisk-Dst-Chan", (if applicable)
|
||||
"Asterisk-Last-App", Last application run on the channel
|
||||
"Asterisk-Last-Data", Argument to the last channel
|
||||
"Asterisk-Start-Time",
|
||||
"Asterisk-Answer-Time",
|
||||
"Asterisk-End-Time",
|
||||
"Asterisk-Duration", Duration is the whole length that the entire
|
||||
call lasted. ie. call rx'd to hangup
|
||||
"end time" minus "start time"
|
||||
"Asterisk-Bill-Sec", The duration that a call was up after other
|
||||
end answered which will be <= to duration
|
||||
"end time" minus "answer time"
|
||||
"Asterisk-Disposition", ANSWERED, NO ANSWER, BUSY
|
||||
"Asterisk-AMA-Flags", DOCUMENTATION, BILL, IGNORE etc, specified on
|
||||
a per channel basis like accountcode.
|
||||
"Asterisk-Unique-ID", Unique call identifier
|
||||
"Asterisk-User-Field" User field set via SetCDRUserField
|
||||
|
|
@ -221,6 +221,9 @@
|
|||
/* Define to 1 if you have the `putenv' function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define to indicate the Radius Client library */
|
||||
#undef HAVE_RADIUSCLIENT
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#undef HAVE_REALLOC
|
||||
|
|
74
makeopts.in
74
makeopts.in
|
@ -37,62 +37,62 @@ sysconfdir = @sysconfdir@
|
|||
|
||||
AST_DEVMODE=@AST_DEVMODE@
|
||||
|
||||
OGG_LIB=@ogg_LIB@
|
||||
OGG_INCLUDE=@ogg_INCLUDE@
|
||||
OGG_LIB=@OGG_LIB@
|
||||
OGG_INCLUDE=@OGG_INCLUDE@
|
||||
|
||||
VORBIS_LIB=@vorbis_LIB@
|
||||
VORBIS_INCLUDE=@vorbis_INCLUDE@
|
||||
VORBIS_LIB=@VORBIS_LIB@
|
||||
VORBIS_INCLUDE=@VORBIS_INCLUDE@
|
||||
|
||||
ASOUND_LIB=@asound_LIB@
|
||||
ASOUND_INCLUDE=@asound_INCLUDE@
|
||||
ASOUND_LIB=@ALSA_LIB@
|
||||
ASOUND_INCLUDE=@ALSA_INCLUDE@
|
||||
|
||||
NBS_LIB=@nbs_LIB@
|
||||
NBS_INCLUDE=@nbs_INCLUDE@
|
||||
NBS_LIB=@NBS_LIB@
|
||||
NBS_INCLUDE=@NBS_INCLUDE@
|
||||
|
||||
OSSAUDIO_LIB=@ossaudio_LIB@
|
||||
OSSAUDIO_INCLUDE=@ossaudio_INCLUDE@
|
||||
OSSAUDIO_LIB=@OSS_LIB@
|
||||
OSSAUDIO_INCLUDE=@OSS_INCLUDE@
|
||||
|
||||
SPEEX_LIB=@speex_LIB@
|
||||
SPEEX_INCLUDE=@speex_INCLUDE@
|
||||
SPEEX_LIB=@SPEEX_LIB@
|
||||
SPEEX_INCLUDE=@SPEEX_INCLUDE@
|
||||
|
||||
ZAPTEL_LIB=@tonezone_LIB@
|
||||
ZAPTEL_INCLUDE=@tonezone_INCLUDE@
|
||||
ZAPTEL_LIB=@ZAPTEL_LIB@
|
||||
ZAPTEL_INCLUDE=@ZAPTEL_INCLUDE@
|
||||
|
||||
VPB_LIB=@VPB_LIB@
|
||||
VPB_INCLUDE=@VPB_INCLUDE@
|
||||
|
||||
PRI_LIB=@pri_LIB@
|
||||
PRI_INCLUDE=@pri_INCLUDE@
|
||||
PRI_LIB=@LIBPRI_LIB@
|
||||
PRI_INCLUDE=@LIBPRI_INCLUDE@
|
||||
|
||||
OSPTK_LIB=@osptk_LIB@
|
||||
OSPTK_INCLUDE=@osptk_INCLUDE@
|
||||
OSPTK_LIB=@OSPTK_LIB@
|
||||
OSPTK_INCLUDE=@OSPTK_INCLUDE@
|
||||
|
||||
ODBC_LIB=@odbc_LIB@
|
||||
ODBC_INCLUDE=@odbc_INCLUDE@
|
||||
ODBC_LIB=@UNIXODBC_LIB@
|
||||
ODBC_INCLUDE=@UNIXODBC_INCLUDE@
|
||||
|
||||
PGSQL_LIB=@pq_LIB@
|
||||
PGSQL_INCLUDE=@pq_INCLUDE@
|
||||
|
||||
SQLITE_LIB=@sqlite_LIB@
|
||||
SQLITE_INCLUDE=@sqlite_INCLUDE@
|
||||
SQLITE_LIB=@SQLITE_LIB@
|
||||
SQLITE_INCLUDE=@SQLITE_INCLUDE@
|
||||
|
||||
TDS_LIB=@tds_LIB@
|
||||
TDS_INCLUDE=@tds_INCLUDE@
|
||||
TDS_LIB=@FREETDS_LIB@
|
||||
TDS_INCLUDE=@FREETDS_INCLUDE@
|
||||
|
||||
POPT_LIB=@popt_LIB@
|
||||
POPT_INCLUDE=@popt_INCLUDE@
|
||||
POPT_LIB=@POPT_LIB@
|
||||
POPT_INCLUDE=@POPT_INCLUDE@
|
||||
|
||||
NEWT_LIB=@newt_LIB@
|
||||
NEWT_INCLUDE=@newt_INCLUDE@
|
||||
NEWT_LIB=@NEWT_LIB@
|
||||
NEWT_INCLUDE=@NEWT_INCLUDE@
|
||||
|
||||
PWLIB_LIB=@PWLIB_LIB@
|
||||
PWLIB_INCLUDE=@PWLIB_INCLUDE@
|
||||
|
||||
SSL_LIB=@ssl_LIB@
|
||||
SSL_INCLUDE=@ssl_INCLUDE@
|
||||
SSL_LIB=@OPENSSL_LIB@
|
||||
SSL_INCLUDE=@OPENSSL_INCLUDE@
|
||||
|
||||
Z_LIB=@z_LIB@
|
||||
Z_INCLUDE=@z_INCLUDE@
|
||||
Z_LIB=@ZLIB_LIB@
|
||||
Z_INCLUDE=@ZLIB_INCLUDE@
|
||||
|
||||
QT_LIB=@QT_LIB@
|
||||
QT_INCLUDE=@QT_INCLUDE@
|
||||
|
@ -109,11 +109,13 @@ CURL_LIB=@CURLLIBS@
|
|||
GSM_LIB=@gsm_LIB@
|
||||
GSM_INCLUDE=@gsm_INCLUDE@
|
||||
|
||||
CURSES_LIB=@curses_LIB@
|
||||
CURSES_INCLUDE=@curses_INCLUDE@
|
||||
CURSES_LIB=@CURSES_LIB@
|
||||
CURSES_INCLUDE=@CURSES_INCLUDE@
|
||||
|
||||
NCURSES_LIB=@ncurses_LIB@
|
||||
NCURSES_INCLUDE=@ncurses_INCLUDE@
|
||||
NCURSES_LIB=@NCURSES_LIB@
|
||||
NCURSES_INCLUDE=@NCURSES_INCLUDE@
|
||||
|
||||
EDITLINE_LIBS=@EDITLINE_LIBS@
|
||||
|
||||
RADIUSCLIENT_LIB=@RADIUSCLIENT_LIB@
|
||||
RADIUSCLIENT_INCLUDE=@RADIUSCLIENT_INCLUDE@
|
||||
|
|
Reference in New Issue