Пример #1
0
/* 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;
}
Пример #2
0
/* UPDATED + CHECKED
 */
static inline char *run_remove_location( struct cpl_interpreter *intr )
{
	unsigned short attr_name;
	unsigned short n;
	char *p;
	str url;
	int i;

	url.s = (char*)UNDEF_CHAR;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)>1) {
		LOG(L_ERR,"ERROR:cpl_c:run_remove_location: REMOVE_LOCATION node "
			"suppose to have max one child, not %d!\n",
			NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	/* dirty hack to speed things up in when loc set is already empty */
	if (intr->loc_set==0)
		goto done;

	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 LOCATION_ATTR:
				url.len = n;
				get_str_attr( p, url.s, url.len, intr, script_error,1);
				break;
			default:
				LOG(L_ERR,"ERROR:run_remove_location: unknown attribute "
					"(%d) in REMOVE_LOCATION node\n",attr_name);
				goto script_error;
		}
	}

	if (url.s==(char*)UNDEF_CHAR) {
		DBG("DEBUG:run_remove_location: remove all locs from loc_set\n");
		empty_location_set( &(intr->loc_set) );
	} else {
		remove_location( &(intr->loc_set), url.s, url.len );
	}
	/* set the flag for modifing the location set */
	intr->flags |= CPL_LOC_SET_MODIFIED;

done:
	return get_first_child(intr->ip);
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #3
0
/* UPDATED + CHECKED
 */
static inline char *run_mail( struct cpl_interpreter *intr )
{
	unsigned short attr_name;
	unsigned short n;
	char  *p;
	str subject = {0,0};
	str body    = {0,0};
	str to      = {0,0};
	int i;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)>1) {
		LM_ERR("MAIL node suppose to have max one"
			" child, not %d!\n",NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	/* read the attributes of the MAIL node*/
	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 TO_ATTR:
				get_str_attr(p, to.s, n, intr, script_error,0);
				to.len = n;
				break;
			case SUBJECT_ATTR:
				get_str_attr(p, subject.s, n, intr, script_error,0);
				subject.len = n;
				break;
			case BODY_ATTR:
				get_str_attr(p, body.s, n, intr, script_error,0);
				body.len = n;
				break;
			default:
				LM_ERR("unknown attribute (%d) in MAIL node\n",attr_name);
				goto script_error;
		}
	}

	if (to.len==0) {
		LM_ERR("email has an empty TO hdr!\n");
		goto script_error;
	}
	if (body.len==0 && subject.len==0) {
		LM_WARN("I refuse to send email with no "
			"body and no subject -> skipping...\n");
		goto done;
	}

	/* duplicate the attrs in shm memory */
	p = (char*)shm_malloc( to.len + subject.len + body.len );
	if (!p) {
		LM_ERR("no more shm memory!\n");
		goto runtime_error;
	}
	/* copy the TO */
	memcpy( p, to.s, to.len );
	to.s = p;
	p += to.len;
	/* copy the subject */
	if (subject.len) {
		memcpy( p, subject.s, subject.len );
		subject.s = p;
		p += subject.len;
	}
	/* copy the body */
	if (body.len) {
		memcpy( p, body.s, body.len );
		body.s = p;
		p += body.len;
	}

	/* send the command */
	write_cpl_cmd( CPL_MAIL_CMD, &to, &subject, &body);

done:
	return get_first_child(intr->ip);
runtime_error:
	return CPL_RUNTIME_ERROR;
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #4
0
/* UPDATED + CHECKED
 */
