blob: 1d9f79ef887ea7a6b3e5c1ea28a56f74efe01c41 [file] [log] [blame]
/*
* 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_ipv4.h"
#include "module_ipsec.h"
/* This function returns total arp entries configured in a given hash index */
static int IPV4_Get_Hash_CTEntries(int ct_hash_index)
{
int tot_ct_entries = 0;
PCtEntry pCtEntry;
struct slist_entry *entry;
slist_for_each(pCtEntry, entry, &ct_cache[ct_hash_index], list)
{
if (IS_IPV4(pCtEntry) && (pCtEntry->status & CONNTRACK_ORIG) == CONNTRACK_ORIG)
tot_ct_entries++;
}
return tot_ct_entries;
}
/* This function fills the snapshot of ipv4 CT entries in a given hash index */
static int IPv4_CT_Get_Hash_Snapshot(int ct_hash_index, int ct_total_entries, PCtExCommand pSnapshot)
{
int tot_ct_entries=0;
PCtEntry pCtEntry;
PCtEntry pReplyEntry = NULL;
struct slist_entry *entry;
slist_for_each(pCtEntry, entry, &ct_cache[ct_hash_index], list)
{
if (IS_IPV4(pCtEntry) &&(pCtEntry->status & CONNTRACK_ORIG) == CONNTRACK_ORIG)
{
pReplyEntry = CT_TWIN(pCtEntry);
pSnapshot->Daddr = pCtEntry->Daddr_v4;
pSnapshot->Saddr = pCtEntry->Saddr_v4;
pSnapshot->Sport = pCtEntry->Sport;
pSnapshot->Dport = pCtEntry->Dport;
pSnapshot->DaddrReply = pCtEntry->twin_Daddr;
pSnapshot->SaddrReply = pCtEntry->twin_Saddr;
pSnapshot->SportReply = pCtEntry->twin_Sport;
pSnapshot->DportReply = pCtEntry->twin_Dport;
pSnapshot->protocol = GET_PROTOCOL(pCtEntry);
pSnapshot->fwmark = IP_get_fwmark(pCtEntry, pReplyEntry);
pSnapshot->SA_nr = 0;
pSnapshot->SAReply_nr = 0;
pSnapshot->format = 0;
if ((pCtEntry->status & CONNTRACK_SEC) == CONNTRACK_SEC)
{
int i;
pSnapshot->format |= CT_SECURE;
for (i= 0; i < SA_MAX_OP; i++)
{
if (pCtEntry->hSAEntry[i])
{
pSnapshot->SA_nr++;
pSnapshot->SA_handle[i] = pCtEntry->hSAEntry[i];
}
}
for (i= 0; i < SA_MAX_OP; i++)
{
if (pReplyEntry->hSAEntry[i])
{
pSnapshot->SAReply_nr++;
pSnapshot->SAReply_handle[i] = pReplyEntry->hSAEntry[i];
}
}
}
pSnapshot++;
tot_ct_entries++;
if (--ct_total_entries <= 0)
break;
}
}
return tot_ct_entries;
}
/* This function creates the snapshot memory and returns the
next ipv4 CT entry from the snapshop of the ipv4 conntrack entries of a
single hash to the caller */
int IPv4_Get_Next_Hash_CTEntry(PCtExCommand pCtCmd, int reset_action)
{
int ct_hash_entries;
static PCtExCommand pCtSnapshot = NULL;
static int ct_hash_index = 0,ct_snapshot_entries =0, ct_snapshot_index = 0, ct_snapshot_buf_entries = 0;
PCtExCommand pCt;
if(reset_action)
{
ct_hash_index = 0;
ct_snapshot_entries =0;
ct_snapshot_index = 0;
if(pCtSnapshot)
{
Heap_Free(pCtSnapshot);
pCtSnapshot = NULL;
}
ct_snapshot_buf_entries = 0;
}
if (ct_snapshot_index == 0)
{
while( ct_hash_index < NUM_CT_ENTRIES)
{
ct_hash_entries = IPV4_Get_Hash_CTEntries(ct_hash_index);
if(ct_hash_entries == 0)
{
ct_hash_index++;
continue;
}
if (ct_hash_entries > ct_snapshot_buf_entries)
{
if(pCtSnapshot)
Heap_Free(pCtSnapshot);
pCtSnapshot = Heap_Alloc(ct_hash_entries * sizeof(CtExCommand));
if (!pCtSnapshot)
{
ct_hash_index = 0;
ct_snapshot_buf_entries = 0;
return ERR_NOT_ENOUGH_MEMORY;
}
ct_snapshot_buf_entries = ct_hash_entries;
}
ct_snapshot_entries = IPv4_CT_Get_Hash_Snapshot(ct_hash_index ,ct_hash_entries, pCtSnapshot);
break;
}
if (ct_hash_index >= NUM_CT_ENTRIES)
{
ct_hash_index = 0;
if(pCtSnapshot)
{
Heap_Free(pCtSnapshot);
pCtSnapshot = NULL;
}
ct_snapshot_buf_entries = 0;
return ERR_CT_ENTRY_NOT_FOUND;
}
}
pCt = &pCtSnapshot[ct_snapshot_index++];
SFL_memcpy(pCtCmd, pCt, sizeof(CtExCommand));
if (ct_snapshot_index == ct_snapshot_entries)
{
ct_snapshot_index = 0;
ct_hash_index ++;
}
return NO_ERR;
}
/* This function returns total routes configured in a given hash index */
static int IPV4_Get_Hash_Routes(int rt_hash_index)
{
int tot_routes = 0;
struct slist_entry *entry;
slist_for_each_entry(entry, &rt_cache[rt_hash_index])
{
tot_routes++;
}
return tot_routes;
}
/* This function fills the snapshot of route entries in a given hash index */
static int IPV4_RT_Get_Hash_Snapshot(int rt_hash_index,int rt_total_entries, PRtCommand pSnapshot)
{
int tot_routes=0;
PRouteEntry pRtEntry;
struct slist_entry *entry;
POnifDesc onif_desc;
slist_for_each(pRtEntry, entry, &rt_cache[rt_hash_index], list)
{
COPY_MACADDR(pSnapshot->macAddr, pRtEntry->dstmac);
onif_desc = get_onif_by_index(pRtEntry->itf->index);
if (onif_desc)
strcpy((char *)pSnapshot->outputDevice, (char *)onif_desc->name);
else
pSnapshot->outputDevice[0] = '\0';
pSnapshot->mtu = pRtEntry->mtu;
pSnapshot->id = pRtEntry->id;
pSnapshot++;
tot_routes++;
if (--rt_total_entries <= 0)
break;
}
return tot_routes;
}
/* This function creates the snapshot memory and returns the
next route entry from the snapshop of the route entries of a
single hash to the caller */
int IPV4_Get_Next_Hash_RtEntry(PRtCommand pRtCmd, int reset_action)
{
int rt_hash_entries;
PRtCommand pRt;
static PRtCommand pRtSnapshot = NULL;
static int rt_hash_index = 0, rt_snapshot_entries =0, rt_snapshot_index=0, rt_snapshot_buf_entries = 0;
if(reset_action)
{
rt_hash_index = 0;
rt_snapshot_entries =0;
rt_snapshot_index=0;
if(pRtSnapshot)
{
Heap_Free(pRtSnapshot);
pRtSnapshot = NULL;
}
rt_snapshot_buf_entries = 0;
}
if (rt_snapshot_index == 0)
{
while( rt_hash_index < NUM_ROUTE_ENTRIES)
{
rt_hash_entries = IPV4_Get_Hash_Routes(rt_hash_index);
if(rt_hash_entries == 0)
{
rt_hash_index++;
continue;
}
if(rt_hash_entries > rt_snapshot_buf_entries)
{
if(pRtSnapshot)
Heap_Free(pRtSnapshot);
pRtSnapshot = Heap_Alloc(rt_hash_entries * sizeof(RtCommand));
if (!pRtSnapshot)
{
rt_hash_index = 0;
rt_snapshot_buf_entries = 0;
return ERR_NOT_ENOUGH_MEMORY;
}
rt_snapshot_buf_entries = rt_hash_entries;
}
rt_snapshot_entries = IPV4_RT_Get_Hash_Snapshot(rt_hash_index ,rt_hash_entries, pRtSnapshot);
break;
}
if (rt_hash_index >= NUM_ROUTE_ENTRIES)
{
rt_hash_index = 0;
if(pRtSnapshot)
{
Heap_Free(pRtSnapshot);
pRtSnapshot = NULL;
}
rt_snapshot_buf_entries = 0;
return ERR_RT_ENTRY_NOT_FOUND;
}
}
pRt = &pRtSnapshot[rt_snapshot_index++];
SFL_memcpy(pRtCmd, pRt, sizeof(RtCommand));
if (rt_snapshot_index == rt_snapshot_entries)
{
rt_snapshot_index = 0;
rt_hash_index ++;
}
return NO_ERR;
}