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