866 lines
35 KiB
C
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
|
|
****************************************************************************
|
|
*/
|