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