static inline char *run_log( struct cpl_interpreter *intr )
{
	char  *p;
	unsigned short attr_name;
	unsigned short n;
	str name    = {0,0};
	str comment = {0,0};
	str user;
	int i;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)>1) {
		LM_ERR("LOG node suppose to have max one child"
			", not %d!\n",NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	/* is logging enabled? */
	if ( cpl_env.log_dir==0 )
		goto done;

	/* read the attributes of the LOG node*/
	p = ATTR_PTR(intr->ip);
	for( i=NR_OF_ATTR(intr->ip); i>0 ; i-- ) {
		get_basic_attr( p, attr_name, n, intr, script_error);
		switch (attr_name) {
			case NAME_ATTR:
				get_str_attr( p, name.s, n, intr, script_error,1);
				name.len = n;
				break;
			case COMMENT_ATTR:
				get_str_attr( p, comment.s, n, intr, script_error,1);
				comment.len = n;
				break;
			default:
				LM_ERR("unknown attribute "
					"(%d) in LOG node\n",attr_name);
				goto script_error;
		}
	}

	if (comment.len==0) {
		LM_NOTICE("LOG node has no comment attr -> skipping\n");
		goto done;
	}

	user.len = intr->user.len + name.len + comment.len;
	/* duplicate the attrs in shm memory */
	user.s = p = (char*)shm_malloc( user.len );
	if (!user.s) {
		LM_ERR("no more shm memory!\n");
		goto runtime_error;
	}
	/* copy the user name */
	memcpy( p, intr->user.s, intr->user.len);
	user.len = intr->user.len;
	p += intr->user.len;
	/* copy the log name */
	if (name.len) {
		memcpy( p, name.s, name.len );
		name.s = p;
		p += name.len;
	}
	/* copy the comment */
	memcpy( p, comment.s, comment.len);
	comment.s = p;

	/* send the command */
	write_cpl_cmd( CPL_LOG_CMD, &user, &name, &comment );

done:
	return get_first_child(intr->ip);
runtime_error:
	return CPL_RUNTIME_ERROR;
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #5
0
/* UPDATED + CHECKED
 */
static inline char *run_redirect( struct cpl_interpreter *intr )
{
	struct location *loc;
	struct lump_rpl *lump;
	unsigned short attr_name;
	unsigned short permanent;
	unsigned short n;
	char *p;
	str lump_str;
	char *cp;
	int i;

	permanent = NO_VAL;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)!=0) {
		LM_ERR("REDIRECT node doesn't suppose "
			"to have any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	/* read the attributes of the REDIRECT node*/
	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 PERMANENT_ATTR:
				if (n!=YES_VAL && n!=NO_VAL) {
					LM_ERR("unsupported value (%d)"
						" in attribute PERMANENT for REDIRECT node",n);
					goto script_error;
				}
				permanent = n;
				break;
			default:
				LM_ERR("unknown attribute "
					"(%d) in REDIRECT node\n",attr_name);
				goto script_error;
		}
	}

	/* build the lump for Contact header */
	lump_str.len = 9 /*"Contact: "*/;
	for(loc=intr->loc_set;loc;loc=loc->next)
		lump_str.len += 1/*"<"*/ + loc->addr.uri.len + 7/*">;q=x.x"*/ +
			2*(loc->next!=0)/*" ,"*/;
	lump_str.len += CRLF_LEN;

	lump_str.s = pkg_malloc( lump_str.len );
	if(!lump_str.s) {
		LM_ERR("out of pkg memory!\n");
		goto runtime_error;
	}
	cp = lump_str.s;
	memcpy( cp , "Contact: " , 9);
	cp += 9;
	for(loc=intr->loc_set;loc;loc=loc->next) {
		*(cp++) = '<';
		memcpy(cp,loc->addr.uri.s,loc->addr.uri.len);
		cp += loc->addr.uri.len;
		memcpy(cp,">;q=",4);
		cp += 4;
		*(cp++) = (loc->addr.priority!=10)?'0':'1';
		*(cp++) = '.';
		*(cp++) = '0'+(loc->addr.priority%10);
		if (loc->next) {
			*(cp++) = ' ';
			*(cp++) = ',';
		}
	}
	memcpy(cp,CRLF,CRLF_LEN);

	/* if still stateless and FORCE_STATEFUL set -> build the transaction */
	if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) {
		i = cpl_fct.tmb.t_newtran( intr->msg );
		if (i<0) {
			LM_ERR("failed to build new transaction!\n");
			pkg_free( lump_str.s );
			goto runtime_error;
		} else if (i==0) {
			LM_ERR("processed INVITE is a retransmission!\n");
			/* instead of generating an error is better just to break the
			 * script by returning EO_SCRIPT */
			pkg_free( lump_str.s );
			return EO_SCRIPT;
		}
		intr->flags |= CPL_IS_STATEFUL;
	}

	/* add the lump to the reply */
	lump = add_lump_rpl( intr->msg, lump_str.s , lump_str.len , LUMP_RPL_HDR);
	if(!lump) {
		LM_ERR("unable to add lump_rpl! \n");
		pkg_free( lump_str.s );
		goto runtime_error;
	}

	/* send the reply */
	if (permanent)
		i = cpl_fct.slb.freply( intr->msg,301,&cpl_301_reason);
	else
		i = cpl_fct.slb.freply( intr->msg,302,&cpl_302_reason);

	/* msg which I'm working on can be in private memory or is a clone into
	 * shared memory (if I'm after a failed proxy); So, it's better to removed
	 * by myself the lump that I added previously */
	unlink_lump_rpl( intr->msg, lump);
	free_lump_rpl( lump );

	if (i!=1) {
		LM_ERR("unable to send redirect reply!\n");
		goto runtime_error;
	}

	return EO_SCRIPT;
runtime_error:
	return CPL_RUNTIME_ERROR;
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #6
0
/* UPDATED + CHECKED
 */
