/* UPDATED + CHECKED */ static inline char *run_sub( struct cpl_interpreter *intr ) { char *p; unsigned short offset; unsigned short attr_name; int i; /* sanity check */ if (NR_OF_KIDS(intr->ip)!=0) { LOG(L_ERR,"ERROR:cpl_c:run_sub: SUB node doesn't suppose to have any " "sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip)); goto script_error; } /* check the number of attr */ i = NR_OF_ATTR( intr->ip ); if (i!=1) { LOG(L_ERR,"ERROR:cpl_c:run_sub: incorrect nr. of attr. %d (<>1) in " "SUB node\n",i); goto script_error; } /* get attr's name */ p = ATTR_PTR(intr->ip); get_basic_attr( p, attr_name, offset, intr, script_error); if (attr_name!=REF_ATTR) { LOG(L_ERR,"ERROR:cpl_c:run_sub: invalid attr. %d (expected %d)in " "SUB node\n", attr_name, REF_ATTR); goto script_error; } /* make the jump */ p = intr->ip - offset; /* check the destination pointer -> are we still inside the buffer ;-) */ if (((char*)p)<intr->script.s) { LOG(L_ERR,"ERROR:cpl_c:run_sub: jump offset lower than the script " "beginning -> underflow!\n"); goto script_error; } check_overflow_by_ptr( p+SIMPLE_NODE_SIZE(intr->ip), intr, script_error); /* check to see if we hit a subaction node */ if ( NODE_TYPE(p)!=SUBACTION_NODE ) { LOG(L_ERR,"ERROR:cpl_c:run_sub: sub. jump hit a nonsubaction node!\n"); goto script_error; } if ( NR_OF_ATTR(p)!=0 ) { LOG(L_ERR,"ERROR:cpl_c:run_sub: inavlid subaction node reached " "(attrs=%d); expected (0)!\n",NR_OF_ATTR(p)); goto script_error; } return get_first_child(p); script_error: return CPL_SCRIPT_ERROR; }
int cpl_run_script( struct cpl_interpreter *intr ) { char *new_ip; do { check_overflow_by_offset( SIMPLE_NODE_SIZE(intr->ip), intr, error); switch ( NODE_TYPE(intr->ip) ) { case CPL_NODE: LM_DBG("processing CPL node \n"); new_ip = run_cpl_node( intr ); /*UPDATED&TESTED*/ break; case ADDRESS_SWITCH_NODE: LM_DBG("processing address-switch node\n"); new_ip = run_address_switch( intr ); /*UPDATED&TESTED*/ break; case STRING_SWITCH_NODE: LM_DBG("processing string-switch node\n"); new_ip = run_string_switch( intr ); /*UPDATED&TESTED*/ break; case PRIORITY_SWITCH_NODE: LM_DBG("processing priority-switch node\n"); new_ip = run_priority_switch( intr ); /*UPDATED&TESTED*/ break; case TIME_SWITCH_NODE: LM_DBG("processing time-switch node\n"); new_ip = run_time_switch( intr ); /*UPDATED&TESTED*/ break; case LANGUAGE_SWITCH_NODE: LM_DBG("processing language-switch node\n"); new_ip = run_language_switch( intr ); /*UPDATED&TESTED*/ break; case LOOKUP_NODE: LM_DBG("processing lookup node\n"); new_ip = run_lookup( intr ); /*UPDATED&TESTED*/ break; case LOCATION_NODE: LM_DBG("processing location node\n"); new_ip = run_location( intr ); /*UPDATED&TESTED*/ break; case REMOVE_LOCATION_NODE: LM_DBG("processing remove_location node\n"); new_ip = run_remove_location( intr ); /*UPDATED&TESTED*/ break; case PROXY_NODE: LM_DBG("processing proxy node\n"); new_ip = run_proxy( intr );/*UPDATED&TESTED*/ break; case REJECT_NODE: LM_DBG("processing reject node\n"); new_ip = run_reject( intr ); /*UPDATED&TESTED*/ break; case REDIRECT_NODE: LM_DBG("processing redirect node\n"); new_ip = run_redirect( intr ); /*UPDATED&TESTED*/ break; case LOG_NODE: LM_DBG("processing log node\n"); new_ip = run_log( intr ); /*UPDATED&TESTED*/ break; case MAIL_NODE: LM_DBG("processing mail node\n"); new_ip = run_mail( intr ); /*UPDATED&TESTED*/ break; case SUB_NODE: LM_DBG("processing sub node\n"); new_ip = run_sub( intr ); /*UPDATED&TESTED*/ break; default: LM_ERR("unknown type node (%d)\n", NODE_TYPE(intr->ip)); goto error; } if (new_ip==CPL_RUNTIME_ERROR) { LM_ERR("runtime error\n"); return SCRIPT_RUN_ERROR; } else if (new_ip==CPL_SCRIPT_ERROR) { LM_ERR("script error\n"); return SCRIPT_FORMAT_ERROR; } else if (new_ip==DEFAULT_ACTION) { LM_DBG("running default action\n"); return run_default(intr); } else if (new_ip==EO_SCRIPT) { LM_DBG("script interpretation done!\n"); return SCRIPT_END; } else if (new_ip==CPL_TO_CONTINUE) { LM_DBG("done for the moment; waiting after signaling!\n"); return SCRIPT_TO_BE_CONTINUED; } /* move to the new instruction */ intr->ip = new_ip; }while(1); error: return SCRIPT_FORMAT_ERROR; }
/* UPDATED + CHECKED */ static inline char *run_lookup( struct cpl_interpreter *intr ) { unsigned short attr_name; unsigned short n; unsigned char clear; char *p; char *kid; char *failure_kid = 0; char *success_kid = 0; char *notfound_kid = 0; int i; time_t tc; urecord_t* r; ucontact_t* contact; clear = NO_VAL; /* check the params */ for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) { get_basic_attr(p,attr_name,n,intr,script_error); switch (attr_name) { case CLEAR_ATTR: if (n!=YES_VAL && n!=NO_VAL) LM_WARN("invalid value (%u) found" " for param. CLEAR in LOOKUP node -> using " "default (%u)!\n",n,clear); else clear = n; break; default: LM_ERR("unknown attribute (%d) in LOOKUP node\n",attr_name); goto script_error; } } /* check the kids */ for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) { kid = intr->ip + KID_OFFSET(intr->ip,i); check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error); switch ( NODE_TYPE(kid) ) { case SUCCESS_NODE : success_kid = kid; break; case NOTFOUND_NODE: notfound_kid = kid; break; case FAILURE_NODE: failure_kid = kid; break; default: LM_ERR("unknown output node type" " (%d) for LOOKUP node\n",NODE_TYPE(kid)); goto script_error; } } kid = failure_kid; if (cpl_env.lu_domain) { /* fetch user's contacts via usrloc */ tc = time(0); cpl_fct.ulb.lock_udomain( cpl_env.lu_domain, &intr->user ); i = cpl_fct.ulb.get_urecord( cpl_env.lu_domain, &intr->user, &r); if (i < 0) { /* failure */ LM_ERR("failed to query usrloc\n"); cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user ); } else if (i > 0) { /* not found */ LM_DBG("'%.*s' Not found in usrloc\n", intr->user.len, intr->user.s); cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user ); kid = notfound_kid; } else { contact = r->contacts; /* skip expired contacts */ while ((contact) && (contact->expires <= tc)) contact = contact->next; /* any contacts left? */ if (contact) { /* clear loc set if requested */ if (clear) empty_location_set( &(intr->loc_set) ); /* start adding locations to set */ do { LM_DBG("adding <%.*s>q=%d\n", contact->c.len,contact->c.s,(int)(10*contact->q)); if (add_location( &(intr->loc_set), &contact->c, &contact->received, (int)(10*contact->q), CPL_LOC_DUPL| ((contact->cflags&cpl_fct.ulb.nat_flag)?CPL_LOC_NATED:0) )==-1) { LM_ERR("unable to add location to set :-(\n"); cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user ); goto runtime_error; } contact = contact->next; }while( contact && cpl_env.lu_append_branches); /* set the flag for modifying the location set */ intr->flags |= CPL_LOC_SET_MODIFIED; /* we found a valid contact */ kid = success_kid; } else { /* no valid contact found */ kid = notfound_kid; } cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain, &intr->user ); } } if (kid) return get_first_child(kid); return DEFAULT_ACTION; runtime_error: return CPL_RUNTIME_ERROR; script_error: return CPL_SCRIPT_ERROR; }