/* 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; }
/* 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; }