/*
 *
 *  Copyright (C) 2007 Mindspeed Technologies, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "cmm.h"
#include <ctype.h>

/*****************************************************************
* cmmSetTimeout
******************************************************************/
int timeoutSet(daemon_handle_t daemon_handle, char *argv[], int argc) 
{

	unsigned short proto;
	unsigned long long in_val1, in_val2 =0;
	fpp_timeout_cmd_t cmd;
	unsigned char rcv_buff[256];
	int arg =0;

	memset(&cmd, 0, sizeof(fpp_timeout_cmd_t));
	
	if ((argc < 2) || (argc > 4))
		goto usage;

	if(strncmp(argv[arg], "udp", strlen(argv[arg])) == 0)
		proto = IPPROTO_UDP;
	else if (strncmp(argv[arg], "tcp", strlen(argv[arg])) == 0) 
		proto = IPPROTO_TCP;
	else if (strncmp(argv[arg], "other", strlen(argv[arg])) == 0)
		proto = 0;
	else
		goto usage;
	
        in_val1 = strtoll(argv[++arg], NULL, 10);
	while(++arg < argc) // we need to look for some optional parameters
	{
		if(strncmp(argv[arg],"4rd", strlen(argv[arg])) == 0)
			cmd.sam_4o6_timeout = 1;
		else
			in_val2 = strtoll(argv[arg], NULL, 10);
	}
 

	if ((in_val1 <= 0) || (in_val1 >= UINT32_MAX)) // Cover negative, max values, null values and errors
		goto usage;
        else if (in_val2 >= UINT32_MAX)
		goto usage;
	else 
	{
		cmd.protocol = proto;
		cmd.timeout_value1 = in_val1;
                cmd.timeout_value2 = in_val2;
		if(cmmSendToDaemon(daemon_handle, FPP_CMD_IPV4_SET_TIMEOUT, &cmd, sizeof(cmd), &rcv_buff) == 2)
		{
			if(((unsigned short *)rcv_buff)[0] != 0)
				cmm_print(DEBUG_STDERR,"Error %d received from FPP for CMD_IPV4_SET_TIMEOUT\n",((unsigned short *)rcv_buff)[0]);
		}
		return 0;
	}


usage:
	cmm_print(DEBUG_ERROR, "Usage: set timeout <udp tcp other> value [value2] [4rd]\n");
	return -1;
}
/*****************************************************************
* cmmSetTimeout
******************************************************************/
int cmmtimeoutSet(daemon_handle_t daemon_handle, char *argv[], int argc, int tab) 
{
	if(argc > tab)
		return timeoutSet(daemon_handle, &argv[tab], argc - tab);
	else
                cmm_print(DEBUG_ERROR, "Usage: set timeout <udp tcp other> value [value2] [4rd]\n");

	return 0;
}

int cmmFeGetTimeout(FCI_CLIENT *fci_handle, struct ctTable *ctEntry, unsigned int *timeout)
{
	unsigned short rcvBuffer[256];
	unsigned short rcvBytes = 0;
	fpp_timeout_cmd_t *conntime;
	fpp_ct_cmd_t cmd;
	fpp_ct6_cmd_t cmd6;
	int rc;

	if (ctEntry->family == AF_INET)
	{
		memset(&cmd, 0, sizeof(fpp_ct_cmd_t));

		cmd.protocol = nfct_get_attr_u8(ctEntry->ct, ATTR_ORIG_L4PROTO);

		cmd.saddr = nfct_get_attr_u32(ctEntry->ct, ATTR_ORIG_IPV4_SRC);
		cmd.daddr = nfct_get_attr_u32(ctEntry->ct, ATTR_ORIG_IPV4_DST);
		cmd.saddr_reply = nfct_get_attr_u32(ctEntry->ct, ATTR_REPL_IPV4_SRC);
		cmd.daddr_reply = nfct_get_attr_u32(ctEntry->ct, ATTR_REPL_IPV4_DST);

		cmd.sport = nfct_get_attr_u16(ctEntry->ct, ATTR_ORIG_PORT_SRC);
		cmd.dport = nfct_get_attr_u16(ctEntry->ct, ATTR_ORIG_PORT_DST);
		cmd.sport_reply = nfct_get_attr_u16(ctEntry->ct, ATTR_REPL_PORT_SRC);
		cmd.dport_reply = nfct_get_attr_u16(ctEntry->ct, ATTR_REPL_PORT_DST);
		cmd.fwmark = nfct_get_attr_u32(ctEntry->ct, ATTR_MARK);

		rc = fci_query(fci_handle, FPP_CMD_IPV4_GET_TIMEOUT, sizeof(fpp_ct_cmd_t), (unsigned short *)&cmd, &rcvBytes, rcvBuffer);
	}
	else
	{
		memset(&cmd6, 0, sizeof(fpp_ct6_cmd_t));

		cmd6.protocol = nfct_get_attr_u8(ctEntry->ct, ATTR_ORIG_L4PROTO);

		memcpy(cmd6.saddr, nfct_get_attr(ctEntry->ct, ATTR_ORIG_IPV6_SRC), 16);
		memcpy(cmd6.daddr, nfct_get_attr(ctEntry->ct, ATTR_ORIG_IPV6_DST), 16);
		memcpy(cmd6.saddr_reply, nfct_get_attr(ctEntry->ct, ATTR_REPL_IPV6_SRC), 16);
		memcpy(cmd6.daddr_reply, nfct_get_attr(ctEntry->ct, ATTR_REPL_IPV6_DST), 16);
	
		cmd6.sport = nfct_get_attr_u16(ctEntry->ct, ATTR_ORIG_PORT_SRC);
		cmd6.dport = nfct_get_attr_u16(ctEntry->ct, ATTR_ORIG_PORT_DST);
		cmd6.sport_reply = nfct_get_attr_u16(ctEntry->ct, ATTR_REPL_PORT_SRC);
		cmd6.dport_reply = nfct_get_attr_u16(ctEntry->ct, ATTR_REPL_PORT_DST);
		cmd6.fwmark = nfct_get_attr_u32(ctEntry->ct, ATTR_MARK);

		rc = fci_query(fci_handle, FPP_CMD_IPV6_GET_TIMEOUT, sizeof(fpp_ct6_cmd_t), (unsigned short *)&cmd6, &rcvBytes, rcvBuffer);
	}

	if (rc != 0)
	{
		cmm_print(DEBUG_ERROR, "%s: error %d received from FPP for CMD_IPV4/IPV6_GET_TIMEOUT\n", __func__, rc);
		goto err;
	}


	if (rcvBytes != sizeof(fpp_timeout_cmd_t))
	{
		cmm_print(DEBUG_ERROR, "%s: wrong response length %d received from FPP for CMD_IPV4/IPV6_GET_TIMEOUT\n", __func__, rcvBytes);
		goto err;
	}

	conntime = (fpp_timeout_cmd_t *)rcvBuffer;
	*timeout = conntime->timeout_value1;

	return 0;

err:
	return -1;
}

