/*! * get the To-tag for stateless reply */ int sl_get_reply_totag(struct sip_msg *msg, str *totag) { if(msg==NULL || totag==NULL) return -1; calc_crc_suffix(msg, tag_suffix); *totag = sl_tag; return 1; }
/* * Establishing a new dialog, UAS side */ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d) { dlg_t* res; str tag; if (!_req || /*!_tag ||*/ !_d) { LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n"); return -1; } if (_code > 299) { DBG("new_dlg_uas(): Status code >= 300, no dialog created\n"); } res = (dlg_t*)shm_malloc(sizeof(dlg_t)); if (res == 0) { LOG(L_ERR, "new_dlg_uac(): No memory left\n"); return -3; } /* Clear everything */ memset(res, 0, sizeof(dlg_t)); if (request2dlg(_req, res) < 0) { LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n"); free_dlg(res); return -4; } if (_code > 100) { tag.s = tm_tags; tag.len = TOTAG_VALUE_LEN; calc_crc_suffix(_req, tm_tag_suffix); if (str_duplicate(&res->id.loc_tag, &tag) < 0) { free_dlg(res); return -5; } } *_d = res; if (_code < 100) (*_d)->state = DLG_NEW; else if (_code < 200) (*_d)->state = DLG_EARLY; else (*_d)->state = DLG_CONFIRMED; if (calculate_hooks(*_d) < 0) { LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n"); free_dlg(res); return -6; } #ifdef DIALOG_CALLBACKS run_new_dlg_callbacks(DLG_CB_UAS, res, _req); #endif return 0; }
/* Returns: 0 : ACK to a local reply -1 : error 1 : is not an ACK or a non-local ACK */ int sl_filter_ACK(struct sip_msg *msg, unsigned int flags, void *bar ) { str *tag_str; if (msg->first_line.u.request.method_value!=METHOD_ACK) goto pass_it; /*check the timeout value*/ if ( *(sl_timeout)<= get_ticks() ) { DBG("DEBUG : sl_filter_ACK: to late to be a local ACK!\n"); goto pass_it; } /*force to parse to header -> we need it for tag param*/ if (parse_headers( msg, HDR_TO_F, 0 )==-1) { LOG(L_ERR,"ERROR : SL_FILTER_ACK: unable to parse To header\n"); return -1; } if (msg->to) { tag_str = &(get_to(msg)->tag_value); if ( tag_str->len==TOTAG_VALUE_LEN ) { /* calculate the variable part of to-tag */ calc_crc_suffix(msg, tag_suffix); /* test whether to-tag equal now */ if (memcmp(tag_str->s,sl_tag.s,sl_tag.len)==0) { LM_DBG("SL local ACK found -> dropping it!\n" ); update_sl_filtered_acks(); sl_run_callbacks(SLCB_ACK_FILTERED, msg, 0, 0, 0, 0); if(unlikely(_sl_filtered_ack_route>=0)) { run_top_route(event_rt.rlist[_sl_filtered_ack_route], msg, 0); } return 0; } } } pass_it: return 1; }
/* Returns: 0 : ACK to a local reply -1 : error 1 : is not an ACK or a non-local ACK */ int sl_filter_ACK(struct sip_msg *msg, void *bar ) { str *tag_str; if (msg->first_line.u.request.method_value!=METHOD_ACK) goto pass_it; /*check the timeout value*/ if ( *(sl_timeout)<= get_ticks() ) { LM_DBG("to late to be a local ACK!\n"); goto pass_it; } /*force to parse to header -> we need it for tag param*/ if (parse_headers( msg, HDR_TO_F, 0 )==-1) { LM_ERR("unable to parse To header\n"); return -1; } if (msg->to) { tag_str = &(get_to(msg)->tag_value); if ( tag_str->len==TOTAG_VALUE_LEN ) { /* calculate the variable part of to-tag */ calc_crc_suffix(msg, tag_suffix); /* test whether to-tag equal now */ if (memcmp(tag_str->s,sl_tag.s,sl_tag.len)==0) { LM_DBG("local ACK found -> dropping it!\n"); if_update_stat( sl_enable_stats, rcv_acks, 1); run_sl_callbacks( SLCB_ACK_IN, msg, 0, 0, 0, 0 ); return 0; } } } pass_it: return 1; }
/* send a UAS reply * returns 1 if everything was OK or -1 for error */ static int _reply( struct cell *trans, struct sip_msg* p_msg, unsigned int code, str *text, int lock ) { unsigned int len; char * buf, *dset; struct bookmark bm; int dset_len; if (code>=200) set_kr(REQ_RPLD); /* compute the buffer in private memory prior to entering lock; * create to-tag if needed */ /* if that is a redirection message, dump current message set to it */ if (code>=300 && code<400) { dset=print_dset(p_msg, &dset_len); if (dset) { add_lump_rpl(p_msg, dset, dset_len, LUMP_RPL_HDR); } } /* check if the UAS retranmission port needs to be updated */ if ( (p_msg->msg_flags ^ trans->uas.request->msg_flags) & FL_FORCE_RPORT ) su_setport( &trans->uas.response.dst.to, p_msg->rcv.src_port ); if (code>=180 && p_msg->to && (get_to(p_msg)->tag_value.s==0 || get_to(p_msg)->tag_value.len==0)) { calc_crc_suffix( p_msg, tm_tag_suffix ); buf = build_res_buf_from_sip_req(code,text, &tm_tag, p_msg, &len, &bm); return _reply_light( trans, buf, len, code, tm_tag.s, TOTAG_VALUE_LEN, lock, &bm); } else { buf = build_res_buf_from_sip_req(code,text, 0 /*no to-tag*/, p_msg, &len, &bm); return _reply_light(trans,buf,len,code, 0, 0 /* no to-tag */, lock, &bm); } }
/* Returns: 0 : ACK to a local reply -1 : error 1 : is not an ACK or a non-local ACK */ int sl_filter_ACK(struct sip_msg *msg, void *bar ) { str *tag_str; if (msg->first_line.u.request.method_value!=METHOD_ACK) goto pass_it; /*check the timeout value*/ if ( *(sl_timeout)<= get_ticks() ) { DBG("DEBUG : sl_filter_ACK: to late to be a local ACK!\n"); goto pass_it; } /*force to parse to header -> we need it for tag param*/ if (parse_headers( msg, HDR_TO_F, 0 )==-1) { LOG(L_ERR,"ERROR : SL_FILTER_ACK: unable to parse To header\n"); return -1; } if (msg->to) { tag_str = &(get_to(msg)->tag_value); if ( tag_str->len==TOTAG_VALUE_LEN ) { /* calculate the variable part of to-tag */ calc_crc_suffix(msg, tag_suffix); /* test whether to-tag equal now */ if (memcmp(tag_str->s,sl_tag.s,sl_tag.len)==0) { DBG("DEBUG: sl_filter_ACK : local ACK found -> dropping it! \n" ); return 0; } } } pass_it: return 1; }
int t_reply_with_body( struct cell *trans, unsigned int code, str *text, str *body, str *new_header, str *to_tag ) { struct lump_rpl *hdr_lump; struct lump_rpl *body_lump; str rpl; int ret; struct bookmark bm; struct sip_msg* p_msg = trans->uas.request; str to_tag_rpl= {0, 0}; /* add the lumps for new_header and for body (by bogdan) */ if (new_header && new_header->len) { hdr_lump = add_lump_rpl( p_msg, new_header->s, new_header->len, LUMP_RPL_HDR ); if ( !hdr_lump ) { LM_ERR("failed to add hdr lump\n"); goto error; } } else { hdr_lump = 0; } /* body lump */ if(body && body->len) { body_lump = add_lump_rpl( p_msg, body->s, body->len, LUMP_RPL_BODY ); if (body_lump==0) { LM_ERR("failed add body lump\n"); goto error_1; } } else { body_lump = 0; } if(to_tag && to_tag->len) { rpl.s = build_res_buf_from_sip_req(code, text, to_tag, p_msg, (unsigned int*)&rpl.len, &bm); to_tag_rpl = *to_tag; } else if (code>=180 && p_msg->to && (get_to(p_msg)->tag_value.s==0 || get_to(p_msg)->tag_value.len==0)) { calc_crc_suffix( p_msg, tm_tag_suffix ); rpl.s = build_res_buf_from_sip_req(code,text, &tm_tag, p_msg, (unsigned int*)&rpl.len, &bm); to_tag_rpl.s = tm_tag.s; to_tag_rpl.len = TOTAG_VALUE_LEN; } else { rpl.s = build_res_buf_from_sip_req(code,text, 0 /*no to-tag*/, p_msg, (unsigned int*)&rpl.len, &bm); } /* since the msg (trans->uas.request) is a clone into shm memory, to avoid * memory leak or crashing (lumps are create in private memory) I will * remove the lumps by myself here (bogdan) */ if ( hdr_lump ) { unlink_lump_rpl( p_msg, hdr_lump); free_lump_rpl( hdr_lump ); } if( body_lump ) { unlink_lump_rpl( p_msg, body_lump); free_lump_rpl( body_lump ); } if (rpl.s==0) { LM_ERR("failed in doing build_res_buf_from_sip_req()\n"); goto error; } ret=_reply_light( trans, rpl.s, rpl.len, code, to_tag_rpl.s, to_tag_rpl.len, 1 /* lock replies */, &bm ); /* mark the transaction as replied */ if (code>=200) set_kr(REQ_RPLD); return ret; error_1: if ( hdr_lump ) { unlink_lump_rpl( p_msg, hdr_lump); free_lump_rpl( hdr_lump ); } error: return -1; }
/* this is the code which decides what and when shall be relayed upstream; note well -- it assumes it is entered locked with REPLY_LOCK and it returns unlocked! */ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, unsigned int msg_status, branch_bm_t *cancel_bitmap ) { int relay; int save_clone; char *buf; /* length of outbound reply */ unsigned int res_len; int relayed_code; struct sip_msg *relayed_msg; struct bookmark bm; int totag_retr; enum rps reply_status; /* retransmission structure of outbound reply and request */ struct retr_buf *uas_rb; str cb_s; str text; /* keep compiler warnings about use of uninit vars silent */ res_len=0; buf=0; relayed_msg=0; relayed_code=0; totag_retr=0; /* remember, what was sent upstream to know whether we are * forwarding a first final reply or not */ /* *** store and relay message as needed *** */ reply_status = t_should_relay_response(t, msg_status, branch, &save_clone, &relay, cancel_bitmap, p_msg ); LM_DBG("branch=%d, save=%d, relay=%d\n", branch, save_clone, relay ); /* store the message if needed */ if (save_clone) /* save for later use, typically branch picking */ { if (!store_reply( t, branch, p_msg )) goto error01; } uas_rb = & t->uas.response; if (relay >= 0 ) { /* initialize sockets for outbound reply */ uas_rb->activ_type=msg_status; t->relaied_reply_branch = relay; /* try building the outbound reply from either the current * or a stored message */ relayed_msg = branch==relay ? p_msg : t->uac[relay].reply; if (relayed_msg==FAKED_REPLY) { relayed_code = branch==relay ? msg_status : t->uac[relay].last_received; text.s = error_text(relayed_code); text.len = strlen(text.s); /* FIXME - bogdan*/ if (relayed_code>=180 && t->uas.request->to && (get_to(t->uas.request)->tag_value.s==0 || get_to(t->uas.request)->tag_value.len==0)) { calc_crc_suffix( t->uas.request, tm_tag_suffix ); buf = build_res_buf_from_sip_req( relayed_code, &text, &tm_tag, t->uas.request, &res_len, &bm ); } else { buf = build_res_buf_from_sip_req( relayed_code, &text, 0/* no to-tag */, t->uas.request, &res_len, &bm ); } } else { /* run callbacks for all types of responses - * even if they are shmem-ed or not */ if (has_tran_tmcbs(t,TMCB_RESPONSE_FWDED) ) { run_trans_callbacks( TMCB_RESPONSE_FWDED, t, t->uas.request, relayed_msg, msg_status ); } relayed_code=relayed_msg->REPLY_STATUS; buf = build_res_buf_from_sip_res( relayed_msg, &res_len, uas_rb->dst.send_sock); /* remove all lumps which are not in shm * added either by build_res_buf_from_sip_res, or by * the callbacks that have been called with shmem-ed messages - vlad */ if (branch!=relay) { del_notflaged_lumps( &(relayed_msg->add_rm), LUMPFLAG_SHMEM); del_notflaged_lumps( &(relayed_msg->body_lumps), LUMPFLAG_SHMEM); } } if (!buf) { LM_ERR("no mem for outbound reply buffer\n"); goto error02; } /* attempt to copy the message to UAS's shmem: - copy to-tag for ACK matching as well - allocate little a bit more for provisional as larger messages are likely to follow and we will be able to reuse the memory frag */ uas_rb->buffer.s = (char*)shm_resize( uas_rb->buffer.s, res_len + (msg_status<200 ? REPLY_OVERBUFFER_LEN : 0)); if (!uas_rb->buffer.s) { LM_ERR("no more share memory\n"); goto error03; } uas_rb->buffer.len = res_len; memcpy( uas_rb->buffer.s, buf, res_len ); if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */ update_local_tags(t, &bm, uas_rb->buffer.s, buf); } stats_trans_rpl( relayed_code, (relayed_msg==FAKED_REPLY)?1:0 ); /* update the status ... */ t->uas.status = relayed_code; if (is_invite(t) && relayed_msg!=FAKED_REPLY && relayed_code>=200 && relayed_code < 300 && has_tran_tmcbs( t, TMCB_RESPONSE_OUT|TMCB_RESPONSE_PRE_OUT)) { totag_retr=update_totag_set(t, relayed_msg); } }; /* if relay ... */ UNLOCK_REPLIES( t ); /* Setup retransmission timer _before_ the reply is sent * to avoid race conditions */ if (reply_status == RPS_COMPLETED) { /* for auth related replies, we do not do retransmission (via set_final_timer()), but only wait for a final reply (put_on_wait() ) - see RFC 3261 (26.3.2.4 DoS Protection) */ if ((relayed_code != 401) && (relayed_code != 407)) set_final_timer(t); else put_on_wait(t); } /* send it now (from the private buffer) */ if (relay >= 0) { /* run the PRE sending out callback */ if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_PRE_OUT) ) { cb_s.s = buf; cb_s.len = res_len; set_extra_tmcb_params( &cb_s, &uas_rb->dst); run_trans_callbacks_locked(TMCB_RESPONSE_PRE_OUT,t,t->uas.request, relayed_msg, relayed_code); } SEND_PR_BUFFER( uas_rb, buf, res_len ); LM_DBG("sent buf=%p: %.9s..., shmem=%p: %.9s\n", buf, buf, uas_rb->buffer.s, uas_rb->buffer.s ); /* run the POST sending out callback */ if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) { cb_s.s = buf; cb_s.len = res_len; set_extra_tmcb_params( &cb_s, &uas_rb->dst); run_trans_callbacks_locked( TMCB_RESPONSE_OUT, t, t->uas.request, relayed_msg, relayed_code); } pkg_free( buf ); } /* success */ return reply_status; error03: pkg_free( buf ); error02: if (save_clone) { if (t->uac[branch].reply!=FAKED_REPLY) sip_msg_free( t->uac[branch].reply ); t->uac[branch].reply = NULL; } error01: text.s = "Reply processing error"; text.len = sizeof("Reply processing error")-1; t_reply_unsafe( t, t->uas.request, 500, &text ); UNLOCK_REPLIES(t); if (is_invite(t)) cancel_uacs( t, *cancel_bitmap ); /* a serious error occurred -- attempt to send an error reply; it will take care of clean-ups */ /* failure */ return RPS_ERROR; }
int sl_send_reply_helper(struct sip_msg *msg ,int code, str *text) { str buf; union sockaddr_union to; char *dset; int dset_len; struct bookmark dummy_bm; int backup_mhomed; int ret; if ( msg->REQ_METHOD==METHOD_ACK) return 0; update_sock_struct_from_ip( &to, msg ); /* if that is a redirection message, dump current message set to it */ if (code>=300 && code<400) { dset=print_dset(msg, &dset_len); if (dset) { add_lump_rpl(msg, dset, dset_len, LUMP_RPL_HDR); } } /* add a to-tag if there is a To header field without it */ if ( code>=180 && (msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to)) && (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) ) { calc_crc_suffix( msg, tag_suffix ); buf.s = build_res_buf_from_sip_req( code, text, &sl_tag, msg, (unsigned int*)&buf.len, &dummy_bm); } else { buf.s = build_res_buf_from_sip_req( code, text, 0, msg, (unsigned int*)&buf.len, &dummy_bm); } if (!buf.s) { LM_ERR("response building failed\n"); goto error; } run_sl_callbacks( SLCB_REPLY_OUT, msg, &buf, code, text, &to ); /* supress multhoming support when sending a reply back -- that makes sure that replies will come from where requests came in; good for NATs (there is no known use for mhomed for locally generated replies; note: forwarded cross-interface replies do benefit of mhomed! */ backup_mhomed=mhomed; mhomed=0; /* use for sending the received interface -bogdan*/ ret = msg_send( msg->rcv.bind_address, msg->rcv.proto, &to, msg->rcv.proto_reserved1, buf.s, buf.len); mhomed=backup_mhomed; pkg_free(buf.s); if (ret<0) goto error; *(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME; update_sl_reply_stat(code); return 1; error: return -1; }
int sl_send_reply(struct sip_msg *msg , int code, char* reason) { char *buf, *dset; unsigned int len; struct dest_info dst; struct bookmark dummy_bm; int backup_mhomed, ret, dset_len; if ( msg->first_line.u.request.method_value==METHOD_ACK) { LOG(L_WARN, "Warning: sl_send_reply: I won't send a reply for ACK!!\n"); goto error; } init_dest_info(&dst); if (reply_to_via) { if (update_sock_struct_from_via( &dst.to, msg, msg->via1 )==-1) { LOG(L_ERR, "ERROR: sl_send_reply: " "cannot lookup reply dst: %s\n", msg->via1->host.s ); goto error; } } else update_sock_struct_from_ip( &dst.to, msg ); /* if that is a redirection message, dump current message set to it */ if (code>=300 && code<400) { dset=print_dset(msg, &dset_len); if (dset) { add_lump_rpl(msg, dset, dset_len, LUMP_RPL_HDR); } } /* add a to-tag if there is a To header field without it */ if ( /* since RFC3261, we append to-tags anywhere we can, except * 100 replies */ /* msg->first_line.u.request.method_value==METHOD_INVITE && */ code>=180 && (msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to)) && (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) ) { calc_crc_suffix( msg, tag_suffix ); buf = build_res_buf_from_sip_req(code,reason,&sl_tag,msg,&len,&dummy_bm); } else { buf = build_res_buf_from_sip_req(code,reason,0,msg,&len,&dummy_bm); } if (!buf) { DBG("DEBUG: sl_send_reply: response building failed\n"); goto error; } /* supress multhoming support when sending a reply back -- that makes sure that replies will come from where requests came in; good for NATs (there is no known use for mhomed for locally generated replies; note: forwarded cross-interface replies do benefit of mhomed! */ backup_mhomed=mhomed; mhomed=0; /* use for sending the received interface -bogdan*/ dst.proto=msg->rcv.proto; dst.send_sock=msg->rcv.bind_address; dst.id=msg->rcv.proto_reserved1; #ifdef USE_COMP dst.comp=msg->via1->comp_no; #endif ret = msg_send(&dst, buf, len); mhomed=backup_mhomed; pkg_free(buf); if (ret<0) { goto error; } *(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME; update_sl_stats(code); return 1; error: update_sl_failures(); return -1; }
/*! * helper function for stateless reply */ int sl_reply_helper(struct sip_msg *msg, int code, char *reason, str *tag) { str buf = {0, 0}; str dset = {0, 0}; struct dest_info dst; struct bookmark dummy_bm; int backup_mhomed, ret; str text; int rt, backup_rt; struct run_act_ctx ctx; struct sip_msg pmsg; if (msg->first_line.u.request.method_value==METHOD_ACK) goto error; init_dest_info(&dst); if (reply_to_via) { if (update_sock_struct_from_via(&dst.to, msg, msg->via1 )==-1) { LOG(L_ERR, "ERROR: sl_reply_helper: cannot lookup reply dst: %s\n", msg->via1->host.s); goto error; } } else update_sock_struct_from_ip(&dst.to, msg); /* if that is a redirection message, dump current message set to it */ if (code>=300 && code<400) { dset.s=print_dset(msg, &dset.len); if (dset.s) { add_lump_rpl(msg, dset.s, dset.len, LUMP_RPL_HDR); } } text.s = reason; text.len = strlen(reason); /* add a to-tag if there is a To header field without it */ if ( /* since RFC3261, we append to-tags anywhere we can, except * 100 replies */ /* msg->first_line.u.request.method_value==METHOD_INVITE && */ code>=180 && (msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to)) && (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) ) { if(tag!=NULL && tag->s!=NULL) { buf.s = build_res_buf_from_sip_req(code, &text, tag, msg, (unsigned int*)&buf.len, &dummy_bm); } else { calc_crc_suffix( msg, tag_suffix ); buf.s = build_res_buf_from_sip_req(code, &text, &sl_tag, msg, (unsigned int*)&buf.len, &dummy_bm); } } else { buf.s = build_res_buf_from_sip_req(code, &text, 0, msg, (unsigned int*)&buf.len, &dummy_bm); } if (!buf.s) { DBG("DEBUG: sl_reply_helper: response building failed\n"); goto error; } sl_run_callbacks(SLCB_REPLY_READY, msg, code, reason, &buf, &dst); /* supress multhoming support when sending a reply back -- that makes sure that replies will come from where requests came in; good for NATs (there is no known use for mhomed for locally generated replies; note: forwarded cross-interface replies do benefit of mhomed! */ backup_mhomed=mhomed; mhomed=0; /* use for sending the received interface -bogdan*/ dst.proto=msg->rcv.proto; dst.send_sock=msg->rcv.bind_address; dst.id=msg->rcv.proto_reserved1; #ifdef USE_COMP dst.comp=msg->via1->comp_no; #endif dst.send_flags=msg->rpl_send_flags; ret = msg_send(&dst, buf.s, buf.len); mhomed=backup_mhomed; rt = route_lookup(&event_rt, "sl:local-response"); if (unlikely(rt >= 0 && event_rt.rlist[rt] != NULL)) { if (likely(build_sip_msg_from_buf(&pmsg, buf.s, buf.len, inc_msg_no()) == 0)) { char *tmp = NULL; struct onsend_info onsnd_info; onsnd_info.to=&dst.to; onsnd_info.send_sock=dst.send_sock; onsnd_info.buf=buf.s; onsnd_info.len=buf.len; p_onsend=&onsnd_info; if (unlikely(!IS_SIP(msg))) { /* This is an HTTP reply... So fudge in a CSeq into the parsed message message structure so that $rm will work in the route */ struct hdr_field *hf; struct cseq_body *cseqb; char *tmp2; int len; if ((hf = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field))) == NULL) { LM_ERR("out of package memory\n"); goto event_route_error; } if ((cseqb = (struct cseq_body *) pkg_malloc(sizeof(struct cseq_body))) == NULL) { LM_ERR("out of package memory\n"); pkg_free(hf); goto event_route_error; } if ((tmp = (char *) pkg_malloc(sizeof(char) * (msg->first_line.u.request.method.len + 5))) == NULL) { LM_ERR("out of package memory\n"); pkg_free(cseqb); pkg_free(hf); goto event_route_error; } memset(hf, 0, sizeof(struct hdr_field)); memset(cseqb, 0, sizeof(struct cseq_body)); len = sprintf(tmp, "0 %.*s\r\n", msg->first_line.u.request.method.len, msg->first_line.u.request.method.s); tmp2 = parse_cseq(tmp, &tmp[len], cseqb); hf->type = HDR_CSEQ_T; hf->body.s = tmp; hf->body.len = tmp2 - tmp; hf->parsed = cseqb; pmsg.parsed_flag|=HDR_CSEQ_F; pmsg.cseq = hf; if (pmsg.last_header==0) { pmsg.headers=hf; pmsg.last_header=hf; } else { pmsg.last_header->next=hf; pmsg.last_header=hf; } } backup_rt = get_route_type(); set_route_type(LOCAL_ROUTE); init_run_actions_ctx(&ctx); run_top_route(event_rt.rlist[rt], &pmsg, 0); set_route_type(backup_rt); p_onsend=0; if (tmp != NULL) pkg_free(tmp); event_route_error: free_sip_msg(&pmsg); } } pkg_free(buf.s); if (ret<0) { goto error; } *(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME; update_sl_stats(code); return 1; error: update_sl_failures(); return -1; }