Index: /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/APIForIDE.c
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/APIForIDE.c	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/APIForIDE.c	(working copy)
@@ -114,6 +114,7 @@
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("http::body", -1), Tcl_NewStringObj("query http request/response body", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("http::respond", -1), Tcl_NewStringObj("build a response and send to client", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("http::redirect", -1), Tcl_NewStringObj("http request redirect", -1));
+	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("http::is_redirect", -1), Tcl_NewStringObj("check if http response is redirected", -1));
 
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("xml::elementname", -1), Tcl_NewStringObj("query or set current xml element name", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("xml::stop_parse", -1), Tcl_NewStringObj("stop xml paring", -1));
@@ -134,6 +135,8 @@
 
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("ip::client_addr", -1), Tcl_NewStringObj("query or set TCP payload", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("ip::client_port", -1), Tcl_NewStringObj("query or set TCP payload string", -1));
+	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("ip::local_addr", -1), Tcl_NewStringObj("return the IP address of the virtual server the client is connected to", -1));
+	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("ip::local_port", -1), Tcl_NewStringObj("return the port of the virtual server the client is connected to", -1));
 
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::select_server", -1), Tcl_NewStringObj("send request to a real server", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::select_group", -1), Tcl_NewStringObj("send request to a real server group", -1));
@@ -141,6 +144,7 @@
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::server_is_active", -1), Tcl_NewStringObj("check whether a real server is active and enabled", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::active_members", -1), Tcl_NewStringObj("query active memeber in a real server group", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::server", -1), Tcl_NewStringObj("query current real service", -1));
+	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("slb::vs_name", -1), Tcl_NewStringObj("retrieve current virtual service name", -1));
 
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("tcp::reset_client_conn", -1), Tcl_NewStringObj("reset client connection", -1));
 	Tcl_DictObjPut(NULL, dict, Tcl_NewStringObj("tcp::reset_server_conn", -1), Tcl_NewStringObj("reset server connection", -1));
Index: /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/http_policy.c
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/http_policy.c	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/http_policy.c	(working copy)
@@ -2053,6 +2053,67 @@
 	return TCL_OK;
 }
 