static inline char *run_reject( struct cpl_interpreter *intr )
{
	unsigned short attr_name;
	unsigned short status;
	unsigned short n;
	str reason;
	char *p;
	int i;

	reason.s = (char*)UNDEF_CHAR;
	status = UNDEF_CHAR;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)!=0) {
		LM_ERR("REJECT node doesn't suppose to have "
			"any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	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 STATUS_ATTR:
				status = n;
				break;
			case REASON_ATTR:
				reason.len = n;
				get_str_attr( p, reason.s, reason.len, intr, script_error,1);
				break;
			default:
				LM_ERR("unknown attribute "
					"(%d) in REJECT node\n",attr_name);
				goto script_error;
		}
	}

	if (status==UNDEF_CHAR) {
		LM_ERR("mandatory attribute STATUS not found\n");
		goto script_error;
	}
	if (status<400 || status>=700) {
		LM_ERR("bad attribute STATUS (%d)\n",status);
		goto script_error;
	}

	if (reason.s==(char*)UNDEF_CHAR ) {
		switch (status) {
			case 486:
				reason.s = "Busy Here";
				reason.len = 9;
				break;
			case 404:
				reason.s = "Not Found";
				reason.len = 9;
				break;
			case 603:
				reason.s = "Decline";
				reason.len = 7;
				break;
			case 500:
				reason.s = "Internal Server Error";
				reason.len = 21;
				break;
			default:
				reason.s = "Generic Error";
				reason.len = 13;
		}
	}

	/* if still stateless and FORCE_STATEFUL set -> build the transaction */
	if ( !(intr->flags&CPL_IS_STATEFUL) && intr->flags&CPL_FORCE_STATEFUL) {
		i = cpl_fct.tmb.t_newtran( intr->msg );
		if (i<0) {
			LM_ERR("failed to build new transaction!\n");
			goto runtime_error;
		} else if (i==0) {
			LM_ERR(" processed INVITE is a retransmission!\n");
			/* instead of generating an error is better just to break the
			 * script by returning EO_SCRIPT */
			return EO_SCRIPT;
		}
		intr->flags |= CPL_IS_STATEFUL;
	}

	/* send the reply */
	i = cpl_fct.slb.freply(intr->msg, (int)status, &reason );

	if ( i!=1 ) {
		LM_ERR("unable to send reject reply!\n");
		goto runtime_error;
	}

	return EO_SCRIPT;
runtime_error:
	return CPL_RUNTIME_ERROR;
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #7
0
/* UPDATED + CHECKED
 */
static inline char *run_location( struct cpl_interpreter *intr )
{
	unsigned short attr_name;
	unsigned short n;
	char  *p;
	unsigned char  prio;
	unsigned char  clear;
	str url;
	int i;

	clear = NO_VAL;
	prio = 10;
	url.s = (char*)UNDEF_CHAR;
	url.len = 0;

	/* sanity check */
	if (NR_OF_KIDS(intr->ip)>1) {
		LM_ERR("LOCATION node suppose to have max "
			"one child, not %d!\n",NR_OF_KIDS(intr->ip));
		goto script_error;
	}

	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 URL_ATTR:
				url.len = n;
				get_str_attr( p, url.s, url.len, intr, script_error,1);
				break;
			case PRIORITY_ATTR:
				if ( n>10)
					LM_WARN("invalid value (%u) found"
						" for param. PRIORITY in LOCATION node -> using "
						"default (%u)!\n",n,prio);
				else
					prio = n;
				break;
			case CLEAR_ATTR:
				if (n!=YES_VAL && n!=NO_VAL)
					LM_WARN("invalid value (%u) found"
						" for param. CLEAR in LOCATION node -> using "
						"default (%u)!\n",n,clear);
				else
					clear = n;
				break;
			default:
				LM_ERR("unknown attribute (%d) in "
					"LOCATION node\n",attr_name);
				goto script_error;
		}
	}

	if (url.s==(char*)UNDEF_CHAR) {
		LM_ERR("param. URL missing in LOCATION node\n");
		goto script_error;
	}

	if (clear)
		empty_location_set( &(intr->loc_set) );
	if (add_location( &(intr->loc_set), &url, 0, prio, 0/*no dup*/ )==-1) {
		LM_ERR("unable to add location to set :-(\n");
		goto runtime_error;
	}
	/* set the flag for modifying the location set */
	intr->flags |= CPL_LOC_SET_MODIFIED;

	return get_first_child(intr->ip);
runtime_error:
	return CPL_RUNTIME_ERROR;
script_error:
	return CPL_SCRIPT_ERROR;
}
Пример #8
0
/* 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;
}