42 #include RADIUS_HEADER_STR
50 #define DATE_FORMAT "%Y-%m-%d %T %z"
52 #define VENDOR_CODE 22736
55 PW_AST_ACCT_CODE = 101,
61 PW_AST_DST_CHAN = 107,
62 PW_AST_LAST_APP = 108,
63 PW_AST_LAST_DATA = 109,
64 PW_AST_START_TIME = 110,
65 PW_AST_ANSWER_TIME = 111,
66 PW_AST_END_TIME = 112,
67 PW_AST_DURATION = 113,
68 PW_AST_BILL_SEC = 114,
69 PW_AST_DISPOSITION = 115,
70 PW_AST_AMA_FLAGS = 116,
71 PW_AST_UNIQUE_ID = 117,
72 PW_AST_USER_FIELD = 118
84 static const char desc[] =
"RADIUS CDR Backend";
85 static const char name[] =
"radius";
86 static const char cdr_config[] =
"cdr.conf";
88 #ifdef FREERADIUS_CLIENT
89 static char radiuscfg[PATH_MAX] =
"/etc/radiusclient/radiusclient.conf";
91 static char radiuscfg[PATH_MAX] =
"/etc/radiusclient-ng/radiusclient.conf";
96 static rc_handle *rh = NULL;
98 static int build_radius_record(VALUE_PAIR **tosend,
struct ast_cdr *cdr)
100 int recordtype = PW_STATUS_STOP;
105 if (!rc_avpair_add(rh, tosend, PW_ACCT_STATUS_TYPE, &recordtype, 0, 0))
109 if (!rc_avpair_add(rh, tosend, PW_AST_ACCT_CODE, &cdr->
accountcode, strlen(cdr->
accountcode), VENDOR_CODE))
113 if (!rc_avpair_add(rh, tosend, PW_AST_SRC, &cdr->
src, strlen(cdr->
src), VENDOR_CODE))
117 if (!rc_avpair_add(rh, tosend, PW_AST_DST, &cdr->
dst, strlen(cdr->
dst), VENDOR_CODE))
121 if (!rc_avpair_add(rh, tosend, PW_AST_DST_CTX, &cdr->
dcontext, strlen(cdr->
dcontext), VENDOR_CODE))
125 if (!rc_avpair_add(rh, tosend, PW_AST_CLID, &cdr->
clid, strlen(cdr->
clid), VENDOR_CODE))
129 if (!rc_avpair_add(rh, tosend, PW_AST_CHAN, &cdr->channel, strlen(cdr->channel), VENDOR_CODE))
133 if (!rc_avpair_add(rh, tosend, PW_AST_DST_CHAN, &cdr->
dstchannel, strlen(cdr->
dstchannel), VENDOR_CODE))
137 if (!rc_avpair_add(rh, tosend, PW_AST_LAST_APP, &cdr->
lastapp, strlen(cdr->
lastapp), VENDOR_CODE))
141 if (!rc_avpair_add(rh, tosend, PW_AST_LAST_DATA, &cdr->
lastdata, strlen(cdr->
lastdata), VENDOR_CODE))
149 if (!rc_avpair_add(rh, tosend, PW_AST_START_TIME, timestr, strlen(timestr), VENDOR_CODE))
156 if (!rc_avpair_add(rh, tosend, PW_AST_ANSWER_TIME, timestr, strlen(timestr), VENDOR_CODE))
163 if (!rc_avpair_add(rh, tosend, PW_AST_END_TIME, timestr, strlen(timestr), VENDOR_CODE))
167 if (!rc_avpair_add(rh, tosend, PW_AST_DURATION, &cdr->
duration, 0, VENDOR_CODE))
171 if (!rc_avpair_add(rh, tosend, PW_AST_BILL_SEC, &cdr->
billsec, 0, VENDOR_CODE))
176 if (!rc_avpair_add(rh, tosend, PW_AST_DISPOSITION, tmp, strlen(tmp), VENDOR_CODE))
181 if (!rc_avpair_add(rh, tosend, PW_AST_AMA_FLAGS, tmp, strlen(tmp), VENDOR_CODE))
186 if (!rc_avpair_add(rh, tosend, PW_AST_UNIQUE_ID, &cdr->
uniqueid, strlen(cdr->
uniqueid), VENDOR_CODE))
192 if (!rc_avpair_add(rh, tosend, PW_AST_USER_FIELD, &cdr->
userfield, strlen(cdr->
userfield), VENDOR_CODE))
200 if (!rc_avpair_add(rh, tosend, PW_USER_NAME, &cdr->channel, strlen(cdr->channel), 0))
204 if (!rc_avpair_add(rh, tosend, PW_ACCT_SESSION_ID, &cdr->
uniqueid, strlen(cdr->
uniqueid), 0))
210 static int radius_log(
struct ast_cdr *cdr)
212 int result = ERROR_RC;
213 VALUE_PAIR *tosend = NULL;
215 if (build_radius_record(&tosend, cdr)) {
216 ast_debug(1,
"Unable to create RADIUS record. CDR not recorded!\n");
220 result = rc_acct(rh, 0, tosend);
221 if (result != OK_RC) {
222 ast_log(LOG_ERROR,
"Failed to record Radius CDR record!\n");
227 rc_avpair_free(tosend);
233 static int unload_module(
void)
246 static int load_module(
void)
252 if ((cfg =
ast_config_load(cdr_config, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
256 if ((tmp = ast_variable_retrieve(cfg,
"radius",
"radiuscfg")))
263 if (!(rh = rc_read_config(radiuscfg))) {
264 ast_log(LOG_NOTICE,
"Cannot load radiusclient-ng configuration file %s.\n", radiuscfg);
269 if (rc_read_dictionary(rh, rc_conf_str(rh,
"dictionary"))) {
270 ast_log(LOG_NOTICE,
"Cannot load radiusclient-ng dictionary file.\n");
285 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"RADIUS CDR Backend",
286 .support_level = AST_MODULE_SUPPORT_EXTENDED,
288 .unload = unload_module,
char accountcode[AST_MAX_ACCOUNT_CODE]
Asterisk main include file. File version handling, generic pbx functions.
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
char dstchannel[AST_MAX_EXTENSION]
char dcontext[AST_MAX_EXTENSION]
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
char lastdata[AST_MAX_EXTENSION]
#define ast_config_load(filename, flags)
Load a config file.
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
char uniqueid[AST_MAX_UNIQUEID]
char dst[AST_MAX_EXTENSION]
#define ast_debug(level,...)
Log a DEBUG message.
Responsible for call detail data.
char lastapp[AST_MAX_EXTENSION]
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Module has failed to load, may be in an inconsistent state.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Structure used to handle boolean flags.
static struct ast_flags global_flags[1]
char src[AST_MAX_EXTENSION]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
char clid[AST_MAX_EXTENSION]
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
char userfield[AST_MAX_USER_FIELD]