+int HTTP_is_redirect(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_Obj *const argv[])
+{
+	CHECK_FOR_COMPILE;
+	slb_vs_t *vs_p = (slb_vs_t *) Tcl_GetAssocData(interp, ASSOC_DATA_VS_ID, NULL);
+
+	if (argc != 1)
+	{
+		ePolicy_log_vs(EPOLICY_LOG_ERROR, vs_p, "%s: invalid param number: %d", __FUNCTION__, argc );
+		return TCL_ERROR;
+	}
+
+	ePolicy_message *msg = (ePolicy_message *)Tcl_GetAssocData(interp, CLIENT_DATA_HTTP_CURRENT_MESSAGE, NULL);
+	if(!msg || !msg->message_header_frames || msg->message_header_frames->f_datalen <= 0) {
+		ePolicy_log_vs(EPOLICY_LOG_ERROR, vs_p, "%s: msg %p invalid", __FUNCTION__, msg);
+		return TCL_OK;
+	}
+
+	/* Check status code is 3XX */
+	int i = 0, data_len = 0;
+	char *p = NULL;
+	char* data = NULL;
+
+	if(msg->type != MESSAGE_TYPE_HTTP_RESPONSE) {
+		ePolicy_log_vs(EPOLICY_LOG_ERROR, vs_p, "%s: msg is not http response", __FUNCTION__);
+		return TCL_OK;
+	}
+	p = data = (char *)msg->message_header_frames->f_data;
+	data_len = msg->message_header_frames->f_datalen;
+
+	do {
+		for(; i < data_len; i++)
+			if(p[i] == ' ')
+				break;
+		if(i >= data_len-1)
+			break;
+		i++;
+		p = &p[i];
+		i = 0;
+		for(; i < data_len; i++)
+			if(p[i] == ' ')
+				break;
+		if((unsigned char *)p + i == data + data_len)
+			break;
+	} while(0);
+
+	/* Extract the status code (3-digit number) */
+	unsigned int j, status_code = 0;
+	for (i = 0; i < 3; i++) {
+		status_code = status_code * 10 + (p[i] - '0');
+	}
+
+	/* Check if the status code is in the 3xx range */
+	if (status_code >= 300 && status_code < 400) {
+		Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
+	} else {
+		Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+	}
+
+	return TCL_OK;
+}
+
 static const ePolicyCmdInfo builtInCmds[] = {
     /*
      * Commands for HTTP header.
@@ -2069,6 +2130,7 @@
 	{"http::body",				HTTP_body,			NULL},
 	{"http::respond",			HTTP_respond,		NULL},
 	{"http::redirect",			HTTP_redirect,		NULL},
+	{"http::is_redirect",		HTTP_is_redirect,	NULL},
     {NULL,						NULL,				NULL}
 };
 
Index: /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/slb_command.c
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/slb_command.c	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/lib/libepolicy/slb_command.c	(working copy)
@@ -373,6 +373,38 @@
 	return TCL_OK;
 }
 
+int ip_local_address(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_Obj *const argv[])
+{
+	CHECK_FOR_COMPILE;
+	slb_vs_t *vs_p = (slb_vs_t *) Tcl_GetAssocData(interp, ASSOC_DATA_VS_ID, NULL);
+
+	if (argc != 1)
+	{
+		Tcl_WrongNumArgs(interp, 1, argv, "");
+		return TCL_ERROR;
+	}
+
+	Tcl_SetObjResult(interp, Tcl_NewStringObj(vs_p->ipstr, -1));
+
+	return TCL_OK;
+}
+
+int ip_local_port(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_Obj *const argv[])
+{
+	CHECK_FOR_COMPILE;
+	slb_vs_t *vs_p = (slb_vs_t *) Tcl_GetAssocData(interp, ASSOC_DATA_VS_ID, NULL);
+
+	if (argc != 1)
+	{
+		Tcl_WrongNumArgs(interp, 1, argv, "");
+		return TCL_ERROR;
+	}
+
+	Tcl_SetObjResult(interp, Tcl_NewIntObj(vs_p->port));
+
+	return TCL_OK;
+}
+
 int check_rs_is_active(char *rs_name, slb_vs_t *vs_p)
 {	
 	int ret;
@@ -1201,6 +1233,28 @@
 	return TCL_OK;
 }
 
+int slb_vs_name(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_Obj *const argv[]) {
+	int ret;
+	slb_vs_t *vs_p = NULL;
+	
+	CHECK_FOR_COMPILE;
+	if (argc != 1)
+	{
+		Tcl_WrongNumArgs(interp, 1, argv, "");
+		return TCL_ERROR;
+	}
+	
+	vs_p = (slb_vs_t *) Tcl_GetAssocData(interp, ASSOC_DATA_VS_ID, NULL);
+	if (vs_p == NULL) {
+		ePolicy_log_vs(EPOLICY_LOG_ERROR, vs_p, "%s: client conn not found vs", __FUNCTION__);
+		return TCL_OK;
+	}
+	
+	Tcl_SetObjResult(interp, Tcl_NewStringObj(vs_p->name, -1));
+	
+	return TCL_OK;	
+}
+
 int md5_cmd(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_Obj *const argv[]) {
 	char *input_data = NULL;
 	int intput_len = 0;
@@ -2124,6 +2178,8 @@
 	{"ip::client_port",			ip_client_port, 		NULL},
 	{"ip::server_addr",			ip_server_address,		NULL},
 	{"ip::server_port",			ip_server_port,		NULL},
+	{"ip::local_addr",			ip_local_address,	NULL},
+	{"ip::local_port",			ip_local_port,		NULL},
 	{"slb::select_server",	    slb_select_server,	NULL},
 	{"md5",						md5_cmd,	NULL},
 	{"b64encode",				b64encode,	NULL},
@@ -2144,6 +2200,7 @@
 	{"slb::get_client_conn",    slb_get_client_conn,  NULL},
 	{"slb::get_server_conn",    slb_get_server_conn,  NULL},
 	{"slb::vs_is_active",    	slb_vs_is_active,  NULL},
+	{"slb::vs_name",    		slb_vs_name,  	NULL},
 	{"timer::add",				add_timer,		NULL},
 	{"timer::remove",			remove_timer,	NULL},
 	{"timer::id",				current_expired_timer_id,	NULL},
Index: /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy.syntax
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy.syntax	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy.syntax	(working copy)
@@ -47,6 +47,7 @@
 ##nagelfar syntax http::body x?
 ##nagelfar syntax http::respond x
 ##nagelfar syntax http::redirect x
+##nagelfar syntax http::is_redirect
 
 
 ##nagelfar syntax xml::elementname x?
@@ -70,6 +71,7 @@
 ##nagelfar syntax diameter::is_response
 
 
+##nagelfar syntax slb::vs_name
 ##nagelfar syntax slb::vs_is_active
 ##nagelfar syntax slb::select_server x
 ##nagelfar syntax slb::select_group x
@@ -91,6 +93,8 @@
 ##nagelfar syntax ip::client_port
 ##nagelfar syntax ip::server_addr x?
 ##nagelfar syntax ip::server_port
+##nagelfar syntax ip::local_addr
+##nagelfar syntax ip::local_port
 
 
 ##nagelfar syntax tcp::is_server_conn
@@ -111,6 +115,7 @@
 ##nagelfar syntax md5 x
 ##nagelfar syntax b64encode x
 ##nagelfar syntax clock_seconds
+##nagelfar syntax clock_milliseconds
 ##nagelfar syntax userdata x x
 ##nagelfar syntax log x
 ##nagelfar syntax read_list_from_file x x?
Index: /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy_no_socket.syntax
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy_no_socket.syntax	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/epolicy_no_socket.syntax	(working copy)
@@ -47,6 +47,7 @@
 ##nagelfar syntax http::body x?
 ##nagelfar syntax http::respond x
 ##nagelfar syntax http::redirect x
+##nagelfar syntax http::is_redirect
 
 
 ##nagelfar syntax xml::elementname x?
@@ -70,6 +71,7 @@
 ##nagelfar syntax diameter::is_response
 
 
+##nagelfar syntax slb::vs_name
 ##nagelfar syntax slb::vs_is_active
 ##nagelfar syntax slb::select_server x
 ##nagelfar syntax slb::select_group x
@@ -91,6 +93,8 @@
 ##nagelfar syntax ip::client_port
 ##nagelfar syntax ip::server_addr x?
 ##nagelfar syntax ip::server_port
+##nagelfar syntax ip::local_addr
+##nagelfar syntax ip::local_port
 
 
 ##nagelfar syntax tcp::is_server_conn
@@ -112,6 +116,7 @@
 ##nagelfar syntax md5 x
 ##nagelfar syntax b64encode x
 ##nagelfar syntax clock_seconds
+##nagelfar syntax clock_milliseconds
 ##nagelfar syntax userdata x x
 ##nagelfar syntax log x
 ##nagelfar syntax read_list_from_file x x?
Index: /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/nagelfar.syntax
===================================================================
--- /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/nagelfar.syntax	(revision 38759)
+++ /branches/rel_apv_10_7_2_5_irule/usr/click/tools/nagelfar132/nagelfar.syntax	(working copy)
@@ -48,6 +48,7 @@
 ##nagelfar syntax http::body x?
 ##nagelfar syntax http::respond x
 ##nagelfar syntax http::redirect x
+##nagelfar syntax http::is_redirect
 
 
 ##nagelfar syntax xml::elementname x?
@@ -70,7 +71,7 @@
 ##nagelfar syntax diameter::is_response
 
 
-
+##nagelfar syntax slb::vs_name
 ##nagelfar syntax slb::select_server x
 ##nagelfar syntax slb::select_group x
 ##nagelfar syntax slb::group_is_active x
@@ -89,6 +90,8 @@
 
 ##nagelfar syntax ip::client_addr x?
 ##nagelfar syntax ip::client_port
+##nagelfar syntax ip::local_addr
+##nagelfar syntax ip::local_port
 
 
 ##nagelfar syntax tcp::is_server_conn
@@ -108,6 +111,7 @@
 
 ##nagelfar syntax md5 x
 ##nagelfar syntax clock_seconds
+##nagelfar syntax clock_milliseconds
 ##nagelfar syntax userdata x x
 ##nagelfar syntax log x
 ##nagelfar syntax read_list_from_file x x?
