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 #include <stdio.h>
00033 #include <string.h>
00034 #include <time.h>
00035 #include <stdlib.h>
00036
00037 #include "../../mem/mem.h"
00038 #include "../../mem/shm_mem.h"
00039 #include "../../str.h"
00040 #include "../../ut.h"
00041 #include "../../dprint.h"
00042 #include "../../parser/msg_parser.h"
00043 #include "../../data_lump_rpl.h"
00044 #include "../tm/tm_load.h"
00045 #include "../usrloc/usrloc.h"
00046 #include "CPL_tree.h"
00047 #include "loc_set.h"
00048 #include "cpl_utils.h"
00049 #include "cpl_nonsig.h"
00050 #include "cpl_sig.h"
00051 #include "cpl_env.h"
00052 #include "cpl_run.h"
00053
00054
00055 #define EO_SCRIPT ((char*)0xffffffff)
00056 #define DEFAULT_ACTION ((char*)0xfffffffe)
00057 #define CPL_SCRIPT_ERROR ((char*)0xfffffffd)
00058 #define CPL_RUNTIME_ERROR ((char*)0xfffffffc)
00059 #define CPL_TO_CONTINUE ((char*)0xfffffffb)
00060
00061 #define HDR_NOT_FOUND ((char*)0xffffffff)
00062 #define UNDEF_CHAR (0xff)
00063
00064
00065 static str cpl_301_reason = str_init("Moved permanently");
00066 static str cpl_302_reason = str_init("Moved temporarily");
00067
00068 #define check_overflow_by_ptr(_ptr_,_intr_,_error_) \
00069 do {\
00070 if ( (char*)(_ptr_)>(_intr_)->script.len+(_intr_)->script.s ) {\
00071 LM_ERR("overflow detected ip=%p ptr=%p in "\
00072 "func. %s, line %d\n",(_intr_)->ip,_ptr_,__FILE__,__LINE__);\
00073 goto _error_; \
00074 } \
00075 }while(0)
00076
00077 #define check_overflow_by_offset(_len_,_intr_,_error_) \
00078 do {\
00079 if ( (char*)((_intr_)->ip+(_len_)) > \
00080 (_intr_)->script.len+(_intr_)->script.s ) {\
00081 LM_ERR("overflow detected ip=%p offset=%d in "\
00082 "func. %s, line %d\n",(_intr_)->ip,_len_,__FILE__,__LINE__);\
00083 goto _error_; \
00084 } \
00085 }while(0)
00086
00087 #define get_first_child(_node_) \
00088 ((NR_OF_KIDS(_node_)==0)?DEFAULT_ACTION:(_node_)+KID_OFFSET(_node_,0))
00089
00090 #define get_basic_attr(_p_,_code_,_n_,_intr_,_error_) \
00091 do{\
00092 check_overflow_by_ptr( (_p_)+BASIC_ATTR_SIZE, _intr_, _error_);\
00093 _code_ = ntohs( *((unsigned short*)(_p_)) );\
00094 _n_ = ntohs( *((unsigned short*)((_p_)+2)) );\
00095 (_p_) += 4;\
00096 }while(0)
00097
00098 #define get_str_attr(_p_,_s_,_len_,_intr_,_error_,_FIXUP_) \
00099 do{\
00100 if ( ((int)(_len_))-(_FIXUP_)<=0 ) {\
00101 LM_ERR("%s:%d: attribute is an empty string\n",\
00102 __FILE__,__LINE__);\
00103 goto _error_; \
00104 } else {\
00105 check_overflow_by_ptr( (_p_)+(_len_), _intr_, _error_);\
00106 _s_ = _p_;\
00107 (_p_) += (_len_) + 1*(((_len_)&0x0001)==1);\
00108 (_len_) -= (_FIXUP_);\
00109 }\
00110 }while(0)
00111
00112
00113
00114 struct cpl_interpreter* new_cpl_interpreter( struct sip_msg *msg, str *script)
00115 {
00116 struct cpl_interpreter *intr = 0;
00117
00118 intr = (struct cpl_interpreter*)shm_malloc(sizeof(struct cpl_interpreter));
00119 if (!intr) {
00120 LM_ERR("no more shm free memory!\n");
00121 goto error;
00122 }
00123 memset( intr, 0, sizeof(struct cpl_interpreter));
00124
00125
00126 intr->script.s = script->s;
00127 intr->script.len = script->len;
00128 intr->recv_time = time(0);
00129 intr->ip = script->s;
00130 intr->msg = msg;
00131
00132
00133 if ( NODE_TYPE(intr->ip)!=CPL_NODE ) {
00134 LM_ERR("first node is not CPL!!\n");
00135 goto error;
00136 }
00137
00138 return intr;
00139 error:
00140 return 0;
00141 }
00142
00143
00144
00145 void free_cpl_interpreter(struct cpl_interpreter *intr)
00146 {
00147 if (intr) {
00148 empty_location_set( &(intr->loc_set) );
00149 if (intr->script.s)
00150 shm_free( intr->script.s);
00151 if (intr->user.s)
00152 shm_free(intr->user.s);
00153 if (intr->flags&CPL_RURI_DUPLICATED)
00154 shm_free(intr->ruri);
00155 if (intr->flags&CPL_TO_DUPLICATED)
00156 shm_free(intr->to);
00157 if (intr->flags&CPL_FROM_DUPLICATED)
00158 shm_free(intr->from);
00159 if (intr->flags&CPL_SUBJECT_DUPLICATED)
00160 shm_free(intr->subject);
00161 if (intr->flags&CPL_ORGANIZATION_DUPLICATED)
00162 shm_free(intr->organization);
00163 if (intr->flags&CPL_USERAGENT_DUPLICATED)
00164 shm_free(intr->user_agent);
00165 if (intr->flags&CPL_ACCEPTLANG_DUPLICATED)
00166 shm_free(intr->accept_language);
00167 if (intr->flags&CPL_PRIORITY_DUPLICATED)
00168 shm_free(intr->priority);
00169 shm_free(intr);
00170 }
00171 }
00172
00173
00174
00175
00176
00177 static inline char *run_cpl_node( struct cpl_interpreter *intr )
00178 {
00179 char *kid;
00180 unsigned char start;
00181 int i;
00182
00183 start = (intr->flags&CPL_RUN_INCOMING)?INCOMING_NODE:OUTGOING_NODE;
00184
00185 for(i=0;i<NR_OF_KIDS(intr->ip);i++) {
00186 kid= intr->ip + KID_OFFSET(intr->ip,i);
00187 if ( NODE_TYPE(kid)==start ) {
00188 return get_first_child(kid);
00189 } else
00190 if (NODE_TYPE(kid)==SUBACTION_NODE ||
00191 NODE_TYPE(kid)==ANCILLARY_NODE ||
00192 NODE_TYPE(kid)==INCOMING_NODE ||
00193 NODE_TYPE(kid)==OUTGOING_NODE ) {
00194 continue;
00195 } else {
00196 LM_ERR("unknown child type (%d) "
00197 "for CPL node!!\n",NODE_TYPE(kid));
00198 return CPL_SCRIPT_ERROR;
00199 }
00200 }
00201
00202 LM_DBG("CPL node has no %d subnode -> default\n", start);
00203 return DEFAULT_ACTION;
00204 }
00205
00206
00207
00208
00209
00210 static inline char *run_lookup( struct cpl_interpreter *intr )
00211 {
00212 unsigned short attr_name;
00213 unsigned short n;
00214 unsigned char clear;
00215 char *p;
00216 char *kid;
00217 char *failure_kid = 0;
00218 char *success_kid = 0;
00219 char *notfound_kid = 0;
00220 int i;
00221 time_t tc;
00222 urecord_t* r;
00223 ucontact_t* contact;
00224
00225 clear = NO_VAL;
00226
00227
00228 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00229 get_basic_attr(p,attr_name,n,intr,script_error);
00230 switch (attr_name) {
00231 case CLEAR_ATTR:
00232 if (n!=YES_VAL && n!=NO_VAL)
00233 LM_WARN("invalid value (%u) found"
00234 " for param. CLEAR in LOOKUP node -> using "
00235 "default (%u)!\n",n,clear);
00236 else
00237 clear = n;
00238 break;
00239 default:
00240 LM_ERR("unknown attribute (%d) in LOOKUP node\n",attr_name);
00241 goto script_error;
00242 }
00243 }
00244
00245
00246 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00247 kid = intr->ip + KID_OFFSET(intr->ip,i);
00248 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00249 switch ( NODE_TYPE(kid) ) {
00250 case SUCCESS_NODE :
00251 success_kid = kid;
00252 break;
00253 case NOTFOUND_NODE:
00254 notfound_kid = kid;
00255 break;
00256 case FAILURE_NODE:
00257 failure_kid = kid;
00258 break;
00259 default:
00260 LM_ERR("unknown output node type"
00261 " (%d) for LOOKUP node\n",NODE_TYPE(kid));
00262 goto script_error;
00263 }
00264 }
00265
00266 kid = failure_kid;
00267
00268 if (cpl_env.lu_domain) {
00269
00270 tc = time(0);
00271 cpl_fct.ulb.lock_udomain( cpl_env.lu_domain, &intr->user );
00272 i = cpl_fct.ulb.get_urecord( cpl_env.lu_domain, &intr->user, &r);
00273 if (i < 0) {
00274
00275 LM_ERR("failed to query usrloc\n");
00276 cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user );
00277 } else if (i > 0) {
00278
00279 LM_DBG("'%.*s' Not found in usrloc\n",
00280 intr->user.len, intr->user.s);
00281 cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user );
00282 kid = notfound_kid;
00283 } else {
00284 contact = r->contacts;
00285
00286 while ((contact) && (contact->expires <= tc))
00287 contact = contact->next;
00288
00289 if (contact) {
00290
00291 if (clear)
00292 empty_location_set( &(intr->loc_set) );
00293
00294 do {
00295 LM_DBG("adding <%.*s>q=%d\n",
00296 contact->c.len,contact->c.s,(int)(10*contact->q));
00297 if (add_location( &(intr->loc_set), &contact->c,
00298 &contact->received, (int)(10*contact->q),
00299 CPL_LOC_DUPL|
00300 ((contact->cflags&cpl_fct.ulb.nat_flag)?CPL_LOC_NATED:0)
00301 )==-1) {
00302 LM_ERR("unable to add location to set :-(\n");
00303 cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user );
00304 goto runtime_error;
00305 }
00306 contact = contact->next;
00307 }while( contact && cpl_env.lu_append_branches);
00308
00309 intr->flags |= CPL_LOC_SET_MODIFIED;
00310
00311 kid = success_kid;
00312 } else {
00313
00314 kid = notfound_kid;
00315 }
00316 cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user );
00317 }
00318
00319 }
00320
00321 if (kid)
00322 return get_first_child(kid);
00323 return DEFAULT_ACTION;
00324 runtime_error:
00325 return CPL_RUNTIME_ERROR;
00326 script_error:
00327 return CPL_SCRIPT_ERROR;
00328 }
00329
00330
00331
00332
00333
00334 static inline char *run_location( struct cpl_interpreter *intr )
00335 {
00336 unsigned short attr_name;
00337 unsigned short n;
00338 char *p;
00339 unsigned char prio;
00340 unsigned char clear;
00341 str url;
00342 int i;
00343
00344 clear = NO_VAL;
00345 prio = 10;
00346 url.s = (char*)UNDEF_CHAR;
00347 url.len = 0;
00348
00349
00350 if (NR_OF_KIDS(intr->ip)>1) {
00351 LM_ERR("LOCATION node suppose to have max "
00352 "one child, not %d!\n",NR_OF_KIDS(intr->ip));
00353 goto script_error;
00354 }
00355
00356 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00357 get_basic_attr(p,attr_name,n,intr,script_error);
00358 switch (attr_name) {
00359 case URL_ATTR:
00360 url.len = n;
00361 get_str_attr( p, url.s, url.len, intr, script_error,1);
00362 break;
00363 case PRIORITY_ATTR:
00364 if ( n>10)
00365 LM_WARN("invalid value (%u) found"
00366 " for param. PRIORITY in LOCATION node -> using "
00367 "default (%u)!\n",n,prio);
00368 else
00369 prio = n;
00370 break;
00371 case CLEAR_ATTR:
00372 if (n!=YES_VAL && n!=NO_VAL)
00373 LM_WARN("invalid value (%u) found"
00374 " for param. CLEAR in LOCATION node -> using "
00375 "default (%u)!\n",n,clear);
00376 else
00377 clear = n;
00378 break;
00379 default:
00380 LM_ERR("unknown attribute (%d) in "
00381 "LOCATION node\n",attr_name);
00382 goto script_error;
00383 }
00384 }
00385
00386 if (url.s==(char*)UNDEF_CHAR) {
00387 LM_ERR("param. URL missing in LOCATION node\n");
00388 goto script_error;
00389 }
00390
00391 if (clear)
00392 empty_location_set( &(intr->loc_set) );
00393 if (add_location( &(intr->loc_set), &url, 0, prio, 0 )==-1) {
00394 LM_ERR("unable to add location to set :-(\n");
00395 goto runtime_error;
00396 }
00397
00398 intr->flags |= CPL_LOC_SET_MODIFIED;
00399
00400 return get_first_child(intr->ip);
00401 runtime_error:
00402 return CPL_RUNTIME_ERROR;
00403 script_error:
00404 return CPL_SCRIPT_ERROR;
00405 }
00406
00407
00408
00409
00410
00411 static inline char *run_remove_location( struct cpl_interpreter *intr )
00412 {
00413 unsigned short attr_name;
00414 unsigned short n;
00415 char *p;
00416 str url;
00417 int i;
00418
00419 url.s = (char*)UNDEF_CHAR;
00420
00421
00422 if (NR_OF_KIDS(intr->ip)>1) {
00423 LM_ERR("REMOVE_LOCATION node suppose to have max one child, not %d!\n",
00424 NR_OF_KIDS(intr->ip));
00425 goto script_error;
00426 }
00427
00428
00429 if (intr->loc_set==0)
00430 goto done;
00431
00432 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00433 get_basic_attr(p,attr_name,n,intr,script_error);
00434 switch (attr_name) {
00435 case LOCATION_ATTR:
00436 url.len = n;
00437 get_str_attr( p, url.s, url.len, intr, script_error,1);
00438 break;
00439 default:
00440 LM_ERR("unknown attribute "
00441 "(%d) in REMOVE_LOCATION node\n",attr_name);
00442 goto script_error;
00443 }
00444 }
00445
00446 if (url.s==(char*)UNDEF_CHAR) {
00447 LM_DBG("remove all locs from loc_set\n");
00448 empty_location_set( &(intr->loc_set) );
00449 } else {
00450 remove_location( &(intr->loc_set), url.s, url.len );
00451 }
00452
00453 intr->flags |= CPL_LOC_SET_MODIFIED;
00454
00455 done:
00456 return get_first_child(intr->ip);
00457 script_error:
00458 return CPL_SCRIPT_ERROR;
00459 }
00460
00461
00462
00463
00464
00465 static inline char *run_sub( struct cpl_interpreter *intr )
00466 {
00467 char *p;
00468 unsigned short offset;
00469 unsigned short attr_name;
00470 int i;
00471
00472
00473 if (NR_OF_KIDS(intr->ip)!=0) {
00474 LM_ERR("SUB node doesn't suppose to have any "
00475 "sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));
00476 goto script_error;
00477 }
00478
00479
00480 i = NR_OF_ATTR( intr->ip );
00481 if (i!=1) {
00482 LM_ERR("incorrect nr. of attr. %d (<>1) in SUB node\n",i);
00483 goto script_error;
00484 }
00485
00486 p = ATTR_PTR(intr->ip);
00487 get_basic_attr( p, attr_name, offset, intr, script_error);
00488 if (attr_name!=REF_ATTR) {
00489 LM_ERR("invalid attr. %d (expected %d)in "
00490 "SUB node\n", attr_name, REF_ATTR);
00491 goto script_error;
00492 }
00493
00494 p = intr->ip - offset;
00495
00496 if (((char*)p)<intr->script.s) {
00497 LM_ERR("jump offset lower than the script "
00498 "beginning -> underflow!\n");
00499 goto script_error;
00500 }
00501 check_overflow_by_ptr( p+SIMPLE_NODE_SIZE(intr->ip), intr, script_error);
00502
00503 if ( NODE_TYPE(p)!=SUBACTION_NODE ) {
00504 LM_ERR("sub. jump hit a nonsubaction node!\n");
00505 goto script_error;
00506 }
00507 if ( NR_OF_ATTR(p)!=0 ) {
00508 LM_ERR("invalid subaction node reached "
00509 "(attrs=%d); expected (0)!\n",NR_OF_ATTR(p));
00510 goto script_error;
00511 }
00512
00513 return get_first_child(p);
00514 script_error:
00515 return CPL_SCRIPT_ERROR;
00516 }
00517
00518
00519
00520
00521
00522 static inline char *run_reject( struct cpl_interpreter *intr )
00523 {
00524 unsigned short attr_name;
00525 unsigned short status;
00526 unsigned short n;
00527 str reason;
00528 char *p;
00529 int i;
00530
00531 reason.s = (char*)UNDEF_CHAR;
00532 status = UNDEF_CHAR;
00533
00534
00535 if (NR_OF_KIDS(intr->ip)!=0) {
00536 LM_ERR("REJECT node doesn't suppose to have "
00537 "any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));
00538 goto script_error;
00539 }
00540
00541 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00542 get_basic_attr( p, attr_name, n, intr, script_error);
00543 switch (attr_name) {
00544 case STATUS_ATTR:
00545 status = n;
00546 break;
00547 case REASON_ATTR:
00548 reason.len = n;
00549 get_str_attr( p, reason.s, reason.len, intr, script_error,1);
00550 break;
00551 default:
00552 LM_ERR("unknown attribute "
00553 "(%d) in REJECT node\n",attr_name);
00554 goto script_error;
00555 }
00556 }
00557
00558 if (status==UNDEF_CHAR) {
00559 LM_ERR("mandatory attribute STATUS not found\n");
00560 goto script_error;
00561 }
00562 if (status<400 || status>=700) {
00563 LM_ERR("bad attribute STATUS (%d)\n",status);
00564 goto script_error;
00565 }
00566
00567 if (reason.s==(char*)UNDEF_CHAR ) {
00568 switch (status) {
00569 case 486:
00570 reason.s = "Busy Here";
00571 reason.len = 9;
00572 break;
00573 case 404:
00574 reason.s = "Not Found";
00575 reason.len = 9;
00576 break;
00577 case 603:
00578 reason.s = "Decline";
00579 reason.len = 7;
00580 break;
00581 case 500:
00582 reason.s = "Internal Server Error";
00583 reason.len = 21;
00584 break;
00585 default:
00586 reason.s = "Generic Error";
00587 reason.len = 13;
00588 }
00589 }
00590
00591
00592 if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) {
00593 i = cpl_fct.tmb.t_newtran( intr->msg );
00594 if (i<0) {
00595 LM_ERR("failed to build new transaction!\n");
00596 goto runtime_error;
00597 } else if (i==0) {
00598 LM_ERR(" processed INVITE is a retransmission!\n");
00599
00600
00601 return EO_SCRIPT;
00602 }
00603 intr->flags |= CPL_IS_STATEFUL;
00604 }
00605
00606
00607 i = cpl_fct.slb.send_reply(intr->msg, (int)status, &reason );
00608
00609 if ( i!=1 ) {
00610 LM_ERR("unable to send reject reply!\n");
00611 goto runtime_error;
00612 }
00613
00614 return EO_SCRIPT;
00615 runtime_error:
00616 return CPL_RUNTIME_ERROR;
00617 script_error:
00618 return CPL_SCRIPT_ERROR;
00619 }
00620
00621
00622
00623
00624
00625 static inline char *run_redirect( struct cpl_interpreter *intr )
00626 {
00627 struct location *loc;
00628 struct lump_rpl *lump;
00629 unsigned short attr_name;
00630 unsigned short permanent;
00631 unsigned short n;
00632 char *p;
00633 str lump_str;
00634 char *cp;
00635 int i;
00636
00637 permanent = NO_VAL;
00638
00639
00640 if (NR_OF_KIDS(intr->ip)!=0) {
00641 LM_ERR("REDIRECT node doesn't suppose "
00642 "to have any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));
00643 goto script_error;
00644 }
00645
00646
00647 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00648 get_basic_attr( p, attr_name, n, intr, script_error);
00649 switch (attr_name) {
00650 case PERMANENT_ATTR:
00651 if (n!=YES_VAL && n!=NO_VAL) {
00652 LM_ERR("unsupported value (%d)"
00653 " in attribute PERMANENT for REDIRECT node",n);
00654 goto script_error;
00655 }
00656 permanent = n;
00657 break;
00658 default:
00659 LM_ERR("unknown attribute "
00660 "(%d) in REDIRECT node\n",attr_name);
00661 goto script_error;
00662 }
00663 }
00664
00665
00666 lump_str.len = 9 ;
00667 for(loc=intr->loc_set;loc;loc=loc->next)
00668 lump_str.len += 1 + loc->addr.uri.len + 7 +
00669 2*(loc->next!=0);
00670 lump_str.len += CRLF_LEN;
00671
00672 lump_str.s = pkg_malloc( lump_str.len );
00673 if(!lump_str.s) {
00674 LM_ERR("out of pkg memory!\n");
00675 goto runtime_error;
00676 }
00677 cp = lump_str.s;
00678 memcpy( cp , "Contact: " , 9);
00679 cp += 9;
00680 for(loc=intr->loc_set;loc;loc=loc->next) {
00681 *(cp++) = '<';
00682 memcpy(cp,loc->addr.uri.s,loc->addr.uri.len);
00683 cp += loc->addr.uri.len;
00684 memcpy(cp,">;q=",4);
00685 cp += 4;
00686 *(cp++) = (loc->addr.priority!=10)?'0':'1';
00687 *(cp++) = '.';
00688 *(cp++) = '0'+(loc->addr.priority%10);
00689 if (loc->next) {
00690 *(cp++) = ' ';
00691 *(cp++) = ',';
00692 }
00693 }
00694 memcpy(cp,CRLF,CRLF_LEN);
00695
00696
00697 if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) {
00698 i = cpl_fct.tmb.t_newtran( intr->msg );
00699 if (i<0) {
00700 LM_ERR("failed to build new transaction!\n");
00701 pkg_free( lump_str.s );
00702 goto runtime_error;
00703 } else if (i==0) {
00704 LM_ERR("processed INVITE is a retransmission!\n");
00705
00706
00707 pkg_free( lump_str.s );
00708 return EO_SCRIPT;
00709 }
00710 intr->flags |= CPL_IS_STATEFUL;
00711 }
00712
00713
00714 lump = add_lump_rpl( intr->msg, lump_str.s , lump_str.len , LUMP_RPL_HDR);
00715 if(!lump) {
00716 LM_ERR("unable to add lump_rpl! \n");
00717 pkg_free( lump_str.s );
00718 goto runtime_error;
00719 }
00720
00721
00722 if (permanent)
00723 i = cpl_fct.slb.send_reply( intr->msg,301,&cpl_301_reason);
00724 else
00725 i = cpl_fct.slb.send_reply( intr->msg,302,&cpl_302_reason);
00726
00727
00728
00729
00730 unlink_lump_rpl( intr->msg, lump);
00731 free_lump_rpl( lump );
00732
00733 if (i!=1) {
00734 LM_ERR("unable to send redirect reply!\n");
00735 goto runtime_error;
00736 }
00737
00738 return EO_SCRIPT;
00739 runtime_error:
00740 return CPL_RUNTIME_ERROR;
00741 script_error:
00742 return CPL_SCRIPT_ERROR;
00743 }
00744
00745
00746
00747
00748
00749 static inline char *run_log( struct cpl_interpreter *intr )
00750 {
00751 char *p;
00752 unsigned short attr_name;
00753 unsigned short n;
00754 str name = {0,0};
00755 str comment = {0,0};
00756 str user;
00757 int i;
00758
00759
00760 if (NR_OF_KIDS(intr->ip)>1) {
00761 LM_ERR("LOG node suppose to have max one child"
00762 ", not %d!\n",NR_OF_KIDS(intr->ip));
00763 goto script_error;
00764 }
00765
00766
00767 if ( cpl_env.log_dir==0 )
00768 goto done;
00769
00770
00771 p = ATTR_PTR(intr->ip);
00772 for( i=NR_OF_ATTR(intr->ip); i>0 ; i-- ) {
00773 get_basic_attr( p, attr_name, n, intr, script_error);
00774 switch (attr_name) {
00775 case NAME_ATTR:
00776 get_str_attr( p, name.s, n, intr, script_error,1);
00777 name.len = n;
00778 break;
00779 case COMMENT_ATTR:
00780 get_str_attr( p, comment.s, n, intr, script_error,1);
00781 comment.len = n;
00782 break;
00783 default:
00784 LM_ERR("unknown attribute "
00785 "(%d) in LOG node\n",attr_name);
00786 goto script_error;
00787 }
00788 }
00789
00790 if (comment.len==0) {
00791 LM_NOTICE("LOG node has no comment attr -> skipping\n");
00792 goto done;
00793 }
00794
00795 user.len = intr->user.len + name.len + comment.len;
00796
00797 user.s = p = (char*)shm_malloc( user.len );
00798 if (!user.s) {
00799 LM_ERR("no more shm memory!\n");
00800 goto runtime_error;
00801 }
00802
00803 memcpy( p, intr->user.s, intr->user.len);
00804 user.len = intr->user.len;
00805 p += intr->user.len;
00806
00807 if (name.len) {
00808 memcpy( p, name.s, name.len );
00809 name.s = p;
00810 p += name.len;
00811 }
00812
00813 memcpy( p, comment.s, comment.len);
00814 comment.s = p;
00815
00816
00817 write_cpl_cmd( CPL_LOG_CMD, &user, &name, &comment );
00818
00819 done:
00820 return get_first_child(intr->ip);
00821 runtime_error:
00822 return CPL_RUNTIME_ERROR;
00823 script_error:
00824 return CPL_SCRIPT_ERROR;
00825 }
00826
00827
00828
00829
00830
00831 static inline char *run_mail( struct cpl_interpreter *intr )
00832 {
00833 unsigned short attr_name;
00834 unsigned short n;
00835 char *p;
00836 str subject = {0,0};
00837 str body = {0,0};
00838 str to = {0,0};
00839 int i;
00840
00841
00842 if (NR_OF_KIDS(intr->ip)>1) {
00843 LM_ERR("MAIL node suppose to have max one"
00844 " child, not %d!\n",NR_OF_KIDS(intr->ip));
00845 goto script_error;
00846 }
00847
00848
00849 for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {
00850 get_basic_attr(p, attr_name, n, intr, script_error);
00851 switch (attr_name) {
00852 case TO_ATTR:
00853 get_str_attr(p, to.s, n, intr, script_error,0);
00854 to.len = n;
00855 break;
00856 case SUBJECT_ATTR:
00857 get_str_attr(p, subject.s, n, intr, script_error,0);
00858 subject.len = n;
00859 break;
00860 case BODY_ATTR:
00861 get_str_attr(p, body.s, n, intr, script_error,0);
00862 body.len = n;
00863 break;
00864 default:
00865 LM_ERR("unknown attribute (%d) in MAIL node\n",attr_name);
00866 goto script_error;
00867 }
00868 }
00869
00870 if (to.len==0) {
00871 LM_ERR("email has an empty TO hdr!\n");
00872 goto script_error;
00873 }
00874 if (body.len==0 && subject.len==0) {
00875 LM_WARN("I refuse to send email with no "
00876 "body and no subject -> skipping...\n");
00877 goto done;
00878 }
00879
00880
00881 p = (char*)shm_malloc( to.len + subject.len + body.len );
00882 if (!p) {
00883 LM_ERR("no more shm memory!\n");
00884 goto runtime_error;
00885 }
00886
00887 memcpy( p, to.s, to.len );
00888 to.s = p;
00889 p += to.len;
00890
00891 if (subject.len) {
00892 memcpy( p, subject.s, subject.len );
00893 subject.s = p;
00894 p += subject.len;
00895 }
00896
00897 if (body.len) {
00898 memcpy( p, body.s, body.len );
00899 body.s = p;
00900 p += body.len;
00901 }
00902
00903
00904 write_cpl_cmd( CPL_MAIL_CMD, &to, &subject, &body);
00905
00906 done:
00907 return get_first_child(intr->ip);
00908 runtime_error:
00909 return CPL_RUNTIME_ERROR;
00910 script_error:
00911 return CPL_SCRIPT_ERROR;
00912 }
00913
00914
00915
00916 static inline int run_default( struct cpl_interpreter *intr )
00917 {
00918 if (!(intr->flags&CPL_PROXY_DONE)) {
00919
00920 if ( !(intr->flags&CPL_LOC_SET_MODIFIED) ) {
00921
00922 if (intr->loc_set==0 ) {
00923
00924
00925
00926
00927 return SCRIPT_DEFAULT;
00928 } else {
00929
00930
00931
00932
00933
00934
00935 return SCRIPT_DEFAULT;
00936 }
00937 } else {
00938
00939
00940
00941 if (!cpl_proxy_to_loc_set(intr->msg,&(intr->loc_set),intr->flags))
00942 return SCRIPT_END;
00943 return SCRIPT_RUN_ERROR;
00944 }
00945 } else {
00946
00947
00948
00949
00950
00951
00952 return SCRIPT_END;
00953 }
00954
00955 }
00956
00957
00958
00959
00960 #include "cpl_switches.h"
00961
00962 #include "cpl_proxy.h"
00963
00964
00965
00966 int cpl_run_script( struct cpl_interpreter *intr )
00967 {
00968 char *new_ip;
00969
00970 do {
00971 check_overflow_by_offset( SIMPLE_NODE_SIZE(intr->ip), intr, error);
00972 switch ( NODE_TYPE(intr->ip) ) {
00973 case CPL_NODE:
00974 LM_DBG("processing CPL node \n");
00975 new_ip = run_cpl_node( intr );
00976 break;
00977 case ADDRESS_SWITCH_NODE:
00978 LM_DBG("processing address-switch node\n");
00979 new_ip = run_address_switch( intr );
00980 break;
00981 case STRING_SWITCH_NODE:
00982 LM_DBG("processing string-switch node\n");
00983 new_ip = run_string_switch( intr );
00984 break;
00985 case PRIORITY_SWITCH_NODE:
00986 LM_DBG("processing priority-switch node\n");
00987 new_ip = run_priority_switch( intr );
00988 break;
00989 case TIME_SWITCH_NODE:
00990 LM_DBG("processing time-switch node\n");
00991 new_ip = run_time_switch( intr );
00992 break;
00993 case LANGUAGE_SWITCH_NODE:
00994 LM_DBG("processing language-switch node\n");
00995 new_ip = run_language_switch( intr );
00996 break;
00997 case LOOKUP_NODE:
00998 LM_DBG("processing lookup node\n");
00999 new_ip = run_lookup( intr );
01000 break;
01001 case LOCATION_NODE:
01002 LM_DBG("processing location node\n");
01003 new_ip = run_location( intr );
01004 break;
01005 case REMOVE_LOCATION_NODE:
01006 LM_DBG("processing remove_location node\n");
01007 new_ip = run_remove_location( intr );
01008 break;
01009 case PROXY_NODE:
01010 LM_DBG("processing proxy node\n");
01011 new_ip = run_proxy( intr );
01012 break;
01013 case REJECT_NODE:
01014 LM_DBG("processing reject node\n");
01015 new_ip = run_reject( intr );
01016 break;
01017 case REDIRECT_NODE:
01018 LM_DBG("processing redirect node\n");
01019 new_ip = run_redirect( intr );
01020 break;
01021 case LOG_NODE:
01022 LM_DBG("processing log node\n");
01023 new_ip = run_log( intr );
01024 break;
01025 case MAIL_NODE:
01026 LM_DBG("processing mail node\n");
01027 new_ip = run_mail( intr );
01028 break;
01029 case SUB_NODE:
01030 LM_DBG("processing sub node\n");
01031 new_ip = run_sub( intr );
01032 break;
01033 default:
01034 LM_ERR("unknown type node (%d)\n",
01035 NODE_TYPE(intr->ip));
01036 goto error;
01037 }
01038
01039 if (new_ip==CPL_RUNTIME_ERROR) {
01040 LM_ERR("runtime error\n");
01041 return SCRIPT_RUN_ERROR;
01042 } else if (new_ip==CPL_SCRIPT_ERROR) {
01043 LM_ERR("script error\n");
01044 return SCRIPT_FORMAT_ERROR;
01045 } else if (new_ip==DEFAULT_ACTION) {
01046 LM_DBG("running default action\n");
01047 return run_default(intr);
01048 } else if (new_ip==EO_SCRIPT) {
01049 LM_DBG("script interpretation done!\n");
01050 return SCRIPT_END;
01051 } else if (new_ip==CPL_TO_CONTINUE) {
01052 LM_DBG("done for the moment; waiting after signaling!\n");
01053 return SCRIPT_TO_BE_CONTINUED;
01054 }
01055
01056 intr->ip = new_ip;
01057 }while(1);
01058
01059 error:
01060 return SCRIPT_FORMAT_ERROR;
01061 }