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 <stdio.h>
00033 #include <string.h>
00034 #include <time.h>
00035
00036 #include "../../sr_module.h"
00037 #include "../../dprint.h"
00038 #include "../../mem/mem.h"
00039 #include "../../modules/tm/t_hooks.h"
00040 #include "../../modules/tm/tm_load.h"
00041 #include "../../modules/tm/h_table.h"
00042 #include "../../parser/msg_parser.h"
00043 #include "../../parser/parse_from.h"
00044 #include "../../parser/digest/digest.h"
00045 #include "../../usr_avp.h"
00046 #include "../../id.h"
00047 #include "attrs.h"
00048 #include "../../modules/tm/tm_load.h"
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #define ALL_LOG_FMT "acdfgimnoprstuxDFIMPRSTUX"
00086 #define ALL_LOG_FMT_LEN (sizeof(ALL_LOG_FMT) - 1)
00087
00088 #define A_SEPARATOR ", "
00089 #define A_SEPARATOR_LEN (sizeof(A_SEPARATOR) - 1)
00090 #define A_EQ "="
00091 #define A_EQ_LEN (sizeof(A_EQ) - 1)
00092 #define A_EOL "\n\0"
00093 #define A_EOL_LEN (sizeof(A_EOL) - 1)
00094
00095 #define ACC "ACC: "
00096 #define ACC_LEN (sizeof(ACC) - 1)
00097
00098 #define ACC_REQUEST "request accounted: "
00099 #define ACC_MISSED "call missed: "
00100 #define ACC_ANSWERED "transaction answered: "
00101 #define ACC_ACKED "request acknowledged: "
00102
00103 #define NA "n/a"
00104
00105 #define ATR(atr) atr_arr[cnt].s = A_##atr; atr_arr[cnt].len = sizeof(A_##atr) - 1;
00106
00107 #define A_ATTRS "attrs"
00108 #define A_CALLID "callid"
00109 #define A_TOTAG "to_tag"
00110 #define A_FROM "from"
00111 #define A_FLAGS "flags"
00112 #define A_IURI "in_ruri"
00113 #define A_METHOD "sip_method"
00114 #define A_CSEQ "cseq"
00115 #define A_OURI "out_ruri"
00116 #define A_FROMTAG "from_tag"
00117 #define A_TO "to"
00118 #define A_DIGUSER "digest_username"
00119 #define A_REQTIMESTAMP "request_timestamp"
00120 #define A_TODID "to_did"
00121 #define A_FROMURI "from_uri"
00122 #define A_FROMUID "from_uid"
00123 #define A_FROMDID "from_did"
00124 #define A_DIGREALM "digest_realm"
00125 #define A_STATUS "sip_status"
00126 #define A_TOURI "to_uri"
00127 #define A_TOUID "to_uid"
00128 #define A_RESTIMESTAMP "response_timestamp"
00129 #define A_SRCIP "src_ip"
00130 #define A_SRCPORT "src_port"
00131 #define A_SERVERID "server_id"
00132
00133 MODULE_VERSION
00134
00135 struct tm_binds tmb;
00136
00137 static int mod_init( void );
00138 static int fix_log_flag( modparam_t type, void* val);
00139 static int fix_log_missed_flag( modparam_t type, void* val);
00140
00141 static int log_level = L_NOTICE;
00142
00143 static int early_media = 0;
00144 static int failed_transactions = 0;
00145 static int report_cancels = 0;
00146 static int report_ack = 0;
00147 static int log_flag = 0;
00148 static int log_missed_flag = 0;
00149 static char* log_fmt = ALL_LOG_FMT;
00150
00151
00152 static char* attrs = "";
00153 avp_ident_t* avps;
00154 int avps_n;
00155
00156 static int acc_log_request0(struct sip_msg *rq, char *p1, char *p2);
00157 static int acc_log_missed0(struct sip_msg *rq, char *p1, char *p2);
00158 static int acc_log_request1(struct sip_msg *rq, char *p1, char *p2);
00159 static int acc_log_missed1(struct sip_msg *rq, char *p1, char *p2);
00160
00161 static str na = STR_STATIC_INIT(NA);
00162
00163
00164 static cmd_export_t cmds[] = {
00165 {"acc_syslog_log", acc_log_request0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00166 {"acc_syslog_missed", acc_log_missed0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00167 {"acc_syslog_log", acc_log_request1, 1, fixup_var_str_1, REQUEST_ROUTE | FAILURE_ROUTE},
00168 {"acc_syslog_missed", acc_log_missed1, 1, fixup_var_str_1, REQUEST_ROUTE | FAILURE_ROUTE},
00169 {0, 0, 0, 0, 0}
00170 };
00171
00172
00173 static param_export_t params[] = {
00174 {"early_media", PARAM_INT, &early_media },
00175 {"failed_transactions", PARAM_INT, &failed_transactions },
00176 {"report_ack", PARAM_INT, &report_ack },
00177 {"report_cancels", PARAM_INT, &report_cancels },
00178 {"log_flag", PARAM_INT, &log_flag },
00179 {"log_flag", PARAM_STRING|PARAM_USE_FUNC, fix_log_flag},
00180 {"log_missed_flag", PARAM_INT, &log_missed_flag },
00181 {"log_missed_flag", PARAM_STRING|PARAM_USE_FUNC, fix_log_missed_flag},
00182 {"log_level", PARAM_INT, &log_level },
00183 {"log_fmt", PARAM_STRING, &log_fmt },
00184 {"attrs", PARAM_STRING, &attrs },
00185 {0, 0, 0}
00186 };
00187
00188
00189 struct module_exports exports= {
00190 "acc_syslog",
00191 cmds,
00192 0,
00193 params,
00194 mod_init,
00195 0,
00196 0,
00197 0,
00198 0
00199 };
00200
00201
00202
00203
00204 static int fix_log_flag( modparam_t type, void* val)
00205 {
00206 return fix_flag(type, val, "acc_syslog", "log_flag", &log_flag);
00207 }
00208
00209
00210
00211
00212 static int fix_log_missed_flag( modparam_t type, void* val)
00213 {
00214 return fix_flag(type, val, "acc_syslog", "log_missed_flag", &log_missed_flag);
00215 }
00216
00217
00218 #define TM_BUF_LEN sizeof("10000-12-31 23:59:59")
00219
00220 static inline int convert_time(str* buf, time_t time)
00221 {
00222 struct tm* tm;
00223
00224 if (!buf->s || buf->len < TM_BUF_LEN) {
00225 LOG(L_ERR, "ERROR:acc:convert_time: Buffer too short\n");
00226 return -1;
00227 }
00228
00229 tm = gmtime(&time);
00230 buf->len = strftime(buf->s, buf->len, "%Y-%m-%d %H:%M:%S", tm);
00231 return 0;
00232 }
00233
00234
00235 static inline int skip_cancel(struct sip_msg *msg)
00236 {
00237 return (msg->REQ_METHOD == METHOD_CANCEL) && report_cancels == 0;
00238 }
00239
00240
00241
00242
00243
00244
00245 #define append(buf, ptr) \
00246 do { \
00247 memcpy((buf).s, (ptr), sizeof(ptr) - 1); \
00248 (buf).s += sizeof(ptr) - 1; \
00249 (buf).len -= sizeof(ptr) - 1; \
00250 } while(0);
00251
00252
00253 #define str_append_str(buf, str) \
00254 do { \
00255 memcpy((buf).s, (str).s, (str).len); \
00256 (buf).s += (str).len; \
00257 (buf).len -= (str).len; \
00258 } while(0);
00259
00260
00261 int verify_fmt(char *fmt) {
00262
00263 if (!fmt) {
00264 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string zero\n");
00265 return -1;
00266 }
00267
00268 if (!(*fmt)) {
00269 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string empty\n");
00270 return -1;
00271 }
00272
00273 if (strlen(fmt) > ALL_LOG_FMT_LEN) {
00274 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string too long\n");
00275 return -1;
00276 }
00277
00278 while(*fmt) {
00279 if (!strchr(ALL_LOG_FMT, *fmt)) {
00280 LOG(L_ERR, "ERROR:acc:verify_fmt: char in log_fmt invalid: %c\n", *fmt);
00281 return -1;
00282 }
00283 fmt++;
00284 }
00285 return 1;
00286 }
00287
00288
00289
00290
00291
00292
00293 static inline int is_acc_on(struct sip_msg *rq)
00294 {
00295 return log_flag && isflagset(rq, log_flag) == 1;
00296 }
00297
00298
00299
00300
00301
00302
00303 static inline int is_mc_on(struct sip_msg *rq)
00304 {
00305 return log_missed_flag && isflagset(rq, log_missed_flag) == 1;
00306 }
00307
00308
00309 static inline void preparse_req(struct sip_msg *rq)
00310 {
00311
00312
00313
00314
00315
00316
00317 parse_headers(rq, HDR_CALLID_F | HDR_FROM_F | HDR_TO_F | HDR_CSEQ_F, 0 );
00318 parse_from_header(rq);
00319 }
00320
00321
00322
00323 static inline int should_acc_reply(struct cell* t, int code)
00324 {
00325 struct sip_msg *r;
00326
00327 r = t->uas.request;
00328
00329
00330 if (r == 0) {
00331 LOG(L_ERR, "ERROR:acc:should_acc_reply: 0 request\n");
00332 return 0;
00333 }
00334
00335
00336
00337 if (!failed_transactions && code >= 300) return 0;
00338 if (!is_acc_on(r)) return 0;
00339 if (skip_cancel(r)) return 0;
00340 if (code < 200 && ! (early_media && code == 183)) return 0;
00341 return 1;
00342 }
00343
00344
00345
00346 static inline str* cred_user(struct sip_msg* rq)
00347 {
00348 struct hdr_field* h;
00349 auth_body_t* cred;
00350
00351 get_authorized_cred(rq->proxy_auth, &h);
00352 if (!h) get_authorized_cred(rq->authorization, &h);
00353 if (!h) return 0;
00354 cred = (auth_body_t*)(h->parsed);
00355 if (!cred || !cred->digest.username.user.len)
00356 return 0;
00357 return &cred->digest.username.user;
00358 }
00359
00360
00361
00362 static inline str* cred_realm(struct sip_msg* rq)
00363 {
00364 str* realm;
00365 struct hdr_field* h;
00366 auth_body_t* cred;
00367
00368 get_authorized_cred(rq->proxy_auth, &h);
00369 if (!h) get_authorized_cred(rq->authorization, &h);
00370 if (!h) return 0;
00371 cred = (auth_body_t*)(h->parsed);
00372 if (!cred) return 0;
00373 realm = GET_REALM(&cred->digest);
00374 if (!realm->len || !realm->s) {
00375 return 0;
00376 }
00377 return realm;
00378 }
00379
00380
00381
00382
00383
00384 static inline struct hdr_field* valid_to(struct cell* t, struct sip_msg* reply)
00385 {
00386 if (reply == FAKED_REPLY || !reply || !reply->to) {
00387 return t->uas.request->to;
00388 } else {
00389 return reply->to;
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 static int fmt2strar(char *fmt,
00401 struct sip_msg *rq,
00402 str* ouri,
00403 struct hdr_field *to,
00404 str *phrase,
00405 int *total_len,
00406 int *attr_len,
00407 str **val_arr,
00408 str *atr_arr,
00409 time_t req_time)
00410 {
00411 static char flags_buf[INT2STR_MAX_LEN], tm_buf[TM_BUF_LEN],
00412 rqtm_buf[TM_BUF_LEN], srcip_buf[IP_ADDR_MAX_STR_SIZE],
00413 srcport_buf[INT2STR_MAX_LEN], serverid_buf[INT2STR_MAX_LEN];
00414 int cnt, tl, al;
00415 struct to_body* from, *pto;
00416 static str mycode, flags, tm_s, rqtm_s, src_ip, src_port, from_uid, to_uid, server_id_str;
00417 str *cr, *at;
00418 struct cseq_body *cseq;
00419 char* p;
00420
00421 cnt = tl = al = 0;
00422
00423
00424
00425
00426
00427
00428
00429 while(*fmt) {
00430 if (cnt == ALL_LOG_FMT_LEN) {
00431 LOG(L_ERR, "ERROR:acc:fmt2strar: Formatting string is too long\n");
00432 return 0;
00433 }
00434
00435 switch(*fmt) {
00436 case 'a':
00437 at = print_attrs(avps, avps_n, 1);
00438 if (!at) {
00439 val_arr[cnt] = &na;
00440 } else {
00441 val_arr[cnt] = at;
00442 }
00443 ATR(ATTRS);
00444 break;
00445
00446 case 'c':
00447 val_arr[cnt] = (rq->callid && rq->callid->body.len) ? &rq->callid->body : &na;
00448 ATR(CALLID);
00449 break;
00450
00451 case 'd':
00452 val_arr[cnt] = (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) ? & pto->tag_value : &na;
00453 ATR(TOTAG);
00454 break;
00455
00456 case 'f':
00457 val_arr[cnt] = (rq->from && rq->from->body.len) ? &rq->from->body : &na;
00458 ATR(FROM);
00459 break;
00460
00461 case 'g':
00462 p = int2str(rq->flags, &flags.len);
00463 memcpy(flags_buf, p, flags.len);
00464 flags.s = flags_buf;
00465 val_arr[cnt] = &flags;
00466 ATR(FLAGS);
00467 break;
00468
00469 case 'i':
00470 val_arr[cnt] = &rq->first_line.u.request.uri;
00471 ATR(IURI);
00472 break;
00473
00474 case 'm':
00475 val_arr[cnt] = &rq->first_line.u.request.method;
00476 ATR(METHOD);
00477 break;
00478
00479 case 'n':
00480 if (rq->cseq && (cseq = get_cseq(rq)) && cseq->number.len) val_arr[cnt] = &cseq->number;
00481 else val_arr[cnt]=&na;
00482 ATR(CSEQ);
00483 break;
00484
00485 case 'o':
00486 val_arr[cnt] = ouri;
00487 ATR(OURI);
00488 break;
00489
00490 case 'p':
00491
00492
00493
00494 src_ip.s = srcip_buf;
00495 p = ip_addr2a(&rq->rcv.src_ip);
00496 src_ip.len = strlen(p);
00497 memcpy(src_ip.s, p, src_ip.len);
00498 val_arr[cnt] = &src_ip;
00499 ATR(SRCIP);
00500 break;
00501
00502 case 'r':
00503 if (rq->from && (from = get_from(rq)) && from->tag_value.len) {
00504 val_arr[cnt] = &from->tag_value;
00505 } else {
00506 val_arr[cnt] = &na;
00507 }
00508 ATR(FROMTAG);
00509 break;
00510
00511 case 's':
00512 p = int2str(server_id, &server_id_str.len);
00513 memcpy(serverid_buf, p, server_id_str.len);
00514 server_id_str.s = serverid_buf;
00515 val_arr[cnt] = &server_id_str;
00516 ATR(SERVERID);
00517 break;
00518
00519 case 't':
00520 val_arr[cnt] = (to && to->body.len) ? &to->body : &na;
00521 ATR(TO);
00522 break;
00523
00524 case 'u':
00525 cr = cred_user(rq);
00526 if (cr) val_arr[cnt] = cr;
00527 else val_arr[cnt] = &na;
00528 ATR(DIGUSER);
00529 break;
00530
00531 case 'x':
00532 rqtm_s.s = rqtm_buf;
00533 rqtm_s.len = TM_BUF_LEN;
00534 convert_time(&rqtm_s, req_time);
00535 val_arr[cnt] = &rqtm_s;
00536 ATR(REQTIMESTAMP);
00537 break;
00538
00539 case 'D':
00540 val_arr[cnt] = &na;
00541 ATR(TODID);
00542 break;
00543
00544 case 'F':
00545 if (rq->from && (from = get_from(rq)) && from->uri.len) {
00546 val_arr[cnt] = &from->uri;
00547 } else val_arr[cnt] = &na;
00548 ATR(FROMURI);
00549 break;
00550
00551 case 'I':
00552 if (get_from_uid(&from_uid, rq) < 0) {
00553 val_arr[cnt] = &na;
00554 } else {
00555 val_arr[cnt] = &from_uid;
00556 }
00557 ATR(FROMUID);
00558 break;
00559
00560 case 'M':
00561 val_arr[cnt] = &na;
00562 ATR(FROMDID);
00563 break;
00564
00565 case 'P':
00566 p = int2str(rq->rcv.src_port, &src_port.len);
00567 memcpy(srcport_buf, p, src_port.len);
00568 src_port.s = srcport_buf;
00569 val_arr[cnt] = &src_port;
00570 ATR(SRCPORT);
00571 break;
00572
00573 case 'R':
00574 cr = cred_realm(rq);
00575 if (cr) val_arr[cnt] = cr;
00576 else val_arr[cnt] = &na;
00577 ATR(DIGREALM);
00578 break;
00579
00580 case 'S':
00581 if (phrase->len >= 3) {
00582 mycode.s = phrase->s;
00583 mycode.len = 3;
00584 val_arr[cnt] = &mycode;
00585 } else val_arr[cnt] = &na;
00586 ATR(STATUS);
00587 break;
00588
00589 case 'T':
00590 if (rq->to && (pto = get_to(rq)) && pto->uri.len) val_arr[cnt] = &pto->uri;
00591 else val_arr[cnt] = &na;
00592 ATR(TOURI);
00593 break;
00594
00595 case 'U':
00596 if (get_to_uid(&to_uid, rq) < 0) {
00597 val_arr[cnt] = &na;
00598 } else {
00599 val_arr[cnt] = &to_uid;
00600 }
00601 ATR(TOUID);
00602 break;
00603
00604 case 'X':
00605 tm_s.s = tm_buf;
00606 tm_s.len = TM_BUF_LEN;
00607 convert_time(&tm_s, time(0));
00608 val_arr[cnt] = &tm_s;
00609 ATR(RESTIMESTAMP);
00610 break;
00611
00612 default:
00613 LOG(L_CRIT, "BUG:acc:fmt2strar: unknown char: %c\n", *fmt);
00614 return 0;
00615 }
00616
00617 tl += val_arr[cnt]->len;
00618 al += atr_arr[cnt].len;
00619 fmt++;
00620 cnt++;
00621 }
00622
00623 *total_len = tl;
00624 *attr_len = al;
00625 return cnt;
00626 }
00627
00628
00629
00630 static int log_request(struct sip_msg* rq, str* ouri, struct hdr_field* to, str* txt, str* phrase, time_t req_time)
00631 {
00632 static str* val_arr[ALL_LOG_FMT_LEN];
00633 static str atr_arr[ALL_LOG_FMT_LEN];
00634 int len, attr_cnt, attr_len, i;
00635 char *log_msg;
00636 str buf;
00637
00638 if (skip_cancel(rq)) return 1;
00639
00640 attr_cnt = fmt2strar(log_fmt, rq, ouri, to, phrase, &len, &attr_len, val_arr, atr_arr, req_time);
00641 if (!attr_cnt) {
00642 LOG(L_ERR, "ERROR:acc:log_request: fmt2strar failed\n");
00643 return -1;
00644 }
00645
00646 len += attr_len + ACC_LEN + txt->len + A_EOL_LEN + attr_cnt * (A_SEPARATOR_LEN + A_EQ_LEN) - A_SEPARATOR_LEN;
00647 log_msg = pkg_malloc(len);
00648 if (!log_msg) {
00649 LOG(L_ERR, "ERROR:acc:log_request: No memory left for %d bytes\n", len);
00650 return -1;
00651 }
00652
00653
00654
00655
00656
00657 buf.s = log_msg + ACC_LEN + txt->len - A_SEPARATOR_LEN;
00658 buf.len = len - ACC_LEN - txt->len + A_SEPARATOR_LEN;
00659
00660 for (i = 0; i < attr_cnt; i++) {
00661 append(buf, A_SEPARATOR);
00662 str_append_str(buf, atr_arr[i]);
00663 append(buf, A_EQ);
00664 str_append_str(buf, *(val_arr[i]))
00665 }
00666
00667
00668 append(buf, A_EOL);
00669
00670
00671 buf.s = log_msg;
00672 buf.len = len;
00673 append(buf, ACC);
00674 str_append_str(buf, *txt);
00675
00676 LOG(log_level, "%s", log_msg);
00677 pkg_free(log_msg);
00678 return 1;
00679 }
00680
00681
00682 static void log_reply(struct cell* t , struct sip_msg* reply, unsigned int code, time_t req_time)
00683 {
00684 str code_str, *ouri;
00685 static str lead = STR_STATIC_INIT(ACC_ANSWERED);
00686 static char code_buf[INT2STR_MAX_LEN];
00687 char* p;
00688
00689 p = int2str(code, &code_str.len);
00690 memcpy(code_buf, p, code_str.len);
00691 code_str.s = code_buf;
00692
00693 if (t->relayed_reply_branch >= 0) {
00694 ouri = &t->uac[t->relayed_reply_branch].uri;
00695 } else {
00696 ouri = GET_NEXT_HOP(t->uas.request);
00697 }
00698
00699 log_request(t->uas.request, ouri, valid_to(t,reply), &lead, &code_str, req_time);
00700 }
00701
00702
00703 static void log_ack(struct cell* t , struct sip_msg *ack, time_t req_time)
00704 {
00705 struct sip_msg *rq;
00706 struct hdr_field *to;
00707 static str lead = STR_STATIC_INIT(ACC_ACKED);
00708 static char code_buf[INT2STR_MAX_LEN];
00709 str code_str;
00710 char* p;
00711
00712 rq = t->uas.request;
00713 if (ack->to) to = ack->to;
00714 else to = rq->to;
00715 p = int2str(t->uas.status, &code_str.len);
00716 memcpy(code_buf, p, code_str.len);
00717 code_str.s = code_buf;
00718 log_request(ack, GET_RURI(ack), to, &lead, &code_str, req_time);
00719 }
00720
00721
00722 static void log_missed(struct cell* t, struct sip_msg* reply, unsigned int code, time_t req_time)
00723 {
00724 str acc_text, *ouri;
00725 static str leading_text = STR_STATIC_INIT(ACC_MISSED);
00726
00727 get_reply_status(&acc_text, reply, code);
00728 if (acc_text.s == 0) {
00729 LOG(L_ERR, "ERROR:acc:log_missed: get_reply_status failed\n" );
00730 return;
00731 }
00732
00733 if (t->relayed_reply_branch >= 0) {
00734 ouri = &t->uac[t->relayed_reply_branch].uri;
00735 } else {
00736 ouri = GET_NEXT_HOP(t->uas.request);
00737 }
00738
00739 log_request(t->uas.request, ouri, valid_to(t, reply), &leading_text, &acc_text, req_time);
00740 pkg_free(acc_text.s);
00741 }
00742
00743
00744
00745
00746
00747
00748 static int acc_log_request1(struct sip_msg *rq, char* p1, char* p2)
00749 {
00750 str phrase;
00751 str txt = STR_STATIC_INIT(ACC_REQUEST);
00752
00753 if (get_str_fparam(&phrase, rq, (fparam_t*)p1) < 0) {
00754 phrase.s = 0;
00755 phrase.len = 0;
00756 }
00757 preparse_req(rq);
00758 return log_request(rq, GET_RURI(rq), rq->to, &txt, &phrase, time(0));
00759 }
00760
00761
00762
00763
00764
00765
00766 static int acc_log_missed1(struct sip_msg *rq, char* p1, char* p2)
00767 {
00768 str phrase;
00769 str txt = STR_STATIC_INIT(ACC_MISSED);
00770
00771 if (get_str_fparam(&phrase, rq, (fparam_t*)p1) < 0) {
00772 phrase.s = 0;
00773 phrase.len = 0;
00774 }
00775 preparse_req(rq);
00776 return log_request(rq, GET_RURI(rq), rq->to, &txt, &phrase, time(0));
00777 }
00778
00779
00780
00781
00782
00783
00784
00785 static int acc_log_request0(struct sip_msg *rq, char* p1, char* p2)
00786 {
00787 static str phrase = STR_NULL;
00788 str txt = STR_STATIC_INIT(ACC_REQUEST);
00789 return log_request(rq, GET_RURI(rq), rq->to, &txt, &phrase, time(0));
00790 }
00791
00792
00793
00794
00795
00796
00797 static int acc_log_missed0(struct sip_msg *rq, char* p1, char* p2)
00798 {
00799 static str phrase = STR_NULL;
00800 str txt = STR_STATIC_INIT(ACC_MISSED);
00801 preparse_req(rq);
00802 return log_request(rq, GET_RURI(rq), rq->to, &txt, &phrase, time(0));
00803 }
00804
00805
00806
00807 static void ack_handler(struct cell* t, int type, struct tmcb_params* ps)
00808 {
00809 if (is_acc_on(t->uas.request)) {
00810 preparse_req(ps->req);
00811 log_ack(t, ps->req, (time_t)*(ps->param));
00812 }
00813 }
00814
00815
00816
00817 static void failure_handler(struct cell *t, int type, struct tmcb_params* ps)
00818 {
00819
00820 if (t->uas.request == 0) {
00821 DBG("DBG:acc:failure_handler: No uas.request, skipping local transaction\n");
00822 return;
00823 }
00824
00825 if (is_invite(t) && ps->code >= 300) {
00826 if (is_mc_on(t->uas.request)) {
00827 log_missed(t, ps->rpl, ps->code, (time_t)*(ps->param));
00828 resetflag(t->uas.request, log_missed_flag);
00829 }
00830 }
00831 }
00832
00833
00834
00835 static void replyout_handler(struct cell* t, int type, struct tmcb_params* ps)
00836 {
00837 if (t->uas.request == 0) {
00838 DBG("DBG:acc:replyout_handler: No uas.request, local transaction, skipping\n");
00839 return;
00840 }
00841
00842
00843
00844
00845
00846 failure_handler(t, type, ps);
00847 if (!should_acc_reply(t, ps->code)) return;
00848 if (is_acc_on(t->uas.request)) log_reply(t, ps->rpl, ps->code, (time_t)*(ps->param));
00849 }
00850
00851
00852
00853 static void replyin_handler(struct cell *t, int type, struct tmcb_params* ps)
00854 {
00855
00856 if (t->uas.request == 0) {
00857 LOG(L_ERR, "ERROR:acc:replyin_handler:replyin_handler: 0 request\n");
00858 return;
00859 }
00860
00861
00862
00863 if (((is_invite(t) && ps->code >= 300 && is_mc_on(t->uas.request))
00864 || should_acc_reply(t, ps->code))
00865 && (ps->rpl && ps->rpl != FAKED_REPLY)) {
00866 parse_headers(ps->rpl, HDR_TO_F, 0);
00867 }
00868 }
00869
00870
00871
00872 void on_req(struct cell* t, int type, struct tmcb_params *ps)
00873 {
00874 time_t req_time;
00875
00876 req_time = time(0);
00877
00878 if (is_acc_on(ps->req) || is_mc_on(ps->req)) {
00879 if (tmb.register_tmcb(0, t, TMCB_RESPONSE_OUT, replyout_handler,
00880 (void*)req_time, 0) <= 0) {
00881 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_RESPONSE_OUT callback\n");
00882 return;
00883 }
00884
00885 if (report_ack) {
00886 if (tmb.register_tmcb(0, t, TMCB_E2EACK_IN, ack_handler,
00887 (void*)req_time, 0) <= 0) {
00888 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_E2EACK_IN callback\n");
00889 return;
00890 }
00891 }
00892
00893 if (tmb.register_tmcb(0, t, TMCB_ON_FAILURE_RO, failure_handler,
00894 (void*)req_time, 0) <= 0) {
00895 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_ON_FAILURE_RO callback\n");
00896 return;
00897 }
00898
00899 if (tmb.register_tmcb(0, t, TMCB_RESPONSE_IN, replyin_handler,
00900 (void*)req_time, 0) <= 0) {
00901 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_RESPONSE_IN callback\n");
00902 return;
00903 }
00904
00905
00906 preparse_req(ps->req);
00907
00908 if (ps->req->REQ_METHOD == METHOD_INVITE) {
00909 DBG("DEBUG: noisy_timer set for accounting\n");
00910 t->flags |= T_NOISY_CTIMER_FLAG;
00911 }
00912 }
00913 }
00914
00915
00916 static int mod_init(void)
00917 {
00918 load_tm_f load_tm;
00919
00920
00921 if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
00922 LOG(L_ERR, "ERROR:acc:mod_init: can't import load_tm\n");
00923 return -1;
00924 }
00925
00926 if (load_tm( &tmb )==-1) return -1;
00927 if (verify_fmt(log_fmt)==-1) return -1;
00928
00929
00930
00931 if (tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, on_req, 0, 0) <= 0) {
00932 LOG(L_ERR,"ERROR:acc:mod_init: cannot register TMCB_REQUEST_IN "
00933 "callback\n");
00934 return -1;
00935 }
00936
00937 if (parse_attrs(&avps, &avps_n, attrs) < 0) {
00938 ERR("Error while parsing 'attrs' module parameter\n");
00939 return -1;
00940 }
00941
00942 return 0;
00943 }