/*
 *  Copyright (c) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
*/
#include "fe.h"
#include "module_ipv6.h"
#include "module_ipsec.h"


/* This function returns total ipv6 conntrack entries 
   configured in a given hash index */
static int IPv6_Get_Hash_CtEntries(int ct6_hash_index)
{
	int tot_ipv6_ct_entries = 0;
	PCtEntryIPv6 pCtEntryIPv6;
	struct slist_entry *entry;
	
	slist_for_each(pCtEntryIPv6, entry, &ct_cache[ct6_hash_index], list)
	{
	    	if (IS_IPV6(pCtEntryIPv6) && (pCtEntryIPv6->status & CONNTRACK_ORIG) == CONNTRACK_ORIG)
	    	    	tot_ipv6_ct_entries++;
	}
		
	return tot_ipv6_ct_entries;

}

/* This function fills the snapshot of ipv6 CT entries in a given hash index */
static int IPv6_CT_Get_Hash_Snapshot(int ct6_hash_index,int v6_ct_total_entries, PCtExCommandIPv6 pSnapshot)
{
	
	int tot_ipv6_ct_entries=0;
	PCtEntryIPv6 pCtEntryIPv6;
	PCtEntryIPv6 twin_entry;
	struct slist_entry *entry;
	
	slist_for_each(pCtEntryIPv6, entry, &ct_cache[ct6_hash_index], list)
	{
	     	if (IS_IPV6(pCtEntryIPv6) && (pCtEntryIPv6->status & CONNTRACK_ORIG) == CONNTRACK_ORIG)
	     	{
				twin_entry = CT6_TWIN(pCtEntryIPv6);

				SFL_memcpy(pSnapshot->Daddr, pCtEntryIPv6->Daddr_v6, IPV6_ADDRESS_LENGTH);
				SFL_memcpy(pSnapshot->Saddr, pCtEntryIPv6->Saddr_v6, IPV6_ADDRESS_LENGTH);
				pSnapshot->Sport = 	pCtEntryIPv6->Sport;
				pSnapshot->Dport = 	pCtEntryIPv6->Dport;
			
				SFL_memcpy(pSnapshot->DaddrReply, twin_entry->Daddr_v6, IPV6_ADDRESS_LENGTH);
				SFL_memcpy(pSnapshot->SaddrReply, twin_entry->Saddr_v6, IPV6_ADDRESS_LENGTH);
				pSnapshot->SportReply = 	twin_entry->Sport;
				pSnapshot->DportReply = 	twin_entry->Dport;
				pSnapshot->protocol   =  GET_PROTOCOL(pCtEntryIPv6); 
				pSnapshot->fwmark     = IP_get_fwmark((PCtEntry)pCtEntryIPv6, (PCtEntry)twin_entry);
				pSnapshot->SA_nr      =	0;
				pSnapshot->SAReply_nr	= 	0;
				pSnapshot->format = 0;
				
				if ((pCtEntryIPv6->status & CONNTRACK_SEC) == CONNTRACK_SEC)
				{
					int i;
					pSnapshot->format |= CT_SECURE;
					for (i= 0; i < SA_MAX_OP; i++)
					{
						if (pCtEntryIPv6->hSAEntry[i])
						{
							pSnapshot->SA_nr++;
							pSnapshot->SA_handle[i] = pCtEntryIPv6->hSAEntry[i];
						}
					}
					
					for (i= 0; i < SA_MAX_OP; i++)
					{
						if (twin_entry->hSAEntry[i])
						{
							pSnapshot->SAReply_nr++;
							pSnapshot->SAReply_handle[i] = twin_entry->hSAEntry[i];
						}
						
					}
							
				}
				
				pSnapshot++;
				tot_ipv6_ct_entries++;
				
				if (--v6_ct_total_entries <= 0)
					break;
	     	}
	}
		
	return tot_ipv6_ct_entries;

}


/* This function creates the snapshot memory and returns the 
   next ipv6 CT entry from the snapshop of the ipv6 conntrack entries of a
   single hash to the caller  */
   
int IPv6_Get_Next_Hash_CTEntry(PCtExCommandIPv6 pV6CtCmd, int reset_action)
{
	int ipv6_ct_hash_entries;
	PCtExCommandIPv6 pV6Ct;
	static PCtExCommandIPv6 pV6CtSnapshot = NULL;
	static int v6_ct_hash_index = 0, v6_ct_snapshot_entries =0, v6_ct_snapshot_index=0, v6_ct_snapshot_buf_entries = 0;
	
	if(reset_action)
	{
		v6_ct_hash_index = 0;
		v6_ct_snapshot_entries =0;
		v6_ct_snapshot_index=0;
		if(pV6CtSnapshot)
		{
			Heap_Free(pV6CtSnapshot);
			pV6CtSnapshot = NULL;	
		}
		v6_ct_snapshot_buf_entries = 0;
	}
	
	if (v6_ct_snapshot_index == 0)
	{
		while( v6_ct_hash_index < NUM_CT_ENTRIES)
		{
		
			ipv6_ct_hash_entries = IPv6_Get_Hash_CtEntries(v6_ct_hash_index);
			if(ipv6_ct_hash_entries == 0)
			{
				v6_ct_hash_index++;
				continue;
			}
		   	
		   	if(ipv6_ct_hash_entries > v6_ct_snapshot_buf_entries)
		   	{
		   		
		   		if(pV6CtSnapshot)
		   			Heap_Free(pV6CtSnapshot);
				pV6CtSnapshot = Heap_Alloc(ipv6_ct_hash_entries * sizeof(CtExCommandIPv6));
			
				if (!pV6CtSnapshot)
				{
			    	v6_ct_hash_index = 0;
			    	v6_ct_snapshot_buf_entries = 0;
					return ERR_NOT_ENOUGH_MEMORY;
				}
				v6_ct_snapshot_buf_entries = ipv6_ct_hash_entries;
				
		   	}
			v6_ct_snapshot_entries = IPv6_CT_Get_Hash_Snapshot(v6_ct_hash_index , ipv6_ct_hash_entries,pV6CtSnapshot);
		
					
			break;
		}
		
		if (v6_ct_hash_index >= NUM_CT_ENTRIES)
		{
			v6_ct_hash_index = 0;
			if(pV6CtSnapshot)
			{
				Heap_Free(pV6CtSnapshot);
				pV6CtSnapshot = NULL;	
			}
			v6_ct_snapshot_buf_entries = 0;
			return ERR_CT_ENTRY_NOT_FOUND;
		}
		   
	}
	
	pV6Ct = &pV6CtSnapshot[v6_ct_snapshot_index++];
	SFL_memcpy(pV6CtCmd, pV6Ct, sizeof(CtExCommandIPv6));
	if (v6_ct_snapshot_index == v6_ct_snapshot_entries)
	{
		v6_ct_snapshot_index = 0;
		v6_ct_hash_index ++;
	}
		
	
	return NO_ERR;	
		
}