static void FragTimeoutSetUsage()
{
	cmm_print(DEBUG_STDOUT, 
			"Usage: set frag  \n"
			"\n"
			"                                  [ipv4 | ipv6 |  sam-ipv4]\n"
			"                                  [timeout {0-65536} (in ms)] \n"
			"                                  [mode {acp | drop} (not supported for sam-ipv4)]\n"
		);
}

int cmmFragTimeoutSet(char ** keywords, int tabStart, daemon_handle_t daemon_handle)
{
	int cpt = tabStart;
	unsigned int tmp;
	char * endptr;
	char rcvBuffer[256];
	int command;	
	fpp_frag_timeout_cmd_t cmd;


        if(!keywords[cpt])
               goto keyword_error;

	if (!strcasecmp(keywords[cpt], "ipv6"))
		command = FPP_CMD_IPV6_FRAGTIMEOUT;
	else if (!strcasecmp(keywords[cpt], "ipv4"))
		command = FPP_CMD_IPV4_FRAGTIMEOUT;
        else if(!strcasecmp(keywords[cpt], "sam-ipv4"))
               command = FPP_CMD_IPV4_SAMFRAGTIMEOUT;
	else
		goto keyword_error;


	if (!keywords[++cpt])
			goto print_help;

	if (strcasecmp(keywords[cpt], "timeout") == 0)
	{
		if (!keywords[++cpt])
			goto print_help;
		
		/*Get an integer from the string*/
		endptr = NULL;
		tmp = strtoul(keywords[cpt], &endptr, 0);
		if ((keywords[cpt] == endptr) ||  (tmp > USHRT_MAX))
		{
			cmm_print(DEBUG_CRIT, "ERROR: timeout must be a number between 0 and %d\n", USHRT_MAX);
			goto  print_help;
		}
		cmd.timeout = tmp;
	}
	else
		goto keyword_error;


	if(command == FPP_CMD_IPV4_SAMFRAGTIMEOUT)
	{
		if(keywords[++cpt])
		{
			cmm_print(DEBUG_CRIT,"ERROR: %s not supported for type sam-ipv4 \n",keywords[cpt]);
			goto keyword_error;
		}
	}
	else 
	{
		if(!keywords[++cpt])
			goto print_help;
		if(strcasecmp(keywords[cpt], "mode") == 0) 
		{
			if(!keywords[++cpt])
				goto print_help;

			if(strcasecmp(keywords[cpt], "drop") == 0)
			{
				cmd.mode = 1; 
			}
			else if(strcasecmp(keywords[cpt], "acp") == 0)
			{
				cmd.mode = 0;
			}
			else
			{
				cmm_print(DEBUG_CRIT, "frag ERROR: mode must be either drop or acp \n");
				goto print_help;
			}
		}
		else
			goto keyword_error;
	}

	if (cmmSendToDaemon(daemon_handle, command, &cmd, sizeof(cmd), rcvBuffer) < sizeof(unsigned short) || cmmDaemonCmdRC(rcvBuffer))
		cmm_print(DEBUG_CRIT,  "%s: error sending message to daemon\n", __func__);
	
	return 0;



keyword_error:
	cmm_print(DEBUG_STDOUT,"ERR: unknown keyword %s\n", keywords[cpt]);

print_help:
	FragTimeoutSetUsage();
	return -1;
}
