static int xl_get_dset(struct sip_msg *msg, str *res, str *hp, int hi, int hf) { if(msg==NULL || res==NULL) return -1; res->s = print_dset(msg, &res->len); if ((res->s) == NULL) return xl_get_null(msg, res, hp, hi, hf); res->len -= CRLF_LEN; return 0; }
/* 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); } }
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; }
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; }
/*! * 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; }