/* * Request OSP authorization and routeing * param msg SIP message * param ignore1 * param ignore2 * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure, MODULE_RETURNCODE_ERROR error */ int ospRequestRouting( struct sip_msg* msg, char* ignore1, char* ignore2) { int errcode; time_t authtime; char calling[OSP_STRBUF_SIZE]; char called[OSP_STRBUF_SIZE]; char rn[OSP_STRBUF_SIZE]; char cic[OSP_STRBUF_SIZE]; int npdi; OSPE_OPERATOR_NAME type; char opname[OSPC_OPNAME_NUMBER][OSP_STRBUF_SIZE]; char source[OSP_STRBUF_SIZE]; char sourcebuf[OSP_STRBUF_SIZE]; char srcdev[OSP_STRBUF_SIZE]; char srcdevbuf[OSP_STRBUF_SIZE]; char rpid[OSP_STRBUF_SIZE]; char pai[OSP_STRBUF_SIZE]; char divuser[OSP_STRBUF_SIZE]; char divhost[OSP_STRBUF_SIZE]; char divhostbuf[OSP_STRBUF_SIZE]; char pci[OSP_STRBUF_SIZE]; struct usr_avp* snidavp = NULL; int_str snidval; char snid[OSP_STRBUF_SIZE]; struct usr_avp* cinfoavp = NULL; int_str cinfoval; unsigned int cinfonum = 0, i; char cinfo[OSP_DEF_CINFOS][OSP_STRBUF_SIZE]; char cinfostr[OSP_STRBUF_SIZE]; unsigned int callidnumber = 1; OSPT_CALL_ID* callids[callidnumber]; unsigned int logsize = 0; char* detaillog = NULL; char tohost[OSP_STRBUF_SIZE]; char tohostbuf[OSP_STRBUF_SIZE]; const char* preferred[2] = { NULL }; unsigned int destcount; OSPTTRANHANDLE trans = -1; int result = MODULE_RETURNCODE_FALSE; if ((errcode = OSPPTransactionNew(_osp_provider, &trans)) != OSPC_ERR_NO_ERROR) { LM_ERR("failed to create new OSP transaction (%d)\n", errcode); } else if (ospGetFromUserpart(msg, calling, sizeof(calling)) != 0) { LM_ERR("failed to extract calling number\n"); } else if ((ospGetUriUserpart(msg, called, sizeof(called)) != 0) && (ospGetToUserpart(msg, called, sizeof(called)) != 0)) { LM_ERR("failed to extract called number\n"); } else if (ospGetCallId(msg, &(callids[0])) != 0) { LM_ERR("failed to extract call id\n"); } else if (ospGetSource(msg, source, sizeof(source)) != 0) { LM_ERR("failed to extract source address\n"); } else if (ospGetSourceDevice(msg, srcdev, sizeof(srcdev)) != 0) { LM_ERR("failed to extract source deivce address\n"); } else { authtime = time(NULL); ospConvertToOutAddress(source, sourcebuf, sizeof(sourcebuf)); ospConvertToOutAddress(srcdev, srcdevbuf, sizeof(srcdevbuf)); switch (_osp_service_type) { case 1: OSPPTransactionSetServiceType(trans, OSPC_SERVICE_NPQUERY); ospGetToHostpart(msg, tohost, sizeof(tohost)); ospConvertToOutAddress(tohost, tohostbuf, sizeof(tohostbuf)); preferred[0] = tohostbuf; destcount = 1; break; case 0: default: OSPPTransactionSetServiceType(trans, OSPC_SERVICE_VOICE); destcount = _osp_max_dests; break; } if (ospGetNpParameters(msg, rn, sizeof(rn), cic, sizeof(cic), &npdi) == 0) { OSPPTransactionSetNumberPortability(trans, rn, cic, npdi); } for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) { if (ospGetOperatorName(msg, type, opname[type], sizeof(opname[type])) == 0) { OSPPTransactionSetOperatorName(trans, type, opname[type]); } } if (ospGetRpidUserpart(msg, rpid, sizeof(rpid)) == 0) { OSPPTransactionSetRemotePartyId(trans, OSPC_NFORMAT_E164, rpid); } if (ospGetPaiUserpart(msg, pai, sizeof(pai)) == 0) { OSPPTransactionSetAssertedId(trans, OSPC_NFORMAT_E164, pai); } if (ospGetDiversion(msg, divuser, sizeof(divuser), divhost, sizeof(divhost)) == 0) { ospConvertToOutAddress(divhost, divhostbuf, sizeof(divhostbuf)); } else { divhostbuf[0] = '\0'; } OSPPTransactionSetDiversion(trans, divuser, divhostbuf); OSPPTransactionSetProtocol(trans, OSPC_PROTTYPE_SOURCE, OSPC_PROTNAME_SIP); if (ospGetPChargeInfoUserpart(msg, pci, sizeof(pci)) == 0) { OSPPTransactionSetChargeInfo(trans, OSPC_NFORMAT_E164, pci); } if ((_osp_snid_avpid >= 0) && ((snidavp = search_first_avp(_osp_snid_avptype, _osp_snid_avpid, &snidval, 0)) != NULL) && (snidavp->flags & AVP_VAL_STR) && (snidval.s.s && snidval.s.len)) { snprintf(snid, sizeof(snid), "%.*s", snidval.s.len, snidval.s.s); snid[sizeof(snid) - 1] = '\0'; OSPPTransactionSetNetworkIds(trans, snid, ""); } else { snid[0] = '\0'; } if (_osp_cinfo_avpid >= 0) { for (i = 0, cinfoavp = search_first_avp(_osp_cinfo_avptype, _osp_cinfo_avpid, NULL, 0); ((i < OSP_DEF_CINFOS) && (cinfoavp != NULL)); i++, cinfoavp = search_next_avp(cinfoavp, NULL)) { get_avp_val(cinfoavp, &cinfoval); if ((cinfoavp->flags & AVP_VAL_STR) && (cinfoval.s.s && cinfoval.s.len)) { snprintf(cinfo[i], sizeof(cinfo[i]), "%.*s", cinfoval.s.len, cinfoval.s.s); cinfo[i][sizeof(cinfo[i]) - 1] = '\0'; } else { cinfo[i][0] = '\0'; } } cinfonum = i; cinfostr[0] = '\0'; for (i = 0; i < cinfonum; i++) { if (cinfo[cinfonum - i - 1][0] != '\0') { OSPPTransactionSetCustomInfo(trans, i, cinfo[cinfonum - i - 1]); snprintf(cinfostr + strlen(cinfostr), sizeof(cinfostr) - strlen(cinfostr), "custom_info%d '%s' ", i + 1, cinfo[cinfonum - i - 1]); } } cinfostr[sizeof(cinfostr) - 1] = '\0'; } LM_INFO("request auth and routing for: " "service_type '%d' " "source '%s' " "source_dev '%s' " "source_networkid '%s' " "calling '%s' " "called '%s' " "preferred '%s' " "nprn '%s' " "npcic '%s' " "npdi '%d' " /* "spid '%s' " "ocn '%s' " "spn '%s' " "altspn '%s' " "mcc '%s' " "mnc '%s' " */ "rpid '%s' " "pai '%s' " "div_user '%s' " "div_host '%s' " "pci '%s' " "call_id '%.*s' " "dest_count '%d' " "%s\n", _osp_service_type, sourcebuf, srcdevbuf, snid, calling, called, (preferred[0] == NULL) ? "" : preferred[0], rn, cic, npdi, /* opname[OSPC_OPNAME_SPID], opname[OSPC_OPNAME_OCN], opname[OSPC_OPNAME_SPN], opname[OSPC_OPNAME_ALTSPN], opname[OSPC_OPNAME_MCC], opname[OSPC_OPNAME_MNC], */ rpid, pai, divuser, divhostbuf, pci, callids[0]->Length, callids[0]->Value, destcount, cinfostr); /* try to request authorization */ errcode = OSPPTransactionRequestAuthorisation( trans, /* transaction handle */ sourcebuf, /* from the configuration file */ srcdevbuf, /* source device of call, protocol specific, in OSP format */ calling, /* calling number in nodotted e164 notation */ OSPC_NFORMAT_E164, /* calling number format */ called, /* called number */ OSPC_NFORMAT_E164, /* called number format */ "", /* optional username string, used if no number */ callidnumber, /* number of call ids, here always 1 */ callids, /* sized-1 array of call ids */ preferred, /* preferred destinations */ &destcount, /* max destinations, after call dest_count */ &logsize, /* size allocated for detaillog (next param) 0=no log */ detaillog); /* memory location for detaillog to be stored */ if ((errcode == OSPC_ERR_NO_ERROR) && (ospLoadRoutes(trans, destcount, source, srcdev, called, authtime, rpid, pai, divuser, divhostbuf, pci) == 0)) { LM_INFO("there are '%d' OSP routes, call_id '%.*s'\n", destcount, callids[0]->Length, callids[0]->Value); result = MODULE_RETURNCODE_TRUE; } else { LM_ERR("failed to request auth and routing (%d), call_id '%.*s'\n", errcode, callids[0]->Length, callids[0]->Value); switch (errcode) { case OSPC_ERR_TRAN_ROUTE_BLOCKED: result = -403; break; case OSPC_ERR_TRAN_ROUTE_NOT_FOUND: result = -404; break; case OSPC_ERR_TRAN_CALLING_INVALID: result = -428; break; case OSPC_ERR_TRAN_CALLED_FILTERING: result = -484; break; case OSPC_ERR_NO_ERROR: /* AuthRsp ok but ospLoadRoutes fails */ result = MODULE_RETURNCODE_ERROR; break; default: result = MODULE_RETURNCODE_FALSE; break; } } } if (callids[0] != NULL) { OSPPCallIdDelete(&(callids[0])); } if (trans != -1) { OSPPTransactionDelete(trans); } return result; }
static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps) { static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; char statusbuf[8]; int len; if(t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || req==NULL) { LM_DBG("no reply\n"); return; } LM_DBG("trace onreply in \n"); avp = NULL; if(traced_user_avp>=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; strcpy(statusbuf, int2str(ps->code, &len)); db_vals[3].val.str_val.s = statusbuf; db_vals[3].val.str_val.len = len; set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff, &msg->rcv.src_ip, msg->rcv.src_port, msg->rcv.proto); if(trace_local_ip.s && trace_local_ip.len > 0){ set_columns_to_trace_local_ip(db_vals[7], db_vals[8], db_vals[9]); } else { set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff, &msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto); } db_vals[10].val.time_val = time(NULL); db_vals[11].val.string_val = "in"; db_vals[12].val.str_val.s = get_from(msg)->tag_value.s; db_vals[12].val.str_val.len = get_from(msg)->tag_value.len; if (save_siptrace(req,avp,&avp_value,db_keys,db_vals) < 0) { LM_ERR("failed to save siptrace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif return; error: return; }
static void trace_sl_onreply_out( unsigned int types, struct sip_msg* req, struct sl_cb_param *sl_param) { static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[5]; if(req==NULL || sl_param==NULL) { LM_ERR("bad parameters\n"); goto error; } if( trace_is_off() ) { LM_DBG("trace off...\n"); return; } LM_DBG("trace slonreply out \n"); avp = NULL; if(traced_user_avp >= 0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && !flag_trace_is_set(req)) { LM_DBG("nothing to trace...\n"); return; } msg = req; if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_vals[0].val.blob_val.s = (sl_param->buffer)?sl_param->buffer->s:""; db_vals[0].val.blob_val.len = (sl_param->buffer)?sl_param->buffer->len:0; /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; if(trace_local_ip.s && trace_local_ip.len > 0){ set_columns_to_trace_local_ip( db_vals[4], db_vals[5], db_vals[6]); } else { set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff, &msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto); } strcpy(statusbuf, int2str(sl_param->code, &len)); db_vals[3].val.str_val.s = statusbuf; db_vals[3].val.str_val.len = len; memset(&to_ip, 0, sizeof(struct ip_addr)); if(sl_param->dst==0) { set_columns_to_any(db_vals[7], db_vals[8], db_vals[9]); } else { su2ip_addr(&to_ip, sl_param->dst); set_sock_columns( db_vals[7], db_vals[8],db_vals[9], toip_buff, &to_ip, (unsigned short)su_getport(sl_param->dst), req->rcv.proto); } db_vals[10].val.time_val = time(NULL); db_vals[11].val.string_val = "out"; db_vals[12].val.str_val.s = get_from(msg)->tag_value.s; db_vals[12].val.str_val.len = get_from(msg)->tag_value.len; if (save_siptrace(msg,avp,&avp_value,db_keys,db_vals) < 0) { LM_ERR("failed to save siptrace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif return; error: return; }
int save(struct sip_msg* _m, char* _d, char* _f, char* _s) { struct sip_msg* msg = _m; struct cell* t = NULL; contact_t* _c; contact_t* reply_c = NULL; contact_t* request_c = NULL; int st; int ret; int requested_exp = 0; int enforced_exp = 0; int_str val; struct lump* l; char* p; char forced_binding_buf[MAX_FORCED_BINDING_LEN]; str forced_binding = {NULL, 0}; str *binding_uri; if(_m->first_line.type != SIP_REPLY) return save_aux(_m, NULL, _d, _f, _s); memset(&val, 0, sizeof(int_str)); if(!tmb.t_gett) { LM_ERR("TM module not loaded - can not save on reply\n"); return -1; } t = tmb.t_gett(); if(!t || t==T_UNDEFINED) { LM_ERR("Transaction not created on Register - can not save on reply\n"); return -1; } msg = t->uas.request; if(!msg) { LM_ERR("NULL request - can not save on reply\n"); return -1; } if (parse_message(_m) < 0) return -1; if (check_contacts(_m, &st) > 0) return -1; if (parse_message(msg) < 0) return -1; if (check_contacts(msg, &st) > 0) return -1; /* msg - request _m - reply */ request_c = get_first_contact(msg); if(request_c) { /* For now, we deal only with the first contact * FIXME: implement multiple contact handling - see check_contacts() */ if(!request_c->expires || !request_c->expires->body.len) { if (msg->expires && ((exp_body_t*)(msg->expires->parsed))->valid) { requested_exp = ((exp_body_t*)(msg->expires->parsed))->val; } else { LM_WARN("No expired defined\n"); } } else { if (str2int(&(request_c->expires->body), (unsigned int*)&requested_exp)<0) { LM_ERR("unable to get expires from [%.*s]\n", request_c->expires->body.len, request_c->expires->body.s); return -1; } } LM_DBG("Binding received from client [%.*s] with requested expires [%d]\n", request_c->uri.len, request_c->uri.s, requested_exp); /* We will use the Contact from request: * - check if a modified contact was set in avp */ if (mct_avp_name >= 0 && search_first_avp(mct_avp_type,mct_avp_name,&val,0) && val.s.len > 0) { LM_DBG("Binding sent to upper registrar [%.*s]\n", val.s.len, val.s.s); binding_uri = &val.s; } else { binding_uri = &request_c->uri; } if (requested_exp) { /* Let's get the contact from reply */ _c = get_first_contact(_m); while (_c) { if (compare_uris(binding_uri, NULL, &_c->uri, NULL) == 0) { if(_c->expires && _c->expires->body.len) { if(str2int(&(_c->expires->body), (unsigned int*)&enforced_exp)<0) { LM_ERR("unable to get expires from [%.*s]\n", _c->expires->body.len, _c->expires->body.s); return -1; } LM_DBG("Binding received from upper registrar" " [%.*s] with imposed expires [%d]\n", _c->uri.len, _c->uri.s, enforced_exp); reply_c = _c; forced_binding.len = request_c->uri.len + 11 + reply_c->expires->body.len; if (forced_binding.len <= MAX_FORCED_BINDING_LEN) { forced_binding.s = forced_binding_buf; forced_binding_buf[0] = '<'; memcpy(&forced_binding_buf[1], request_c->uri.s, request_c->uri.len); memcpy(&forced_binding_buf[request_c->uri.len + 1], ">;expires=", 10); memcpy(&forced_binding_buf[request_c->uri.len + 11], reply_c->expires->body.s, reply_c->expires->body.len); LM_DBG("forcing binding [%.*s]\n", forced_binding.len, forced_binding.s); break; } else { LM_ERR("forced binding to BIG:" " %d > MAX_FORCED_BINDING_LEN\n", forced_binding.len); return -1; } } } else { LM_DBG("Unmatched binding [%.*s]\n", _c->uri.len, _c->uri.s); } _c = get_next_contact(_c); } } ret = save_aux(msg, forced_binding.s?&forced_binding:NULL, _d, _f, _s); } else { LM_DBG("No Contact in request => this is an interogation\n"); ret = 1; } /* if the contact was changed in register - put the modif value */ if(request_c && requested_exp && val.s.s) { if(reply_c) { LM_DBG("replacing contact uri [%.*s] with [%.*s]\n", reply_c->uri.len, reply_c->uri.s, request_c->uri.len, request_c->uri.s); /* replace with what was received in Register */ /* reply_c->uri - now contains the initial received value */ if((l=del_lump(_m, reply_c->uri.s - _m->buf, reply_c->uri.len, 0))==0) { LM_ERR("Failed to delete contact uri lump\n"); ret = -1; goto done; } p = pkg_malloc( request_c->uri.len); if (p==0) { LM_ERR("no more pkg mem\n"); ret = -1; goto done; } memcpy( p, request_c->uri.s, request_c->uri.len ); if (insert_new_lump_after( l, p, request_c->uri.len, 0)==0) { LM_ERR("insert new lump failed\n"); pkg_free(p); ret =-1; goto done; } } } done: clean_msg_clone(t->uas.request, t->uas.request, t->uas.end_request); return ret; }
static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps) { struct sip_msg* msg; int_str avp_value; struct usr_avp* avp; if(t==NULL || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } msg = ps->req; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return; } if( trace_is_off() ) { LM_DBG("trace off...\n"); return; } if (msg->msg_flags & FL_USE_SIPTRACE) { return; } LM_DBG("trace on req in \n"); avp = NULL; if(traced_user_avp>=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if( (avp==NULL) && !flag_trace_is_set(msg)) { LM_DBG("nothing to trace...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); return; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_REQUEST_BUILT, trace_onreq_out, 0, 0) <=0) { LM_ERR("can't register trace_onreq_out\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_IN, trace_onreply_in, 0, 0) <=0) { LM_ERR("can't register trace_onreply_in\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_OUT, trace_onreply_out, 0, 0) <=0) { LM_ERR("can't register trace_onreply_out\n"); return; } }
/* * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */ static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c, str* _ua) { ucontact_t* c, *c2; str callid; int cseq, e, ret; int set, reset; qvalue_t q; unsigned int nated; str* recv; int_str rcv_avp; int_str val; rcv_avp.n=rcv_avp_no; if (isflagset(_m, nat_flag) == 1) { nated = FL_NAT; } else { nated = FL_NONE; } if (max_contacts) { ret = test_max_contacts(_m, _r, _c); if (ret != 0) { build_contact(_r->contacts); return -1; } } _c = get_first_contact(_m); while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { build_contact(_r->contacts); LOG(L_ERR, "update(): Error while calculating expires\n"); return -1; } if (ul.get_ucontact(_r, &_c->uri, &c) > 0) { /* Contact not found */ if (e != 0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -2; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*) &cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -3; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (ul.insert_ucontact(_r, &_c->uri, e, q, &callid, cseq, nated | mem_only, &c2, _ua, recv) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "update(): Error while inserting contact\n"); return -4; } } } else { if (e == 0) { if (mem_only) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c) < 0) { rerrno = R_UL_DEL_C; LOG(L_ERR, "update(): Error while deleting contact\n"); return -5; } } else { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -6; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -7; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } set = nated | mem_only; reset = ~(nated | mem_only) & (FL_NAT | FL_MEM); if (ul.update_ucontact(c, e, q, &callid, cseq, set, reset, _ua, recv) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "update(): Error while updating contact\n"); return -8; } if (desc_time_order) { move_on_top(_r, c); } } } _c = get_next_contact(_c); } return 0; }
int is_other_contact_f(struct sip_msg* msg, char* _d, char *_s) { pv_spec_p spec = (pv_spec_p)_s; struct usr_avp *avp = NULL; urecord_t *r = NULL; str ip, contact; str uri, aor; ucontact_t *c; contact_t* ct; int exp, found; udomain_t* ud = (udomain_t*)_d; if (parse_message(msg) < 0) { LM_ERR("unable to parse message\n"); return -2; } if (!ud) { LM_ERR("no location specified\n"); return -2; } /* msg doesn't have contacts */ if (!msg->contact || !(ct = (((contact_body_t*)msg->contact->parsed)->contacts))) return -1; while (ct) { /* if expires is 0 */ calc_contact_expires(msg, ct->expires, &exp, NULL); if (exp) break; ct = ct->next; } if (!ct) { LM_DBG("contact has expire 0\n"); return -1; } uri = get_to(msg)->uri; if (extract_aor(&uri, &aor,0,0) < 0) { LM_ERR("failed to extract AOR record\n"); return -2; } ul.lock_udomain(ud, &aor); ul.get_urecord(ud, &aor, &r); if (!r) { /* dont't test anything */ LM_DBG("no contact found for aor=<%.*s>\n", aor.len, aor.s); found = -1; goto end; } else { c = r->contacts; } while (c) { if (!c->received.len || !c->received.s || c->received.len < 4 /* sip:*/) { c = c->next; continue; } contact.s = c->received.s + 4; /* check for "sips:" */ if (*contact.s == ':') { contact.len = c->received.len - 5; contact.s++; } else { /* skip "sip:" */ contact.len = c->received.len - 4; } avp = NULL; found = 0; /* the ip should always be a string */ while ((avp = search_first_avp(spec->pvp.pvn.u.isname.type, spec->pvp.pvn.u.isname.name.n, (int_str *)&ip, avp))!=0) { if (!(avp->flags & AVP_VAL_STR)) { LM_NOTICE("avp value should be string\n"); continue; } if ((contact.len == ip.len || (contact.len>ip.len && contact.s[ip.len]==':')) && !memcmp(contact.s, ip.s, ip.len)) { found = 1; break; } } if (!found) { LM_DBG("no contact <%.*s> registered earlier\n", contact.len, contact.s); found = 1; goto end; } c = c->next; } found = -1; end: ul.unlock_udomain(ud, &aor); return found; }
static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; char statusbuf[8]; if(t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || req==NULL) { LM_DBG("no reply\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; if(trace_local_ip) db_vals[5].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info ...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; int faked = 0; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[8]; str *sbuf; struct dest_info *dst; if (t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(t->uas.request)) { LM_DBG("trace off...\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || msg==FAKED_REPLY) { msg = t->uas.request; faked = 1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; sbuf = (str*)ps->extra1; if(faked==0) { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s!=NULL) { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } else if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } } else { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s==NULL) { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } else { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = (struct dest_info*)ps->extra2; if(dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, &dst->to); siptrace_copy_proto(dst->proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(&dst->to), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
static int sip_trace(struct sip_msg *msg, char *s1, char *s2) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+6]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+6]; int_str avp_value; struct usr_avp *avp; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return -1; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) { LM_DBG("trace off...\n"); return -1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse call-id\n"); goto error; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; if(msg->first_line.type==SIP_REQUEST) { db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; } else { db_vals[2].val.str_val.s = ""; db_vals[2].val.str_val.len = 0; } db_keys[3] = status_column; db_vals[3].type = DB_STR; db_vals[3].nul = 0; if(msg->first_line.type==SIP_REPLY) { db_vals[3].val.str_val.s = msg->first_line.u.reply.status.s; db_vals[3].val.str_val.len = msg->first_line.u.reply.status.len; } else { db_vals[3].val.str_val.s = ""; db_vals[3].val.str_val.len = 0; } db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if(trace_on_flag!=NULL && *trace_on_flag!=0) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS if(msg->first_line.type==SIP_REPLY) { update_stat(siptrace_rpl, 1); } else { update_stat(siptrace_req, 1); } #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return 1; error: return -1; }
static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps) { struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; if(t==NULL || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } msg = ps->req; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(msg)) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); return; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } if (msg->REQ_METHOD==METHOD_INVITE) { LM_DBG("noisy_timer set for tracing\n"); t->flags |= T_NOISY_CTIMER_FLAG; } if(tmb.register_tmcb( 0, t, TMCB_REQUEST_BUILT, trace_onreq_out, 0) <=0) { LM_ERR("can't register trace_onreq_out\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_IN, trace_onreply_in, 0) <=0) { LM_ERR("can't register trace_onreply_in\n"); return; } if(tmb.register_tmcb( 0, t, TMCB_RESPONSE_OUT, trace_onreply_out, 0) <=0) { LM_ERR("can't register trace_onreply_out\n"); return; } }
static void trace_sl_onreply_out( unsigned int types, struct sip_msg* req, struct sl_cb_param *sl_param) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; int faked = 0; struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[5]; if(req==NULL || sl_param==NULL) { LM_ERR("bad parameters\n"); goto error; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } msg = req; faked = 1; if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = (sl_param->buffer)?sl_param->buffer->s:""; db_vals[0].val.blob_val.len = (sl_param->buffer)?sl_param->buffer->len:0; /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(sl_param->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); if(sl_param->dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, sl_param->dst); siptrace_copy_proto(req->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(sl_param->dst), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(msg) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
/*! \brief * Fills the common part (for all contacts) of the info structure */ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f, int _use_regid) { static ucontact_info_t ci; static str no_ua = str_init("n/a"); static str callid; static str path_received = {0,0}; static str path; static str received = {0,0}; static int received_found; static unsigned int allowed, allow_parsed; static struct sip_msg *m = 0; int_str val; if (_m!=0) { memset( &ci, 0, sizeof(ucontact_info_t)); /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); if (callid.len > CALLID_MAX_SIZE) { rerrno = R_CALLID_LEN; LM_ERR("callid too long\n"); goto error; } ci.callid = &callid; /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) { rerrno = R_INV_CSEQ; LM_ERR("failed to convert cseq number\n"); goto error; } /* set received socket */ if (_m->flags&sock_flag) { ci.sock = get_sock_val(_m); if (ci.sock==0) ci.sock = _m->rcv.bind_address; } else { ci.sock = _m->rcv.bind_address; } /* set tcp connection id */ if (_m->rcv.proto==PROTO_TCP || _m->rcv.proto==PROTO_TLS || _m->rcv.proto==PROTO_WS || _m->rcv.proto==PROTO_WSS) { ci.tcpconn_id = _m->rcv.proto_reserved1; } else { ci.tcpconn_id = -1; } /* additional info from message */ if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent && _m->user_agent->body.len>0 && _m->user_agent->body.len<MAX_UA_SIZE) { ci.user_agent = &_m->user_agent->body; } else { ci.user_agent = &no_ua; } /* extract Path headers */ if (path_enabled) { if (build_path_vector(_m, &path, &path_received) < 0) { rerrno = R_PARSE_PATH; goto error; } if (path.len && path.s) { ci.path = &path; if (path_mode != PATH_MODE_OFF) { /* save in msg too for reply */ if (set_path_vector(_m, &path) < 0) { rerrno = R_PARSE_PATH; goto error; } } } } ci.last_modified = act_time; /* set flags */ ci.flags = _f; getbflagsval(0, &ci.cflags); /* get received */ if (path_received.len && path_received.s) { ci.cflags |= ul.nat_flag; ci.received = path_received; } allow_parsed = 0; /* not parsed yet */ received_found = 0; /* not found yet */ m = _m; /* remember the message */ } else { memset( &ci.instance, 0, sizeof(str)); } if(_c!=0) { /* hook uri address - should be more than 'sip:' chars */ if(_c->uri.s!=NULL && _c->uri.len>4) ci.c = &_c->uri; /* Calculate q value of the contact */ if (m && m->id == q_override_msg_id) { ci.q = q_override_value; } else if (calc_contact_q(_c->q, &ci.q) < 0) { rerrno = R_INV_Q; LM_ERR("failed to calculate q\n"); goto error; } /* set expire time */ ci.expires = _e; /* Get methods of contact */ if (_c->methods) { if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { rerrno = R_PARSE; LM_ERR("failed to parse contact methods\n"); goto error; } } else { /* check on Allow hdr */ if (allow_parsed == 0) { if (m && parse_allow( m ) != -1) { allowed = get_allow_methods(m); } else { allowed = ALL_METHODS; } allow_parsed = 1; } ci.methods = allowed; } /* get received */ if (ci.received.len==0) { if (_c->received) { ci.received = _c->received->body; } else { if (received_found==0) { memset(&val, 0, sizeof(int_str)); if (rcv_avp_name.n!=0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len>RECEIVED_MAX_SIZE) { rerrno = R_CONTACT_LEN; LM_ERR("received too long\n"); goto error; } received = val.s; } else { received.s = 0; received.len = 0; } received_found = 1; } ci.received = received; } } if(_c->instance!=NULL && _c->instance->body.len>0) ci.instance = _c->instance->body; if(_use_regid && _c->instance!=NULL && _c->reg_id!=NULL && _c->reg_id->body.len>0) { if(str2int(&_c->reg_id->body, &ci.reg_id)<0 || ci.reg_id==0) { LM_ERR("invalid reg-id value\n"); goto error; } } if(sruid_next(&_reg_sruid)<0) goto error; ci.ruid = _reg_sruid.uid; LM_DBG("generated ruid is: %.*s\n", ci.ruid.len, ci.ruid.s); } return &ci; error: return 0; }
/*! \brief * Adds to request a destination set that includes all highest priority * class contacts in "serial_avp" AVP. If called from a route block, * rewrites the request uri with first contact and adds the remaining * contacts as branches. If called from failure route block, adds all * contacts as brances. Removes added contacts from "serial_avp" AVP. */ int next_branches( struct sip_msg *msg) { struct usr_avp *avp, *prev; int_str val; struct socket_info *sock_info; qvalue_t q; str uri, dst_uri, path; char *p; unsigned int flags; int rval; if (route_type != REQUEST_ROUTE && route_type != FAILURE_ROUTE ) { /* unsupported route type */ LM_ERR("called from unsupported route type %d\n", route_type); goto error; } /* Find first avp */ avp = search_first_avp(0, serial_avp, &val, 0); if (!avp) { LM_DBG("no AVPs -- we are done!\n"); goto error; } if (!val.s.s) { LM_ERR("invalid avp value\n"); goto error; } /* *sock_info, flags, q, uri, 0, dst_uri, 0, path, 0,... */ p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += uri.len + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += dst_uri.len + 1; path.s = p; path.len = strlen(p); /* Set Request-URI */ if ( set_ruri(msg, &uri) == -1 || set_dst_uri(msg, &dst_uri) == -1 || set_path_vector(msg, &path) == -1 ) goto error1; msg->force_send_socket = sock_info; set_ruri_q( q ); setb0flags( flags ); LM_DBG("Msg information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); /* Append branches until out of branches or Q_FLAG is set */ while (avp != NULL) { if (!val.s.s) { LM_ERR("invalid avp value\n"); continue; } p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += strlen(p) + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += strlen(p) + 1; path.s = p; path.len = strlen(p); LM_DBG("Branch information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); rval = append_branch(msg, &uri, &dst_uri, &path, q, flags, sock_info); if (rval == -1) { LM_ERR("append_branch failed\n"); goto error1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); } return 2; done: return (search_next_avp(avp, NULL)==NULL)?2:1; error1: destroy_avp(avp); error: return -1; }
/*! \brief * Extract Address of Record */ int extract_aor(str* _uri, str* _a) { static char aor_buf[MAX_AOR_LEN]; str tmp; struct sip_uri puri; int user_len; int_str avp_val; struct usr_avp *avp; str *uri; str realm_prefix; memset(aor_buf, 0, MAX_AOR_LEN); if (aor_avp_name.n != 0) { avp = search_first_avp(aor_avp_type, aor_avp_name, &avp_val, 0); if (avp && is_avp_str_val(avp)) { uri = &avp_val.s; } else { uri = _uri; } } else { uri = _uri; } if (parse_uri(uri->s, uri->len, &puri) < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } if ((puri.user.len + puri.host.len + 1 + 4) > MAX_AOR_LEN || puri.user.len > USERNAME_MAX_SIZE || puri.host.len > DOMAIN_MAX_SIZE) { rerrno = R_AOR_LEN; LM_ERR("Address Of Record too long\n"); return -2; } _a->s = aor_buf; _a->len = puri.user.len + 4; strncpy(_a->s, "sip:", 4); str tmps; tmps.s = _a->s + 4; tmps.len = puri.user.len; if (un_escape(&puri.user, &tmps) < 0) { rerrno = R_UNESCAPE; LM_ERR("failed to unescape username\n"); return -3; } user_len = tmps.len + 4;//_a->len; if (user_len>4) aor_buf[_a->len++] = '@'; /* strip prefix (if defined) */ realm_prefix.s = cfg_get(registrar, registrar_cfg, realm_pref); realm_prefix.len = strlen(realm_prefix.s); if (realm_prefix.len && realm_prefix.len < puri.host.len && (memcmp(realm_prefix.s, puri.host.s, realm_prefix.len) == 0)) { memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len, puri.host.len - realm_prefix.len); _a->len += puri.host.len - realm_prefix.len; } else { memcpy(aor_buf + _a->len, puri.host.s, puri.host.len); _a->len += puri.host.len; } if (cfg_get(registrar, registrar_cfg, case_sensitive) && user_len) { tmp.s = _a->s + user_len + 1; tmp.len = _a->s + _a->len - tmp.s; strlower(&tmp); } else { strlower(_a); } return 0; }
/* initiate a report if we previously enabled accounting for this t */ static inline void acc_onreply( struct cell* t, struct sip_msg *req, struct sip_msg *reply, int code) { str new_uri_bk; str dst_uri_bk; struct dlg_cell *dlg = NULL; str flags_s; int_str table; struct usr_avp *avp; /* acc_onreply is bound to TMCB_REPLY which may be called from _reply, like when FR hits; we should not miss this event for missed calls either */ if (is_invite(t) && code>=300 && is_mc_on(req) ) on_missed(t, req, reply, code); if (!should_acc_reply(req, reply, code)) return; /* for reply processing, set as new_uri the winning branch */ if (t->relaied_reply_branch>=0) { new_uri_bk = req->new_uri; dst_uri_bk = req->dst_uri; req->new_uri = t->uac[t->relaied_reply_branch].uri; req->dst_uri = t->uac[t->relaied_reply_branch].duri; req->parsed_uri_ok = 0; } else { new_uri_bk.len = dst_uri_bk.len = -1; new_uri_bk.s = dst_uri_bk.s = NULL; } /* set env variables */ env_set_to( get_rpl_to(t,reply) ); env_set_code_status( code, reply); /* search for table avp */ table.s = db_table_acc; if (db_table_name != -1 && is_db_acc_on(req)) { avp = search_first_avp(db_table_name_type, db_table_name, &table, 0); if (!avp) { LM_DBG("table not set: using default %.*s\n", db_table_acc.len, db_table_acc.s); } else { if (!(avp->flags & AVP_VAL_STR)) { LM_WARN("invalid integer table name: using default %.*s\n", db_table_acc.len, db_table_acc.s); table.s = db_table_acc; } } } if (is_invite(t) && is_cdr_acc_on(req) && code >= 200 && code < 300 && (dlg=dlg_api.get_dlg()) != NULL) { /* if dialog module loaded and INVITE and success reply */ if (store_core_leg_values(dlg, req) < 0) { LM_ERR("cannot store core and leg values\n"); return; } if(is_log_acc_on(req) && store_log_extra_values(dlg,req,reply)<0){ LM_ERR("cannot store string values\n"); return; } if(is_aaa_acc_on(req) && store_aaa_extra_values(dlg, req, reply)<0){ LM_ERR("cannot store aaa extra values\n"); return; } if (is_db_acc_on(req) && store_db_extra_values(dlg,req,reply)<0) { LM_ERR("cannot store database extra values\n"); return; } flags_s.s = (char*)&req->flags; flags_s.len = sizeof(unsigned int); /* store flags into dlg */ if ( dlg_api.store_dlg_value(dlg, &flags_str, &flags_s) < 0) { LM_ERR("cannot store flag value into dialog\n"); return; } /* store flags into dlg */ if ( dlg_api.store_dlg_value(dlg, &table_str, &table.s) < 0) { LM_ERR("cannot store the table name into dialog\n"); return; } /* register database callbacks */ if (dlg_api.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_EXPIRED, acc_dlg_callback,(void *)(long)req->flags,0) != 0) { LM_ERR("cannot register callback for database accounting\n"); return; } } else { /* do old accounting */ if ( is_log_acc_on(req) ) { env_set_text( ACC_ANSWERED, ACC_ANSWERED_LEN); acc_log_request( req, reply ); } if (is_aaa_acc_on(req)) acc_aaa_request( req, reply ); if (is_db_acc_on(req)) { env_set_text( table.s.s, table.s.len); acc_db_request( req, reply, &acc_ins_list); } } /* DIAMETER */ #ifdef DIAM_ACC if (is_diam_acc_on(req)) acc_diam_request( req, reply ); #endif if (new_uri_bk.len>=0) { req->new_uri = new_uri_bk; req->dst_uri = dst_uri_bk; req->parsed_uri_ok = 0; } }
/* * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */ static inline int insert(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a, str *ua) { urecord_t* r = 0; ucontact_t* c; int e, cseq; qvalue_t q; str callid; unsigned int flags; str* recv; int_str rcv_avp; int_str val; int num; rcv_avp.n=rcv_avp_no; if (isflagset(_m, nat_flag) == 1) flags = FL_NAT; else flags = FL_NONE; flags |= mem_only; num = 0; while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { LOG(L_ERR, "insert(): Error while calculating expires\n"); return -1; } /* Skip contacts with zero expires */ if (e == 0) goto skip; if (max_contacts && (num >= max_contacts)) { rerrno = R_TOO_MANY; ul.delete_urecord(_d, _a); return -1; } num++; if (r == 0) { if (ul.insert_urecord(_d, _a, &r) < 0) { rerrno = R_UL_NEW_R; LOG(L_ERR, "insert(): Can't insert new record structure\n"); return -2; } } /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "insert(): Error while calculating q\n"); ul.delete_urecord(_d, _a); return -3; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "insert(): Error while converting cseq number\n"); ul.delete_urecord(_d, _a); return -4; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (ul.insert_ucontact(r, &_c->uri, e, q, &callid, cseq, flags, &c, ua, recv) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "insert(): Error while inserting contact\n"); ul.delete_urecord(_d, _a); return -5; } skip: _c = get_next_contact(_c); } if (r) { if (!r->contacts) { ul.delete_urecord(_d, _a); } else { build_contact(r->contacts); } } return 0; }
int pv_get_tm_branch_avp(struct sip_msg *msg, pv_param_t *param, pv_value_t *val) { int avp_name; int_str avp_value; unsigned short name_type; int idx, idxf, res=0; struct usr_avp **old_list=NULL; struct usr_avp **avp_list=NULL; struct usr_avp *avp; int_str avp_value0; struct usr_avp *avp0; int n=0; char *p; if (!msg || !val) goto error; avp_list = get_bavp_list(); if (!avp_list) { pv_get_null(msg, param, val); goto success; } if (!param) { LM_ERR("bad parameters\n"); goto error; } if (pv_get_avp_name(msg, param, &avp_name, &name_type)) { LM_ALERT("BUG in getting bavp name\n"); goto error; } /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); goto error; } /* setting the avp head */ old_list = set_avp_list(avp_list); if (!old_list) { LM_CRIT("no bavp head list found\n"); goto error; } if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0) { pv_get_null(msg, param, val); goto success; } val->flags = PV_VAL_STR; if ( (idxf==0 || idxf==PV_IDX_INT) && idx==0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } goto success; } if(idxf==PV_IDX_ALL) { p = pv_local_buf; do { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); } if(p-pv_local_buf+val->rs.len+1>PV_LOCAL_BUF_SIZE) { LM_ERR("local buffer length exceeded!\n"); pv_get_null(msg, param, val); goto success; } memcpy(p, val->rs.s, val->rs.len); p += val->rs.len; if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) { LM_ERR("local buffer length exceeded\n"); pv_get_null(msg, param, val); goto success; } memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); p += PV_FIELD_DELIM_LEN; } while ((avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0); *p = 0; val->rs.s = pv_local_buf; val->rs.len = p - pv_local_buf; goto success; } /* we have a numeric index */ if(idx<0) { n = 1; avp0 = avp; while ((avp0=search_first_avp(name_type, avp_name, &avp_value0, avp0))!=0) n++; idx = -idx; if(idx>n) { LM_DBG("index out of range\n"); pv_get_null(msg, param, val); goto success; } idx = n - idx; if(idx==0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } goto success; } } n=0; while(n<idx && (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0) n++; if(avp!=0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } } goto success; error: res = -1; success: if (old_list) set_avp_list(old_list); return res; }
int do_load_balance(struct sip_msg *req, int grp, struct lb_res_str_list *rl, unsigned int alg, struct lb_data *data) { static struct lb_resource **call_res = NULL; static unsigned int call_res_no = 0; static unsigned int *dst_bitmap = NULL; static unsigned int bitmap_size = 0; unsigned int * used_dst_bitmap; struct lb_resource *res; int size; int i,j; unsigned int load, ld; struct lb_dst *dst; struct lb_dst *it; struct lb_dst *last_dst; struct usr_avp *grp_avp; struct usr_avp *mask_avp; struct usr_avp *id_avp; int_str grp_val; int_str mask_val; int_str id_val; /* get references to the resources */ if (rl->n>call_res_no) { call_res = (struct lb_resource**)pkg_realloc (call_res, rl->n*sizeof(struct lb_resorce*)); if (call_res==NULL) { LM_ERR("no more pkg mem - res ptr realloc\n"); return -1; } call_res_no = rl->n; } for( i=0,res=data->resources ; (i<rl->n)&&res ; res=res->next) { if (search_resource_str( rl, &res->name)) { call_res[i++] = res; LM_DBG("found requested (%d) resource %.*s\n", i-1, res->name.len,res->name.s); } } if (i!=rl->n) { LM_ERR("unknown resource in input string\n"); return -1; } /* any previous iteration due failover ? */ grp_avp = search_first_avp( 0, grp_avp_name, &grp_val, 0); mask_avp = search_first_avp( 0, mask_avp_name, &mask_val, 0); id_avp = search_first_avp( 0, id_avp_name, &id_val, 0); if ( grp_avp && mask_avp && id_avp && ((grp_avp->flags&AVP_VAL_STR)==0) && (mask_avp->flags&AVP_VAL_STR) && ((id_avp->flags&AVP_VAL_STR)==0) ) { /* not the first iteration -> use data from AVPs */ grp = grp_val.n ; used_dst_bitmap = (unsigned int*)mask_val.s.s; /* set the previous dst as used (not selected) */ for(last_dst=data->dsts,i=0,j=0 ; last_dst ; last_dst=last_dst->next) { if (last_dst->id==id_val.n) {used_dst_bitmap[i] &= ~(1<<j);break;} j++; if (j==sizeof(unsigned int)) {i++;j=0;} } } else { /* first iteration for this call */ grp_avp = mask_avp = id_avp = NULL; last_dst = NULL; /* search destinations that fulfill the resources */ for( size=(unsigned int)(-1),i=0 ; i<rl->n ; i++) { if (call_res[i]->bitmap_size<size) size = call_res[i]->bitmap_size; } if (size>bitmap_size) { dst_bitmap = (unsigned int*)pkg_realloc ( dst_bitmap, size*sizeof(unsigned int) ); if (dst_bitmap==NULL) { LM_ERR("no more pkg mem - bitmap realloc\n"); return -1; } bitmap_size = size; } memset( dst_bitmap, 0xff , size*sizeof(unsigned int) ); for( i=0 ; i<rl->n ; i++) { for( j=0 ; j<size ; j++) dst_bitmap[j] &= call_res[i]->dst_bitmap[j]; } used_dst_bitmap = dst_bitmap; /* create dialog */ if (lb_dlg_binds.create_dlg( req , 0)!=1 ) { LM_ERR("failed to create dialog\n"); return -1; } } /* end - first LB run */ /* lock the resources */ for( i=0 ; i<rl->n ; i++) get_lock( call_res[i]->lock ); /* do the load-balancing */ load = 0; dst = NULL; for( it=data->dsts,i=0,j=0 ; it ; it=it->next) { if ( (used_dst_bitmap[i] & (1<<j)) && it->group==grp && (it->flags&LB_DST_STAT_DSBL_FLAG)==0 ) { /* valid destination (resources & group & status) */ if ( (ld = get_dst_load(call_res, rl->n, it, alg)) > load) { /* computing a max */ load = ld; dst = it; } LM_DBG("destination <%.*s> selected for LB set with free=%d " "(max=%d)\n",it->uri.len, it->uri.s,ld, load); } j++; if (j==8*sizeof(unsigned int)) {i++;j=0;} } /* if re-trying, remove the dialog from previous profiles */ if (last_dst) { for( i=0 ; i<rl->n ; i++) { if (lb_dlg_binds.unset_profile( req, &last_dst->profile_id, call_res[i]->profile)!=1) LM_ERR("failed to remove from profile\n"); } } if (dst==NULL) { LM_DBG("no destination found\n"); } else { /* add to the profiles */ for( i=0 ; i<rl->n ; i++) { if (lb_dlg_binds.set_profile( req, &dst->profile_id, call_res[i]->profile)!=0) LM_ERR("failed to add to profile\n"); } } /* unlock the resources*/ for( i=0 ; i<rl->n ; i++) release_lock( call_res[i]->lock ); if (dst) { /* change (add/edit) the AVPs for the next iteration */ if (grp_avp==NULL && mask_avp==NULL) { grp_val.n = grp; if (add_avp( 0, grp_avp_name, grp_val)!=0) { LM_ERR("failed to add GRP AVP"); } mask_val.s.s = (char*)used_dst_bitmap; mask_val.s.len = bitmap_size*sizeof(unsigned int); if (add_avp( AVP_VAL_STR, mask_avp_name, mask_val)!=0) { LM_ERR("failed to add MASK AVP"); } } if (id_avp) { id_avp->data = (void*)(long)dst->id; } else { id_val.n = dst->id; if (add_avp( 0, id_avp_name, id_val)!=0) { LM_ERR("failed to add ID AVP"); } } /* set dst uri */ if (set_dst_uri( req, &dst->uri )!=0) { LM_ERR("failed to set duri\n"); return -2; } } return dst?0:-2; }
/*! * \brief Apply DP-DDDS policy to current SIP message * * Apply DP-DDDS policy to current SIP message. This means * build a new destination URI from the policy AVP and export it * as AVP. Then in kamailio.cfg this new target AVP can be pushed * into the destination URI $duri * \param _msg SIP message * \param _s1 unused * \param _s2 unused * \return negative on failure, positive on succes */ int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) { str *domain; int_str val; struct usr_avp *avp; char duri[MAX_URI_SIZE]; str duri_str; int len, didsomething; char *at; /* pointer to current location inside duri */ str host; int port, proto; struct socket_info* si; if (!is_route_type(REQUEST_ROUTE)) { LM_ERR("unsupported route type\n"); return -1; } /* * set the send_socket */ /* search for send_socket AVP */ avp = search_first_avp(send_socket_avp_name_str, send_socket_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string send_socket_avp, " "return with error ...\n"); return -1; } LM_DBG("send_socket_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); /* parse phostport - AVP str val is asciiz */ /* FIXME: This code relies on the fact that the string value of an AVP * is zero terminated, which may or may not be true in the future */ if (parse_phostport(val.s.s, &(host.s), &(host.len), &port, &proto)) { LM_ERR("could not parse send_socket, return with error ...\n"); return -1; } si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto); if (si) { set_force_socket(_msg, si); } else { LM_WARN("could not find socket for" "send_socket '%.*s'\n", val.s.len, ZSW(val.s.s)); } } else { LM_DBG("send_socket_avp not found\n"); } /* * set the destination URI */ didsomething = 0; /* if no AVP is set, there is no need to set the DURI in the end */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("failed to parse R-URI\n"); return -1; } at = (char *)&(duri[0]); len = 0; if ( (len + 4) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add uri schema\n"); return -1; } memcpy(at, "sip:", 4); at = at + 4; len = len + 4; domain = &(_msg->parsed_uri.host); LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s)); /* search for prefix and add it to duri buffer */ avp = search_first_avp(domain_prefix_avp_name_str, domain_prefix_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n"); return -1; } LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); if ( (len + val.s.len +1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain prefix\n"); return -1; } memcpy(at, val.s.s, val.s.len); at = at + val.s.len; *at = '.'; at = at + 1; /* add . as delimiter between prefix and domain */ didsomething = 1; } else { LM_DBG("domain_prefix_avp not found\n"); } /* add domain to duri buffer */ avp = search_first_avp(domain_replacement_avp_name_str, domain_replacement_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_replacement_avp, return with" "error ...\n"); return -1; } LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s)); if ( (len + val.s.len +1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain replacement\n"); return -1; } memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("domain_replacement_avp not found, using original domain '" "%.*s'\n",domain->len, domain->s); if ( (len + domain->len) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain\n"); return -1; } memcpy(at, domain->s, domain->len); at = at + domain->len; } /* search for suffix and add it to duri buffer */ avp = search_first_avp(domain_suffix_avp_name_str, domain_suffix_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string domain_suffix_avp,return with error .." "\n"); return -1; } LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); if ( (len + val.s.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain suffix\n"); return -1; } *at = '.'; at = at + 1; /* add . as delimiter between domain and suffix */ memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("domain_suffix_avp not found\n"); } /* search for port override and add it to duri buffer */ avp = search_first_avp(port_override_avp_name_str, port_override_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string port_override_avp, return with error ...\n"); return -1; } LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s)); /* We do not check if the port is valid */ if ( (len + val.s.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add domain suffix\n"); return -1; } *at = ':'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("port_override_avp not found, using original port\n"); if (_msg->parsed_uri.port.len) { LM_DBG("port found in RURI, reusing it for DURI\n"); if ( (len + _msg->parsed_uri.port.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to copy port\n"); return -1; } *at = ':'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len); at = at + _msg->parsed_uri.port.len; } else { LM_DBG("port not found in RURI, no need to copy it to DURI\n"); } } /* search for transport override and add it to duri buffer */ avp = search_first_avp(transport_override_avp_name_str, transport_override_name, &val, 0); if (avp) { if ( !(avp->flags&AVP_VAL_STR) || !val.s.s || !val.s.len) { LM_ERR("empty or non-string transport_override_avp, " "return with error ...\n"); return -1; } LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s)); if ( (len + val.s.len + 11) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to add transport override\n"); return -1; } /* add : as transport parameter to duri; NOTE: no checks if transport parameter is valid */ memcpy(at, ";transport=", 11); at = at + 11; memcpy(at, val.s.s, val.s.len); at = at + val.s.len; didsomething = 1; } else { LM_DBG("transport_override_avp not found, using original transport\n"); if (_msg->parsed_uri.transport.len) { LM_DBG("transport found in RURI, reusing it for DURI\n"); if ( (len + _msg->parsed_uri.transport.len + 1) > MAX_URI_SIZE) { LM_ERR("duri buffer to small to copy transport\n"); return -1; } *at = ';'; at = at + 1; /* add : as delimiter between domain and port */ memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len; } else { LM_DBG("transport not found in RURI, no need to copy it to DURI\n"); } } /* write new target DURI into DURI */ if (didsomething == 0) { LM_DBG("no domainpolicy AVP set, no need to push new DURI\n"); return 2; } duri_str.s = (char *)&(duri[0]); duri_str.len = at - duri_str.s; LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s)); if(set_dst_uri(_msg, &duri_str)<0) { LM_ERR("failed to se dst uri\n"); return -1; } /* dst_uri changes, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ return 1; }
/*! \brief * Fills the common part (for all contacts) of the info structure */ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f, unsigned int _flags) { static ucontact_info_t ci; static str no_ua = str_init("n/a"); static str callid; static str path_received = {0,0}; static str path; static str received = {0,0}; static int received_found; static unsigned int allowed, allow_parsed; static struct sip_msg *m = 0; static int_str attr_avp_value; static struct usr_avp *avp_attr; int_str val; if (_m!=0) { memset( &ci, 0, sizeof(ucontact_info_t)); /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); if (callid.len > CALLID_MAX_SIZE) { rerrno = R_CALLID_LEN; LM_ERR("callid too long\n"); goto error; } ci.callid = &callid; /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) { rerrno = R_INV_CSEQ; LM_ERR("failed to convert cseq number\n"); goto error; } /* set received socket */ if ( _flags®_SAVE_SOCKET_FLAG) { ci.sock = get_sock_hdr(_m); if (ci.sock==0) ci.sock = _m->rcv.bind_address; } else { ci.sock = _m->rcv.bind_address; } /* additional info from message */ if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent && _m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) { ci.user_agent = &_m->user_agent->body; } else { ci.user_agent = &no_ua; } /* extract Path headers */ if ( _flags®_SAVE_PATH_FLAG ) { if (build_path_vector(_m, &path, &path_received, _flags) < 0) { rerrno = R_PARSE_PATH; goto error; } if (path.len && path.s) { ci.path = &path; /* save in msg too for reply */ if (set_path_vector(_m, &path) < 0) { rerrno = R_PARSE_PATH; goto error; } } } ci.last_modified = act_time; /* set flags */ ci.flags = _f; ci.cflags = getb0flags(_m); /* get received */ if (path_received.len && path_received.s) { ci.cflags |= ul.nat_flag; ci.received = path_received; } allow_parsed = 0; /* not parsed yet */ received_found = 0; /* not found yet */ m = _m; /* remember the message */ } if(_c!=0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &ci.q) < 0) { rerrno = R_INV_Q; LM_ERR("failed to calculate q\n"); goto error; } /* set expire time */ ci.expires = _e; /* Get methods of contact */ if (_c->methods) { if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { rerrno = R_PARSE; LM_ERR("failed to parse contact methods\n"); goto error; } } else { /* check on Allow hdr */ if (allow_parsed == 0) { if (m && parse_allow( m ) != -1) { allowed = get_allow_methods(m); } else { allowed = ALL_METHODS; } allow_parsed = 1; } ci.methods = allowed; } if (_c->instance) { ci.instance = _c->instance->body; } /* get received */ if (ci.received.len==0) { if (_c->received) { ci.received = _c->received->body; } else { if (received_found==0) { memset(&val, 0, sizeof(int_str)); if (rcv_avp_name>=0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len>RECEIVED_MAX_SIZE) { rerrno = R_CONTACT_LEN; LM_ERR("received too long\n"); goto error; } received = val.s; } else { received.s = 0; received.len = 0; } received_found = 1; } ci.received = received; } } /* additional information (script pvar) */ if (attr_avp_name != -1) { avp_attr = search_first_avp(attr_avp_type, attr_avp_name, &attr_avp_value, NULL); if (avp_attr) { ci.attr = &attr_avp_value.s; LM_DBG("Attributes: %.*s\n", ci.attr->len, ci.attr->s); } } } return &ci; error: return 0; }
/** Get the function parameter value as string. * @return 0 - Success * -1 - Cannot get value */ int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param) { int_str val; int ret; avp_t* avp; pv_value_t pv_val; switch(param->type) { case FPARAM_REGEX: case FPARAM_UNSPEC: case FPARAM_INT: return -1; case FPARAM_STRING: dst->s = param->v.asciiz; dst->len = strlen(param->v.asciiz); break; case FPARAM_STR: *dst = param->v.str; break; case FPARAM_AVP: avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0); if (unlikely(!avp)) { LM_DBG("Could not find AVP from function parameter '%s'\n", param->orig); return -1; } if (likely(avp->flags & AVP_VAL_STR)) { *dst = val.s; } else { /* The caller does not know of what type the AVP will be so * convert int AVPs into string here */ dst->s = int2str(val.n, &dst->len); } break; case FPARAM_SELECT: ret = run_select(dst, param->v.select, msg); if (unlikely(ret < 0 || ret > 0)) return -1; break; case FPARAM_PVS: if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) && ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR))){ *dst=pv_val.rs; }else{ LM_ERR("Could not convert PV to str\n"); return -1; } break; case FPARAM_PVE: dst->s=pv_get_buffer(); dst->len=pv_get_buffer_size(); if (unlikely(pv_printf(msg, param->v.pve, dst->s, &dst->len)!=0)){ LM_ERR("Could not convert the PV-formated string to str\n"); dst->len=0; return -1; }; break; } return 0; }
int evi_raise_script_event(event_id_t id, void * _a, void * _v) { pv_spec_p vals = (pv_spec_p)_v; pv_spec_p attrs = (pv_spec_p)_a; struct usr_avp *v_avp = NULL; struct usr_avp *a_avp = NULL; int err = evi_probe_event(id); int_str val, attr; str *at; evi_params_p params = NULL; if (err < 0) return err; else if (!err) return 1; if (!vals) goto raise; if (!(params = evi_get_params())) { LM_ERR("cannot create parameters list\n"); goto raise; } /* handle parameters */ while ((v_avp = search_first_avp(vals->pvp.pvn.u.isname.type, vals->pvp.pvn.u.isname.name.n, &val, v_avp))) { at = NULL; /* check attribute */ if (attrs) { err = -1; a_avp = search_first_avp(attrs->pvp.pvn.u.isname.type, attrs->pvp.pvn.u.isname.name.n, &attr, a_avp); if (!a_avp) { LM_ERR("missing attribute\n"); goto error; } if (!(a_avp->flags & AVP_VAL_STR)) { LM_ERR("invalid attribute name - must be string\n"); goto error; } at = &attr.s; } if (v_avp->flags & AVP_VAL_STR) err = evi_param_add_str(params, at, &val.s); else err = evi_param_add_int(params, at, &val.n); if (err) { LM_ERR("error while adding parameter\n"); goto error; } } /* check if there were too many attribute names */ if (attrs && a_avp && search_first_avp(attrs->pvp.pvn.u.isname.type, attrs->pvp.pvn.u.isname.name.n, &attr, a_avp)) { /* only signal error - continue */ LM_ERR("too many attribute names\n"); } raise: err = evi_raise_event(id, params); return err ? err : 1; error: evi_free_params(params); return -1; }
/** Get the function parameter value as integer. * @return 0 - Success * -1 - Cannot get value */ int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param) { int_str val; int ret; avp_t* avp; str tmp; pv_value_t pv_val; switch(param->type) { case FPARAM_INT: *dst = param->v.i; return 0; case FPARAM_REGEX: case FPARAM_UNSPEC: case FPARAM_STRING: case FPARAM_STR: LM_ERR("Unsupported param type for int value: %d\n", param->type); return -1; case FPARAM_AVP: avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0); if (unlikely(!avp)) { LM_DBG("Could not find AVP from function parameter '%s'\n", param->orig); return -1; } if (avp->flags & AVP_VAL_STR) { if (str2int(&val.s, (unsigned int*)dst) < 0) { LM_ERR("Could not convert AVP string value to int\n"); return -1; } } else { *dst = val.n; } break; case FPARAM_SELECT: ret = run_select(&tmp, param->v.select, msg); if (unlikely(ret < 0 || ret > 0)) return -1; if (unlikely(str2int(&tmp, (unsigned int*)dst) < 0)) { LM_ERR("Could not convert select result to int\n"); return -1; } break; case FPARAM_PVS: if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) && ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT))){ *dst=pv_val.ri; }else{ LM_ERR("Could not convert PV to int\n"); return -1; } break; case FPARAM_PVE: LM_ERR("Unsupported param type for int value: %d\n", param->type); return -1; default: LM_ERR("Unexpected param type: %d\n", param->type); return -1; } return 0; }
static void trace_msg_out(struct sip_msg* msg, str *sbuf, struct socket_info* send_sock, int proto, union sockaddr_union *to) { static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; avp = NULL; if(traced_user_avp>=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if ( (avp==NULL) && !flag_trace_is_set(msg) ) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } LM_DBG("trace msg out \n"); if(sbuf!=NULL && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else { db_vals[0].val.blob_val.s = "No request buffer"; db_vals[0].val.blob_val.len = sizeof("No request buffer")-1; } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; if(sbuf!=NULL && sbuf->len > 7 && !strncasecmp(sbuf->s, "CANCEL ", 7)) { db_vals[2].val.str_val.s = "CANCEL"; db_vals[2].val.str_val.len = 6; } else { db_vals[2].val.str_val= REQ_LINE(msg).method; } db_vals[3].val.str_val.s = ""; db_vals[3].val.str_val.len = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); if (trace_local_ip.s && trace_local_ip.len > 0){ set_columns_to_trace_local_ip( db_vals[4], db_vals[5], db_vals[6]); } else { if(send_sock==0 || send_sock->sock_str.s==0) { set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff, &msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto); } else { char *nbuff = proto2str(send_sock->proto,fromip_buff); db_vals[4].val.str_val.s = fromip_buff; db_vals[4].val.str_val.len = nbuff - fromip_buff; db_vals[5].val.str_val = send_sock->address_str; db_vals[6].val.int_val = send_sock->port_no; } } if(to==0) { set_columns_to_any(db_vals[7], db_vals[8], db_vals[9]); } else { su2ip_addr(&to_ip, to); set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff, &to_ip, (unsigned short)su_getport(to), proto); } db_vals[10].val.time_val = time(NULL); db_vals[11].val.string_val = "out"; db_vals[12].val.str_val.s = get_from(msg)->tag_value.s; db_vals[12].val.str_val.len = get_from(msg)->tag_value.len; if (save_siptrace(msg,avp,&avp_value,db_keys,db_vals) < 0) { LM_ERR("failed to save siptrace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_req, 1); #endif return; error: return; }
/** Get the function parameter value as string or/and integer (if possible). * @return 0 - Success * -1 - Cannot get value */ int get_is_fparam(int* i_dst, str* s_dst, struct sip_msg* msg, fparam_t* param, unsigned int *flags) { int_str val; int ret; avp_t* avp; str tmp; pv_value_t pv_val; *flags = 0; switch(param->type) { case FPARAM_INT: *i_dst = param->v.i; *flags |= PARAM_INT; return 0; case FPARAM_REGEX: case FPARAM_UNSPEC: case FPARAM_STRING: s_dst->s = param->v.asciiz; s_dst->len = strlen(param->v.asciiz); *flags |= PARAM_STR; break; case FPARAM_STR: *s_dst = param->v.str; *flags |= PARAM_STR; break; case FPARAM_AVP: avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0); if (unlikely(!avp)) { LM_DBG("Could not find AVP from function parameter '%s'\n", param->orig); return -1; } if (avp->flags & AVP_VAL_STR) { *s_dst = val.s; *flags |= PARAM_STR; if (str2int(&val.s, (unsigned int*)i_dst) < 0) { LM_ERR("Could not convert AVP string value to int\n"); return -1; } } else { *i_dst = val.n; *flags |= PARAM_INT; } break; case FPARAM_SELECT: ret = run_select(&tmp, param->v.select, msg); if (unlikely(ret < 0 || ret > 0)) return -1; if (unlikely(str2int(&tmp, (unsigned int*)i_dst) < 0)) { LM_ERR("Could not convert select result to int\n"); return -1; } *flags |= PARAM_INT; break; case FPARAM_PVS: if (likely(pv_get_spec_value(msg, param->v.pvs, &pv_val)==0)) { if ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT){ *i_dst=pv_val.ri; *flags |= PARAM_INT; } if ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR){ *s_dst=pv_val.rs; *flags |= PARAM_STR; } }else{ LM_ERR("Could not get PV\n"); return -1; } break; case FPARAM_PVE: s_dst->s=pv_get_buffer(); s_dst->len=pv_get_buffer_size(); if (unlikely(pv_printf(msg, param->v.pve, s_dst->s, &s_dst->len)!=0)){ LM_ERR("Could not convert the PV-formated string to str\n"); s_dst->len=0; return -1; } *flags |= PARAM_STR; break; } /* Let's convert to int, if possible */ if (!(*flags & PARAM_INT) && (*flags & PARAM_STR) && str2sint(s_dst, i_dst) == 0) *flags |= PARAM_INT; if (!*flags) return -1; return 0; }
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps) { int faked = 0; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[8]; str *sbuf; struct dest_info *dst; if (t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } LM_DBG("trace onreply out \n"); avp = NULL; if(traced_user_avp>=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); req = ps->req; msg = ps->rpl; if(msg==NULL || msg==FAKED_REPLY) { msg = t->uas.request; faked = 1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } sbuf = (str*)ps->extra1; if(faked==0) { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s!=NULL) { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } else if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } } else { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s==NULL) { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } else { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; if(trace_local_ip.s && trace_local_ip.len > 0){ set_columns_to_trace_local_ip(db_vals[4], db_vals[5], db_vals[6]); } else { set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff, &msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto); } strcpy(statusbuf, int2str(ps->code, &len)); db_vals[3].val.str_val.s = statusbuf; db_vals[3].val.str_val.len = len; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = (struct dest_info*)ps->extra2; if(dst==0) { set_columns_to_any( db_vals[7], db_vals[8], db_vals[9]); } else { su2ip_addr(&to_ip, &dst->to); set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff, &to_ip, (unsigned long)su_getport(&dst->to), dst->proto); } db_vals[10].val.time_val = time(NULL); db_vals[11].val.string_val = "out"; db_vals[12].val.str_val.s = get_from(msg)->tag_value.s; db_vals[12].val.str_val.len = get_from(msg)->tag_value.len; if (save_siptrace(req,avp,&avp_value,db_keys,db_vals) < 0) { LM_ERR("failed to save siptrace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif return; error: return; }
inline static struct proxy_l* t_protoaddr2proxy(char *proto_par, char *addr_par) { struct proxy_l *proxy = 0; avp_t* avp; avp_value_t val; int proto, port, err; str s; char *c; switch(((fparam_t *)proto_par)->type) { case FPARAM_AVP: if (!(avp = search_first_avp(((fparam_t *)proto_par)->v.avp.flags, ((fparam_t *)proto_par)->v.avp.name, &val, 0))) { proto = PROTO_NONE; } else { if (avp->flags & AVP_VAL_STR) { proto = str2proto(val.s.s, val.s.len); } else { proto = val.n; } } break; case FPARAM_INT: proto = ((fparam_t *)proto_par)->v.i; break; case FPARAM_STRING: proto = str2proto( ((fparam_t *)proto_par)->v.asciiz, strlen(((fparam_t *)proto_par)->v.asciiz)); break; default: ERR("BUG: Invalid proto parameter value in t_protoaddr2proxy\n"); return 0; } switch(((fparam_t *)addr_par)->type) { case FPARAM_AVP: if (!(avp = search_first_avp(((fparam_t *)addr_par)->v.avp.flags, ((fparam_t *)addr_par)->v.avp.name, &val, 0))) { s.len = 0; } else { if ((avp->flags & AVP_VAL_STR) == 0) { LOG(L_ERR, "tm:t_protoaddr2proxy: avp <%.*s> value is not string\n", ((fparam_t *)addr_par)->v.avp.name.s.len, ((fparam_t *)addr_par)->v.avp.name.s.s); return 0; } s = val.s; } break; case FPARAM_STRING: s.s = ((fparam_t *) addr_par)->v.asciiz; s.len = strlen(s.s); break; default: ERR("BUG: Invalid addr parameter value in t_protoaddr2proxy\n"); return 0; } port = 5060; if (s.len) { c = memchr(s.s, ':', s.len); if (c) { port = str2s(c+1, s.len-(c-s.s+1), &err); if (err!=0) { LOG(L_ERR, "tm:t_protoaddr2proxy: bad port number <%.*s>\n", s.len, s.s); return 0; } s.len = c-s.s; } } if (!s.len) { LOG(L_ERR, "tm: protoaddr2proxy: host name is empty\n"); return 0; } proxy=mk_proxy(&s, port, proto); if (proxy==0) { LOG(L_ERR, "tm: protoaddr2proxy: bad host name in URI <%.*s>\n", s.len, s.s ); return 0; } return proxy; }
static int trace_dialog(struct sip_msg *msg) { unsigned char n; struct dlg_cell* dlg; struct usr_avp *avp; static int_str avp_value; str *name; if (!msg) { LM_ERR("no msg specified\n"); return -1; } if (trace_is_off()) { LM_DBG("Trace if off...\n"); return -1; } /* any need to do tracing here ? check the triggers */ avp = traced_user_avp<0 ? NULL : search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if (avp==NULL && (msg->flags&trace_flag)==0) { LM_DBG("Nothing to trace here\n"); return -1; } if (dlgb.create_dlg(msg,0)<1) { LM_ERR("failed to create dialog\n"); return -1; } dlg = dlgb.get_dlg(); if (dlg==NULL) { LM_CRIT("BUG: no dialog found after create dialog\n"); return -1; } if(dlgb.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_TERMINATED, trace_transaction,0,0)!=0) { LM_ERR("failed to register dialog callback\n"); return -1; } /* store in dialog the user avps for tracing ; we will restore them for each transactin from the dialog */ if(traced_user_avp>=0) { n = 0; while(avp!=NULL) { /* generate a name */ name = generate_val_name(n); if (!is_avp_str_val(avp)) avp_value.s.s=int2str(avp_value.n, &avp_value.s.len); /* add the avp value as dialog var */ dlgb.store_dlg_value( dlg, name, &avp_value.s); /* next avp */ avp = search_next_avp( avp, &avp_value); n++; } } /* set the flag to trace the rest of the transaction */ if (msg->flags&trace_flag) { avp_value.s.s = "1"; avp_value.s.len = 1; dlgb.store_dlg_value( dlg, &st_flag_val, &avp_value.s); } /* trace current request */ sip_trace(msg); /* we also want to catch the incoming cancel */ if ( tmb.register_tmcb( msg, NULL,TMCB_TRANS_CANCELLED, siptrace_dlg_cancel, NULL, NULL)<0 ) { LM_ERR("failed to register trans cancelled TMCB\n"); } return 1; }
/* * Adds to request a new destination set that includes all highest * priority class contacts in contacts_avp. Request URI is rewritten with * first contact and the remaining contacts (if any) are added as branches. * Removes used contacts from contacts_avp. Returns 1, if contacts_avp * was not empty and a destination set was successfully added. Returns -2, * if contacts_avp was empty and thus there was nothing to do. * Returns -1 in case of an error. */ int t_next_contacts(struct sip_msg* msg, char* key, char* value) { struct usr_avp *avp, *prev; int_str val; str uri, dst, path; struct socket_info *sock; unsigned int flags; struct search_state st; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Load Request-URI and branches */ /* Find first contacts_avp value */ avp = search_first_avp(contacts_avp_type, contacts_avp, &val, &st); if (!avp) { LM_DBG("no AVPs - we are done!\n"); return -2; } LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } /* Rewrite Request-URI */ rewrite_uri(msg, &uri); if (dst.s && dst.len) set_dst_uri(msg, &dst); else reset_dst_uri(msg); if (path.s && path.len) set_path_vector(msg, &path); else reset_path_vector(msg); set_force_socket(msg, sock); setbflagsval(0, flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } /* Append branches until out of branches or Q_FLAG is set */ prev = avp; while ((avp = search_next_avp(&st, &val))) { destroy_avp(prev); LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) { LM_ERR("appending branch failed\n"); destroy_avp(avp); return -1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } prev = avp; } destroy_avp(prev); return 1; }