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