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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <stdio.h>
00047 #include <time.h>
00048
00049 #include "../../dprint.h"
00050 #include "../../error.h"
00051 #include "../../mem/mem.h"
00052 #include "../../usr_avp.h"
00053 #include "../../db/db.h"
00054 #include "../../parser/hf.h"
00055 #include "../../parser/msg_parser.h"
00056 #include "../../parser/parse_from.h"
00057 #include "../../parser/digest/digest.h"
00058 #include "../tm/t_funcs.h"
00059 #include "acc_mod.h"
00060 #include "acc.h"
00061 #include "acc_extra.h"
00062 #include "acc_logic.h"
00063
00064 #ifdef RAD_ACC
00065 #include "../../radius.h"
00066 #endif
00067
00068 #ifdef DIAM_ACC
00069 #include "diam_dict.h"
00070 #include "diam_message.h"
00071 #include "diam_tcp.h"
00072 #endif
00073
00074 extern struct acc_extra *log_extra;
00075 extern struct acc_extra *leg_info;
00076 extern struct acc_enviroment acc_env;
00077
00078 #ifdef RAD_ACC
00079 extern struct acc_extra *rad_extra;
00080 #endif
00081
00082 #ifdef DIAM_ACC
00083 extern char *diameter_client_host;
00084 extern int diameter_client_port;
00085 extern struct acc_extra *dia_extra;
00086 #endif
00087
00088 #ifdef SQL_ACC
00089 static db_func_t acc_dbf;
00090 static db_con_t* db_handle=0;
00091 extern struct acc_extra *db_extra;
00092 #endif
00093
00094
00095
00096 static str val_arr[ACC_CORE_LEN+MAX_ACC_EXTRA+MAX_ACC_LEG];
00097 static int int_arr[ACC_CORE_LEN+MAX_ACC_EXTRA+MAX_ACC_LEG];
00098 static char type_arr[ACC_CORE_LEN+MAX_ACC_EXTRA+MAX_ACC_LEG];
00099
00100
00101
00102
00103 #define get_ft_body( _ft_hdr) \
00104 ((struct to_body*)_ft_hdr->parsed)
00105
00106 #define SET_EMPTY_VAL(_i) \
00107 do { \
00108 c_vals[_i].s = 0; \
00109 c_vals[_i].len = 0; \
00110 } while(0)
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 static inline int core2strar( struct sip_msg *req, str *c_vals,
00121 int *i_vals, char *t_vals)
00122 {
00123 struct to_body *ft_body;
00124 struct hdr_field *from;
00125 struct hdr_field *to;
00126
00127
00128 c_vals[0] = req->first_line.u.request.method;
00129 t_vals[0] = TYPE_STR;
00130
00131
00132 if (req->msg_flags&FL_REQ_UPSTREAM) {
00133 LM_DBG("the flag UPSTREAM is set -> swap F/T\n"); \
00134 from = acc_env.to;
00135 to = req->from;
00136 } else {
00137 from = req->from;
00138 to = acc_env.to;
00139 }
00140
00141 if (from && (ft_body=get_ft_body(from)) && ft_body->tag_value.len) {
00142 c_vals[1] = ft_body->tag_value;
00143 t_vals[1] = TYPE_STR;
00144 } else {
00145 SET_EMPTY_VAL(1);
00146 t_vals[1] = TYPE_NULL;
00147 }
00148
00149 if (to && (ft_body=get_ft_body(to)) && ft_body->tag_value.len) {
00150 c_vals[2] = ft_body->tag_value;
00151 t_vals[2] = TYPE_STR;
00152 } else {
00153 SET_EMPTY_VAL(2);
00154 t_vals[2] = TYPE_NULL;
00155 }
00156
00157
00158 if (req->callid && req->callid->body.len) {
00159 c_vals[3] = req->callid->body;
00160 t_vals[3] = TYPE_STR;
00161 } else {
00162 SET_EMPTY_VAL(3);
00163 t_vals[3] = TYPE_NULL;
00164 }
00165
00166
00167 c_vals[4] = acc_env.code_s;
00168 i_vals[4] = acc_env.code;
00169 t_vals[4] = TYPE_INT;
00170
00171
00172 c_vals[5] = acc_env.reason;
00173 t_vals[5] = TYPE_STR;
00174
00175 acc_env.ts = time(NULL);
00176 return ACC_CORE_LEN;
00177 }
00178
00179
00180
00181
00182
00183
00184 static str log_attrs[ACC_CORE_LEN+MAX_ACC_EXTRA+MAX_ACC_LEG];
00185
00186 #define SET_LOG_ATTR(_n,_atr) \
00187 do { \
00188 log_attrs[_n].s=A_##_atr; \
00189 log_attrs[_n].len=A_##_atr##_LEN; \
00190 n++; \
00191 } while(0)
00192
00193 void acc_log_init(void)
00194 {
00195 struct acc_extra *extra;
00196 int n;
00197
00198 n = 0;
00199
00200
00201 SET_LOG_ATTR(n,METHOD);
00202 SET_LOG_ATTR(n,FROMTAG);
00203 SET_LOG_ATTR(n,TOTAG);
00204 SET_LOG_ATTR(n,CALLID);
00205 SET_LOG_ATTR(n,CODE);
00206 SET_LOG_ATTR(n,STATUS);
00207
00208
00209 for(extra=log_extra; extra ; extra=extra->next)
00210 log_attrs[n++] = extra->name;
00211
00212
00213 for( extra=leg_info ; extra ; extra=extra->next)
00214 log_attrs[n++] = extra->name;
00215 }
00216
00217
00218 int acc_log_request( struct sip_msg *rq)
00219 {
00220 static char log_msg[MAX_SYSLOG_SIZE];
00221 static char *log_msg_end=log_msg+MAX_SYSLOG_SIZE-2;
00222 char *p;
00223 int n;
00224 int m;
00225 int i;
00226
00227
00228 m = core2strar( rq, val_arr, int_arr, type_arr);
00229
00230
00231 m += extra2strar( log_extra, rq, val_arr+m, int_arr+m, type_arr+m);
00232
00233 for ( i=0,p=log_msg ; i<m ; i++ ) {
00234 if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
00235 LM_WARN("acc message too long, truncating..\n");
00236 p = log_msg_end;
00237 break;
00238 }
00239 *(p++) = A_SEPARATOR_CHR;
00240 memcpy(p, log_attrs[i].s, log_attrs[i].len);
00241 p += log_attrs[i].len;
00242 *(p++) = A_EQ_CHR;
00243 memcpy(p, val_arr[i].s, val_arr[i].len);
00244 p += val_arr[i].len;
00245 }
00246
00247
00248 if ( leg_info ) {
00249 n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m, 1);
00250 do {
00251 for (i=m; i<m+n; i++) {
00252 if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
00253 LM_WARN("acc message too long, truncating..\n");
00254 p = log_msg_end;
00255 break;
00256 }
00257 *(p++) = A_SEPARATOR_CHR;
00258 memcpy(p, log_attrs[i].s, log_attrs[i].len);
00259 p += log_attrs[i].len;
00260 *(p++) = A_EQ_CHR;
00261 memcpy(p, val_arr[i].s, val_arr[i].len);
00262 p += val_arr[i].len;
00263 }
00264 }while (p!=log_msg_end && (n=legs2strar(leg_info,rq,val_arr+m,
00265 int_arr+m,type_arr+m,
00266 0))!=0);
00267 }
00268
00269
00270 *(p++) = '\n';
00271 *(p++) = 0;
00272
00273 LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu%s",
00274 acc_env.text.len, acc_env.text.s,(unsigned long) acc_env.ts, log_msg);
00275
00276 return 1;
00277 }
00278
00279
00280
00281
00282
00283
00284 #ifdef SQL_ACC
00285
00286
00287 static db_key_t db_keys[ACC_CORE_LEN+1+MAX_ACC_EXTRA+MAX_ACC_LEG];
00288 static db_val_t db_vals[ACC_CORE_LEN+1+MAX_ACC_EXTRA+MAX_ACC_LEG];
00289
00290
00291 static void acc_db_init_keys(void)
00292 {
00293 struct acc_extra *extra;
00294 int time_idx;
00295 int i;
00296 int n;
00297
00298
00299 n = 0;
00300
00301 db_keys[n++] = &acc_method_col;
00302 db_keys[n++] = &acc_fromtag_col;
00303 db_keys[n++] = &acc_totag_col;
00304 db_keys[n++] = &acc_callid_col;
00305 db_keys[n++] = &acc_sipcode_col;
00306 db_keys[n++] = &acc_sipreason_col;
00307 db_keys[n++] = &acc_time_col;
00308 time_idx = n-1;
00309
00310
00311 for(extra=db_extra; extra ; extra=extra->next)
00312 db_keys[n++] = &extra->name;
00313
00314
00315 for( extra=leg_info ; extra ; extra=extra->next)
00316 db_keys[n++] = &extra->name;
00317
00318
00319 for(i=0; i<n; i++) {
00320 VAL_TYPE(db_vals+i)=DB_STR;
00321 VAL_NULL(db_vals+i)=0;
00322 }
00323 VAL_TYPE(db_vals+time_idx)=DB_DATETIME;
00324 }
00325
00326
00327
00328
00329 int acc_db_init(const str* db_url)
00330 {
00331 if (db_bind_mod(db_url, &acc_dbf)<0){
00332 LM_ERR("bind_db failed\n");
00333 return -1;
00334 }
00335
00336
00337 if (!DB_CAPABILITY(acc_dbf, DB_CAP_INSERT)) {
00338 LM_ERR("database module does not implement insert function\n");
00339 return -1;
00340 }
00341
00342 acc_db_init_keys();
00343
00344 return 0;
00345 }
00346
00347
00348
00349
00350 int acc_db_init_child(const str *db_url)
00351 {
00352 db_handle=acc_dbf.init(db_url);
00353 if (db_handle==0){
00354 LM_ERR("unable to connect to the database\n");
00355 return -1;
00356 }
00357 return 0;
00358 }
00359
00360
00361
00362 void acc_db_close(void)
00363 {
00364 if (db_handle && acc_dbf.close)
00365 acc_dbf.close(db_handle);
00366 }
00367
00368
00369 int acc_db_request( struct sip_msg *rq)
00370 {
00371 int m;
00372 int n;
00373 int i;
00374
00375
00376 m = core2strar( rq, val_arr, int_arr, type_arr );
00377
00378 for(i=0; i<m; i++)
00379 VAL_STR(db_vals+i) = val_arr[i];
00380
00381 VAL_TIME(db_vals+(m++)) = acc_env.ts;
00382
00383
00384 m += extra2strar( db_extra, rq, val_arr+m, int_arr+m, type_arr+m);
00385
00386 for( i++ ; i<m; i++)
00387 VAL_STR(db_vals+i) = val_arr[i];
00388
00389 if (acc_dbf.use_table(db_handle, &acc_env.text) < 0) {
00390 LM_ERR("error in use_table\n");
00391 return -1;
00392 }
00393
00394
00395 if ( !leg_info ) {
00396 if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) {
00397 LM_ERR("failed to insert into database\n");
00398 return -1;
00399 }
00400 } else {
00401 n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m,1);
00402 do {
00403 for (i=m; i<m+n; i++)
00404 VAL_STR(db_vals+i)=val_arr[i];
00405 if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) {
00406 LM_ERR("failed to insert into database\n");
00407 return -1;
00408 }
00409 }while ( (n=legs2strar(leg_info,rq,val_arr+m,int_arr+m,
00410 type_arr+m,0))!=0 );
00411 }
00412
00413 return 1;
00414 }
00415
00416 #endif
00417
00418
00419
00420 #if defined(RAD_ACC) || defined (DIAM_ACC)
00421 #ifndef UINT4
00422 #define UINT4 uint32_t
00423 #endif
00424 inline static UINT4 phrase2code(str *phrase)
00425 {
00426 UINT4 code;
00427 int i;
00428
00429 if (phrase->len<3) return 0;
00430 code=0;
00431 for (i=0;i<3;i++) {
00432 if (!(phrase->s[i]>='0' && phrase->s[i]<'9'))
00433 return 0;
00434 code=code*10+phrase->s[i]-'0';
00435 }
00436 return code;
00437 }
00438 #endif
00439
00440
00441
00442
00443
00444 #ifdef RAD_ACC
00445 enum { RA_ACCT_STATUS_TYPE=0, RA_SERVICE_TYPE, RA_SIP_RESPONSE_CODE,
00446 RA_SIP_METHOD, RA_TIME_STAMP, RA_STATIC_MAX};
00447 enum {RV_STATUS_START=0, RV_STATUS_STOP, RV_STATUS_ALIVE, RV_STATUS_FAILED,
00448 RV_SIP_SESSION, RV_STATIC_MAX};
00449 static struct attr
00450 rd_attrs[RA_STATIC_MAX+ACC_CORE_LEN-2+MAX_ACC_EXTRA+MAX_ACC_LEG];
00451 static struct val rd_vals[RV_STATIC_MAX];
00452
00453 int init_acc_rad(char *rad_cfg, int srv_type)
00454 {
00455 int n;
00456
00457 memset(rd_attrs, 0, sizeof(rd_attrs));
00458 memset(rd_vals, 0, sizeof(rd_vals));
00459 rd_attrs[RA_ACCT_STATUS_TYPE].n = "Acct-Status-Type";
00460 rd_attrs[RA_SERVICE_TYPE].n = "Service-Type";
00461 rd_attrs[RA_SIP_RESPONSE_CODE].n = "Sip-Response-Code";
00462 rd_attrs[RA_SIP_METHOD].n = "Sip-Method";
00463 rd_attrs[RA_TIME_STAMP].n = "Event-Timestamp";
00464 n = RA_STATIC_MAX;
00465
00466 rd_attrs[n++].n = "Sip-From-Tag";
00467 rd_attrs[n++].n = "Sip-To-Tag";
00468 rd_attrs[n++].n = "Acct-Session-Id";
00469
00470 rd_vals[RV_STATUS_START].n = "Start";
00471 rd_vals[RV_STATUS_STOP].n = "Stop";
00472 rd_vals[RV_STATUS_ALIVE].n = "Alive";
00473 rd_vals[RV_STATUS_FAILED].n = "Failed";
00474 rd_vals[RV_SIP_SESSION].n = "Sip-Session";
00475
00476
00477 n += extra2attrs( rad_extra, rd_attrs, n);
00478
00479 n += extra2attrs( leg_info, rd_attrs, n);
00480
00481
00482 if ((rh = rc_read_config(rad_cfg)) == NULL) {
00483 LM_ERR("failed to open radius config file: %s\n", rad_cfg );
00484 return -1;
00485 }
00486
00487 if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))!=0) {
00488 LM_ERR("failed to read radius dictionary\n");
00489 return -1;
00490 }
00491
00492 INIT_AV(rh, rd_attrs, n, rd_vals, RV_STATIC_MAX, "acc", -1, -1);
00493
00494 if (srv_type != -1)
00495 rd_vals[RV_SIP_SESSION].v = srv_type;
00496
00497 return 0;
00498 }
00499
00500
00501 static inline UINT4 rad_status( struct sip_msg *req, int code )
00502 {
00503 str tag;
00504 unsigned int in_dialog_req = 0;
00505
00506 tag = get_to(req)->tag_value;
00507 if(tag.s!=0 && tag.len!=0)
00508 in_dialog_req = 1;
00509
00510 if (req->REQ_METHOD==METHOD_INVITE && in_dialog_req == 0
00511 && code>=200 && code<300)
00512 return rd_vals[RV_STATUS_START].v;
00513 if ((req->REQ_METHOD==METHOD_BYE || req->REQ_METHOD==METHOD_CANCEL))
00514 return rd_vals[RV_STATUS_STOP].v;
00515 if (in_dialog_req != 0)
00516 return rd_vals[RV_STATUS_ALIVE].v;
00517 return rd_vals[RV_STATUS_FAILED].v;
00518 }
00519
00520 #define ADD_RAD_AVPAIR(_attr,_val,_len) \
00521 do { \
00522 if (!rc_avpair_add(rh, &send, rd_attrs[_attr].v, _val, _len, 0)) { \
00523 LM_ERR("failed to add %s, %d\n", rd_attrs[_attr].n, _attr); \
00524 goto error; \
00525 } \
00526 }while(0)
00527
00528 int acc_rad_request( struct sip_msg *req )
00529 {
00530 int attr_cnt;
00531 VALUE_PAIR *send;
00532 UINT4 av_type;
00533 int offset;
00534 int i;
00535
00536 send=NULL;
00537
00538 attr_cnt = core2strar( req, val_arr, int_arr, type_arr );
00539
00540 attr_cnt -= 2;
00541
00542 av_type = rad_status( req, acc_env.code);
00543 ADD_RAD_AVPAIR( RA_ACCT_STATUS_TYPE, &av_type, -1);
00544
00545 av_type = rd_vals[RV_SIP_SESSION].v;
00546 ADD_RAD_AVPAIR( RA_SERVICE_TYPE, &av_type, -1);
00547
00548 av_type = (UINT4)acc_env.code;
00549 ADD_RAD_AVPAIR( RA_SIP_RESPONSE_CODE, &av_type, -1);
00550
00551 av_type = req->REQ_METHOD;
00552 ADD_RAD_AVPAIR( RA_SIP_METHOD, &av_type, -1);
00553
00554
00555 av_type = (UINT4)acc_env.ts;
00556 ADD_RAD_AVPAIR( RA_TIME_STAMP, &av_type, -1);
00557
00558
00559 attr_cnt += extra2strar(rad_extra, req, val_arr+attr_cnt,
00560 int_arr+attr_cnt, type_arr+attr_cnt);
00561
00562
00563
00564 offset = RA_STATIC_MAX-1;
00565 for( i=1; i<attr_cnt; i++) {
00566 switch (type_arr[i]) {
00567 case TYPE_STR:
00568 ADD_RAD_AVPAIR(offset+i, val_arr[i].s, val_arr[i].len);
00569 break;
00570 case TYPE_INT:
00571 ADD_RAD_AVPAIR(offset+i, &(int_arr[i]), -1);
00572 break;
00573 default:
00574 break;
00575 }
00576 }
00577
00578
00579 if ( leg_info ) {
00580 offset += attr_cnt;
00581 attr_cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1);
00582 do {
00583 for (i=0; i<attr_cnt; i++)
00584 ADD_RAD_AVPAIR( offset+i, val_arr[i].s, val_arr[i].len );
00585 }while ( (attr_cnt=legs2strar(leg_info,req,val_arr,int_arr,
00586 type_arr, 0))!=0 );
00587 }
00588
00589 if (rc_acct(rh, SIP_PORT, send)!=OK_RC) {
00590 LM_ERR("radius-ing failed\n");
00591 goto error;
00592 }
00593 rc_avpair_free(send);
00594 return 1;
00595
00596 error:
00597 rc_avpair_free(send);
00598 return -1;
00599 }
00600
00601 #endif
00602
00603
00604
00605
00606
00607 #ifdef DIAM_ACC
00608
00609 #define AA_REQUEST 265
00610 #define AA_ANSWER 265
00611
00612 #define ACCOUNTING_REQUEST 271
00613 #define ACCOUNTING_ANSWER 271
00614
00615 static int diam_attrs[ACC_CORE_LEN+MAX_ACC_EXTRA+MAX_ACC_LEG];
00616
00617 int acc_diam_init()
00618 {
00619 int n;
00620 int m;
00621
00622 n = 0;
00623
00624 diam_attrs[n++] = AVP_SIP_METHOD;
00625 diam_attrs[n++] = AVP_SIP_FROM_TAG;
00626 diam_attrs[n++] = AVP_SIP_TO_TAG;
00627 diam_attrs[n++] = AVP_SIP_CALLID;
00628 diam_attrs[n++] = AVP_SIP_STATUS;
00629
00630 m = extra2int( dia_extra, diam_attrs+n);
00631 if (m<0) {
00632 LM_ERR("extra names for DIAMETER must be integer AVP codes\n");
00633 return -1;
00634 }
00635 n += m;
00636
00637 m = extra2int( leg_info, diam_attrs+n);
00638 if (m<0) {
00639 LM_ERR("leg info names for DIAMTER must be integer AVP codes\n");
00640 return -1;
00641 }
00642 n += m;
00643
00644 return 0;
00645 }
00646
00647
00648 inline unsigned long diam_status(struct sip_msg *rq, int code)
00649 {
00650 if ((rq->REQ_METHOD==METHOD_INVITE || rq->REQ_METHOD==METHOD_ACK)
00651 && code>=200 && code<300)
00652 return AAA_ACCT_START;
00653
00654 if ((rq->REQ_METHOD==METHOD_BYE || rq->REQ_METHOD==METHOD_CANCEL))
00655 return AAA_ACCT_STOP;
00656
00657 if (code>=200 && code <=300)
00658 return AAA_ACCT_EVENT;
00659
00660 return -1;
00661 }
00662
00663
00664 int acc_diam_request( struct sip_msg *req )
00665 {
00666 int attr_cnt;
00667 int cnt;
00668 AAAMessage *send = NULL;
00669 AAA_AVP *avp;
00670 struct sip_uri puri;
00671 str *uri;
00672 int ret;
00673 int i;
00674 int status;
00675 char tmp[2];
00676 unsigned int mid;
00677
00678 attr_cnt = core2strar( req, val_arr, int_arr, type_arr );
00679
00680 attr_cnt--;
00681
00682 if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) {
00683 LM_ERR("failed to create new AAA request\n");
00684 return -1;
00685 }
00686
00687
00688 if( (status = diam_status(req, acc_env.code))<0) {
00689 LM_ERR("status unknown\n");
00690 goto error;
00691 }
00692 tmp[0] = status+'0';
00693 tmp[1] = 0;
00694 if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp,
00695 1, AVP_DUPLICATE_DATA)) == 0) {
00696 LM_ERR("failed to create AVP:no more free memory!\n");
00697 goto error;
00698 }
00699 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00700 LM_ERR("avp not added \n");
00701 AAAFreeAVP(&avp);
00702 goto error;
00703 }
00704
00705 mid = req->id;
00706 if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid),
00707 sizeof(mid), AVP_DUPLICATE_DATA)) == 0) {
00708 LM_ERR("failed to create AVP:no more free memory!\n");
00709 goto error;
00710 }
00711 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00712 LM_ERR("avp not added \n");
00713 AAAFreeAVP(&avp);
00714 goto error;
00715 }
00716
00717
00718 if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING,
00719 SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) {
00720 LM_ERR("failed to create AVP:no more free memory!\n");
00721 goto error;
00722 }
00723 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00724 LM_ERR("avp not added \n");
00725 AAAFreeAVP(&avp);
00726 goto error;
00727 }
00728
00729
00730 attr_cnt += extra2strar( dia_extra, req, val_arr, int_arr, type_arr);
00731
00732
00733 for(i=0; i<attr_cnt; i++) {
00734 if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len,
00735 AVP_DUPLICATE_DATA)) == 0) {
00736 LM_ERR("failed to create AVP: no more free memory!\n");
00737 goto error;
00738 }
00739 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00740 LM_ERR("avp not added \n");
00741 AAAFreeAVP(&avp);
00742 goto error;
00743 }
00744 }
00745
00746
00747 if ( leg_info ) {
00748 cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1);
00749 do {
00750 for (i=0; i<cnt; i++) {
00751 if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0,
00752 val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) {
00753 LM_ERR("failed to create AVP: no more free memory!\n");
00754 goto error;
00755 }
00756 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00757 LM_ERR("avp not added \n");
00758 AAAFreeAVP(&avp);
00759 goto error;
00760 }
00761 }
00762 } while ( (cnt=legs2strar(leg_info,req,val_arr,int_arr,
00763 type_arr,0))!=0 );
00764 }
00765
00766 if (get_uri(req, &uri) < 0) {
00767 LM_ERR("failed to get uri, From/To URI not found\n");
00768 goto error;
00769 }
00770
00771 if (parse_uri(uri->s, uri->len, &puri) < 0) {
00772 LM_ERR("failed to parse From/To URI\n");
00773 goto error;
00774 }
00775
00776
00777 if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
00778 puri.host.len, AVP_DUPLICATE_DATA)) == 0) {
00779 LM_ERR("failed to create AVP:no more free memory!\n");
00780 goto error;
00781 }
00782
00783 if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
00784 LM_ERR("avp not added \n");
00785 AAAFreeAVP(&avp);
00786 goto error;
00787 }
00788
00789
00790 if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) {
00791 LM_ERR("message buffer not created\n");
00792 goto error;
00793 }
00794
00795 if(sockfd==AAA_NO_CONNECTION) {
00796 sockfd = init_mytcp(diameter_client_host, diameter_client_port);
00797 if(sockfd==AAA_NO_CONNECTION) {
00798 LM_ERR("failed to reconnect to Diameter client\n");
00799 goto error;
00800 }
00801 }
00802
00803
00804 ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, req->id);
00805 if(ret == AAA_CONN_CLOSED) {
00806 LM_NOTICE("connection to Diameter client closed.It will be "
00807 "reopened by the next request\n");
00808 close(sockfd);
00809 sockfd = AAA_NO_CONNECTION;
00810 goto error;
00811 }
00812
00813 if(ret != ACC_SUCCESS) {
00814
00815 LM_ERR("message sending to the DIAMETER backend authorization "
00816 "server failed\n");
00817 goto error;
00818 }
00819
00820 AAAFreeMessage(&send);
00821 return 1;
00822
00823 error:
00824 AAAFreeMessage(&send);
00825 return -1;
00826 }
00827
00828 #endif
00829