00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 278132 $")
00037
00038 #include <radiusclient-ng.h>
00039
00040 #include "asterisk/channel.h"
00041 #include "asterisk/cdr.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/utils.h"
00044
00045
00046 #define DATE_FORMAT "%Y-%m-%d %T %z"
00047
00048 #define VENDOR_CODE 22736
00049
00050 enum {
00051 PW_AST_ACCT_CODE = 101,
00052 PW_AST_SRC = 102,
00053 PW_AST_DST = 103,
00054 PW_AST_DST_CTX = 104,
00055 PW_AST_CLID = 105,
00056 PW_AST_CHAN = 106,
00057 PW_AST_DST_CHAN = 107,
00058 PW_AST_LAST_APP = 108,
00059 PW_AST_LAST_DATA = 109,
00060 PW_AST_START_TIME = 110,
00061 PW_AST_ANSWER_TIME = 111,
00062 PW_AST_END_TIME = 112,
00063 PW_AST_DURATION = 113,
00064 PW_AST_BILL_SEC = 114,
00065 PW_AST_DISPOSITION = 115,
00066 PW_AST_AMA_FLAGS = 116,
00067 PW_AST_UNIQUE_ID = 117,
00068 PW_AST_USER_FIELD = 118
00069 };
00070
00071 enum {
00072
00073 RADIUS_FLAG_USEGMTIME = (1 << 0),
00074
00075 RADIUS_FLAG_LOGUNIQUEID = (1 << 1),
00076
00077 RADIUS_FLAG_LOGUSERFIELD = (1 << 2)
00078 };
00079
00080 static const char desc[] = "RADIUS CDR Backend";
00081 static const char name[] = "radius";
00082 static const char cdr_config[] = "cdr.conf";
00083
00084 static char radiuscfg[PATH_MAX] = "/etc/radiusclient-ng/radiusclient.conf";
00085
00086 static struct ast_flags global_flags = { RADIUS_FLAG_USEGMTIME | RADIUS_FLAG_LOGUNIQUEID | RADIUS_FLAG_LOGUSERFIELD };
00087
00088 static rc_handle *rh = NULL;
00089
00090 static int build_radius_record(VALUE_PAIR **tosend, struct ast_cdr *cdr)
00091 {
00092 int recordtype = PW_STATUS_STOP;
00093 struct ast_tm tm;
00094 char timestr[128];
00095 char *tmp;
00096
00097 if (!rc_avpair_add(rh, tosend, PW_ACCT_STATUS_TYPE, &recordtype, 0, 0))
00098 return -1;
00099
00100
00101 if (!rc_avpair_add(rh, tosend, PW_AST_ACCT_CODE, &cdr->accountcode, strlen(cdr->accountcode), VENDOR_CODE))
00102 return -1;
00103
00104
00105 if (!rc_avpair_add(rh, tosend, PW_AST_SRC, &cdr->src, strlen(cdr->src), VENDOR_CODE))
00106 return -1;
00107
00108
00109 if (!rc_avpair_add(rh, tosend, PW_AST_DST, &cdr->dst, strlen(cdr->dst), VENDOR_CODE))
00110 return -1;
00111
00112
00113 if (!rc_avpair_add(rh, tosend, PW_AST_DST_CTX, &cdr->dcontext, strlen(cdr->dcontext), VENDOR_CODE))
00114 return -1;
00115
00116
00117 if (!rc_avpair_add(rh, tosend, PW_AST_CLID, &cdr->clid, strlen(cdr->clid), VENDOR_CODE))
00118 return -1;
00119
00120
00121 if (!rc_avpair_add(rh, tosend, PW_AST_CHAN, &cdr->channel, strlen(cdr->channel), VENDOR_CODE))
00122 return -1;
00123
00124
00125 if (!rc_avpair_add(rh, tosend, PW_AST_DST_CHAN, &cdr->dstchannel, strlen(cdr->dstchannel), VENDOR_CODE))
00126 return -1;
00127
00128
00129 if (!rc_avpair_add(rh, tosend, PW_AST_LAST_APP, &cdr->lastapp, strlen(cdr->lastapp), VENDOR_CODE))
00130 return -1;
00131
00132
00133 if (!rc_avpair_add(rh, tosend, PW_AST_LAST_DATA, &cdr->lastdata, strlen(cdr->lastdata), VENDOR_CODE))
00134 return -1;
00135
00136
00137
00138 ast_strftime(timestr, sizeof(timestr), DATE_FORMAT,
00139 ast_localtime(&cdr->start, &tm,
00140 ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME) ? "GMT" : NULL));
00141 if (!rc_avpair_add(rh, tosend, PW_AST_START_TIME, timestr, strlen(timestr), VENDOR_CODE))
00142 return -1;
00143
00144
00145 ast_strftime(timestr, sizeof(timestr), DATE_FORMAT,
00146 ast_localtime(&cdr->answer, &tm,
00147 ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME) ? "GMT" : NULL));
00148 if (!rc_avpair_add(rh, tosend, PW_AST_ANSWER_TIME, timestr, strlen(timestr), VENDOR_CODE))
00149 return -1;
00150
00151
00152 ast_strftime(timestr, sizeof(timestr), DATE_FORMAT,
00153 ast_localtime(&cdr->end, &tm,
00154 ast_test_flag(&global_flags, RADIUS_FLAG_USEGMTIME) ? "GMT" : NULL));
00155 if (!rc_avpair_add(rh, tosend, PW_AST_END_TIME, timestr, strlen(timestr), VENDOR_CODE))
00156 return -1;
00157
00158
00159 if (!rc_avpair_add(rh, tosend, PW_AST_DURATION, &cdr->duration, 0, VENDOR_CODE))
00160 return -1;
00161
00162
00163 if (!rc_avpair_add(rh, tosend, PW_AST_BILL_SEC, &cdr->billsec, 0, VENDOR_CODE))
00164 return -1;
00165
00166
00167 tmp = ast_cdr_disp2str(cdr->disposition);
00168 if (!rc_avpair_add(rh, tosend, PW_AST_DISPOSITION, tmp, strlen(tmp), VENDOR_CODE))
00169 return -1;
00170
00171
00172 tmp = ast_cdr_flags2str(cdr->amaflags);
00173 if (!rc_avpair_add(rh, tosend, PW_AST_AMA_FLAGS, tmp, strlen(tmp), VENDOR_CODE))
00174 return -1;
00175
00176 if (ast_test_flag(&global_flags, RADIUS_FLAG_LOGUNIQUEID)) {
00177
00178 if (!rc_avpair_add(rh, tosend, PW_AST_UNIQUE_ID, &cdr->uniqueid, strlen(cdr->uniqueid), VENDOR_CODE))
00179 return -1;
00180 }
00181
00182 if (ast_test_flag(&global_flags, RADIUS_FLAG_LOGUSERFIELD)) {
00183
00184 if (!rc_avpair_add(rh, tosend, PW_AST_USER_FIELD, &cdr->userfield, strlen(cdr->userfield), VENDOR_CODE))
00185 return -1;
00186 }
00187
00188
00189
00190
00191 if (!rc_avpair_add(rh, tosend, PW_USER_NAME, &cdr->channel, strlen(cdr->channel), 0))
00192 return -1;
00193
00194
00195 if (!rc_avpair_add(rh, tosend, PW_ACCT_SESSION_ID, &cdr->uniqueid, strlen(cdr->uniqueid), 0))
00196 return -1;
00197
00198 return 0;
00199 }
00200
00201 static int radius_log(struct ast_cdr *cdr)
00202 {
00203 int result = ERROR_RC;
00204 VALUE_PAIR *tosend = NULL;
00205
00206 if (build_radius_record(&tosend, cdr)) {
00207 ast_debug(1, "Unable to create RADIUS record. CDR not recorded!\n");
00208 goto return_cleanup;
00209 }
00210
00211 result = rc_acct(rh, 0, tosend);
00212 if (result != OK_RC) {
00213 ast_log(LOG_ERROR, "Failed to record Radius CDR record!\n");
00214 }
00215
00216 return_cleanup:
00217 if (tosend) {
00218 rc_avpair_free(tosend);
00219 }
00220
00221 return result;
00222 }
00223
00224 static int unload_module(void)
00225 {
00226 ast_cdr_unregister(name);
00227 return 0;
00228 }
00229
00230 static int load_module(void)
00231 {
00232 struct ast_config *cfg;
00233 struct ast_flags config_flags = { 0 };
00234 int res;
00235 const char *tmp;
00236
00237 if ((cfg = ast_config_load(cdr_config, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
00238 ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "usegmtime")), RADIUS_FLAG_USEGMTIME);
00239 ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguniqueid")), RADIUS_FLAG_LOGUNIQUEID);
00240 ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguserfield")), RADIUS_FLAG_LOGUSERFIELD);
00241 if ((tmp = ast_variable_retrieve(cfg, "radius", "radiuscfg")))
00242 ast_copy_string(radiuscfg, tmp, sizeof(radiuscfg));
00243 ast_config_destroy(cfg);
00244 } else
00245 return AST_MODULE_LOAD_DECLINE;
00246
00247
00248 rc_openlog("asterisk");
00249
00250
00251 if (!(rh = rc_read_config(radiuscfg))) {
00252 ast_log(LOG_NOTICE, "Cannot load radiusclient-ng configuration file %s.\n", radiuscfg);
00253 return AST_MODULE_LOAD_DECLINE;
00254 }
00255
00256
00257 if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))) {
00258 ast_log(LOG_NOTICE, "Cannot load radiusclient-ng dictionary file.\n");
00259 return AST_MODULE_LOAD_DECLINE;
00260 }
00261
00262 res = ast_cdr_register(name, desc, radius_log);
00263 return AST_MODULE_LOAD_SUCCESS;
00264 }
00265
00266 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "RADIUS CDR Backend",
00267 .load = load_module,
00268 .unload = unload_module,
00269 .load_pri = AST_MODPRI_CDR_DRIVER,
00270 );