00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "../../globals.h"
00050 #include "../../forward.h"
00051 #include "../../dprint.h"
00052 #include "../../md5utils.h"
00053 #include "../../msg_translator.h"
00054 #include "../../udp_server.h"
00055 #include "../../timer.h"
00056 #include "../../mem/mem.h"
00057 #include "../../mem/shm_mem.h"
00058 #include "../../crc.h"
00059 #include "../../dset.h"
00060 #include "../../data_lump_rpl.h"
00061 #include "../../action.h"
00062 #include "../../config.h"
00063 #include "../../tags.h"
00064 #include "sl.h"
00065 #include "sl_funcs.h"
00066 #include "sl_cb.h"
00067 #include "../../usr_avp.h"
00068 #include <string.h>
00069
00070 static char sl_tag_buf[TOTAG_VALUE_LEN];
00071 static str sl_tag = {sl_tag_buf,TOTAG_VALUE_LEN};
00072
00073 static char *tag_suffix;
00074
00075
00076 static unsigned int *sl_timeout = 0;
00077
00078
00079
00080 int sl_startup(void)
00081 {
00082
00083 init_tags( sl_tag.s, &tag_suffix,
00084 "Kamailio-stateless",
00085 SL_TOTAG_SEPARATOR );
00086
00087
00088 sl_timeout = (unsigned int*)shm_malloc(sizeof(unsigned int));
00089 if (!sl_timeout)
00090 {
00091 LM_ERR("no more shm memory!\n");
00092 return -1;
00093 }
00094 *(sl_timeout)=get_ticks();
00095
00096 return 0;
00097 }
00098
00099
00100
00101 int sl_shutdown(void)
00102 {
00103 if (sl_timeout)
00104 shm_free(sl_timeout);
00105 return 1;
00106 }
00107
00108
00109
00110 static inline void update_sl_reply_stat(int code)
00111 {
00112 stat_var *numerical_stat;
00113
00114
00115 if (!sl_enable_stats)
00116 return;
00117
00118
00119
00120
00121 if (code < 200 ) {
00122 update_stat( tx_1xx_rpls , 1);
00123 } else if (code<300) {
00124 update_stat( tx_2xx_rpls , 1);
00125 } else if (code<400) {
00126 update_stat( tx_3xx_rpls , 1);
00127 } else if (code<500) {
00128 update_stat( tx_4xx_rpls , 1);
00129 } else if (code<600) {
00130 update_stat( tx_5xx_rpls , 1);
00131 } else {
00132 update_stat( tx_6xx_rpls , 1);
00133 }
00134
00135 update_stat( sent_rpls , 1);
00136
00137 numerical_stat = get_stat_var_from_num_code(code, 1);
00138
00139 if (numerical_stat != NULL)
00140 update_stat(numerical_stat, 1);
00141 }
00142
00143 int sl_get_reply_totag(struct sip_msg *msg, str *totag)
00144 {
00145 if(msg==NULL || totag==NULL)
00146 return -1;
00147 calc_crc_suffix(msg, tag_suffix);
00148 *totag = sl_tag;
00149 return 1;
00150 }
00151
00152
00153 int sl_send_reply_helper(struct sip_msg *msg ,int code, str *text, str *tag)
00154 {
00155 str buf;
00156 union sockaddr_union to;
00157 char *dset;
00158 int dset_len;
00159 struct bookmark dummy_bm;
00160 int backup_mhomed;
00161 int ret;
00162
00163 if ( msg->first_line.u.request.method_value==METHOD_ACK)
00164 goto error;
00165
00166 if (reply_to_via) {
00167 if (update_sock_struct_from_via( &(to), msg, msg->via1 )==-1) {
00168 LM_ERR("cannot lookup reply dst: %s\n", msg->via1->host.s );
00169 goto error;
00170 }
00171 } else update_sock_struct_from_ip( &to, msg );
00172
00173
00174 if (code>=300 && code<400) {
00175 dset=print_dset(msg, &dset_len);
00176 if (dset) {
00177 add_lump_rpl(msg, dset, dset_len, LUMP_RPL_HDR);
00178 }
00179 }
00180
00181
00182 if ( code>=180 &&
00183 (msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to))
00184 && (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) )
00185 {
00186 if(tag!=NULL && tag->s!=NULL) {
00187 buf.s = build_res_buf_from_sip_req( code, text, tag,
00188 msg, (unsigned int*)&buf.len, &dummy_bm);
00189 } else {
00190 calc_crc_suffix( msg, tag_suffix );
00191 buf.s = build_res_buf_from_sip_req( code, text, &sl_tag, msg,
00192 (unsigned int*)&buf.len, &dummy_bm);
00193 }
00194 } else {
00195 buf.s = build_res_buf_from_sip_req( code, text, 0, msg,
00196 (unsigned int*)&buf.len, &dummy_bm);
00197 }
00198 if (!buf.s) {
00199 LM_ERR("response building failed\n");
00200 goto error;
00201 }
00202
00203 run_sl_callbacks( SLCB_REPLY_OUT, msg, &buf, code, text, &to );
00204
00205
00206
00207
00208
00209
00210 backup_mhomed=mhomed;
00211 mhomed=0;
00212
00213 ret = msg_send( msg->rcv.bind_address, msg->rcv.proto, &to,
00214 msg->rcv.proto_reserved1, buf.s, buf.len);
00215 mhomed=backup_mhomed;
00216 pkg_free(buf.s);
00217
00218 if (ret<0)
00219 goto error;
00220
00221 *(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME;
00222
00223 update_sl_reply_stat(code);
00224
00225 return 1;
00226
00227 error:
00228 return -1;
00229 }
00230
00231
00232
00233 int sl_send_reply(struct sip_msg *msg ,int code, str *text)
00234 {
00235 return sl_send_reply_helper(msg, code, text, 0);
00236 }
00237
00238
00239
00240 int sl_send_reply_dlg(struct sip_msg *msg ,int code, str *text, str *tag)
00241 {
00242 return sl_send_reply_helper(msg, code, text, tag);
00243 }
00244
00245
00246
00247 int sl_reply_error(struct sip_msg *msg )
00248 {
00249 char err_buf[MAX_REASON_LEN];
00250 int sip_error;
00251 str text;
00252 int ret;
00253
00254 ret = err2reason_phrase( prev_ser_error, &sip_error,
00255 err_buf, sizeof(err_buf), "SL");
00256 if (ret<=0) {
00257 LM_ERR("err2reason failed\n");
00258 return -1;
00259 }
00260 text.len = ret;
00261 text.s = err_buf;
00262 LM_DBG("error text is %.*s\n",text.len,text.s);
00263
00264 ret = sl_send_reply_helper( msg, sip_error, &text, 0);
00265 if (ret==-1)
00266 return -1;
00267 if_update_stat( sl_enable_stats, sent_err_rpls , 1);
00268 return ret;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 int sl_filter_ACK(struct sip_msg *msg, void *bar )
00278 {
00279 str *tag_str;
00280
00281 if (msg->first_line.u.request.method_value!=METHOD_ACK)
00282 goto pass_it;
00283
00284
00285 if ( *(sl_timeout)<= get_ticks() )
00286 {
00287 LM_DBG("to late to be a local ACK!\n");
00288 goto pass_it;
00289 }
00290
00291
00292 if (parse_headers( msg, HDR_TO_F, 0 )==-1)
00293 {
00294 LM_ERR("unable to parse To header\n");
00295 return -1;
00296 }
00297
00298 if (msg->to) {
00299 tag_str = &(get_to(msg)->tag_value);
00300 if ( tag_str->len==TOTAG_VALUE_LEN )
00301 {
00302
00303 calc_crc_suffix(msg, tag_suffix);
00304
00305 if (memcmp(tag_str->s,sl_tag.s,sl_tag.len)==0) {
00306 LM_DBG("local ACK found -> dropping it!\n");
00307 if_update_stat( sl_enable_stats, rcv_acks, 1);
00308 run_sl_callbacks( SLCB_ACK_IN, msg, 0, 0, 0, 0 );
00309 return 0;
00310 }
00311 }
00312 }
00313
00314 pass_it:
00315 return 1;
00316 }