00001
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <fnmatch.h>
00031
00032 #include "../../sr_module.h"
00033 #include "../../dprint.h"
00034 #include "../../data_lump.h"
00035 #include "../../msg_translator.h"
00036 #include "../../tcp_options.h"
00037 #include "../../mod_fix.h"
00038
00039 #include "api.h"
00040
00041 MODULE_VERSION
00042
00043 static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2);
00044
00045 static int change_reply_status_f(sip_msg_t*, char*, char*);
00046 static int change_reply_status_fixup(void** param, int param_no);
00047
00048 static int w_keep_hf_f(sip_msg_t*, char*, char*);
00049
00050 static int w_fnmatch2_f(sip_msg_t*, char*, char*);
00051 static int w_fnmatch3_f(sip_msg_t*, char*, char*, char*);
00052 static int fixup_fnmatch(void** param, int param_no);
00053
00054 static int w_remove_body_f(struct sip_msg*, char*, char *);
00055 static int bind_textopsx(textopsx_api_t *tob);
00056
00057 static int mod_init(void);
00058
00059
00060 static cmd_export_t cmds[] = {
00061 {"msg_apply_changes", (cmd_function)msg_apply_changes_f, 0,
00062 0, REQUEST_ROUTE },
00063 {"change_reply_status", change_reply_status_f, 2,
00064 change_reply_status_fixup, ONREPLY_ROUTE },
00065 {"remove_body", (cmd_function)w_remove_body_f, 0,
00066 0, ANY_ROUTE },
00067 {"keep_hf", (cmd_function)w_keep_hf_f, 1,
00068 fixup_regexp_null, ANY_ROUTE },
00069 {"fnmatch", (cmd_function)w_fnmatch2_f, 2,
00070 fixup_fnmatch, ANY_ROUTE },
00071 {"fnmatch", (cmd_function)w_fnmatch3_f, 3,
00072 fixup_fnmatch, ANY_ROUTE },
00073 {"bind_textopsx", (cmd_function)bind_textopsx, 1,
00074 0, ANY_ROUTE },
00075
00076
00077 {0,0,0,0,0}
00078 };
00079
00080
00081 struct module_exports exports= {
00082 "textopsx",
00083 cmds,
00084 0,
00085 0,
00086 mod_init,
00087 0,
00088 0,
00089 0,
00090 0
00091 };
00092
00093
00097 static int mod_init(void)
00098 {
00099 #ifdef USE_TCP
00100 tcp_set_clone_rcvbuf(1);
00101 #endif
00102 return 0;
00103 }
00104
00108 static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2)
00109 {
00110 struct dest_info dst;
00111 str obuf;
00112 sip_msg_t tmp;
00113
00114 if(get_route_type()!=REQUEST_ROUTE)
00115 {
00116 LM_ERR("invalid usage - not in request route\n");
00117 return -1;
00118 }
00119
00120 init_dest_info(&dst);
00121 dst.proto = PROTO_UDP;
00122 obuf.s = build_req_buf_from_sip_req(msg,
00123 (unsigned int*)&obuf.len, &dst,
00124 BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
00125 if(obuf.s == NULL)
00126 {
00127 LM_ERR("couldn't update msg buffer content\n");
00128 return -1;
00129 }
00130 if(obuf.len>=BUF_SIZE)
00131 {
00132 LM_ERR("new buffer overflow (%d)\n", obuf.len);
00133 pkg_free(obuf.s);
00134 return -1;
00135 }
00136
00137 memcpy(&tmp, msg, sizeof(sip_msg_t));
00138
00139
00140 if(msg->dst_uri.s!=NULL)
00141 {
00142 msg->dst_uri.s = NULL;
00143 msg->dst_uri.len = 0;
00144 }
00145 if(msg->path_vec.s!=NULL)
00146 {
00147 msg->path_vec.s = NULL;
00148 msg->path_vec.len = 0;
00149 }
00150
00151
00152 free_sip_msg(msg);
00153 memset(msg, 0, sizeof(sip_msg_t));
00154
00155
00156 msg->buf = tmp.buf;
00157 msg->id = tmp.id;
00158 msg->rcv = tmp.rcv;
00159 msg->set_global_address = tmp.set_global_address;
00160 msg->set_global_port = tmp.set_global_port;
00161 msg->flags = tmp.flags;
00162 msg->msg_flags = tmp.msg_flags;
00163 msg->hash_index = tmp.hash_index;
00164 msg->force_send_socket = tmp.force_send_socket;
00165 msg->fwd_send_flags = tmp.fwd_send_flags;
00166 msg->rpl_send_flags = tmp.rpl_send_flags;
00167 msg->dst_uri = tmp.dst_uri;
00168 msg->path_vec = tmp.path_vec;
00169
00170 memcpy(msg->buf, obuf.s, obuf.len);
00171 msg->len = obuf.len;
00172 msg->buf[msg->len] = '\0';
00173
00174
00175 pkg_free(obuf.s);
00176
00177
00178 LM_DBG("SIP Request content updated - reparsing\n");
00179 if (parse_msg(msg->buf, msg->len, msg)!=0){
00180 LM_ERR("parse_msg failed\n");
00181 return -1;
00182 }
00183
00184 return 1;
00185 }
00186
00187
00191 static int change_reply_status_fixup(void** param, int param_no)
00192 {
00193 if (param_no == 1) {
00194 return fixup_var_int_12(param, param_no);
00195 } else if (param_no == 2)
00196 return fixup_var_pve_str_12(param, param_no);
00197 else
00198 return 0;
00199 }
00200
00204 static int change_reply_status_f(struct sip_msg* msg, char* _code, char* _reason)
00205 {
00206 int code;
00207 str reason;
00208 struct lump *l;
00209 char *ch;
00210
00211 if (get_int_fparam(&code, msg, (fparam_t*)_code)
00212 || get_str_fparam(&reason, msg, (fparam_t*)_reason)
00213 || (reason.len == 0)
00214 ) {
00215 LOG(L_ERR, "ERROR: textops: cannot get parameter\n");
00216 return -1;
00217 }
00218
00219 if ((code < 100) || (code > 699)) {
00220 LOG(L_ERR, "ERROR: textops: wrong status code: %d\n",
00221 code);
00222 return -1;
00223 }
00224
00225 if (((code < 300) || (msg->REPLY_STATUS < 300))
00226 && (code/100 != msg->REPLY_STATUS/100)
00227 ) {
00228 LOG(L_ERR, "ERROR: textops: the class of provisional or "
00229 "positive final replies cannot be changed\n");
00230 return -1;
00231 }
00232
00233
00234 msg->first_line.u.reply.statuscode = code;
00235 msg->first_line.u.reply.status.s[2] = code % 10 + '0'; code /= 10;
00236 msg->first_line.u.reply.status.s[1] = code % 10 + '0'; code /= 10;
00237 msg->first_line.u.reply.status.s[0] = code + '0';
00238
00239 l = del_lump(msg,
00240 msg->first_line.u.reply.reason.s - msg->buf,
00241 msg->first_line.u.reply.reason.len,
00242 0);
00243 if (!l) {
00244 LOG(L_ERR, "ERROR: textops(): Failed to add del lump\n");
00245 return -1;
00246 }
00247
00248 ch = (char *)pkg_malloc(reason.len);
00249 if (!ch) {
00250 LOG(L_ERR, "ERROR: textops: Not enough memory\n");
00251 return -1;
00252 }
00253 memcpy(ch, reason.s, reason.len);
00254 if (insert_new_lump_after(l, ch, reason.len, 0)==0){
00255 LOG(L_ERR, "ERROR: textops: failed to add new lump: %.*s\n",
00256 reason.len, ch);
00257 pkg_free(ch);
00258 return -1;
00259 }
00260
00261 return 1;
00262 }
00263
00264
00268 static int w_remove_body_f(struct sip_msg *msg, char *p1, char *p2)
00269 {
00270 str body = {0,0};
00271
00272 body.len = 0;
00273 body.s = get_body(msg);
00274 if (body.s==0)
00275 {
00276 LM_DBG("no body in the message\n");
00277 return 1;
00278 }
00279 body.len = msg->buf + msg->len - body.s;
00280 if (body.len<=0)
00281 {
00282 LM_DBG("empty body in the message\n");
00283 return 1;
00284 }
00285 if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0)
00286 {
00287 LM_ERR("cannot remove body\n");
00288 return -1;
00289 }
00290 return 1;
00291 }
00292
00293
00297 static int w_keep_hf_f(struct sip_msg* msg, char* key, char* foo)
00298 {
00299 struct hdr_field *hf;
00300 regex_t *re;
00301 regmatch_t pmatch;
00302 char c;
00303 struct lump* l;
00304
00305 re = (regex_t*)key;
00306
00307
00308 parse_headers(msg, HDR_EOH_F, 0);
00309 for (hf=msg->headers; hf; hf=hf->next)
00310 {
00311 switch(hf->type) {
00312 case HDR_FROM_T:
00313 case HDR_TO_T:
00314 case HDR_CALLID_T:
00315 case HDR_CSEQ_T:
00316 case HDR_VIA_T:
00317 case HDR_VIA2_T:
00318 case HDR_CONTACT_T:
00319 case HDR_CONTENTLENGTH_T:
00320 case HDR_CONTENTTYPE_T:
00321 case HDR_ROUTE_T:
00322 case HDR_RECORDROUTE_T:
00323 case HDR_MAXFORWARDS_T:
00324 continue;
00325 default:
00326 ;
00327 }
00328
00329 c = hf->name.s[hf->name.len];
00330 hf->name.s[hf->name.len] = '\0';
00331 if (regexec(re, hf->name.s, 1, &pmatch, 0)!=0)
00332 {
00333
00334 hf->name.s[hf->name.len] = c;
00335 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
00336 if (l==0)
00337 {
00338 LM_ERR("cannot remove header\n");
00339 return -1;
00340 }
00341 } else {
00342 hf->name.s[hf->name.len] = c;
00343 }
00344 }
00345
00346 return -1;
00347 }
00348
00352 static int w_fnmatch(str *val, str *match, str *flags)
00353 {
00354 int i;
00355 i = 0;
00356 #ifdef FNM_CASEFOLD
00357 if(flags && (flags->s[0]=='i' || flags->s[0]=='I'))
00358 i = FNM_CASEFOLD;
00359 #endif
00360 if(fnmatch(match->s, val->s, i)==0)
00361 return 0;
00362 return -1;
00363 }
00364
00368 static int w_fnmatch2_f(sip_msg_t *msg, char *val, char *match)
00369 {
00370 str sval;
00371 str smatch;
00372 if(get_str_fparam(&sval, msg, (fparam_t*)val)<0
00373 || get_str_fparam(&smatch, msg, (fparam_t*)match)<0)
00374 {
00375 LM_ERR("invalid parameters");
00376 return -1;
00377 }
00378 if(w_fnmatch(&sval, &smatch, NULL)<0)
00379 return -1;
00380 return 1;
00381 }
00382
00386 static int w_fnmatch3_f(sip_msg_t *msg, char *val, char *match, char *flags)
00387 {
00388 str sval;
00389 str smatch;
00390 str sflags;
00391 if(get_str_fparam(&sval, msg, (fparam_t*)val)<0
00392 || get_str_fparam(&smatch, msg, (fparam_t*)match)<0
00393 || get_str_fparam(&sflags, msg, (fparam_t*)flags)<0)
00394 {
00395 LM_ERR("invalid parameters");
00396 return -1;
00397 }
00398 if(w_fnmatch(&sval, &smatch, &sflags)<0)
00399 return -1;
00400 return 1;
00401 }
00402
00406 static int fixup_fnmatch(void** param, int param_no)
00407 {
00408 if (param_no == 1) {
00409 return fixup_var_pve_12(param, param_no);
00410 } else if (param_no == 2) {
00411 return fixup_var_pve_12(param, param_no);
00412 } else if (param_no == 3) {
00413 return fixup_var_pve_12(param, param_no);
00414 } else {
00415 return 0;
00416 }
00417
00418 }
00419
00420
00421
00422
00423 static int bind_textopsx(textopsx_api_t *tob){
00424 if(tob==NULL){
00425 LM_WARN("textopsx_binds: Cannot load textopsx API into a NULL pointer\n");
00426 return -1;
00427 }
00428 tob->msg_apply_changes = msg_apply_changes_f;
00429 return 0;
00430 }