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