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 #include <stdio.h>
00043 #include <string.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #include <unistd.h>
00047 #include <fcntl.h>
00048 #include <signal.h>
00049
00050 #include "../../mem/shm_mem.h"
00051 #include "../../mem/mem.h"
00052 #include "../../sr_module.h"
00053 #include "../../str.h"
00054 #include "../../ut.h"
00055 #include "../../dprint.h"
00056 #include "../../data_lump_rpl.h"
00057 #include "../../usr_avp.h"
00058 #include "../../parser/parse_uri.h"
00059 #include "../../parser/parse_from.h"
00060 #include "../../parser/parse_content.h"
00061 #include "../../parser/parse_disposition.h"
00062 #include "../../lib/srdb2/db.h"
00063 #include "../../cfg/cfg_struct.h"
00064 #include "cpl_run.h"
00065 #include "cpl_env.h"
00066 #include "cpl_db.h"
00067 #include "cpl_loader.h"
00068 #include "cpl_parser.h"
00069 #include "cpl_nonsig.h"
00070 #include "cpl_rpc.h"
00071 #include "loc_set.h"
00072
00073
00074 #define MAX_PROXY_RECURSE 10
00075 #define MAX_USERHOST_LEN 256
00076
00077
00078
00079 static char *DB_URL = 0;
00080 static char *DB_TABLE = 0;
00081 static char *dtd_file = 0;
00082 static char *lookup_domain = 0;
00083 static pid_t aux_process = 0;
00084 static char *timer_avp = 0;
00085
00086
00087 struct cpl_enviroment cpl_env = {
00088 0,
00089 0,
00090 0,
00091 6,
00092 0,
00093 {0,0},
00094 {-1,-1},
00095 {0,0},
00096 0,
00097 0,
00098 0,
00099 { 0 }
00100 };
00101
00102 struct cpl_functions cpl_fct;
00103
00104
00105 MODULE_VERSION
00106
00107
00108 static int cpl_invoke_script (struct sip_msg* msg, char* str, char* str2);
00109 static int w_process_register(struct sip_msg* msg, char* str, char* str2);
00110 static int w_process_register_norpl(struct sip_msg* msg, char* str,char* str2);
00111 static int cpl_process_register(struct sip_msg* msg, int no_rpl);
00112 static int fixup_cpl_run_script(void** param, int param_no);
00113 static int cpl_init(void);
00114 static int cpl_child_init(int rank);
00115 static int cpl_exit(void);
00116
00117
00118
00119
00120
00121 static cmd_export_t cmds[] = {
00122 {"cpl_run_script",cpl_invoke_script,2,fixup_cpl_run_script,REQUEST_ROUTE},
00123 {"cpl_process_register",w_process_register,0,0,REQUEST_ROUTE},
00124 {"cpl_process_register_norpl",w_process_register_norpl,0,0,REQUEST_ROUTE},
00125 {0, 0, 0, 0, 0}
00126 };
00127
00128
00129
00130
00131
00132 static param_export_t params[] = {
00133 {"cpl_db", PARAM_STRING, &DB_URL },
00134 {"cpl_table", PARAM_STRING, &DB_TABLE },
00135 {"cpl_dtd_file", PARAM_STRING, &dtd_file },
00136 {"proxy_recurse", PARAM_INT, &cpl_env.proxy_recurse },
00137 {"proxy_route", PARAM_INT, &cpl_env.proxy_route },
00138 {"nat_flag", PARAM_INT, &cpl_env.nat_flag },
00139 {"log_dir", PARAM_STRING, &cpl_env.log_dir },
00140 {"case_sensitive", PARAM_INT, &cpl_env.case_sensitive },
00141 {"realm_prefix", PARAM_STR, &cpl_env.realm_prefix },
00142 {"lookup_domain", PARAM_STRING, &lookup_domain },
00143 {"lookup_append_branches", PARAM_INT, &cpl_env.lu_append_branches},
00144 {"timer_avp", PARAM_STRING, &timer_avp },
00145 {0, 0, 0}
00146 };
00147
00148
00149 struct module_exports exports = {
00150 "cpl-c",
00151 cmds,
00152 cpl_rpc_methods,
00153 params,
00154 cpl_init,
00155 (response_function) 0,
00156 (destroy_function) cpl_exit,
00157 0,
00158 (child_init_function) cpl_child_init
00159 };
00160
00161
00162
00163 static int fixup_cpl_run_script(void** param, int param_no)
00164 {
00165 long flag;
00166
00167 if (param_no==1) {
00168 if (!strcasecmp( "incoming", *param))
00169 flag = CPL_RUN_INCOMING;
00170 else if (!strcasecmp( "outgoing", *param))
00171 flag = CPL_RUN_OUTGOING;
00172 else {
00173 LOG(L_ERR,"ERROR:fixup_cpl_run_script: script directive \"%s\""
00174 " unknown!\n",(char*)*param);
00175 return E_UNSPEC;
00176 }
00177 pkg_free(*param);
00178 *param=(void*)flag;
00179 return 0;
00180 } else if (param_no==2) {
00181 if ( !strcasecmp("is_stateless", *param) ) {
00182 flag = 0;
00183 } else if ( !strcasecmp("is_stateful", *param) ) {
00184 flag = CPL_IS_STATEFUL;
00185 } else if ( !strcasecmp("force_stateful", *param) ) {
00186 flag = CPL_FORCE_STATEFUL;
00187 } else {
00188 LOG(L_ERR,"ERROR:fixup_cpl_run_script: flag \"%s\" (second param)"
00189 " unknown!\n",(char*)*param);
00190 return E_UNSPEC;
00191 }
00192 pkg_free(*param);
00193 *param=(void*)flag;
00194 }
00195 return 0;
00196 }
00197
00198
00199
00200 static int cpl_init(void)
00201 {
00202 bind_usrloc_t bind_usrloc;
00203 load_tm_f load_tm;
00204 struct stat stat_t;
00205 char *ptr;
00206 int val;
00207 str foo;
00208
00209 LOG(L_INFO,"CPL - initializing\n");
00210
00211
00212 if (DB_URL==0) {
00213 LOG(L_CRIT,"ERROR:cpl_init: mandatory parameter \"cpl_db\" "
00214 "found empty\n");
00215 goto error;
00216 }
00217
00218 if (DB_TABLE==0) {
00219 LOG(L_CRIT,"ERROR:cpl_init: mandatory parameter \"cpl_table\" "
00220 "found empty\n");
00221 goto error;
00222 }
00223
00224 if (cpl_env.proxy_recurse>MAX_PROXY_RECURSE) {
00225 LOG(L_CRIT,"ERROR:cpl_init: value of proxy_recurse param (%d) exceeds "
00226 "the maximum safety value (%d)\n",
00227 cpl_env.proxy_recurse,MAX_PROXY_RECURSE);
00228 goto error;
00229 }
00230
00231
00232 if (timer_avp) {
00233 foo.s = timer_avp;
00234 foo.len = strlen(foo.s);
00235 if (parse_avp_spec(&foo,&cpl_env.timer_avp_type,&cpl_env.timer_avp,0)<0){
00236 LOG(L_CRIT,"ERROR:cpl_init: invalid timer AVP specs \"%s\"\n",
00237 timer_avp);
00238 goto error;
00239 }
00240 if (cpl_env.timer_avp_type&AVP_NAME_STR && cpl_env.timer_avp.s.s==foo.s) {
00241 cpl_env.timer_avp.s = foo;
00242 }
00243 }
00244
00245 if (dtd_file==0) {
00246 LOG(L_CRIT,"ERROR:cpl_init: mandatory parameter \"cpl_dtd_file\" "
00247 "found empty\n");
00248 goto error;
00249 } else {
00250
00251 if (stat( dtd_file, &stat_t)==-1) {
00252 LOG(L_ERR,"ERROR:cpl_init: checking file \"%s\" status failed;"
00253 " stat returned %s\n",dtd_file,strerror(errno));
00254 goto error;
00255 }
00256 if ( !S_ISREG( stat_t.st_mode ) ) {
00257 LOG(L_ERR,"ERROR:cpl_init: dir \"%s\" is not a regular file!\n",
00258 dtd_file);
00259 goto error;
00260 }
00261 if (access( dtd_file, R_OK )==-1) {
00262 LOG(L_ERR,"ERROR:cpl_init: checking file \"%s\" for permissions "
00263 "failed; access returned %s\n",dtd_file,strerror(errno));
00264 goto error;
00265 }
00266 }
00267
00268 if (cpl_env.log_dir==0) {
00269 LOG(L_INFO,"INFO:cpl_init: log_dir param found void -> logging "
00270 " disabled!\n");
00271 } else {
00272 if ( strlen(cpl_env.log_dir)>MAX_LOG_DIR_SIZE ) {
00273 LOG(L_ERR,"ERROR:cpl_init: dir \"%s\" has a too long name :-(!\n",
00274 cpl_env.log_dir);
00275 goto error;
00276 }
00277
00278 if (stat( cpl_env.log_dir, &stat_t)==-1) {
00279 LOG(L_ERR,"ERROR:cpl_init: checking dir \"%s\" status failed;"
00280 " stat returned %s\n",cpl_env.log_dir,strerror(errno));
00281 goto error;
00282 }
00283 if ( !S_ISDIR( stat_t.st_mode ) ) {
00284 LOG(L_ERR,"ERROR:cpl_init: dir \"%s\" is not a directory!\n",
00285 cpl_env.log_dir);
00286 goto error;
00287 }
00288 if (access( cpl_env.log_dir, R_OK|W_OK )==-1) {
00289 LOG(L_ERR,"ERROR:cpl_init: checking dir \"%s\" for permissions "
00290 "failed; access returned %s\n",
00291 cpl_env.log_dir, strerror(errno));
00292 goto error;
00293 }
00294 }
00295
00296
00297 if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
00298 LOG(L_ERR, "ERROR:cpl_c:cpl_init: cannot import load_tm\n");
00299 goto error;
00300 }
00301
00302 if (load_tm( &(cpl_fct.tmb) )==-1)
00303 goto error;
00304
00305
00306 if (sl_load_api(&cpl_fct.slb)!=0) {
00307 LM_ERR("cannot bind to SL API\n");
00308 return -1;
00309 }
00310
00311
00312 if (lookup_domain) {
00313
00314 bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
00315 if (!bind_usrloc) {
00316 LOG(L_ERR, "ERROR:cpl_c:cpl_init: Can't bind usrloc\n");
00317 goto error;
00318 }
00319 if (bind_usrloc( &(cpl_fct.ulb) ) < 0) {
00320 LOG(L_ERR, "ERROR:cpl_c:cpl_init: importing usrloc failed\n");
00321 goto error;
00322 }
00323
00324 if (cpl_fct.ulb.register_udomain( lookup_domain, &cpl_env.lu_domain)
00325 < 0) {
00326 LOG(L_ERR, "ERROR:cpl_c:cpl_init: Error while registering domain "
00327 "<%s>\n",lookup_domain);
00328 goto error;
00329 }
00330 } else {
00331 LOG(L_NOTICE,"NOTICE:cpl_init: no lookup_domain given -> disable "
00332 " lookup node\n");
00333 }
00334
00335
00336 if ( pipe( cpl_env.cmd_pipe )==-1 ) {
00337 LOG(L_CRIT,"ERROR:cpl_init: cannot create command pipe: %s!\n",
00338 strerror(errno) );
00339 goto error;
00340 }
00341
00342 if ( (val=fcntl(cpl_env.cmd_pipe[1], F_GETFL, 0))<0 ) {
00343 LOG(L_ERR,"ERROR:cpl_init: getting flags from pipe[1] failed: fcntl "
00344 "said %s!\n",strerror(errno));
00345 goto error;
00346 }
00347 if ( fcntl(cpl_env.cmd_pipe[1], F_SETFL, val|O_NONBLOCK) ) {
00348 LOG(L_ERR,"ERROR:cpl_init: setting flags to pipe[1] failed: fcntl "
00349 "said %s!\n",strerror(errno));
00350 goto error;
00351 }
00352
00353
00354 if (init_CPL_parser( dtd_file )!=1 ) {
00355 LOG(L_ERR,"ERROR:cpl_init: init_CPL_parser failed!\n");
00356 goto error;
00357 }
00358
00359
00360 ptr = getenv("TZ");
00361 cpl_env.orig_tz.len = 3 + (ptr?(strlen(ptr)+1):0);
00362 if ( (cpl_env.orig_tz.s=shm_malloc( cpl_env.orig_tz.len ))==0 ) {
00363 LOG(L_ERR,"ERROR:cpl_init: no more shm mem. for saving TZ!\n");
00364 goto error;
00365 }
00366 memcpy(cpl_env.orig_tz.s,"TZ=",3);
00367 if (ptr)
00368 strcpy(cpl_env.orig_tz.s+3,ptr);
00369
00370
00371 if (cpl_env.realm_prefix.s) {
00372
00373 strlower( &cpl_env.realm_prefix );
00374 }
00375
00376
00377
00378 cfg_register_child(1);
00379
00380 return 0;
00381 error:
00382 return -1;
00383 }
00384
00385
00386
00387 static int cpl_child_init(int rank)
00388 {
00389 pid_t pid;
00390
00391
00392 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00393 return 0;
00394
00395
00396 if (rank==1) {
00397 pid = fork();
00398 if (pid==-1) {
00399 LOG(L_CRIT,"ERROR:cpl_child_init(%d): cannot fork: %s!\n",
00400 rank, strerror(errno));
00401 goto error;
00402 } else if (pid==0) {
00403
00404
00405
00406 if (cfg_child_init()) goto error;
00407
00408 cpl_aux_process( cpl_env.cmd_pipe[0], cpl_env.log_dir);
00409 } else {
00410 LOG(L_INFO,"INFO:cpl_child_init(%d): I just gave birth to a child!"
00411 " I'm a PARENT!!\n",rank);
00412
00413 aux_process = pid;
00414 }
00415 }
00416
00417 return cpl_db_init(DB_URL, DB_TABLE);
00418 error:
00419 return -1;
00420 }
00421
00422
00423
00424 static int cpl_exit(void)
00425 {
00426
00427 if (cpl_env.orig_tz.s)
00428 shm_free(cpl_env.orig_tz.s);
00429
00430
00431 if (!aux_process) {
00432 LOG(L_INFO,"INFO:cpl_c:cpl_exit: aux process hasn't been created -> "
00433 "nothing to kill :-(\n");
00434 } else {
00435
00436 if (kill( aux_process, SIGKILL)!=0) {
00437 if (errno==ESRCH) {
00438 LOG(L_INFO,"INFO:cpl_c:cpl_exit: seems that my child is "
00439 "already dead! :-((\n");
00440 } else {
00441 LOG(L_ERR,"ERROR:cpl_c:cpl_exit: killing the aux. process "
00442 "failed! kill said: %s\n",strerror(errno));
00443 return -1;
00444 }
00445 } else {
00446 LOG(L_INFO,"INFO:cl_c:cpl_exit: I have blood on my hands!! I just"
00447 " killed my own child!");
00448 }
00449 }
00450 return 0;
00451 }
00452
00453
00454
00455 #define BUILD_UH_SHM (1<<0)
00456 #define BUILD_UH_ADDSIP (1<<1)
00457
00458 static inline int build_userhost(struct sip_uri *uri, str *uh, int flg)
00459 {
00460 static char buf[MAX_USERHOST_LEN];
00461 unsigned char do_strip;
00462 char *p;
00463 int i;
00464
00465
00466 do_strip = 0;
00467 if (cpl_env.realm_prefix.len && cpl_env.realm_prefix.len<uri->host.len) {
00468 for( i=cpl_env.realm_prefix.len-1 ; i>=0 ; i-- )
00469 if ( cpl_env.realm_prefix.s[i]!=((uri->host.s[i])|(0x20)) )
00470 break;
00471 if (i==-1)
00472 do_strip = 1;
00473 }
00474
00475
00476 uh->len = 4*((flg&BUILD_UH_ADDSIP)!=0) + uri->user.len + 1 +
00477 uri->host.len - do_strip*cpl_env.realm_prefix.len;
00478 if (flg&BUILD_UH_SHM) {
00479 uh->s = (char*)shm_malloc( uh->len + 1 );
00480 if (!uh->s) {
00481 LOG(L_ERR,"ERROR:cpl-c:build_userhost: no more shm memory.\n");
00482 return -1;
00483 }
00484 } else {
00485 uh->s = buf;
00486 if ( uh->len > MAX_USERHOST_LEN ) {
00487 LOG(L_ERR,"ERROR:cpl-c:build_userhost: user+host longer than %d\n",
00488 MAX_USERHOST_LEN);
00489 return -1;
00490 }
00491 }
00492
00493
00494 p = uh->s;
00495 if (flg&BUILD_UH_ADDSIP) {
00496 memcpy( uh->s, "sip:", 4);
00497 p += 4;
00498 }
00499
00500 if (cpl_env.case_sensitive) {
00501 memcpy( p, uri->user.s, uri->user.len);
00502 p += uri->user.len;
00503 } else {
00504 for(i=0;i<uri->user.len;i++)
00505 *(p++) = (0x20)|(uri->user.s[i]);
00506 }
00507 *(p++) = '@';
00508
00509 for( i=do_strip*cpl_env.realm_prefix.len ; i< uri->host.len ; i++ )
00510 *(p++) = (0x20)|(uri->host.s[i]);
00511 *(p++) = 0;
00512
00513
00514 if (p-uh->s!=uh->len+1) {
00515 LOG(L_CRIT,"BUG:cpl-c:build_userhost: buffer overflow l=%d,w=%ld\n",
00516 uh->len,(long)(p-uh->s));
00517 return -1;
00518 }
00519 return 0;
00520 }
00521
00522
00523
00524 static inline int get_dest_user(struct sip_msg *msg, str *uh, int flg)
00525 {
00526 struct sip_uri uri;
00527
00528
00529 DBG("DEBUG:cpl-c:get_dest_user: trying to get user from new_uri\n");
00530 if ( !msg->new_uri.s || parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)==-1
00531 || !uri.user.len )
00532 {
00533 DBG("DEBUG:cpl-c:get_dest_user: trying to get user from R_uri\n");
00534 if ( parse_uri( msg->first_line.u.request.uri.s,
00535 msg->first_line.u.request.uri.len ,&uri)==-1 || !uri.user.len )
00536 {
00537 DBG("DEBUG:cpl-c:get_dest_user: trying to get user from To\n");
00538 if ( (!msg->to&&( (parse_headers(msg,HDR_TO_F,0)==-1) ||
00539 !msg->to)) ||
00540 parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1
00541 || !uri.user.len)
00542 {
00543 LOG(L_ERR,"ERROR:cpl-c:get_dest_user: unable to extract user"
00544 " name from RURI or To header!\n");
00545 return -1;
00546 }
00547 }
00548 }
00549 return build_userhost( &uri, uh, flg);
00550 }
00551
00552
00553
00554 static inline int get_orig_user(struct sip_msg *msg, str *uh, int flg)
00555 {
00556 struct to_body *from;
00557 struct sip_uri uri;
00558
00559
00560
00561 DBG("DEBUG:cpl-c:get_orig_user: trying to get user from From\n");
00562 if ( parse_from_header( msg )==-1 ) {
00563 LOG(L_ERR,"ERROR:cpl-c:get_orig_user: unable to extract URI "
00564 "from FROM header\n");
00565 return -1;
00566 }
00567 from = (struct to_body*)msg->from->parsed;
00568
00569 if (parse_uri( from->uri.s, from->uri.len, &uri)||!uri.user.len) {
00570 LOG(L_ERR,"ERROR:cpl-c:get_orig_user: unable to extract user name "
00571 "from URI (From header)\n");
00572 return -1;
00573 }
00574 return build_userhost( &uri, uh, flg);
00575 }
00576
00577
00578
00579
00580
00581
00582
00583 static int cpl_invoke_script(struct sip_msg* msg, char* str1, char* str2)
00584 {
00585 struct cpl_interpreter *cpl_intr;
00586 str user;
00587 str loc;
00588 str script;
00589
00590
00591 if ( ((unsigned long)str1)&CPL_RUN_INCOMING ) {
00592
00593 if (get_dest_user( msg, &user, BUILD_UH_SHM)==-1)
00594 goto error0;
00595 } else {
00596
00597 if (get_orig_user( msg, &user, BUILD_UH_SHM)==-1)
00598 goto error0;
00599 }
00600
00601
00602 if (get_user_script(&user, &script, 1)==-1)
00603 goto error1;
00604
00605
00606
00607 if ( !script.s || !script.len ) {
00608 shm_free(user.s);
00609 return 1;
00610 }
00611
00612
00613 if ( (cpl_intr=new_cpl_interpreter(msg,&script))==0 )
00614 goto error2;
00615
00616 cpl_intr->flags =(unsigned int)((unsigned long)str1)|((unsigned long)str2);
00617
00618 cpl_intr->user = user;
00619
00620
00621 if ( ((unsigned long)str1)&CPL_RUN_OUTGOING ) {
00622 if (get_dest_user( msg, &loc,BUILD_UH_ADDSIP)==-1)
00623 goto error3;
00624 if (add_location( &(cpl_intr->loc_set), &loc,10,CPL_LOC_DUPL)==-1)
00625 goto error3;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 switch (cpl_run_script( cpl_intr )) {
00638 case SCRIPT_DEFAULT:
00639 free_cpl_interpreter( cpl_intr );
00640 return 1;
00641 case SCRIPT_END:
00642 free_cpl_interpreter( cpl_intr );
00643 case SCRIPT_TO_BE_CONTINUED:
00644 return 0;
00645 case SCRIPT_RUN_ERROR:
00646 case SCRIPT_FORMAT_ERROR:
00647 goto error3;
00648 }
00649
00650 return 1;
00651 error3:
00652 free_cpl_interpreter( cpl_intr );
00653 return -1;
00654 error2:
00655 shm_free(script.s);
00656 error1:
00657 shm_free(user.s);
00658 error0:
00659 return -1;
00660 }
00661
00662
00663
00664 #define CPL_SCRIPT "script"
00665 #define CPL_SCRIPT_LEN (sizeof(CPL_SCRIPT)-1)
00666 #define ACTION_PARAM "action"
00667 #define ACTION_PARAM_LEN (sizeof(ACTION_PARAM)-1)
00668 #define STORE_ACTION "store"
00669 #define STORE_ACTION_LEN (sizeof(STORE_ACTION)-1)
00670 #define REMOVE_ACTION "remove"
00671 #define REMOVE_ACTION_LEN (sizeof(REMOVE_ACTION)-1)
00672
00673 #define REMOVE_SCRIPT 0xcaca
00674 #define STORE_SCRIPT 0xbebe
00675
00676 #define CONTENT_TYPE_HDR ("Content-Type: application/cpl-xml"CRLF)
00677 #define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)
00678
00679 struct cpl_error {
00680 int err_code;
00681 char *err_msg;
00682 };
00683
00684 static struct cpl_error bad_req = {400,"Bad request"};
00685 static struct cpl_error intern_err = {500,"Internal server error"};
00686 static struct cpl_error bad_cpl = {400,"Bad CPL script"};
00687
00688 static struct cpl_error *cpl_err = &bad_req;
00689
00690
00691 static inline int do_script_action(struct sip_msg *msg, int action)
00692 {
00693 str body = STR_NULL;
00694 str user = STR_NULL;
00695 str bin = STR_NULL;
00696 str log = STR_NULL;
00697
00698
00699 if ( !msg->content_length &&
00700 ((parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1)
00701 || !msg->content_length) )
00702 {
00703 LOG(L_ERR,"ERROR:cpl-c:do_script_action: no Content-Length "
00704 "hdr found!\n");
00705 goto error;
00706 }
00707 body.len = get_content_length( msg );
00708
00709
00710 if (get_dest_user( msg, &user, 0)==-1)
00711 goto error;
00712
00713
00714 switch (action) {
00715 case STORE_SCRIPT :
00716
00717 if (body.len==0) {
00718 LOG(L_ERR,"ERROR:cpl-c:do_script_action: 0 content-len found "
00719 "for store\n");
00720 goto error_1;
00721 }
00722
00723 body.s = get_body( msg );
00724 if (body.s==0) {
00725 LOG(L_ERR,"ERROR:cpl-c:do_script_action: cannot extract "
00726 "body from msg!\n");
00727 goto error_1;
00728 }
00729
00730
00731 if ( encodeCPL( &body, &bin, &log)!=1) {
00732 cpl_err = &bad_cpl;
00733 goto error_1;
00734 }
00735
00736
00737 if (write_to_db(user.s, &body, &bin)!=1) {
00738 cpl_err = &intern_err;
00739 goto error_1;
00740 }
00741 break;
00742 case REMOVE_SCRIPT:
00743
00744 if (body.len!=0) {
00745 LOG(L_ERR,"ERROR:cpl-c:do_script_action: non-0 content-len "
00746 "found for remove\n");
00747 goto error_1;
00748 }
00749
00750 if (rmv_from_db(user.s)!=1) {
00751 cpl_err = &intern_err;
00752 goto error_1;
00753 }
00754 break;
00755 }
00756
00757 if (log.s) pkg_free( log.s );
00758 return 0;
00759 error_1:
00760 if (log.s) pkg_free( log.s );
00761 error:
00762 return -1;
00763 }
00764
00765
00766
00767 static inline int do_script_download(struct sip_msg *msg)
00768 {
00769 str user = STR_NULL;
00770 str script = STR_NULL;
00771
00772
00773 if (get_dest_user( msg, &user, 0)==-1)
00774 goto error;
00775
00776
00777 if (get_user_script(&user, &script, 0)==-1)
00778 goto error;
00779
00780
00781 if (add_lump_rpl( msg, CONTENT_TYPE_HDR, CONTENT_TYPE_HDR_LEN,
00782 LUMP_RPL_HDR)==0) {
00783 LOG(L_ERR,"ERROR:cpl-c:do_script_download: cannot build hdr lump\n");
00784 cpl_err = &intern_err;
00785 goto error;
00786 }
00787
00788 if (script.s!=0) {
00789
00790
00791
00792 if ( add_lump_rpl( msg, script.s, script.len, LUMP_RPL_BODY)==0) {
00793 LOG(L_ERR,"ERROR:cpl-c:do_script_download: cannot build "
00794 "body lump\n");
00795 cpl_err = &intern_err;
00796 goto error;
00797 }
00798
00799 shm_free( script.s );
00800 }
00801
00802 return 0;
00803 error:
00804 if (script.s)
00805 shm_free(script.s);
00806 return -1;
00807 }
00808
00809
00810
00811 static int w_process_register(struct sip_msg* msg, char* str, char* str2)
00812 {
00813 return cpl_process_register( msg, 0);
00814 }
00815
00816
00817
00818 static int w_process_register_norpl(struct sip_msg* msg, char* str,char* str2)
00819 {
00820 return cpl_process_register( msg, 1);
00821 }
00822
00823
00824
00825 static int cpl_process_register(struct sip_msg* msg, int no_rpl)
00826 {
00827 struct disposition *disp;
00828 struct disposition_param *param;
00829 int ret;
00830 int mime;
00831 int *mimes;
00832
00833
00834
00835
00836
00837
00838 mime = parse_content_type_hdr( msg );
00839 if (mime==-1)
00840 goto error;
00841
00842
00843 DBG("DEBUG:cpl_process_register: Content-Type mime found %u, %u\n",
00844 mime>>16,mime&0x00ff);
00845 if ( mime && mime==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML ) {
00846
00847
00848 DBG("DEBUG:cpl_process_register: carrying CPL -> look at "
00849 "Content-Disposition\n");
00850 if (parse_content_disposition( msg )!=0) {
00851 LOG(L_ERR,"ERROR:cpl_process_register: Content-Disposition missing "
00852 "or corrupted\n");
00853 goto error;
00854 }
00855 disp = get_content_disposition(msg);
00856 print_disposition( disp );
00857
00858 if (disp->type.len!=CPL_SCRIPT_LEN ||
00859 strncasecmp(disp->type.s,CPL_SCRIPT,CPL_SCRIPT_LEN) ) {
00860 LOG(L_ERR,"ERROR:cpl_process_register: bogus message - Content-Type"
00861 "says CPL_SCRIPT, but Content-Disposition something else\n");
00862 goto error;
00863 }
00864
00865 for(param=disp->params;param;param=param->next) {
00866 if (param->name.len==ACTION_PARAM_LEN &&
00867 !strncasecmp(param->name.s,ACTION_PARAM,ACTION_PARAM_LEN))
00868 break;
00869 }
00870 if (param==0) {
00871 LOG(L_ERR,"ERROR:cpl_process_register: bogus message - "
00872 "Content-Disposition has no action param\n");
00873 goto error;
00874 }
00875
00876 if (param->body.len==STORE_ACTION_LEN &&
00877 !strncasecmp( param->body.s, STORE_ACTION, STORE_ACTION_LEN)) {
00878
00879
00880 if (do_script_action( msg, STORE_SCRIPT)==-1)
00881 goto error;
00882 } else
00883 if (param->body.len==REMOVE_ACTION_LEN &&
00884 !strncasecmp( param->body.s, REMOVE_ACTION, REMOVE_ACTION_LEN)) {
00885
00886 if (do_script_action( msg, REMOVE_SCRIPT)==-1)
00887 goto error;
00888 } else {
00889 LOG(L_ERR,"ERROR:cpl_process_register: unknown action <%.*s>\n",
00890 param->body.len,param->body.s);
00891 goto error;
00892 }
00893
00894
00895 if (no_rpl)
00896 goto resume_script;
00897
00898
00899 cpl_fct.slb.zreply( msg, 200, "OK");
00900
00901
00902 goto stop_script;
00903 }
00904
00905
00906 if ( (ret=parse_accept_hdr(msg))==-1)
00907 goto error;
00908 if (ret==0 || (mimes=get_accept(msg))==0 )
00909
00910 goto resume_script;
00911
00912
00913 while (*mimes) {
00914 DBG("DEBUG: accept mime found %u, %u\n",
00915 (*mimes)>>16,(*mimes)&0x00ff);
00916 if (*mimes==(TYPE_ALL<<16)+SUBTYPE_ALL ||
00917 *mimes==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML )
00918 break;
00919 mimes++;
00920 }
00921 if (*mimes==0)
00922
00923 goto resume_script;
00924
00925
00926
00927 if (do_script_download( msg )==-1)
00928 goto error;
00929
00930
00931 if (no_rpl)
00932 goto resume_script;
00933
00934
00935 cpl_fct.slb.zreply( msg, 200, "OK");
00936
00937 stop_script:
00938 return 0;
00939 resume_script:
00940 return 1;
00941 error:
00942
00943 cpl_fct.slb.zreply( msg, cpl_err->err_code, cpl_err->err_msg);
00944
00945 return 0;
00946 }
00947
00948
00949