int dlg_create_dialog(struct cell* t, struct sip_msg *req,unsigned int flags) { struct dlg_cell *dlg; str s; int extra_ref; /* module is stricly designed for dialog calls */ if (req->first_line.u.request.method_value!=METHOD_INVITE) return -1; if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) { LM_ERR("bad request or missing TO hdr :-/\n"); return -1; } s = get_to(req)->tag_value; if (s.s!=0 && s.len!=0) return -1; if ( parse_from_header(req)) { LM_ERR("bad request or missing FROM hdr :-/\n"); return -1; } if ((!req->callid && parse_headers(req,HDR_CALLID_F,0)<0) || !req->callid){ LM_ERR("bad request or missing CALLID hdr :-/\n"); return -1; } s = req->callid->body; trim(&s); /* some sanity checks */ if (s.len==0 || get_from(req)->tag_value.len==0) { LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n", s.len, get_from(req)->tag_value.len); return -1; } dlg = build_new_dlg( &s /*callid*/, &(get_from(req)->uri) /*from uri*/, &(get_to(req)->uri) /*to uri*/, &(get_from(req)->tag_value)/*from_tag*/ ); if (dlg==0) { LM_ERR("failed to create new dialog\n"); return -1; } dlg->flags |= flags; /* save caller's tag, cseq, contact and record route*/ if (init_leg_info(dlg, req, t, &(get_from(req)->tag_value),NULL,NULL ) !=0) { LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); return -1; } /* set current dialog */ set_current_dialog(dlg); last_dst_leg = DLG_FIRST_CALLEE_LEG; extra_ref=2; /* extra ref for the callback and current dlg hook */ if (dlg_db_mode == DB_MODE_DELAYED) extra_ref++; /* extra ref for the timer to delete the dialog */ link_dlg( dlg , extra_ref); if ( seq_match_mode!=SEQ_MATCH_NO_ID && add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) { LM_ERR("failed to add RR param\n"); goto error; } if ( d_tmb.register_tmcb( req, t, TMCB_RESPONSE_PRE_OUT|TMCB_RESPONSE_FWDED|TMCB_TRANS_CANCELLED, dlg_onreply, (void*)dlg, unreference_dialog_create)<0 ) { LM_ERR("failed to register TMCB\n"); goto error; } /* complete the dialog setup only if transaction aleady exists; if not, wait for the TMCB_REQUEST_IN callback to do this job */ if (t) { /* first INVITE seen (dialog created, unconfirmed) */ run_create_callbacks( dlg, req); LM_DBG("t hash_index = %u, t label = %u\n",t->hash_index,t->label); dlg->initial_t_hash_index = t->hash_index; dlg->initial_t_label = t->label; dlg->lifetime = get_dlg_timeout(req); t->dialog_ctx = (void*) dlg; dlg->flags |= DLG_FLAG_ISINIT; } if_update_stat( dlg_enable_stats, processed_dlgs, 1); return 0; error: unref_dlg(dlg,2); dialog_cleanup( req, NULL); if_update_stat(dlg_enable_stats, failed_dlgs, 1); return -1; }
static void trace_sl_onreply_out(sl_cbp_t *slcbp) { sip_msg_t *req; struct _siptrace_data sto; struct sip_msg* msg; struct ip_addr to_ip; int len; char statusbuf[5]; if(slcbp==NULL || slcbp->req==NULL) { LM_ERR("bad parameters\n"); return; } req = slcbp->req; memset(&sto, 0, sizeof(struct _siptrace_data)); if(traced_user_avp.n!=0) sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp, &sto.avp_value, &sto.state); if((sto.avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } msg = req; if(sip_trace_prepare(msg)<0) return; sto.body.s = (slcbp->reply)?slcbp->reply->s:""; sto.body.len = (slcbp->reply)?slcbp->reply->len:0; sto.callid = msg->callid->body; sto.method = msg->first_line.u.request.method; if(trace_local_ip.len > 0) { sto.fromip = trace_local_ip; } else { siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff); strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(sto.fromip_buff,":"); strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL)); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); } strcpy(statusbuf, int2str(slcbp->code, &sto.status.len)); sto.status.s = statusbuf; memset(&to_ip, 0, sizeof(struct ip_addr)); if(slcbp->dst==0) { sto.toip.s = "any:255.255.255.255"; sto.toip.len = 19; } else { su2ip_addr(&to_ip, &slcbp->dst->to); siptrace_copy_proto(req->rcv.proto, sto.toip_buff); strcat(sto.toip_buff, ip_addr2a(&to_ip)); strcat(sto.toip_buff, ":"); strcat(sto.toip_buff, int2str((unsigned long)su_getport(&slcbp->dst->to), &len)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); } sto.dir = "out"; sto.fromtag = get_from(msg)->tag_value; sto.totag = get_to(msg)->tag_value; #ifdef STATISTICS sto.stat = siptrace_rpl; #endif sip_trace_store(&sto, NULL); return; }
static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir) { struct _siptrace_data sto; struct onsend_info *snd_inf = NULL; if (dst){ if (dst->send_sock == 0){ dst->send_sock=get_send_socket(0, &dst->to, dst->proto); if (dst->send_sock==0){ LM_ERR("can't forward to af %d, proto %d no corresponding" " listening socket\n", dst->to.s.sa_family, dst->proto); return -1; } } } if(msg==NULL) { LM_DBG("nothing to trace\n"); return -1; } memset(&sto, 0, sizeof(struct _siptrace_data)); if(traced_user_avp.n!=0) sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp, &sto.avp_value, &sto.state); if((sto.avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) { LM_DBG("trace off...\n"); return -1; } if(sip_trace_prepare(msg)<0) return -1; sto.callid = msg->callid->body; if(msg->first_line.type==SIP_REQUEST) { sto.method = msg->first_line.u.request.method; } else { if(parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq==NULL || msg->cseq->parsed==NULL) { LM_ERR("cannot parse cseq header\n"); return -1; } sto.method = get_cseq(msg)->method; } if(msg->first_line.type==SIP_REPLY) { sto.status = msg->first_line.u.reply.status; } else { sto.status.s = ""; sto.status.len = 0; } snd_inf=get_onsend_info(); if(snd_inf==NULL) { sto.body.s = msg->buf; sto.body.len = msg->len; siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff); strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(sto.fromip_buff,":"); strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL)); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); siptrace_copy_proto(msg->rcv.proto, sto.toip_buff); strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(sto.toip_buff,":"); strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); sto.dir = (dir)?dir:"in"; } else { sto.body.s = snd_inf->buf; sto.body.len = snd_inf->len; strncpy(sto.fromip_buff, snd_inf->send_sock->sock_str.s, snd_inf->send_sock->sock_str.len); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); siptrace_copy_proto(snd_inf->send_sock->proto, sto.toip_buff); strcat(sto.toip_buff, suip2a(snd_inf->to, sizeof(*snd_inf->to))); strcat(sto.toip_buff,":"); strcat(sto.toip_buff, int2str((int)su_getport(snd_inf->to), NULL)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); sto.dir = "out"; } sto.fromtag = get_from(msg)->tag_value; sto.totag = get_to(msg)->tag_value; #ifdef STATISTICS if(msg->first_line.type==SIP_REPLY) { sto.stat = siptrace_rpl; } else { sto.stat = siptrace_req; } #endif return sip_trace_store(&sto, dst); }
/*mulit-thread sorting words */ int sortwords_multi(struct word * wlist_head) { pthread_t id[THREAD_NUM]; int nums = wlist_head->len; struct thread_args * targs[THREAD_NUM]; struct thread_args * leftarg; void * res; int ret = -1; int i = 0; int period = nums/THREAD_NUM; int left = nums % THREAD_NUM; struct word * word_list = wlist_head->next; struct merge_node * one=NULL,*two=NULL, *m=NULL; struct timeval begin,end; #ifdef TIME_SORT gettimeofday(&begin, NULL); #endif for(i = 0; i < THREAD_NUM; i++) { targs[i] = calloc(1,sizeof(struct thread_args)); if(targs[i] == NULL) { printf("calloc fail\n"); } word_list[(i+1)*period - 1].next = NULL; targs[i]->begin = 0; targs[i]->end = period-1; targs[i]->tid = i+1; targs[i]->mege.word_list = &word_list[i*period]; ret = pthread_create(&id[i],NULL,qsort_thread,targs[i]); if(ret<0) { printf("pthread create error %d\n",i); } } if(left!=0) { //print("pid %d, left=%d, begin:%d, end:%d \n",0,left, i*period, nums-1); leftarg = calloc(1,sizeof(struct thread_args)); if(leftarg == NULL) { printf("calloc fail\n"); } leftarg->begin = 0; leftarg->end = nums - i*period - 1; leftarg->mege.word_list = &word_list[i*period]; qsort_thread(leftarg); } for(i = 0; i < THREAD_NUM; i++) { ret = pthread_join(id[i],NULL); } #ifdef TIME_SORT gettimeofday(&end, NULL); usetime(&end, &begin, SORT); #endif #ifdef TIME_MEGRE gettimeofday(&begin, NULL); #endif // merge while(1){ if(g_list == NULL) { break; } if(one == NULL) { one = get_from(); continue; } else { two = get_from(); } if( one != NULL && two != NULL) { m = merge(one->word_list,two->word_list); one->word_list = m; wlist_head->next = m; insert_into(one); one = two = NULL; } } #ifdef TIME_MEGRE gettimeofday(&end, NULL); usetime(&end, &begin, MEGRE); #endif }
/*! * \brief Create a new dialog from a sip message * * Create a new dialog from a SIP message, register a callback * to keep track of the dialog with help of the tm module. * This function is either called from the request callback, or * from the dlg_manage function in the configuration script. * \see dlg_onreq * \see w_dlg_manage * \param req SIP message * \param t transaction * \param run_initial_cbs if set zero, initial callbacks are not executed * \return 0 on success, -1 on failure */ int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs) { dlg_cell_t *dlg; str s; str callid; str ftag; str ttag; str req_uri; unsigned int dir; int mlock; dlg = dlg_get_ctx_dialog(); if(dlg != NULL) { dlg_release(dlg); return -1; } if(req->first_line.u.request.method_value != METHOD_INVITE) return -1; if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) { LM_WARN("pre-matching failed\n"); return -1; } if(ttag.s!=0 && ttag.len!=0) return -1; if(pv_printf_s(req, ruri_param_model, &req_uri)<0) { LM_ERR("error - cannot print the r-uri format\n"); return -1; } trim(&req_uri); dir = DLG_DIR_NONE; mlock = 1; /* search dialog by SIP attributes * - if not found, hash table slot is left locked, to avoid races * to add 'same' dialog on parallel forking or not-handled-yet * retransmissions. Release slot after linking new dialog */ dlg = search_dlg(&callid, &ftag, &ttag, &dir); if(dlg) { mlock = 0; if (detect_spirals) { if (spiral_detected == 1) return 0; if ( dlg->state != DLG_STATE_DELETED ) { LM_DBG("Callid '%.*s' found, must be a spiraled request\n", callid.len, callid.s); spiral_detected = 1; if (run_initial_cbs) run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0); /* set ctx dlg id shortcuts */ _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; /* search_dlg() has incremented the ref count by 1 */ dlg_release(dlg); return 0; } dlg_release(dlg); } } spiral_detected = 0; dlg = build_new_dlg (&callid /*callid*/, &(get_from(req)->uri) /*from uri*/, &(get_to(req)->uri) /*to uri*/, &ftag/*from_tag*/, &req_uri /*r-uri*/ ); if (dlg==0) { if(likely(mlock==1)) dlg_hash_release(&callid); LM_ERR("failed to create new dialog\n"); return -1; } /* save caller's tag, cseq, contact and record route*/ if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG, &(get_from(req)->tag_value)) !=0) { if(likely(mlock==1)) dlg_hash_release(&callid); LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); return -1; } /* Populate initial varlist: */ dlg->vars = get_local_varlist_pointer(req, 1); /* if search_dlg() returned NULL, slot was kept locked */ link_dlg(dlg, 0, mlock); if(likely(mlock==1)) dlg_hash_release(&callid); dlg->lifetime = get_dlg_timeout(req); s.s = _dlg_ctx.to_route_name; s.len = strlen(s.s); dlg_set_toroute(dlg, &s); dlg->sflags |= _dlg_ctx.flags; dlg->iflags |= _dlg_ctx.iflags; if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0) dlg->iflags |= DLG_IFLAG_TIMEOUTBYE; if (run_initial_cbs) run_create_callbacks( dlg, req); /* first INVITE seen (dialog created, unconfirmed) */ if ( seq_match_mode!=SEQ_MATCH_NO_ID && add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) { LM_ERR("failed to add RR param\n"); goto error; } if_update_stat( dlg_enable_stats, processed_dlgs, 1); _dlg_ctx.cpid = my_pid(); _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; set_current_dialog(req, dlg); return 0; error: if (!spiral_detected) dlg_unref(dlg, 1); // undo ref regarding linking return -1; }
/*! * \brief Create a new dialog from a sip message * * Create a new dialog from a SIP message, register a callback * to keep track of the dialog with help of the tm module. * This function is either called from the request callback, or * from the dlg_manage function in the configuration script. * \see dlg_onreq * \see w_dlg_manage * \param req SIP message * \param t transaction * \param run_initial_cbs if set zero, initial callbacks are not executed * \return 0 on success, -1 on failure */ int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs) { dlg_cell_t *dlg; str s; str callid; str ftag; str ttag; str req_uri; unsigned int dir; dlg = dlg_get_ctx_dialog(); if(dlg != NULL) { dlg_release(dlg); return -1; } if(req->first_line.u.request.method_value != METHOD_INVITE) return -1; if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) { LM_WARN("pre-matching failed\n"); return -1; } if(ttag.s!=0 && ttag.len!=0) return -1; if(pv_printf_s(req, ruri_param_model, &req_uri)<0) { LM_ERR("error - cannot print the r-uri format\n"); return -1; } trim(&req_uri); if (detect_spirals) { if (spiral_detected == 1) return 0; dir = DLG_DIR_NONE; dlg = get_dlg(&callid, &ftag, &ttag, &dir); if (dlg) { if ( dlg->state != DLG_STATE_DELETED ) { LM_DBG("Callid '%.*s' found, must be a spiraled request\n", callid.len, callid.s); spiral_detected = 1; if (run_initial_cbs) run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0); /* get_dlg() has incremented the ref count by 1 * - it's ok, dlg will be unref at the end of function */ goto finish; } dlg_release(dlg); } } spiral_detected = 0; dlg = build_new_dlg (&callid /*callid*/, &(get_from(req)->uri) /*from uri*/, &(get_to(req)->uri) /*to uri*/, &ftag/*from_tag*/, &req_uri /*r-uri*/ ); if (dlg==0) { LM_ERR("failed to create new dialog\n"); return -1; } /* save caller's tag, cseq, contact and record route*/ if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG, &(get_from(req)->tag_value)) !=0) { LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); return -1; } /* Populate initial varlist: */ dlg->vars = get_local_varlist_pointer(req, 1); link_dlg(dlg, 0); dlg->lifetime = get_dlg_timeout(req); s.s = _dlg_ctx.to_route_name; s.len = strlen(s.s); dlg_set_toroute(dlg, &s); dlg->sflags |= _dlg_ctx.flags; dlg->iflags |= _dlg_ctx.iflags; if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0) dlg->iflags |= DLG_IFLAG_TIMEOUTBYE; if (run_initial_cbs) run_create_callbacks( dlg, req); /* first INVITE seen (dialog created, unconfirmed) */ if ( seq_match_mode!=SEQ_MATCH_NO_ID && add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) { LM_ERR("failed to add RR param\n"); goto error; } /* new dlg - reference it once more for current dialog iuid shortcut */ dlg_ref(dlg, 1); if_update_stat( dlg_enable_stats, processed_dlgs, 1); finish: _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; set_current_dialog(req, dlg); dlg_release(dlg); return 0; error: if (!spiral_detected) dlg_unref(dlg, 1); // undo ref regarding linking return -1; }
/* * Send Radius request to verify source. */ int verify_source(struct sip_msg* _msg, char* s1, char* s2) { aaa_message *send = NULL, *received = NULL; struct hdr_field *hf; uint32_t service; /* Add Request-URI host A_USER_NAME and user as A_SIP_URI_USER */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing Request-URI\n"); return -1; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth\n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _msg->parsed_uri.host.s, _msg->parsed_uri.host.len, 0)) { LM_ERR("error adding PW_USER_NAME\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], _msg->parsed_uri.user.s, _msg->parsed_uri.user.len, 0)) { LM_ERR("error adding PW_SIP_URI_USER\n"); goto err; } /* Add From Tag */ if (parse_from_header(_msg) < 0) { LM_ERR("error while parsing From header field\n"); goto err; } if (_msg->from == NULL || get_from(_msg) == NULL || get_from(_msg)->tag_value.s == NULL || get_from(_msg)->tag_value.len <= 0) { LM_ERR("error while accessing From header tag\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_FROM_TAG], get_from(_msg)->tag_value.s, get_from(_msg)->tag_value.len, 0)) { LM_ERR("error adding PW_SIP_FROM_TAG\n"); goto err; } /* Add Call-Id */ if (parse_headers(_msg, HDR_CALLID_F, 0) == -1 || _msg->callid == NULL || _msg->callid->body.s == NULL || _msg->callid->body.len <= 0) { LM_ERR("error while accessing Call-Id\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_CALL_ID], _msg->callid->body.s, _msg->callid->body.len, 0)) { LM_ERR("error adding PW_SIP_CALL_ID\n"); goto err; } /* Add P-Request-Hash header body */ if (parse_headers(_msg, HDR_EOH_F, 0) < 0) { LM_ERR("cannot pase message!\n"); goto err; } hf = get_header_by_static_name( _msg, "P-Request-Hash"); if (!hf) { LM_ERR("no P-Request-Hash header field\n"); goto err; } if (hf->body.s == NULL || hf->body.len <= 0) { LM_ERR("error while accessing P-Request-Hash body\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_REQUEST_HASH], hf->body.s, hf->body.len, 0)) { LM_ERR("error adding PW_SIP_REQUEST_HASH\n"); goto err; } /* Add Service-Type */ service = vals[V_SIP_VERIFY_SOURCE].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { LM_ERR("error adding PW_SERVICE_TYPE\n"); goto err; } /* Send Request and generate AVPs of positive reply */ if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } LM_DBG("failure\n"); err: if (send) proto.destroy_aaa_message(conn, send); if (received) proto.destroy_aaa_message(conn, received); return -1; }
/* change the r-uri if it is a PSTN format */ static int prefix2domain(struct sip_msg* msg, int mode, int sd_en) { str *d, p, all={"*",1}; int plen; struct sip_uri uri; if(msg==NULL) { LM_ERR("received null msg\n"); return -1; } /* parse the uri, if not yet */ if(msg->parsed_uri_ok==0) if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the R-URI\n"); return -1; } /* if the user part begin with the prefix for PSTN users, extract the code*/ if (msg->parsed_uri.user.len<=0) { LM_DBG("user part of the message is empty\n"); return -1; } if(prefix.len>0) { if (msg->parsed_uri.user.len<=prefix.len) { LM_DBG("user part is less than prefix\n"); return -1; } if(strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } } if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len && strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } p.s = msg->parsed_uri.user.s + prefix.len; p.len = msg->parsed_uri.user.len - prefix.len; lock_start_read( pdt_lock ); if(sd_en==2) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } } else if(sd_en==1) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("ERROR cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } else { /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } /* update the new uri */ if(update_new_uri(msg, plen, d, mode)<0) { LM_ERR("new_uri cannot be updated\n"); goto error; } lock_stop_read( pdt_lock ); return 1; error: lock_stop_read( pdt_lock ); return -1; }
/* * Check if from user is a valid enum based user, and check to make sure * that the src_ip == an srv record that maps to the enum from user. */ int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service) { struct ip_addr addr; struct hostent* he; unsigned short zp; unsigned short proto; char *user_s; int user_len, i, j; char name[MAX_DOMAIN_SIZE]; char uri[MAX_URI_SIZE]; struct sip_uri *furi; struct sip_uri luri; struct rdata* head; str* suffix; str* service; struct rdata* l; struct naptr_rdata* naptr; str pattern, replacement, result; char string[17]; if (parse_from_header(_msg) < 0) { LM_ERR("Failed to parse From header\n"); return -1; } if(_msg->from==NULL || get_from(_msg)==NULL) { LM_DBG("No From header\n"); return -1; } if ((furi = parse_from_uri(_msg)) == NULL) { LM_ERR("Failed to parse From URI\n"); return -1; } suffix = (str*)_suffix; service = (str*)_service; if (is_e164(&(furi->user)) == -1) { LM_ERR("From URI user is not an E164 number\n"); return -1; } /* assert: the from user is a valid formatted e164 string */ user_s = furi->user.s; user_len = furi->user.len; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_NAPTR); if (head == 0) { LM_DBG("No NAPTR record found for %s.\n", name); return -3; } /* we have the naptr records, loop and find an srv record with */ /* same ip address as source ip address, if we do then true is returned */ for (l = head; l; l = l->next) { if (l->type != T_NAPTR) continue; /*should never happen*/ naptr = (struct naptr_rdata*)l->rdata; if (naptr == 0) { LM_ERR("Null rdata in DNS response\n"); free_rdata_list(head); return -4; } LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags " "'%.*s', slen %u, services '%.*s', rlen %u, " "regexp '%.*s'\n", name, naptr->order, naptr->pref, naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len, (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len, (int)(naptr->regexp_len), ZSW(naptr->regexp)); if (sip_match(naptr, service) != 0) { if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern, &replacement) < 0) { free_rdata_list(head); /*clean up*/ LM_ERR("Parsing of NAPTR regexp failed\n"); return -5; } #ifdef LATER if ((pattern.len == 4) && (strncmp(pattern.s, "^.*$", 4) == 0)) { LM_DBG("Resulted in replacement: '%.*s'\n", replacement.len, ZSW(replacement.s)); retval = set_uri(_msg, replacement.s, replacement.len); free_rdata_list(head); /*clean up*/ return retval; } #endif result.s = &(uri[0]); result.len = MAX_URI_SIZE; /* Avoid making copies of pattern and replacement */ pattern.s[pattern.len] = (char)0; replacement.s[replacement.len] = (char)0; /* We have already checked the size of _msg->parsed_uri.user.s */ memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; if (reg_replace(pattern.s, replacement.s, &(string[0]), &result) < 0) { pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; LM_ERR("Regexp replace failed\n"); free_rdata_list(head); /*clean up*/ return -6; } LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s)); if(parse_uri(result.s, result.len, &luri) < 0) { LM_ERR("Parsing of URI <%.*s> failed\n", result.len, result.s); free_rdata_list(head); /*clean up*/ return -7; } pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; zp = 0; proto = PROTO_NONE; he = sip_resolvehost(&luri.host, &zp, &proto, (luri.type==SIPS_URI_T)?1:0 , 0); if (he == NULL){ LM_ERR("Resolving URI <%.*s> failed\n", result.len, result.s); free_rdata_list(head); /*clean up*/ return -9; } hostent2ip_addr(&addr, he, 0); if(ip_addr_cmp(&addr, &_msg->rcv.src_ip)) { free_rdata_list(head); return(1); } } } free_rdata_list(head); /*clean up*/ LM_DBG("FAIL\n"); /* must not have found the record */ return(-8); }
/*Actions are composed as follows: * (the action length and type as always= 5 bytes) * 4:uac_id * * int request(str* method, str* req_uri, str* to, str* from, str* headers, str* body, transaction_cb c, void* cp) * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int cseq; char err_buf[MAX_REASON_LEN]; struct sip_msg *my_msg; struct to_body *fb,*tb; struct cseq_body *cseqb; struct as_uac_param *the_param; dlg_t *my_dlg; int i,k,retval,uac_id,sip_error,ret,err_ret; long clen; str headers,body,fake_uri; uac_req_t uac_r; headers.s=body.s=fake_uri.s=NULL; my_dlg=NULL; my_msg=NULL; the_param=NULL; i=k=clen=0; net2hostL(uac_id,action,k); if(!(headers.s=pkg_malloc(MAX_HEADER))){ LM_ERR("Out of Memory!!"); goto error; } headers.len=0; LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id); if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type==SIP_REPLY){ LM_ERR("trying to create a UAC with a SIP response!!\n"); goto error; } if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); goto error; } if(parse_from_header(my_msg)<0){ LM_ERR("parsing from header ! \n"); goto error; } if(check_transaction_quadruple(my_msg)==0){ as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0); LM_ERR("Headers missing (to,from,call-id,cseq)?"); goto error; } if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || !(get_from(my_msg)->tag_value.len)){ as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0); LM_ERR("From tag missing"); goto error; } fb=my_msg->from->parsed; tb=my_msg->to->parsed; cseqb=my_msg->cseq->parsed; if(0!=(str2int(&cseqb->number,&cseq))){ LM_DBG("unable to parse CSeq\n"); goto error; } if(my_msg->first_line.u.request.method_value != METHOD_ACK && my_msg->first_line.u.request.method_value != METHOD_CANCEL) { /** we trick req_within */ cseq--; } if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\ &(fb->uri),&(tb->uri),&my_dlg) < 0) { as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0); LM_ERR("Error while creating new dialog\n"); goto error; } if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) { as_action_fail_resp(uac_id,SE_UAC, "Error adding the display names to the new dialog",0); LM_ERR("failed to add display names to the new dialog\n"); goto error; } if(tb->tag_value.s && tb->tag_value.len) shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value); /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have * to use req_within instead of req_outside (it sets it's own CSeq,Call-ID * and ftag), so we have to simulate that the dialog is already in completed * state so... */ server_signature=0; my_dlg->state = DLG_CONFIRMED; if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { LM_ERR("Unable to extract allowed headers!!\n"); goto error; } headers.s[headers.len]=0; /*let's get the body*/ if(my_msg->content_length) clen=(long)get_content_length(my_msg); if(clen!=0){ if(!(body.s=pkg_malloc(clen))){ LM_ERR("Out of Memory!"); goto error; } memcpy(body.s,get_body(my_msg),clen); body.len=clen; body.s[clen]=0; LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\ body.len,body.len,body.s,headers.len,headers.len,headers.s); /*t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ }else{ body.s=NULL; body.len=0; } /*Now... create the UAC !! * it would be great to know the hash_index and the label that have been assigned * to our newly created cell, but t_uac does not leave any way for us to know... * only that when that transaction transitions its state (ie. a response is received, * a timeout is reached, etc...) the callback will be called with the given parameter. * * So the only way we have to know who we are, is passing as a parameter a structure with * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id). * */ if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("out of shared memory\n"); goto error; } the_param->who=my_as; the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } /* TODO route_set should be a shm copy of my_msg->route->parsed */ my_dlg->route_set=(rr_t*)my_msg->route->parsed; /** this SHOULD be: shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed); * but it will last more... */ } calculate_hooks(my_dlg); if(flags & SPIRAL_FLAG){ memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); if(fake_uri.len<0){ LM_ERR("printing local uri\n"); goto error; } my_dlg->hooks.next_hop=&fake_uri; } /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events notified to UACs. Let's see if kamailio gets it right by now, if not this is a TODO: check PASS_PROVISIONAL my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ; this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio */ memset(&uac_r,0, sizeof(uac_req_t)); set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb, (void*)the_param); ret=seas_f.tmb.t_request_within(&uac_r); /** now undo all the fakes we have put in my_dlg*/ /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ my_dlg->route_set=(rr_t *)0; if (ret < 0) { err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC"); LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s); LM_ERR("Error on request_within %s\n",err_buf ); if(err_ret > 0) { as_action_fail_resp(uac_id,ret,err_buf,0); }else{ as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0); } goto error; } retval=0; goto exit; error: retval = -1; if(the_param) shm_free(the_param); exit: seas_f.tmb.free_dlg(my_dlg); if(headers.s) pkg_free(headers.s); if(body.s) pkg_free(body.s); if(fake_uri.s) pkg_free(fake_uri.s); if(my_msg){ if(my_msg->headers) free_hdr_field_lst(my_msg->headers); pkg_free(my_msg); } return retval; }
static CallInfo* get_call_info(struct sip_msg *msg, CallControlAction action) { static CallInfo call_info; int headers; memset(&call_info, 0, sizeof(struct CallInfo)); switch (action) { case CAInitialize: headers = HDR_CALLID_F|HDR_FROM_F; break; case CAStart: case CAStop: headers = HDR_CALLID_F; break; default: // Invalid action. Should never get here. assert(False); return NULL; } if (parse_headers(msg, headers, 0) == -1) { LOG(L_ERR, "cannot parse required headers\n"); return NULL; } if (headers & HDR_CALLID_F) { if (msg->callid == NULL) { LOG(L_ERR, "missing Call-ID header\n"); return NULL; } call_info.callid = msg->callid->body; trim(&call_info.callid); } if (headers & HDR_FROM_F) { struct to_body *from; // yeah. suggestive structure name ;) if (msg->from == NULL) { LOG(L_ERR, "missing From header\n"); return NULL; } if (!msg->from->parsed && parse_from_header(msg)==-1) { LOG(L_ERR, "cannot parse From header\n"); return NULL; } from = get_from(msg); if (from->body.s==NULL || from->body.len==0) { LOG(L_ERR, "missing From\n"); return NULL; } if (from->tag_value.s==NULL || from->tag_value.len==0) { LOG(L_ERR, "missing From tag\n"); return NULL; } call_info.from = from->body; call_info.from_tag = from->tag_value; } if (action == CAInitialize) { call_info.ruri = get_canonical_request_uri(msg); call_info.diverter = get_diverter(msg); call_info.source_ip = get_signaling_ip(msg); call_info.sip_application = get_sip_application(msg); } call_info.action = action; return &call_info; }
/*! * \brief Create a new dialog from a sip message * * Create a new dialog from a SIP message, register a callback * to keep track of the dialog with help of the tm module. * This function is either called from the request callback, or * from the dlg_manage function in the configuration script. * \see dlg_onreq * \see w_dlg_manage * \param msg SIP message * \param t transaction * \return 0 on success, -1 on failure */ int dlg_new_dialog(struct sip_msg *req, struct cell *t, const int run_initial_cbs) { struct dlg_cell *dlg; str s; str callid; str ftag; str ttag; str req_uri; unsigned int dir; LM_DBG("starting dlg_new_dialog and method is [%.*s]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s); if (current_dlg_pointer != NULL) return -1; if (req->first_line.u.request.method_value == METHOD_CANCEL) return -1; if (pre_match_parse(req, &callid, &ftag, &ttag, 0) < 0) { LM_WARN("pre-matching failed\n"); return -1; } if (ttag.s != 0 && ttag.len != 0) return -1; if (pv_printf_s(req, ruri_param_model, &req_uri) < 0) { LM_ERR("error - cannot print the r-uri format\n"); return -1; } trim(&req_uri); if (detect_spirals) { if (spiral_detected == 1) return 0; dir = DLG_DIR_NONE; dlg = get_dlg(&callid, &ftag, &ttag, &dir); if (dlg) { LM_DBG("Callid '%.*s' found, must be a spiraled request\n", callid.len, callid.s); spiral_detected = 1; if (run_initial_cbs) run_dlg_callbacks(DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0); //Add did to rr header for all spiralled requested INVITEs if (req->first_line.u.request.method_value == METHOD_INVITE) { if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) { LM_ERR("failed to add RR param\n"); } } // get_dlg has incremented the ref count by 1 unref_dlg(dlg, 1); goto finish; } } spiral_detected = 0; LM_DBG("Building new Dialog for call-id %.*s\n", callid.len, callid.s); LM_DBG("SIP Method: %.*s \n", req->first_line.u.request.method.len, req->first_line.u.request.method.s); dlg = build_new_dlg(&callid /*callid*/, &(get_from(req)->uri) /*from uri*/, &ftag/*from_tag*/, &req_uri /*r-uri*/); if (dlg == 0) { LM_ERR("failed to create new dialog\n"); return -1; } /* save caller's tag, cseq, contact and record route*/ if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG, &(get_from(req)->tag_value)) != 0) { LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); lock_destroy(dlg->dlg_out_entries_lock); lock_dealloc(dlg->dlg_out_entries_lock); return -1; } dlg->transaction = t; /* Populate initial varlist: */ dlg->vars = get_local_varlist_pointer(req, 1); link_dlg(dlg, 0); if (run_initial_cbs) run_create_callbacks(dlg, req); //Dialog will *always* use DID cookie so no need for match mode anymore if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) { LM_ERR("failed to add RR param\n"); goto error; } if (d_tmb.register_tmcb(req, t, TMCB_RESPONSE_READY | TMCB_RESPONSE_FWDED | TMCB_RESPONSE_OUT, dlg_onreply, (void*) dlg, unref_new_dialog) < 0) { LM_ERR("failed to register TMCB\n"); goto error; } // increase reference counter because of registered callback ref_dlg(dlg, 1); dlg->lifetime = get_dlg_timeout(req); s.s = _dlg_ctx.to_route_name; s.len = strlen(s.s); dlg_set_toroute(dlg, &s); dlg->sflags |= _dlg_ctx.flags; if (_dlg_ctx.to_bye != 0) dlg->dflags |= DLG_FLAG_TOBYE; finish: if (t) { // transaction exists ==> keep ref counter large enough to // avoid premature cleanup and ensure proper dialog referencing if (store_dlg_in_tm(req, t, dlg) < 0) { LM_ERR("failed to store dialog in transaction\n"); goto error; } } else { // no transaction exists ==> postpone work until we see the // request being forwarded statefully if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED, store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) { LM_ERR("failed to register callback for storing dialog in transaction\n"); goto error; } } LM_DBG("Setting current dialog\n"); set_current_dialog(req, dlg); _dlg_ctx.dlg = dlg; ref_dlg(dlg, 1); return 0; error: LM_DBG("Error in build_new_dlg"); if (!spiral_detected) unref_dlg(dlg, 1); // undo ref regarding linking return -1; }
void dlg_bridge_tm_callback(struct cell *t, int type, struct tmcb_params *ps) { struct sip_msg *msg = NULL; dlg_transfer_ctx_t *dtc = NULL; struct dlg_cell *dlg = NULL; str s; str cseq; str empty = {"", 0}; if(ps->param==NULL || *ps->param==0) { LM_DBG("message id not received\n"); return; } dtc = *((dlg_transfer_ctx_t**)ps->param); if(dtc==NULL) return; LM_DBG("completed with status %d\n", ps->code); if(ps->code>=300) goto error; /* 2xx - build dialog/send refer */ msg = ps->rpl; if(parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("failed to parse the reply headers\n"); goto error; } if((msg->cseq==NULL || parse_headers(msg,HDR_CSEQ_F,0)<0) || msg->cseq==NULL || msg->cseq->parsed==NULL) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); goto error; } cseq = (get_cseq(msg))->number; if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL) { LM_ERR("bad request or missing TO hdr\n"); goto error; } if(parse_from_header(msg)) { LM_ERR("bad request or missing FROM hdr\n"); goto error; } if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0) || msg->callid==NULL){ LM_ERR("bad request or missing CALLID hdr\n"); goto error; } s = msg->callid->body; trim(&s); /* some sanity checks */ if (s.len==0 || get_from(msg)->tag_value.len==0) { LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n", s.len, get_from(msg)->tag_value.len); goto error; } dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/, &(get_to(msg)->uri) /*to uri*/, &(get_from(msg)->tag_value)/*from_tag*/, &(get_to(msg)->uri) /*use to as r-uri*/ ); if (dlg==0) { LM_ERR("failed to create new dialog\n"); goto error; } dtc->dlg = dlg; if (dlg_set_leg_info(dlg, &(get_from(msg)->tag_value), &empty, &dlg_bridge_controller, &cseq, DLG_CALLER_LEG)!=0) { LM_ERR("dlg_set_leg_info failed\n"); goto error; } if (populate_leg_info(dlg, msg, t, DLG_CALLEE_LEG, &(get_to(msg)->tag_value)) !=0) { LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); goto error; } if(dlg_refer_callee(dtc)!=0) goto error; return; error: dlg_transfer_ctx_free(dtc); return; }
/* takes a pre-filled bin_nonce union (see BIN_NONCE_PREPARE), fills the * MD5s and returns the length of the binary nonce (cannot return error). * See calc_nonce below for more details.*/ inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg, str* secret1, str* secret2, struct sip_msg* msg) { MD5_CTX ctx; str* s; int len; MD5Init(&ctx); MD5Update(&ctx, &b_nonce->raw[0], 4 + 4); if (cfg && msg){ /* auth extra checks => 2 md5s */ len = 4 + 4 + 16 + 16; #if defined USE_NC || defined USE_OT_NONCE if (b_nonce->n.nid_pf & (NF_VALID_NC_ID | NF_VALID_OT_ID)){ /* if extra auth checks enabled, nid & pf are after the 2nd md5 */ MD5Update(&ctx, (unsigned char*)&b_nonce->n.nid_i, nonce_nid_extra_size); len+=nonce_nid_extra_size; } #endif /* USE_NC || USE_OT_NONCE */ MD5Update(&ctx, secret1->s, secret1->len); MD5Final(&b_nonce->n.md5_1[0], &ctx); /* second MD5(auth_extra_checks) */ MD5Init(&ctx); if (cfg & AUTH_CHECK_FULL_URI) { s = GET_RURI(msg); MD5Update(&ctx, s->s, s->len); } if ((cfg & AUTH_CHECK_CALLID) && !(parse_headers(msg, HDR_CALLID_F, 0) < 0 || msg->callid == 0)) { MD5Update(&ctx, msg->callid->body.s, msg->callid->body.len); } if ((cfg & AUTH_CHECK_FROMTAG) && !(parse_from_header(msg) < 0 )) { MD5Update(&ctx, get_from(msg)->tag_value.s, get_from(msg)->tag_value.len); } if (cfg & AUTH_CHECK_SRC_IP) { MD5Update(&ctx, msg->rcv.src_ip.u.addr, msg->rcv.src_ip.len); } MD5Update(&ctx, secret2->s, secret2->len); MD5Final(&b_nonce->n.md5_2[0], &ctx); }else{ /* no extra checks => only one md5 */ len = 4 + 4 + 16; #if defined USE_NC || USE_OT_NONCE if (b_nonce->n_small.nid_pf & (NF_VALID_NC_ID | NF_VALID_OT_ID)){ /* if extra auth checks are not enabled, nid & pf are after the * 1st md5 */ MD5Update(&ctx, (unsigned char*)&b_nonce->n_small.nid_i, nonce_nid_extra_size); len+=nonce_nid_extra_size; } #endif /* USE_NC || USE_OT_NONCE*/ MD5Update(&ctx, secret1->s, secret1->len); MD5Final(&b_nonce->n.md5_1[0], &ctx); } return len; }
static int w_handle_call(struct sip_msg *msg, char *flow_var) { struct cc_flow *flow; struct cc_call *call; str leg = {NULL,0}; str *dn; str val; int dec; int ret = -1; call = NULL; dec = 0; /* get the flow name */ if (fixup_get_svalue(msg, (gparam_p)flow_var, &val)!=0) { LM_ERR("failed to avaluate the flow name variable\n"); return -1; } /* parse FROM URI */ if (parse_from_uri(msg)==NULL) { LM_ERR("failed to parse from hdr\n"); return -2; } lock_get( data->lock ); /* get the flow ID */ flow = get_flow_by_name(data, &val); if (flow==NULL) { LM_ERR("flow <%.*s> does not exists\n", val.len, val.s); ret = -3; goto error; } LM_DBG("using call flow %p\n", flow); if (flow->logged_agents==0 /* no logged agents */ ) { LM_NOTICE("flow <%.*s> closed\n",flow->id.len,flow->id.s); ret = -4; goto error; } update_stat(stg_incalls, 1); update_stat(flow->st_incalls, 1); if (flow->cid.len) { dn = build_displayname(&flow->cid, get_from(msg)); } else if (get_from(msg)->display.len) { dn = &get_from(msg)->display; } else { dn = &get_from(msg)->parsed_uri.user; } LM_DBG("cid=<%.*s>\n",dn->len,dn->s); call = new_cc_call(data, flow, dn, &get_from(msg)->parsed_uri.user); if (call==NULL) { LM_ERR("failed to create new call\n"); ret = -5; goto error; } call->fst_flags |= FSTAT_INCALL; /* get estimated wait time */ call->eta = (unsigned int) (( flow->avg_call_duration * (float)get_stat_val(flow->st_queued_calls) ) / (float)flow->logged_agents); LM_DBG("avg_call_duration=%.2f queued_calls=%lu logedin_agents=%u\n", flow->avg_call_duration, get_stat_val(flow->st_queued_calls), flow->logged_agents); LM_DBG("ETA for new call(%p) is %d\n", call, call->eta); /* one more call to process */ flow->ongoing_calls++; /* there is no need to lock the call here as it is not * yet sharead at all - just we have a ref to it */ /* get the first state */ if (cc_call_state_machine( data, call, &leg )!=0) { LM_ERR("failed to get first call destination \n"); ret = -5; goto error; } lock_release( data->lock ); LM_DBG("new destination for call(%p) is %.*s (state=%d)\n", call, leg.len, leg.s, call->state); /* call still waits for agent ? */ if (call->state!=CC_CALL_TOAGENT) { LM_DBG("** onhold++ Not to agent [%p]\n", call); update_stat( stg_onhold_calls, +1); update_stat( flow->st_onhold_calls, +1); dec = 1; } /* send call to selected destination */ if (set_call_leg( msg, call, &leg)< 0 ) { LM_ERR("failed to set new destination for call\n"); if (dec) { LM_DBG("** onhold-- Error [%p]\n", call); update_stat( stg_onhold_calls, -1); update_stat( flow->st_onhold_calls, -1); } pkg_free(leg.s); goto error1; } pkg_free(leg.s); if(cc_db_insert_call(call) < 0) { LM_ERR("Failed to insert call record in db\n"); } return 1; error: lock_release( data->lock ); error1: if (call) { free_cc_call( data, call); flow->ongoing_calls--; } return ret; }
int dlg_th_post_raw(str *data) { struct sip_msg msg; struct dlg_cell *dlg; memset(&msg,0,sizeof(struct sip_msg)); msg.buf=data->s; msg.len=data->len; if (parse_msg(msg.buf,msg.len,&msg)!=0) { LM_ERR("Invalid SIP msg \n"); goto error; } if (parse_headers(&msg,HDR_EOH_F,0)<0) { LM_ERR("Failed to parse SIP headers\n"); goto error; } if (msg.cseq==NULL || get_cseq(&msg)==NULL) { LM_ERR("Failed to parse CSEQ header \n"); goto error; } if((get_cseq(&msg)->method_id)&MSG_SKIP_BITMASK) { LM_DBG("Skipping %d for DLG callid topo hiding\n",get_cseq(&msg)->method_id); goto error; } if (parse_to_header(&msg)<0 || msg.to==NULL || get_to(&msg)==NULL) { LM_ERR("cannot parse TO header\n"); goto error; } if (parse_from_header(&msg)<0 || msg.from==NULL || get_from(&msg)==NULL) { LM_ERR("cannot parse TO header\n"); goto error; } if (msg.first_line.type==SIP_REQUEST) { if (get_to(&msg)->tag_value.len>0) { /* sequential request, check if callid needs to be unmasked */ dlg = get_current_dialog(); if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) { /* dialog module not involved or not callid topo hiding - let is pass freely */ } else { if (get_from(&msg)->tag_value.len != 0) { if (memcmp(get_from(&msg)->tag_value.s, dlg->legs[0].tag.s,dlg->legs[0].tag.len) == 0) { /* request from caller - need to encode callid */ if (dlg_th_encode_callid(&msg) < 0) { LM_ERR("Failed to mask callid for initial request \n"); goto error; } goto rebuild_req; } else { /* let request go through - was decoded on the in side */ } } else { /* no from tag in request - kinda foobar ? - let it through */ } } } else { /* initial request */ dlg = get_current_dialog(); if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) { /* dialog module not involved or not callid topo hiding - let is pass freely */ } else { /* mask callid */ if (dlg_th_encode_callid(&msg) < 0) { LM_ERR("Failed to mask callid for initial request \n"); goto error; } goto rebuild_req; } } } else if (msg.first_line.type==SIP_REPLY) { /* we need to look at the direction */ dlg = get_current_dialog(); if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) { /* dialog module not involved or not callid topo hiding - let is pass freely */ } else { if (get_from(&msg)->tag_value.len != 0) { if (memcmp(get_from(&msg)->tag_value.s, dlg->legs[0].tag.s,dlg->legs[0].tag.len) == 0) { /* reply going to caller - decode was done on the receiving end, let it unchanged */ } else { /* reply going to callee , need to encode callid */ if (dlg_th_encode_callid(&msg) < 0) { LM_ERR("Failed to decode callid for reply \n"); goto error; } goto rebuild_rpl; } } else { /* no from tag in reply - kinda foobar ? - let it through */ } } } free_sip_msg(&msg); return 0; rebuild_req: data->s = dlg_th_rebuild_req(&msg,&data->len); free_sip_msg(&msg); return 0; rebuild_rpl: data->s = dlg_th_rebuild_rpl(&msg,&data->len); free_sip_msg(&msg); return 0; error: free_sip_msg(&msg); return -1; }
/* create an array of str's for accounting using a formatting string; * this is the heart of the accounting module -- it prints whatever * requested in a way, that can be used for syslog, radius, * sql, whatsoever * tm sip_msg_clones does not clone (shmmem-zed) parsed fields, other then Via1,2. Such fields clone now or use from rq_rp */ static int fmt2strar(char *fmt, /* what would you like to account ? */ struct sip_msg *rq, /* accounted message */ str* ouri, /* Outbound Request-URI */ struct hdr_field *to, unsigned int code, time_t req_time) /* Timestamp of the request */ { int cnt; struct to_body* from, *pto; str *cr, *at; struct cseq_body *cseq; cnt = 0; /* we don't care about parsing here; either the function * was called from script, in which case the wrapping function * is supposed to parse, or from reply processing in which case * TM should have preparsed from REQUEST_IN callback; what's not * here is replaced with NA */ while(*fmt) { if (cnt == ALL_LOG_FMT_LEN) { LOG(L_ERR, "ERROR:acc:fmt2strar: Formatting string is too long\n"); return 0; } switch(*fmt) { case 'a': /* attr */ at = print_attrs(avps, avps_n, 0); if (!at) { vals[cnt].nul = 1; } else { vals[cnt].val.str_val = *at; } break; case 'c': /* sip_callid */ if (rq->callid && rq->callid->body.len) { vals[cnt].val.str_val = rq->callid->body; } else { vals[cnt].nul = 1; } break; case 'd': /* to_tag */ if (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) { vals[cnt].val.str_val = pto->tag_value; } else { vals[cnt].nul = 1; } break; case 'f': /* sip_from */ if (rq->from && rq->from->body.len) { vals[cnt].val.str_val = rq->from->body; } else { vals[cnt].nul = 1; } break; case 'g': /* flags */ vals[cnt].val.int_val = rq->flags; break; case 'i': /* inbound_ruri */ vals[cnt].val.str_val = rq->first_line.u.request.uri; break; case 'm': /* sip_method */ vals[cnt].val.str_val = rq->first_line.u.request.method; break; case 'n': /* sip_cseq */ if (rq->cseq && (cseq = get_cseq(rq)) && cseq->number.len) { str2int(&cseq->number, (unsigned int*)&vals[cnt].val.int_val); } else { vals[cnt].nul = 1; } break; case 'o': /* outbound_ruri */ vals[cnt].val.str_val = *ouri; break; case 'p': vals[cnt].val.int_val = rq->rcv.src_ip.u.addr32[0]; break; break; case 'r': /* from_tag */ if (rq->from && (from = get_from(rq)) && from->tag_value.len) { vals[cnt].val.str_val = from->tag_value; } else { vals[cnt].nul = 1; } break; case 't': /* sip_to */ if (to && to->body.len) vals[cnt].val.str_val = to->body; else vals[cnt].nul = 1; break; case 'u': /* digest_username */ cr = cred_user(rq); if (cr) vals[cnt].val.str_val = *cr; else vals[cnt].nul = 1; break; case 'x': /* request_timestamp */ vals[cnt].val.time_val = req_time; break; case 'D': /* to_did */ vals[cnt].nul = 1; break; case 'F': /* from_uri */ if (rq->from && (from = get_from(rq)) && from->uri.len) { vals[cnt].val.str_val = from->uri; } else vals[cnt].nul = 1; break; case 'I': /* from_uid */ if (get_from_uid(&vals[cnt].val.str_val, rq) < 0) { vals[cnt].nul = 1; } break; case 'M': /* from_did */ vals[cnt].nul = 1; break; case 'P': /* source_port */ vals[cnt].val.int_val = rq->rcv.src_port; break; case 'R': /* digest_realm */ cr = cred_realm(rq); if (cr) vals[cnt].val.str_val = *cr; else vals[cnt].nul = 1; break; case 'S': /* sip_status */ if (code > 0) vals[cnt].val.int_val = code; else vals[cnt].nul = 1; break; case 'T': /* to_uri */ if (rq->to && (pto = get_to(rq)) && pto->uri.len) vals[cnt].val.str_val = pto->uri; else vals[cnt].nul = 1; break; case 'U': /* to_uid */ if (get_to_uid(&vals[cnt].val.str_val, rq) < 0) { vals[cnt].nul = 1; } break; case 'X': /* response_timestamp */ vals[cnt].val.time_val = time(0); break; default: LOG(L_CRIT, "BUG:acc:fmt2strar: unknown char: %c\n", *fmt); return 0; } /* switch (*fmt) */ fmt++; cnt++; } /* while (*fmt) */ return cnt; }
static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps) { struct _siptrace_data sto; sip_msg_t *msg; struct ip_addr to_ip; int len; struct dest_info *dst; if(t==NULL || ps==NULL) { LM_DBG("very weird\n"); return; } if(ps->flags&TMCB_RETR_F) { LM_DBG("retransmission\n"); return; } msg=ps->req; if(msg==NULL) { /* check if it is outgoing cancel, t is INVITE * and send_buf starts with CANCEL */ if(is_invite(t) && ps->send_buf.len>7 && strncmp(ps->send_buf.s, "CANCEL ", 7)==0) { msg = t->uas.request; if(msg==NULL) { LM_DBG("no uas msg for INVITE transaction\n"); return; } else { LM_DBG("recording CANCEL based on INVITE transaction\n"); } } else { LM_DBG("no uas msg, local transaction\n"); return; } } memset(&sto, 0, sizeof(struct _siptrace_data)); if(traced_user_avp.n!=0) sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp, &sto.avp_value, &sto.state); if((sto.avp==NULL) && trace_is_off(msg) ) { LM_DBG("trace off...\n"); return; } if(sip_trace_prepare(msg)<0) return; if(ps->send_buf.len>0) { sto.body = ps->send_buf; } else { sto.body.s = "No request buffer"; sto.body.len = sizeof("No request buffer")-1; } sto.callid = msg->callid->body; if(ps->send_buf.len>10) { sto.method.s = ps->send_buf.s; sto.method.len = 0; while(sto.method.len<ps->send_buf.len) { if(ps->send_buf.s[sto.method.len]==' ') break; sto.method.len++; } if(sto.method.len==ps->send_buf.len) sto.method.len = 10; } else { sto.method = t->method; } sto.status.s = ""; sto.status.len = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = ps->dst; if (trace_local_ip.s && trace_local_ip.len > 0) { sto.fromip = trace_local_ip; } else { if(dst==0 || dst->send_sock==0 || dst->send_sock->sock_str.s==0) { siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff); strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(sto.fromip_buff,":"); strcat(sto.fromip_buff, int2str(msg->rcv.dst_port, NULL)); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); } else { sto.fromip = dst->send_sock->sock_str; } } if(dst==0) { sto.toip.s = "any:255.255.255.255"; sto.toip.len = 19; } else { su2ip_addr(&to_ip, &dst->to); siptrace_copy_proto(dst->proto, sto.toip_buff); strcat(sto.toip_buff, ip_addr2a(&to_ip)); strcat(sto.toip_buff, ":"); strcat(sto.toip_buff, int2str((unsigned long)su_getport(&dst->to), &len)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); } sto.dir = "out"; sto.fromtag = get_from(msg)->tag_value; sto.totag = get_to(msg)->tag_value; #ifdef STATISTICS sto.stat = siptrace_req; #endif sip_trace_store(&sto, NULL); return; }
static int assemble_msg(struct sip_msg* msg, struct tw_info *twi) { static char id_buf[IDBUF_LEN]; static char route_buffer[ROUTE_BUFFER_MAX]; static char append_buf[APPEND_BUFFER_MAX]; static char cmd_buf[CMD_BUFFER_MAX]; static str empty_param = {".",1}; unsigned int hash_index, label; contact_body_t* cb=0; contact_t* c=0; name_addr_t na; rr_t* record_route; struct hdr_field* p_hdr; param_hooks_t hooks; int l; char* s, fproxy_lr; str route, next_hop, append, tmp_s, body, str_uri; if(msg->first_line.type != SIP_REQUEST){ LM_ERR("called for something else then a SIP request\n"); goto error; } /* parse all -- we will need every header field for a UAS */ if ( parse_headers(msg, HDR_EOH_F, 0)==-1) { LM_ERR("parse_headers failed\n"); goto error; } /* find index and hash; (the transaction can be safely used due * to refcounting till script completes) */ if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) { LM_ERR("t_get_trans_ident failed\n"); goto error; } /* parse from header */ if (msg->from->parsed==0 && parse_from_header(msg)<0 ) { LM_ERR("failed to parse <From:> header\n"); goto error; } /* parse the RURI (doesn't make any malloc) */ msg->parsed_uri_ok = 0; /* force parsing */ if (parse_sip_msg_uri(msg)<0) { LM_ERR("uri has not been parsed\n"); goto error; } /* parse contact header */ str_uri.s = 0; str_uri.len = 0; if(msg->contact) { if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) { LM_ERR("failed to parse <Contact:> header\n"); goto error; } cb = (contact_body_t*)msg->contact->parsed; if(cb && (c=cb->contacts)) { str_uri = c->uri; if (find_not_quoted(&str_uri,'<')) { parse_nameaddr(&str_uri,&na); str_uri = na.uri; } } } /* str_uri is taken from caller's contact or from header * for backwards compatibility with pre-3261 (from is already parsed)*/ if(!str_uri.len || !str_uri.s) str_uri = get_from(msg)->uri; /* parse Record-Route headers */ route.s = s = route_buffer; route.len = 0; fproxy_lr = 0; next_hop = empty_param; p_hdr = msg->record_route; if(p_hdr) { if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) { LM_ERR("failed to parse 'Record-Route:' header\n"); goto error; } record_route = (rr_t*)p_hdr->parsed; } else { record_route = 0; } if( record_route ) { if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 && tmp_s.s+1!=record_route->nameaddr.uri.s+ record_route->nameaddr.uri.len) { /* Parse all parameters */ tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s- record_route->nameaddr.uri.s); if (parse_params( &tmp_s, CLASS_URI, &hooks, &record_route->params) < 0) { LM_ERR("failed to parse record route uri params\n"); goto error; } fproxy_lr = (hooks.uri.lr != 0); LM_DBG("record_route->nameaddr.uri: %.*s\n", record_route->nameaddr.uri.len,record_route->nameaddr.uri.s); if(fproxy_lr){ LM_DBG("first proxy has loose routing\n"); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) { /* filter out non-RR hdr and empty hdrs */ if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0) continue; if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){ LM_ERR("failed to parse <Record-route:> header\n"); goto error; } for(record_route=p_hdr->parsed; record_route; record_route=record_route->next){ LM_DBG("record_route->nameaddr.uri: <%.*s>\n", record_route->nameaddr.uri.len, record_route->nameaddr.uri.s); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } if(!fproxy_lr){ copy_route(s,route.len,str_uri.s,str_uri.len); str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } else { next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } } LM_DBG("calculated route: %.*s\n",route.len,route.len ? route.s : ""); LM_DBG("next r-uri: %.*s\n",str_uri.len,str_uri.len ? str_uri.s : ""); if ( REQ_LINE(msg).method_value==METHOD_INVITE || (twi->append && twi->append->add_body) ) { /* get body */ if( get_body(msg,&body)!=0 ){ LM_ERR("get_body failed\n"); goto error; } } else { body = empty_param; } /* flags & additional headers */ append.s = s = append_buf; if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) { LM_ERR("buffer overflow while copying flags\n"); goto error; } append_str(s,"P-MsgFlags: ",12); l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/ if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) { LM_ERR("buffer overflow while copying optional header\n"); goto error; } append_chr(s,'\n'); if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg, twi->append->elems))==0) ) goto error; /* body separator */ append_chr(s,'.'); append.len = s-append.s; eol_line(1).s = s = cmd_buf; if(twi->action.len+12 >= CMD_BUFFER_MAX){ LM_ERR("buffer overflow while copying command name\n"); goto error; } append_str(s,"sip_request.",12); append_str(s,twi->action.s,twi->action.len); eol_line(1).len = s-eol_line(1).s; eol_line(2)=REQ_LINE(msg).method; /* method type */ eol_line(3)=msg->parsed_uri.user; /* user from r-uri */ eol_line(4)=msg->parsed_uri.host; /* domain */ eol_line(5)=msg->rcv.bind_address->address_str; /* dst ip */ eol_line(6)=msg->rcv.dst_port==SIP_PORT ? empty_param : msg->rcv.bind_address->port_no_str; /* port */ /* r_uri ('Contact:' for next requests) */ eol_line(7)=*GET_RURI(msg); /* r_uri for subsequent requests */ eol_line(8)=str_uri.len?str_uri:empty_param; eol_line(9)=get_from(msg)->body; /* from */ eol_line(10)=msg->to->body; /* to */ eol_line(11)=msg->callid->body; /* callid */ eol_line(12)=get_from(msg)->tag_value; /* from tag */ eol_line(13)=get_to(msg)->tag_value; /* to tag */ eol_line(14)=get_cseq(msg)->number; /* cseq number */ eol_line(15).s=id_buf; /* hash:label */ s = int2str(hash_index, &l); if (l+1>=IDBUF_LEN) { LM_ERR("too big hash\n"); goto error; } memcpy(id_buf, s, l); id_buf[l]=':'; eol_line(15).len=l+1; s = int2str(label, &l); if (l+1+eol_line(15).len>=IDBUF_LEN) { LM_ERR("too big label\n"); goto error; } memcpy(id_buf+eol_line(15).len, s, l); eol_line(15).len+=l; eol_line(16) = route.len ? route : empty_param; eol_line(17) = next_hop; eol_line(18) = append; eol_line(19) = body; /* success */ return 1; error: /* 0 would lead to immediate script exit -- -1 returns * with 'false' to script processing */ return -1; }
static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps) { struct _siptrace_data sto; sip_msg_t *msg; sip_msg_t *req; 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; } memset(&sto, 0, sizeof(struct _siptrace_data)); if(traced_user_avp.n!=0) sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp, &sto.avp_value, &sto.state); if((sto.avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } if(sip_trace_prepare(msg)<0) return; sto.body.s = msg->buf; sto.body.len = msg->len; sto.callid = msg->callid->body; sto.method = get_cseq(msg)->method; strcpy(statusbuf, int2str(ps->code, &sto.status.len)); sto.status.s = statusbuf; siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff); strcat(sto.fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(sto.fromip_buff,":"); strcat(sto.fromip_buff, int2str(msg->rcv.src_port, NULL)); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); if(trace_local_ip.s && trace_local_ip.len > 0) { sto.toip = trace_local_ip; } else { siptrace_copy_proto(msg->rcv.proto, sto.toip_buff); strcat(sto.toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(sto.toip_buff,":"); strcat(sto.toip_buff, int2str(msg->rcv.dst_port, NULL)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); } sto.dir = "in"; sto.fromtag = get_from(msg)->tag_value; sto.totag = get_to(msg)->tag_value; #ifdef STATISTICS sto.stat = siptrace_rpl; #endif sip_trace_store(&sto, NULL); return; }
/* * Send Radius request to verify destination and generate AVPs from * reply items of positive response. */ int verify_destination(struct sip_msg* _msg, char* s1, char* s2) { aaa_message *send = NULL, *received = NULL; uint32_t service; /* Add Request-URI host A_USER_NAME and user as A_SIP_URI_USER */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing Request-URI\n"); return -1; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth\n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _msg->parsed_uri.host.s, _msg->parsed_uri.host.len, 0)) { LM_ERR("error adding PW_USER_NAME\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], _msg->parsed_uri.user.s, _msg->parsed_uri.user.len, 0)) { LM_ERR("error adding PW_SIP_URI_USER\n"); goto err; } /* Add From Tag */ if (parse_from_header(_msg) < 0) { LM_ERR("error while parsing From header field\n"); goto err; } if ((_msg->from==NULL) || (get_from(_msg) == NULL) || (get_from(_msg)->tag_value.s == NULL) || (get_from(_msg)->tag_value.len <= 0)) { LM_ERR("error while accessing From header tag\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_FROM_TAG], get_from(_msg)->tag_value.s, get_from(_msg)->tag_value.len, 0)) { LM_ERR("error adding PW_SIP_FROM_TAG\n"); goto err; } /* Add Call-Id */ if ((parse_headers(_msg, HDR_CALLID_F, 0) == -1) || (_msg->callid == NULL) || (_msg->callid->body.s == NULL) || (_msg->callid->body.len <= 0)) { LM_ERR("error while accessing Call-Id\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_CALL_ID], _msg->callid->body.s, _msg->callid->body.len, 0)) { LM_ERR("error adding PW_SIP_CALL_ID\n"); goto err; } /* Add Service-Type */ service = vals[V_SIP_VERIFY_DESTINATION].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { LM_ERR("error adding PW_SERVICE_TYPE\n"); goto err; } /* Send Request and generate AVPs of positive reply */ if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } LM_DBG("failure\n"); err: if (send) proto.destroy_aaa_message(conn, send); if (received) proto.destroy_aaa_message(conn, received); return -1; }
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps) { struct _siptrace_data sto; int faked = 0; struct sip_msg* msg; struct sip_msg* req; struct ip_addr to_ip; int len; char statusbuf[8]; struct dest_info *dst; if (t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } if(ps->flags&TMCB_RETR_F) { LM_DBG("retransmission\n"); return; } memset(&sto, 0, sizeof(struct _siptrace_data)); if(traced_user_avp.n!=0) sto.avp=search_first_avp(traced_user_avp_type, traced_user_avp, &sto.avp_value, &sto.state); if((sto.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(sip_trace_prepare(msg)<0) return; if(faked==0) { if(ps->send_buf.len>0) { sto.body = ps->send_buf; } else if(t->uas.response.buffer!=NULL) { sto.body.s = t->uas.response.buffer; sto.body.len = t->uas.response.buffer_len; } else if(msg->len>0) { sto.body.s = msg->buf; sto.body.len = msg->len; } else { sto.body.s = "No reply buffer"; sto.body.len = sizeof("No reply buffer")-1; } } else { if(ps->send_buf.len>0) { sto.body = ps->send_buf; } else if(t->uas.response.buffer!=NULL) { sto.body.s = t->uas.response.buffer; sto.body.len = t->uas.response.buffer_len; } else { sto.body.s = "No reply buffer"; sto.body.len = sizeof("No reply buffer")-1; } } sto.callid = msg->callid->body; sto.method = get_cseq(msg)->method; if(trace_local_ip.s && trace_local_ip.len > 0) { sto.fromip = trace_local_ip; } else { siptrace_copy_proto(msg->rcv.proto, sto.fromip_buff); strcat(sto.fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(sto.fromip_buff,":"); strcat(sto.fromip_buff, int2str(req->rcv.dst_port, NULL)); sto.fromip.s = sto.fromip_buff; sto.fromip.len = strlen(sto.fromip_buff); } strcpy(statusbuf, int2str(ps->code, &sto.status.len)); sto.status.s = statusbuf; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = ps->dst; if(dst==0) { sto.toip.s = "any:255.255.255.255"; sto.toip.len = 19; } else { su2ip_addr(&to_ip, &dst->to); siptrace_copy_proto(dst->proto, sto.toip_buff); strcat(sto.toip_buff, ip_addr2a(&to_ip)); strcat(sto.toip_buff, ":"); strcat(sto.toip_buff, int2str((unsigned long)su_getport(&dst->to), &len)); sto.toip.s = sto.toip_buff; sto.toip.len = strlen(sto.toip_buff); } sto.dir = "out"; sto.fromtag = get_from(msg)->tag_value; sto.totag = get_to(msg)->tag_value; #ifdef STATISTICS sto.stat = siptrace_rpl; #endif sip_trace_store(&sto, NULL); return; }
int pa_handle_registration(struct sip_msg* _m, char* _domain, char* _s2) { struct pdomain* d = (struct pdomain*)_domain; struct presentity *presentity; str p_uri; struct to_body *from = NULL; int e = 0; // LOG(L_ERR, "pa_handle_registration() entered\n"); paerrno = PA_OK; d = (struct pdomain*)_domain; if (parse_hfs(_m, 0) < 0) { paerrno = PA_PARSE_ERR; LOG(L_ERR, "pa_handle_registration(): Error while parsing headers\n"); return -1; } from = get_from(_m); if (!from || (pa_extract_aor(&from->uri, &p_uri) < 0)) { LOG(L_ERR, "pa_handle_registration(): Error while extracting Address Of Record\n"); goto error; } if (_m->expires) { e = ((exp_body_t*)_m->expires->parsed)->val; } if (from) LOG(L_ERR, "pa_handle_registration: from=%.*s p_uri=%.*s expires=%d\n", from->uri.len, from->uri.s, p_uri.len, p_uri.s, e); lock_pdomain(d); if (find_presentity(d, &p_uri, &presentity) > 0) { LOG(L_ERR, "pa_handle_registration: find_presentity did not find presentity\n"); if (e > 0) { if (create_presentity_only(_m, d, &p_uri, &presentity) < 0) { LOG(L_ERR, "pa_handle_registration(): Error while creating new presentity\n"); goto error2; } } #if 0 else { presence_tuple_t *tuple = NULL; if (_m->contact) { struct hdr_field* ptr = _m->contact; while (ptr) { if (ptr->type == HDR_CONTACT) { if (!ptr->parsed && (parse_contact(ptr) < 0)) { goto next; } } if (find_presence_tuple(contact, presentity, &tuple) == 0) { tuple->state = PS_OFFLINE; } next: ptr = ptr->next; } } db_update_presentity(presentity); } #endif } if (presentity && e > 0) { LOG(L_ERR, "pa_handle_registration about to call d->reg p=%p expires=%d", presentity, e); d->reg(&presentity->uri, &presentity->uri, (void*)callback, presentity); } LOG(L_ERR, "pa_handle_registration about to return 1"); unlock_pdomain(d); return 1; error2: LOG(L_ERR, "pa_handle_registration about to return -1\n"); unlock_pdomain(d); return -1; error: LOG(L_ERR, "pa_handle_registration about to return -2\n"); return -1; }
int rls_handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain) { subs_t subs; pres_ev_t* event = NULL; int err_ret = -1; int ret = to_presence_code; str* contact = NULL; xmlDocPtr doc = NULL; xmlNodePtr service_node = NULL; unsigned int hash_code=0; int to_tag_gen = 0; event_t* parsed_event; param_t* ev_param = NULL; str reason; int rt; str rlsubs_did = {0, 0}; memset(&subs, 0, sizeof(subs_t)); /** sanity checks - parse all headers */ if (parse_headers(msg, HDR_EOH_F, 0)<-1) { LM_ERR("failed parsing all headers\n"); if (slb.freply(msg, 400, &pu_400_rpl) < 0) { LM_ERR("while sending 400 reply\n"); return -1; } return 0; } /* check for To and From headesr */ if(parse_to_uri(msg)<0 || parse_from_uri(msg)<0) { LM_ERR("failed to find To or From headers\n"); if (slb.freply(msg, 400, &pu_400_rpl) < 0) { LM_ERR("while sending 400 reply\n"); return -1; } return 0; } if(get_from(msg)->tag_value.s ==NULL || get_from(msg)->tag_value.len==0) { LM_ERR("no from tag value present\n"); return -1; } if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find callid header\n"); return -1; } if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed parsing Request URI\n"); return -1; } /* check for header 'Support: eventlist' */ if(msg->supported==NULL) { LM_DBG("supported header not found - not for rls\n"); goto forpresence; } if(parse_supported(msg)<0) { LM_ERR("failed to parse supported headers\n"); return -1; } if(!(get_supported(msg) & F_OPTION_TAG_EVENTLIST)) { LM_DBG("No support for 'eventlist' - not for rls\n"); goto forpresence; } /* inspecting the Event header field */ if(msg->event && msg->event->body.len > 0) { if (!msg->event->parsed && (parse_event(msg->event) < 0)) { LM_ERR("cannot parse Event header\n"); goto error; } if(! ( ((event_t*)msg->event->parsed)->type & rls_events) ) { goto forpresence; } } else { goto bad_event; } /* search event in the list */ parsed_event = (event_t*)msg->event->parsed; event = pres_search_event(parsed_event); if(event==NULL) { goto bad_event; } subs.event= event; /* extract the id if any*/ ev_param= parsed_event->params.list; while(ev_param) { if(ev_param->name.len==2 && strncmp(ev_param->name.s, "id", 2)==0) { subs.event_id = ev_param->body; break; } ev_param= ev_param->next; } /* extract dialog information from message headers */ if(pres_extract_sdialog_info(&subs, msg, rls_max_expires, &to_tag_gen, rls_server_address, watcher_user, watcher_domain)<0) { LM_ERR("bad subscribe request\n"); goto error; } hash_code = core_hash(&subs.callid, &subs.to_tag, hash_size); if (CONSTR_RLSUBS_DID(&subs, &rlsubs_did) < 0) { LM_ERR("cannot build rls subs did\n"); goto error; } subs.updated = core_hash(&rlsubs_did, NULL, 0) % (waitn_time * rls_notifier_poll_rate * rls_notifier_processes); if(get_to(msg)->tag_value.s==NULL || get_to(msg)->tag_value.len==0) { /* initial Subscribe */ /*verify if Request URI represents a list by asking xcap server*/ if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host, &subs.pres_uri)<0) { LM_ERR("while constructing uri from user and domain\n"); goto error; } if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user, &subs.watcher_domain, &service_node, &doc)<0) { LM_ERR("while attepmting to get a resource list\n"); goto error; } if(doc==NULL) { /* if not for RLS, pass it to presence serivce */ LM_DBG("list not found - searched for uri <%.*s>\n", subs.pres_uri.len, subs.pres_uri.s); goto forpresence; } /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; subs.local_cseq = 0; if(subs.expires != 0) { subs.version = 1; if (dbmode==RLS_DB_ONLY) { rt=insert_rlsdb( &subs ); } else { rt=pres_insert_shtable(rls_table, hash_code, &subs); } if (rt<0) { LM_ERR("while adding new subscription\n"); goto error; } } } else { /* search if a stored dialog */ if ( dbmode == RLS_DB_ONLY ) { if (rls_dbf.start_transaction) { if (rls_dbf.start_transaction(rls_db, DB_LOCKING_WRITE) < 0) { LM_ERR("in start_transaction\n"); goto error; } } rt = get_dialog_subscribe_rlsdb(&subs); if (rt <= 0) { LM_DBG("subscription dialog not found for <%.*s@%.*s>\n", subs.watcher_user.len, subs.watcher_user.s, subs.watcher_domain.len, subs.watcher_domain.s); if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } goto forpresence; } else if(rt>=400) { reason = (rt==400)?pu_400_rpl:stale_cseq_rpl; if (slb.freply(msg, 400, &reason) < 0) { LM_ERR("while sending reply\n"); goto error; } if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } ret = 0; goto stop; } /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; if (update_dialog_subscribe_rlsdb(&subs) < 0) { LM_ERR("while updating resource list subscription\n"); goto error; } if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } } else { lock_get(&rls_table[hash_code].lock); if(pres_search_shtable(rls_table, subs.callid, subs.to_tag, subs.from_tag, hash_code)==NULL) { lock_release(&rls_table[hash_code].lock); LM_DBG("subscription dialog not found for <%.*s@%.*s>\n", subs.watcher_user.len, subs.watcher_user.s, subs.watcher_domain.len, subs.watcher_domain.s); goto forpresence; } lock_release(&rls_table[hash_code].lock); /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; rt = update_rlsubs(&subs, hash_code); if(rt<0) { LM_ERR("while updating resource list subscription\n"); goto error; } if(rt>=400) { reason = (rt==400)?pu_400_rpl:stale_cseq_rpl; if (slb.freply(msg, 400, &reason) < 0) { LM_ERR("while sending reply\n"); goto error; } ret = 0; goto stop; } } if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user, &subs.watcher_domain, &service_node, &doc)<0) { LM_ERR("failed getting resource list\n"); goto error; } if(doc==NULL) { /* warning: no document returned?!?! */ LM_WARN("no document returned for uri <%.*s>\n", subs.pres_uri.len, subs.pres_uri.s); goto done; } } if (get_to(msg)->tag_value.s==NULL || get_to(msg)->tag_value.len==0) { /* initial subscriber - sending notify with full state */ if(send_full_notify(&subs, service_node, &subs.pres_uri, hash_code)<0) { LM_ERR("failed sending full state notify\n"); goto error; } } /* send subscribe requests for all in the list */ if(resource_subscriptions(&subs, service_node)< 0) { LM_ERR("failed sending subscribe requests to resources in list\n"); goto error; } if (dbmode !=RLS_DB_ONLY) remove_expired_rlsubs(&subs, hash_code); done: ret = 1; stop: forpresence: if(contact!=NULL) { if(contact->s!=NULL) pkg_free(contact->s); pkg_free(contact); } if(subs.pres_uri.s!=NULL) pkg_free(subs.pres_uri.s); if(subs.record_route.s!=NULL) pkg_free(subs.record_route.s); if(doc!=NULL) xmlFreeDoc(doc); if (rlsubs_did.s != NULL) pkg_free(rlsubs_did.s); return ret; bad_event: err_ret = 0; if(reply_489(msg)<0) { LM_ERR("failed sending 489 reply\n"); err_ret = -1; } error: LM_ERR("occurred in rls_handle_subscribe\n"); if(contact!=NULL) { if(contact->s!=NULL) pkg_free(contact->s); pkg_free(contact); } if(subs.pres_uri.s!=NULL) pkg_free(subs.pres_uri.s); if(subs.record_route.s!=NULL) pkg_free(subs.record_route.s); if(doc!=NULL) xmlFreeDoc(doc); if (rlsubs_did.s != NULL) pkg_free(rlsubs_did.s); if (rls_dbf.abort_transaction) { if (rls_dbf.abort_transaction(rls_db) < 0) LM_ERR("in abort_transaction\n"); } return err_ret; }