Files
m241Neelima/components/ip_net2-6.9/ipmipfa/config/ipmipfa_aaa_diameter.c
T
2026-07-30 11:19:44 +05:30

866 lines
35 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipfa_aaa_diameter.c,v $ $Revision: 1.4.16.4 $
* $Source: /home/interpeak/CVSRoot/ipmipfa/config/ipmipfa_aaa_diameter.c,v $
* $Author: jsheng $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmipfa_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPMIPFA_DIAMETER_ENABLE
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_sysvar.h>
#include <ipmip4.h>
#include <private/ipmip4_context.h>
#include <private/ipmip4_if.h>
#include <private/ipmip4_auth.h>
#include <private/ipmip4_sysext.h>
#include <private/ipmip4_util.h>
#include <private/ipmip4_pktbuf.h>
#include <private/ipmip4_diameter.h>
#include "ipmipfa_h.h"
#include "ipmipfa_h.h"
#include "ipmipfa_reg.h"
#include "ipmipfa_node.h"
#include "ipmipfa_pktbuf.h"
#include <ipdiameter.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIPFA_AAA_DIAMETER "AAA-DIAMETER"
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmipfa_aaa_diameter_config_ifp
{
struct Ipmip4_diameter_context *diameter;
/* Should the MN-AAA authentication extension be verified? */
Ip_bool access;
/* MUST the MN-AAA extension be available? */
Ip_bool access_require;
Ip_u32 access_fa_ha_spi;
Ip_u32 access_timeout;
} Ipmipfa_aaa_diameter_config_ifp_t;
typedef struct Ipmipfa_aaa_diameter_pktbuf_data
{
Ip_u32 feature;
} Ipmipfa_aaa_diameter_pktbuf_data_t;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ipmipfa_extension_t ipmipfa_aaa_diameter_srv;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC void
ipmipfa_aaa_diameter_pktaux_free(struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_pktbuf *pbuf,
Ipmipfa_aaa_diameter_pktbuf_data_t *aaa)
{
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(pbuf);
IPMIP_UNUSED_PARAMETER(aaa);
}
IP_STATIC void
ipmipfa_aaa_diameter_AMA(int result,
Ipmipfa_data_t *ctx,
Ipmip_proc_t *proc,
struct Ipmip4_diameter_context *diameter,
Ipmipfa_pktbuf_t *pbuf,
Ipmipfa_node_t *node,
struct Ipdiameter_request_struct *request_v,
struct Ipdiameter_header_struct *request_packet_v,
struct Ipdiameter_header_struct *response_packet_v)
{
Ipmipfa_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&ctx->ipmip4.ipmip, &pbuf->ipmip4.ipmip, ipmipfa_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_TRUE);
Ipmipfa_pktbuf_t *reply = IP_NULL;
IPMIP_UNUSED_PARAMETER(diameter);
IPMIP_UNUSED_PARAMETER(request_v);
IPMIP_UNUSED_PARAMETER(request_packet_v);
if(IP_NULL == aaa)
return;
if (result == IPMIP4_DIAMETER_ACCESS_REQUEST_SUCCESS)
{
/* Time to resolve the AVP's */
Ip_u32 len;
Ip_u8 *val;
int tmp;
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_Result_Code, &len, &val) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Result-Code AVP not present. Poorly formed");
goto error_out;
}
/* Read the value */
tmp = IP_GET_HTONL(val);
if (tmp != DIAMETER_SUCCESS && tmp != DIAMETER_LIMITED_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Result-Code AVP reported error %d", tmp);
goto error_out;
}
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_Home_Agent_Address, &len, &val) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Home Agent Address AVP not present. Poorly formed");
goto error_out;
}
/* Retrieve the address */
pbuf->reginfo.faVisitorResolvedHomeAgent = IP_GET_32ON8((val + 2));
IPCOM_LOG3(DEBUG2, "Extension: Mip-Home-Agent-Address = %s (type = %d, len = %d)",
ipmip_ntop_inet(proc, pbuf->reginfo.faVisitorResolvedHomeAgent),
IP_GET_HTONS(val),
len);
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_Mobile_Node_Address, &len, &val) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Mobile Node Address AVP not present. Poorly formed");
goto error_out;
}
/* Retrieve the address */
pbuf->reginfo.faVisitorResolvedHomeAddress = IP_GET_32ON8((val + 2));
IPCOM_LOG3(DEBUG2, "Extension: Mip-Mobile-Node-Address = %s (type = %d, len = %d)",
ipmip_ntop_inet(proc, pbuf->reginfo.faVisitorResolvedHomeAddress),
IP_GET_HTONS(val),
len);
/**/
pbuf->pktinfo.faVisitorHomeAgentAddress = pbuf->reginfo.faVisitorResolvedHomeAgent;
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_Reg_Reply, &len, &val) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Mobile Node Registration Reply not present. Poorly formed");
goto error_out;
}
reply = (Ipmipfa_pktbuf_t *)ipmip_pktbuf_alloc(&ctx->ipmip4.ipmip, proc, len);
if (reply == IP_NULL)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Mobile Node Failed to allocate memory for reply");
goto error_out;
}
/* Store the reply */
ipmip_buffer_append(&reply->ipmip4.ipmip.packet, val, len);
/* Setup the parameters */
reply->iff.priv = pbuf->iff.priv;
{
/* Create a workable pktinfo */
struct Ip_in_pktinfo pktinfo;
struct Ip_sockaddr_in src;
pktinfo.ipi_addr.s_addr = reply->iff.pub->ifaddr;
pktinfo.ipi_ifindex = reply->iff.pub->ipmip.ifindex;
ipmip_pktbuf_srcinfo_dst_inet(&reply->ipmip4.ipmip, &pktinfo);
ipcom_memset(&src, 0, sizeof(src));
src.sin_addr.s_addr = pbuf->reginfo.faVisitorResolvedHomeAgent;
src.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&src, sizeof(src));
src.sin_port = ip_htons(IPMIP4_PORT);
ipmip_util_dup(&reply->ipmip4.ipmip.srcinfo.src, &src, sizeof(src));
}
/* Got all the required information */
if (IP_BIT_ISTRUE(aaa->feature, IPMIP4_DIAMETER_FEATURE_MN_FA_KEYREQ))
{
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_FA_to_MN_MSA, &len, &val) == IPCOM_SUCCESS)
{
Ip_u32 spi;
Ip_u32 avp_len;
Ip_u8 *avp;
Ip_u32 key_len;
Ip_u8 *key_avp;
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Algorithm_Type, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
if (IP_GET_NTOHL(avp) != 2)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Only the HMAC-SHA1 (2) Algorithm Type is supported");
goto error_out;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-FA-to-MN-MSA is missing");
goto error_out;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_FA_to_MN_SPI, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
spi = IP_GET_NTOHL(avp);
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER FA-to-MN-SPI AVP in MIP-FA-to-MN-MSA is missing or truncated");
goto error_out;
}
/**/
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Session_Key, &key_len, &key_avp) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Session-Key AVP in MIP-FA-to-MN-MSA is missing");
goto error_out;
}
else
{
#ifdef IPTESTENGINE
/* Create the SPI */
IPCOM_LOG3(DEBUG2, "Creating security association with SPI %d, %s (%d)",
spi, ipmip_ntop_hex(proc, key_avp, key_len), key_len);
#endif
if (node->faVisitorMobileSA)
ipmip4_auth_spi_free(node->faVisitorMobileSA);
node->faVisitorMobileSA = ipmip4_auth_spi_create(proc, spi, key_avp, key_len, IPMIP4_AUTH_METHOD_MD5_HMAC);
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-FA-to-MN-MSA is missing but KEYREQ was present in registration");
goto error_out;
}
}
/* Got all the required information */
if (IP_BIT_ISTRUE(aaa->feature, IPMIP4_DIAMETER_FEATURE_FA_HA_KEYREQ))
{
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_FA_to_HA_MSA, &len, &val) == IPCOM_SUCCESS)
{
Ip_u32 spi;
Ip_u32 avp_len;
Ip_u8 *avp;
Ip_u32 key_len;
Ip_u8 *key_avp;
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Algorithm_Type, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
if (IP_GET_NTOHL(avp) != 2)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Only the HMAC-SHA1 (2) Algorithm Type is supported");
goto error_out;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-FA-to-HA-MSA is missing");
goto error_out;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_FA_to_HA_SPI, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
spi = IP_GET_NTOHL(avp);
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER FA-to-HA-SPI AVP in MIP-FA-to-HA-MSA is missing or truncated");
goto error_out;
}
/**/
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Session_Key, &key_len, &key_avp) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Session-Key AVP in MIP-FA-to-HA-MSA is missing");
goto error_out;
}
else
{
#ifdef IPTESTENGINE
/* Create the SPI */
IPCOM_LOG3(DEBUG2, "Creating security association with SPI %d, %s (%d)",
spi, ipmip_ntop_hex(proc, key_avp, key_len), key_len);
#endif
if (node->faVisitorHomeAgentSA)
ipmip4_auth_spi_free(node->faVisitorHomeAgentSA);
node->faVisitorHomeAgentSA = ipmip4_auth_spi_create(proc, spi, key_avp, key_len, IPMIP4_AUTH_METHOD_MD5_HMAC);
pbuf->reginfo.faVisitorSPIForeignHome = node->faVisitorHomeAgentSA;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-FA-to-HA-MSA is missing but KEYREQ was present in registration");
goto error_out;
}
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER authentication request failed");
}
error_out:
/* Are we satisfied? */
if (pbuf->ipmip4.ipmip.message == IP_NULL)
node->faVisitorAAAVerificationTime = ipmip_util_time();
/* Need to finish processing of the previous packet */
ipmip_timer_execute(&ctx->ipmip4.ipmip, &node->service);
/* Insert the REPLY into the processing */
if (reply != IP_NULL)
{
reply->pktinfo.faVisitorForeignHomeSAPolicyOK = 1;
ipmipfa_reg_input_reply(ctx, proc, reply);
}
}
IP_STATIC Ip_bool
ipmipfa_aaa_diameter_access_request(struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_aaa_diameter_config_ifp_t *ifp_config,
Ipmipfa_node_t *node,
Ipmipfa_pktbuf_t *pbuf)
{
Ipmipfa_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&ctx->ipmip4.ipmip, &pbuf->ipmip4.ipmip, ipmipfa_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_TRUE);
Ipdiameter_header *packet;
Ipdiameter_request request;
if(IP_NULL == aaa)
return IP_FALSE;
if (!ipmip4_diameter_request_alloc(&ctx->ipmip4, proc, ifp_config->diameter, &request, &packet))
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"DIAMETER unable to allocate request packet");
return IP_FALSE;
}
/* Set comand code to IPRADIUS_CODE_Access_Request */
ipdiameter_set_hdr_code((Ip_u32 *)packet, DIAMETER_CODE_AA_Mobile_Node_Request);
/***** Add attributes here! *****/
if (pbuf->ipmip4.ext.mobile.nai_mobile != IP_NULL)
(void)ipdiameter_avp_add_array(packet,
DIAMETER_AVP_CODE_User_Name,
DIAMETER_AVP_M_FLAG,
IP_NULL,
(Ip_u8*)IPMIP4_MSGEXT_SHDR_EXT_DATA(pbuf->ipmip4.ext.mobile.nai_mobile),
(Ip_u8)IPMIP4_MSGEXT_SHDR_EXT_SIZE(pbuf->ipmip4.ext.mobile.nai_mobile));
if (pbuf->pktinfo.faVisitorHomeAddress != 0)
{
union Ip_sockaddr_union s_un;
ipcom_memset(&s_un, 0, sizeof(s_un));
s_un.sin.sin_addr.s_addr = pbuf->pktinfo.faVisitorHomeAddress;
s_un.sin.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&s_un.sin, sizeof(s_un.sin));
aaa->feature |= IPMIP4_DIAMETER_FEATURE_MN_HOA_REQ;
(void)ipdiameter_avp_add_ip_address(packet,
DIAMETER_AVP_CODE_MIP_Mobile_Node_Address,
DIAMETER_AVP_M_FLAG,
IP_NULL,
s_un);
}
if (pbuf->pktinfo.faVisitorHomeAgentAddressRequested == 0)
aaa->feature |= IPMIP4_DIAMETER_FEATURE_HA_REQ;
else if (pbuf->pktinfo.faVisitorHomeAgentAddressRequested == 0xffffffff)
aaa->feature |= IPMIP4_DIAMETER_FEATURE_HA_REQ|IPMIP4_DIAMETER_FEATURE_HOA_IN_HOME_REALM;
else
{
union Ip_sockaddr_union s_un;
ipcom_memset(&s_un, 0, sizeof(s_un));
s_un.sin.sin_addr.s_addr = pbuf->pktinfo.faVisitorHomeAgentAddressRequested;
s_un.sin.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&s_un.sin, sizeof(s_un.sin));
(void)ipdiameter_avp_add_ip_address(packet,
DIAMETER_AVP_CODE_MIP_Home_Agent_Address,
DIAMETER_AVP_M_FLAG,
IP_NULL,
s_un);
}
(void)ipdiameter_avp_add_array(packet,
DIAMETER_AVP_CODE_MIP_Reg_Request,
DIAMETER_AVP_M_FLAG,
IP_NULL,
IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet),
IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet));
if (pbuf->ipmip4.ext.mobile.mn_ha_keyreq != IP_NULL)
aaa->feature |= IPMIP4_DIAMETER_FEATURE_MN_HA_KEYREQ;
if (pbuf->ipmip4.ext.mobile.mn_fa_keyreq != IP_NULL)
aaa->feature |= IPMIP4_DIAMETER_FEATURE_MN_FA_KEYREQ;
/**/
if (ifp_config->access_fa_ha_spi && node->faVisitorHomeAgentSA == IP_NULL)
{
aaa->feature |= IPMIP4_DIAMETER_FEATURE_FA_HA_KEYREQ;
ipdiameter_avp_add_u32(packet,
DIAMETER_AVP_CODE_MIP_HA_to_FA_SPI,
DIAMETER_AVP_M_FLAG,
IP_NULL,
ifp_config->access_fa_ha_spi);
}
ipdiameter_avp_add_u32(packet,
DIAMETER_AVP_CODE_MIP_Feature_Vector,
DIAMETER_AVP_M_FLAG,
IP_NULL,
aaa->feature);
if (pbuf->ipmip4.ext.mobile.challenge != IP_NULL)
(void)ipdiameter_avp_add_array(packet,
DIAMETER_AVP_CODE_MIP_FA_Challenge,
DIAMETER_AVP_M_FLAG,
IP_NULL,
IPMIP4_MSGEXT_SHDR_EXT_DATA(pbuf->ipmip4.ext.mobile.challenge),
IPMIP4_MSGEXT_SHDR_EXT_SIZE(pbuf->ipmip4.ext.mobile.challenge));
/* Add the AAA grouped */
{
Ipmip4_ext_gen_auth_t *auth = (Ipmip4_ext_gen_auth_t *)pbuf->ipmip4.ext.mobile.mn_aaa;
Ip_u32 tval;
Ipdiameter_header *grouped = ipdiameter_request_pkt_malloc(0);
/**/
if (grouped == IP_NULL)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"DIAMETER unable to allocate grouped packet");
ipdiameter_request_pkt_free(packet);
return IP_FALSE;
}
tval = IP_GET_NTOHL(&auth->spi[0]);
ipdiameter_avp_add_u32(grouped,
DIAMETER_AVP_CODE_MIP_MN_AAA_SPI,
DIAMETER_AVP_M_FLAG,
IP_NULL,
tval);
/* Size of request */
tval = (Ip_u8 *)auth->authenticator - (Ip_u8 *)IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet);
ipdiameter_avp_add_u32(grouped,
DIAMETER_AVP_CODE_MIP_Auth_Input_Data_Length,
DIAMETER_AVP_M_FLAG,
IP_NULL,
tval);
ipdiameter_avp_add_u32(grouped,
DIAMETER_AVP_CODE_MIP_Authenticator_Offset,
DIAMETER_AVP_M_FLAG,
IP_NULL,
tval);
tval = IP_GET_NTOHS(&auth->length) - 4;
ipdiameter_avp_add_u32(grouped,
DIAMETER_AVP_CODE_MIP_Authenticator_Length,
DIAMETER_AVP_M_FLAG,
IP_NULL,
tval);
tval = ipdiameter_get_hdr_length((Ip_u32 *)grouped) - IPDIAMETER_HDRSIZE;
(void)ipdiameter_avp_add_array(packet,
DIAMETER_AVP_CODE_MIP_MN_AAA_Auth,
DIAMETER_AVP_M_FLAG,
IP_NULL,
grouped->avp,
tval);
ipdiameter_request_pkt_free(grouped);
}
/* Add application id */
return ipmip4_diameter_access_request(&ctx->ipmip4,
proc,
ifp_config->diameter,
(Ipmip4_diameter_func_t)ipmipfa_aaa_diameter_AMA,
&pbuf->ipmip4,
pbuf->node,
&request,
packet,
0);
}
IP_STATIC Ip_bool
ipmipfa_aaa_diameter_request(Ipmipfa_data_t *ctx,
Ipmip_proc_t *proc,
void *global_config,
Ipmipfa_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
Ipmipfa_node_t *node,
Ipmipfa_pktbuf_t *pbuf)
{
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(node_config);
/* OK; we've setup the message structure; time to invoke the access request */
if (!ipmipfa_aaa_diameter_access_request(ctx, proc, ifp_config, node, pbuf))
{
if (pbuf->ipmip4.ipmip.message == IP_NULL)
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"FA not able to communicate with DIAMETER server");
return IP_FALSE;
}
return IP_TRUE;
}
/*
*===========================================================================
* ipmipfa_diameter_auth
*===========================================================================
* Description: Resolve a mobile-AAA extension using DIAMETER
* Parameters: ctx - Context
* proc - Current process
* setup - Setup structure
* ifcfg - Setup structure for current interface.
* pbuf - The container.
* lock - Timer lock
* func - Timer function callback
* an error code.
* Returns: One of IPMIP4_RETCODE_CONTINUE, IPMIP4_RETCODE_SKIPPED or
* IPMIP4_RETCODE_PENDING
*/
IP_STATIC Ip_bool
ipmipfa_aaa_diameter_pkt_req_verify(struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
void *global_config,
Ipmipfa_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
struct Ipmipfa_node *node,
struct Ipmipfa_pktbuf *pbuf)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(node_config);
if (ifp_config->access)
{
/* Do access */
if (pbuf->ipmip4.ext.mobile.mn_aaa != IP_NULL)
{
Ipmip4_ext_gen_auth_t *auth = (Ipmip4_ext_gen_auth_t *)pbuf->ipmip4.ext.mobile.mn_aaa;
Ip_u32 spi = IP_GET_NTOHL(&auth->spi[0]);
Ip_time_t now = ipmip_util_time();
/* Store the SPI for bookkeeping */
pbuf->reginfo.faVisitorSPIMobileAAA = spi;
/* Still in effect? */
if ((now - node->faVisitorAAAVerificationTime) < ifp_config->access_timeout)
{
/* Verify keygen; if we have keygen in play, the keygen must match */
if (pbuf->ipmip4.ext.mobile.mn_ha_keyreq == IP_NULL && pbuf->ipmip4.ext.mobile.mn_fa_keyreq == IP_NULL)
{
/* If not keygen; there has to be security association's that correspond to the overall security policy */
if (pbuf->pktinfo.faVisitorMobileForeignSAPolicyOK != 0 && pbuf->pktinfo.faVisitorMobileHomeSAPolicyOK != 0)
return IP_FALSE;
}
}
}
else if (ifp_config->access_require)
{
/* Required MN-AAA; but it wasn't there */
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"FA required MN-AAA, but it was not provided");
return IP_FALSE;
}
else
{
/* Continue */
return IP_FALSE;
}
/* Mark the forwarding function */
pbuf->request_transport = &ipmipfa_aaa_diameter_srv;
return IP_FALSE;
}
if (pbuf->ipmip4.ext.mobile.mn_aaa != IP_NULL)
return IP_FALSE;
return IP_FALSE;
}
IP_STATIC void
ipmipfa_aaa_diameter_config_ifp(struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
int action,
struct Ipmipfa_iff *ifp,
void *gcfg,
Ipmipfa_aaa_diameter_config_ifp_t *cfg,
Ipmip_cli_message_t *request)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(gcfg);
IPMIP_UNUSED_PARAMETER(request);
if (action == IPMIP_CALLBACK_CONFIG_READ)
{
if (ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.aaa.diameter.enable"), "ipmipfa.if.%s.aaa.diameter.enable", ifp->iff.ipmip.ifname))
{
cfg->diameter = ipmip4_diameter_context_create(&ctx->ipmip4, proc, "ipmipfa.aaa.diameter", "ipmipfa.if.%s.aaa.diametr", ifp->iff.ipmip.ifname);
cfg->access = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.aaa.diameter.access"), "ipmipfa.if.%s.aaa.diameter.access", ifp->iff.ipmip.ifname);
cfg->access_require = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.aaa.diameter.access.required"), "ipmipfa.if.%s.aaa.diameter.access.required", ifp->iff.ipmip.ifname);
cfg->access_fa_ha_spi = ipmip_sysvar_ulong(ipmip_sysvar_ulong(0,"ipmipfa.aaa.diameter.access.fa_ha_spi"), "ipmipfa.if.%s.aaa.diameter.access.fa_ha_spi", ifp->iff.ipmip.ifname);
cfg->access_timeout = ipmip_sysvar_ulong(ipmip_sysvar_ulong(0, "ipmipfa.aaa.diameter.access.time_interval"), "ipmipfa.if.%s.aaa.diameter.access.time_interval", ifp->iff.ipmip.ifname);
}
}
else if (action == IPMIP_CALLBACK_CONFIG_FREE)
{
if (cfg->diameter)
ipmip4_diameter_context_destroy(&ctx->ipmip4, proc, cfg->diameter);
cfg->diameter = IP_NULL;
}
else if (action == IPMIP_CALLBACK_CONFIG_DUMP)
{
if (cfg->diameter)
{
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.enable=enabled",
ifp->iff.ipmip.ifname);
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.access=%s",
ifp->iff.ipmip.ifname, cfg->access? "enabled" : "disabled");
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.access.required=%s",
ifp->iff.ipmip.ifname, cfg->access_require? "enabled" : "disabled");
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.access.time_interval=%d",
ifp->iff.ipmip.ifname, cfg->access_timeout);
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.fa_ha_spi=%u",
ifp->iff.ipmip.ifname, cfg->access_fa_ha_spi);
ipmip4_diameter_context_dump(&ctx->ipmip4, proc, cfg->diameter, request, "ipmipfa.if.%s.aaa.diameter", ifp->iff.ipmip.ifname);
}
else
{
ipmip_cli_config_printf(&request->message,
"ipmipfa.if.%s.aaa.diameter.enable=disabled",
ifp->iff.ipmip.ifname);
}
}
}
IP_STATIC Ip_bool
ipmipfa_aaa_diameter_setup(struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
int action,
void *global_config,
Ipmipfa_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
struct Ipmipfa_node *node,
Ipmip_cli_message_t *request)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(node_config);
IPMIP_UNUSED_PARAMETER(node);
IPMIP_UNUSED_PARAMETER(request);
if (action == IPMIP_CALLBACK_CONFIG_READ)
{
return ifp_config->diameter != IP_NULL;
}
else if (action == IPMIP_CALLBACK_CONFIG_FREE)
{
/* No dyncamically allocated values */
}
else if (action == IPMIP_CALLBACK_CONFIG_DUMP)
{
}
return IP_FALSE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void ipmipfa_aaa_diameter_install(void);
IP_GLOBAL void
ipmipfa_aaa_diameter_install(void)
{
ipcom_memset(&ipmipfa_aaa_diameter_srv, 0, sizeof(ipmipfa_aaa_diameter_srv));
ipmipfa_aaa_diameter_srv.name = IPMIPFA_AAA_DIAMETER;
ipmipfa_aaa_diameter_srv.ifp_data_size = sizeof(Ipmipfa_aaa_diameter_config_ifp_t);
ipmipfa_aaa_diameter_srv.config_ifp = (Ipmipfa_extension_config_ifp_t)ipmipfa_aaa_diameter_config_ifp;
ipmipfa_aaa_diameter_srv.pkt_req_validate = (Ipmipfa_extension_pkt_req_validate_t)ipmipfa_aaa_diameter_pkt_req_verify;
ipmipfa_aaa_diameter_srv.pkt_req_transport = (Ipmipfa_extension_pkt_req_validate_t)ipmipfa_aaa_diameter_request;
ipmipfa_aaa_diameter_srv.setup = (Ipmipfa_extension_setup_t)ipmipfa_aaa_diameter_setup;
/**/
ipmipfa_aaa_diameter_srv.pktaux.pktbuf_data_size = sizeof(Ipmipfa_aaa_diameter_pktbuf_data_t);
ipmipfa_aaa_diameter_srv.pktaux.pktbuf_data_free = (Ipmip_pktbuf_free_data_t)ipmipfa_aaa_diameter_pktaux_free;
ipmipfa_context_register_extension(&ipmipfa_aaa_diameter_srv, IPMIPFA_FUNCTION_AAA);
}
#else
IP_GLOBAL void ipmipfa_aaa_diameter_install(void);
IP_GLOBAL void
ipmipfa_aaa_diameter_install(void)
{
/* Do nothing */
}
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/