rem: len=strlen(":"); if(crt+len>end) goto error_uri; memcpy(crt,":",len);crt+=len; len=uri.passwd.len; if(crt+len>end) goto error_uri;
add: len=uri.passwd.len; if(crt+len+1>end) goto error_uri; *crt=':'; crt++;
context: int do_action(struct action* a, struct sip_msg* msg){	int ret;	int v;	union sockaddr_union* to;	struct socket_info* send_sock;	struct proxy_l* p;	char* tmp;	char *new_uri, *end, *crt;	int len;	int user;	struct sip_uri uri;	struct sip_uri* u;	unsigned short port;	int proto;	/* reset the value of error to E_UNSPEC so avoid unknowledgable	   functions to return with errror (status<0) and not setting it	   leaving there previous error; cache the previous value though	   for functions which want to process it */	prev_ser_error=ser_error;	ser_error=E_UNSPEC;	ret=E_BUG;	switch ((unsigned char)a->type){		case DROP_T:				ret=0;			break;		case FORWARD_T:#ifdef USE_TCP		case FORWARD_TCP_T:#endif		case FORWARD_UDP_T:			if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;#ifdef USE_TCP			else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;#endif			else proto=msg->rcv.proto;			if (a->p1_type==URIHOST_ST){				/*parse uri*/				ret=parse_sip_msg_uri(msg);				if (ret<0) {					LOG(L_ERR, "ERROR: do_action: forward: bad_uri "								" dropping packet\n");					break;				}				u=&msg->parsed_uri;				switch (a->p2_type){					case URIPORT_ST:									port=u->port_no;									break;					case NUMBER_ST:									port=a->p2.number;									break;					default:							LOG(L_CRIT, "BUG: do_action bad forward 2nd"										" param type (%d)\n", a->p2_type);							ret=E_UNSPEC;							goto error_fwd_uri;				}				/* create a temporary proxy*/				p=mk_proxy(&u->host, port, proto);				if (p==0){					LOG(L_ERR, "ERROR:  bad host name in uri,"							" dropping packet\n");					ret=E_BAD_ADDRESS;					goto error_fwd_uri;				}				ret=forward_request(msg, p, proto);				/*free_uri(&uri); -- no longer needed, in sip_msg*/				free_proxy(p); /* frees only p content, not p itself */				free(p);				if (ret>=0) ret=1;			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){				ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);				if (ret>=0) ret=1;			}else{				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",						a->p1_type, a->p2_type);				ret=E_BUG;			}			break;		case SEND_T:		case SEND_TCP_T:			if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){				LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",						a->p1_type, a->p2_type);				ret=E_BUG;				break;			}			to=(union sockaddr_union*) malloc(sizeof(union sockaddr_union));			if (to==0){				LOG(L_ERR, "ERROR: do_action: "							"memory allocation failure\n");				ret=E_OUT_OF_MEM;				break;			}						p=(struct proxy_l*)a->p1.data;						if (p->ok==0){				if (p->host.h_addr_list[p->addr_idx+1])					p->addr_idx++;				else 					p->addr_idx=0;				p->ok=1;			}			ret=hostent2su(	to, &p->host, p->addr_idx,						(p->port)?htons(p->port):htons(SIP_PORT) );			if (ret==0){				p->tx++;				p->tx_bytes+=msg->len;				if (a->type==SEND_T){					/*udp*/					send_sock=get_send_socket(to, PROTO_UDP);					if (send_sock!=0){						ret=udp_send(send_sock, msg->buf, msg->len, to);					}else{						ret=-1;					}				}#ifdef USE_TCP					else{					/*tcp*/					ret=tcp_send(msg->buf, msg->len, to, 0);				}#endif			}			free(to);			if (ret<0){				p->errors++;				p->ok=0;			}else ret=1;						break;		case LOG_T:			if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){				LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",						a->p1_type, a->p2_type);				ret=E_BUG;				break;			}			LOG(a->p1.number, a->p2.string);			ret=1;			break;		/* jku -- introduce a new branch */		case APPEND_BRANCH_T:			if ((a->p1_type!=STRING_ST)) {				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",					a->p1_type );				ret=E_BUG;				break;			}			ret=append_branch( msg, a->p1.string, 				a->p1.string ? strlen(a->p1.string):0 );			break;		/* jku begin: is_length_greater_than */		case LEN_GT_T:			if (a->p1_type!=NUMBER_ST) {				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",					a->p1_type );				ret=E_BUG;				break;			}			/* DBG("XXX: message length %d, max %d\n", 				msg->len, a->p1.number ); */			ret = msg->len >= a->p1.number ? 1 : -1;			break;		/* jku end: is_length_greater_than */					/* jku - begin : flag processing */		case SETFLAG_T:			if (a->p1_type!=NUMBER_ST) {				LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",					a->p1_type );				ret=E_BUG;				break;			}			if (!flag_in_range( a->p1.number )) {				ret=E_CFG;				break;			}			setflag( msg, a->p1.number );			ret=1;			break;		case RESETFLAG_T:			if (a->p1_type!=NUMBER_ST) {				LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",					a->p1_type );				ret=E_BUG;				break;			}			if (!flag_in_range( a->p1.number )) {				ret=E_CFG;				break;			}			resetflag( msg, a->p1.number );			ret=1;			break;					case ISFLAGSET_T:			if (a->p1_type!=NUMBER_ST) {				LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",					a->p1_type );				ret=E_BUG;				break;			}			if (!flag_in_range( a->p1.number )) {				ret=E_CFG;				break;			}			ret=isflagset( msg, a->p1.number );			break;		/* jku - end : flag processing */		case ERROR_T:			if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){				LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",						a->p1_type, a->p2_type);				ret=E_BUG;				break;			}			LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "					"not implemented yet\n", a->p1.string, a->p2.string);			ret=1;			break;		case ROUTE_T:			if (a->p1_type!=NUMBER_ST){				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",						a->p1_type);				ret=E_BUG;				break;			}			if ((a->p1.number>RT_NO)||(a->p1.number<0)){				LOG(L_ERR, "ERROR: invalid routing table number in"							"route(%d)\n", a->p1.number);				ret=E_CFG;				break;			}			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;			break;		case EXEC_T:			if (a->p1_type!=STRING_ST){				LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",						a->p1_type);				ret=E_BUG;				break;			}			LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"						" using dumb version...\n", a->p1.string);			ret=system(a->p1.string);			if (ret!=0){				LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);			}			ret=1;			break;		case REVERT_URI_T:			if (msg->new_uri.s) {				pkg_free(msg->new_uri.s);				msg->new_uri.len=0;				msg->new_uri.s=0;				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/			};			ret=1;			break;		case SET_HOST_T:		case SET_HOSTPORT_T:		case SET_USER_T:		case SET_USERPASS_T:		case SET_PORT_T:		case SET_URI_T:		case PREFIX_T:		case STRIP_T:				user=0;				if (a->type==STRIP_T) {					if (a->p1_type!=NUMBER_ST) {						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",							a->p1_type);						break;					}				} else if (a->p1_type!=STRING_ST){					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",							a->p1_type);					ret=E_BUG;					break;				}				if (a->type==SET_URI_T){					if (msg->new_uri.s) {							pkg_free(msg->new_uri.s);							msg->new_uri.len=0;					}					msg->parsed_uri_ok=0;					len=strlen(a->p1.string);					msg->new_uri.s=pkg_malloc(len+1);					if (msg->new_uri.s==0){						LOG(L_ERR, "ERROR: do_action: memory allocation"								" failure\n");						ret=E_OUT_OF_MEM;						break;					}					memcpy(msg->new_uri.s, a->p1.string, len);					msg->new_uri.s[len]=0;					msg->new_uri.len=len;										ret=1;					break;				}				if (msg->new_uri.s) {					tmp=msg->new_uri.s;					len=msg->new_uri.len;				}else{					tmp=msg->first_line.u.request.uri.s;					len=msg->first_line.u.request.uri.len;				}				if (parse_uri(tmp, len, &uri)<0){					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"								" packet\n", tmp);					ret=E_UNSPEC;					break;				}								new_uri=pkg_malloc(MAX_URI_SIZE);				if (new_uri==0){					LOG(L_ERR, "ERROR: do_action: memory allocation "								" failure\n");					ret=E_OUT_OF_MEM;					break;				}				end=new_uri+MAX_URI_SIZE;				crt=new_uri;				/* begin copying */				len=strlen("sip:"); if(crt+len>end) goto error_uri;				memcpy(crt,"sip:",len);crt+=len;				/* user */				/* prefix (-jiri) */				if (a->type==PREFIX_T) {					tmp=a->p1.string;					len=strlen(tmp); if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;					/* whateever we had before, with prefix we have username now */					user=1;				}				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {					tmp=a->p1.string;					len=strlen(tmp);				} else if (a->type==STRIP_T) {					if (a->p1.number>uri.user.len) {						LOG(L_WARN, "Error: too long strip asked; deleting username: "							"%d of <%.*s>\n", a->p1.number, uri.user.len, uri.user.s );						len=0;					} else if (a->p1.number==uri.user.len) {						len=0;					} else {						tmp=uri.user.s + a->p1.number;						len=uri.user.len - a->p1.number;					}				} else {					tmp=uri.user.s;					len=uri.user.len;				}				if (len){					if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;					user=1; /* we have an user field so mark it */				}				if (a->type==SET_USERPASS_T) tmp=0;				else tmp=uri.passwd.s;				/* passwd */				if (tmp){					len=strlen(":"); if(crt+len>end) goto error_uri;					memcpy(crt,":",len);crt+=len;					len=uri.passwd.len; if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;				}				/* host */				if (user || tmp){ /* add @ */					len=strlen("@"); if(crt+len>end) goto error_uri;					memcpy(crt,"@",len);crt+=len;				}				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {					tmp=a->p1.string;					if (tmp) len = strlen(tmp);				} else {					tmp=uri.host.s;					len = uri.host.len;				}				if (tmp){					if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;				}				/* port */				if (a->type==SET_HOSTPORT_T) tmp=0;				else if (a->type==SET_PORT_T) {					tmp=a->p1.string;					if (tmp) len = strlen(tmp);				} else {					tmp=uri.port.s;					len = uri.port.len;				}				if (tmp){					len=strlen(":"); if(crt+len>end) goto error_uri;					memcpy(crt,":",len);crt+=len;					len=strlen(tmp); if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;				}				/* params */				tmp=uri.params.s;				if (tmp){					len=strlen(";"); if(crt+len>end) goto error_uri;					memcpy(crt,";",len);crt+=len;					len=uri.params.len; if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;				}				/* headers */				tmp=uri.headers.s;				if (tmp){					len=strlen("?"); if(crt+len>end) goto error_uri;					memcpy(crt,"?",len);crt+=len;					len=uri.headers.len; if(crt+len>end) goto error_uri;					memcpy(crt,tmp,len);crt+=len;				}				*crt=0; /* null terminate the thing */				/* copy it to the msg */				if (msg->new_uri.s) pkg_free(msg->new_uri.s);				msg->new_uri.s=new_uri;				msg->new_uri.len=crt-new_uri;				msg->parsed_uri_ok=0;				ret=1;				break;		case IF_T:				/* if null expr => ignore if? */				if ((a->p1_type==EXPR_ST)&&a->p1.data){					v=eval_expr((struct expr*)a->p1.data, msg);					if (v<0){						if (v==EXPR_DROP){ /* hack to quit on DROP*/							ret=0;							break;						}else{							LOG(L_WARN,"WARNING: do_action:"										"error in expression\n");						}					}										ret=1;  /*default is continue */					if (v>0) {						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){							ret=run_actions((struct action*)a->p2.data, msg);						}					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){							ret=run_actions((struct action*)a->p3.data, msg);					}				}			break;		case MODULE_T:			if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,													  (char*)a->p3.data);			}else{				LOG(L_CRIT,"BUG: do_action: bad module call\n");			}			break;		default:			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);	}/*skip:*/	return ret;	error_uri:	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");	if (new_uri) pkg_free(new_uri);	return E_UNSPEC;error_fwd_uri:	/*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/	return ret;}