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

1414 lines
58 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipha_aaa_diameter.c,v $ $Revision: 1.5.16.4 $
* $Source: /home/interpeak/CVSRoot/ipmipha/config/ipmipha_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 "ipmipha_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPMIPHA_DIAMETER_ENABLE
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_hash.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#include <ipmip.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_timer.h>
#include <ipmip4.h>
#include <private/ipmip4_context.h>
#include <private/ipmip4_util.h>
#include <private/ipmip4_sysext.h>
#include <private/ipmip4_auth.h>
#include <private/ipmip4_pkt.h>
#include <private/ipmip4_pktbuf.h>
#include <private/ipmip4_diameter.h>
#include "ipmipha.h"
#include "ipmipha_h.h"
#include "ipmipha_attr_h.h"
#include "ipmipha_if.h"
#include "ipmipha_reg.h"
#include "ipmipha_node.h"
#include "ipmipha_pktbuf.h"
#include <ipdiameter.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIPHA_AAA_DIAMETER "AAA-DIAMETER"
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmipha_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_timeout;
Ipmipha_data_t *data;
} Ipmipha_aaa_diameter_config_ifp_t;
typedef struct Ipmipha_aaa_diameter_pktbuf_data
{
/**/
void *session_id;
Ip_size_t session_id_length;
/**/
void *origin_host;
Ip_size_t origin_host_length;
void *peer;
Ip_u32 hbh_id;
Ip_u32 e2e_id;
Ip_u32 mn_fa_spi;
Ip_u32 fa_ha_spi;
Ip_u32 feature;
Ip_bool mn_ha_keyreq;
Ip_u8 *mn_ha_keyreq_nonce;
Ip_size_t mn_ha_keyreq_nonce_len;
Ip_u8 *mn_ha_keyreq_key;
Ip_size_t mn_ha_keyreq_key_len;
Ip_u32 mn_ha_keyreq_key_spi;
Ip_bool mn_fa_keyreq;
Ip_u8 *mn_fa_keyreq_nonce;
Ip_size_t mn_fa_keyreq_nonce_len;
Ip_u32 mn_fa_keyreq_key_spi;
Ip_bool fa_ha_keyreq;
Ip_u8 *fa_ha_keyreq_key;
Ip_size_t fa_ha_keyreq_key_len;
Ip_u32 fa_ha_keyreq_key_spi;
} Ipmipha_aaa_diameter_pktbuf_data_t;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ipmipha_extension_t ipmipha_aaa_diameter_srv;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC void
ipmipha_aaa_diameter_pktaux_free(struct Ipmipha_data *data,
struct Ipmip_proc *proc,
struct Ipmipha_pktbuf *pbuf,
Ipmipha_aaa_diameter_pktbuf_data_t *aaa)
{
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(pbuf);
if (aaa->origin_host)
ipcom_free(aaa->origin_host);
if (aaa->session_id)
ipcom_free(aaa->session_id);
if (aaa->mn_ha_keyreq_nonce)
ipcom_free(aaa->mn_ha_keyreq_nonce);
if (aaa->mn_ha_keyreq_key)
ipcom_free(aaa->mn_ha_keyreq_key);
if (aaa->mn_fa_keyreq_nonce)
ipcom_free(aaa->mn_fa_keyreq_nonce);
if (aaa->fa_ha_keyreq_key)
ipcom_free(aaa->fa_ha_keyreq_key);
}
IP_STATIC void
ipmipha_aaa_diameter_HAA(struct Ipmipha_data *data,
struct Ipmip_proc *proc,
void *global_config,
Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
Ipmipha_node_t *node,
struct Ipmipha_pktbuf *req_pbuf,
struct Ipmipha_pktbuf *rep_pbuf)
{
Ipdiameter_header *packet;
Ip_u32 result_code = DIAMETER_SUCCESS;
Ipmipha_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&data->ipmip4.ipmip, &req_pbuf->ipmip4.ipmip, ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_FALSE);
if(IP_NULL == aaa)
return;
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(node_config);
IPMIP_UNUSED_PARAMETER(node);
if (!ipmip4_diameter_answer_alloc(&data->ipmip4, proc, ifp_config->diameter, aaa->session_id, aaa->session_id_length, aaa->hbh_id, aaa->e2e_id, &packet))
return;
/* Set comand code to IPRADIUS_CODE_Access_Request */
ipdiameter_set_hdr_code((Ip_u32 *)packet, DIAMETER_CODE_Home_Agent_MIP_Answer);
/***** Add attributes here! *****/
if (req_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(req_pbuf->ipmip4.ext.mobile.nai_mobile),
(Ip_u8)IPMIP4_MSGEXT_SHDR_EXT_SIZE(req_pbuf->ipmip4.ext.mobile.nai_mobile));
if (req_pbuf->pktinfo.haBindingHomeAddress != 0)
{
union Ip_sockaddr_union s_un;
ipcom_memset(&s_un, 0, sizeof(s_un));
s_un.sin.sin_addr.s_addr = req_pbuf->pktinfo.haBindingHomeAddress;
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_Mobile_Node_Address,
DIAMETER_AVP_M_FLAG,
IP_NULL,
s_un);
}
{
union Ip_sockaddr_union s_un;
ipcom_memset(&s_un, 0, sizeof(s_un));
s_un.sin.sin_addr.s_addr = req_pbuf->pktinfo.haBindingHomeAgentAddress;
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_Reply,
DIAMETER_AVP_M_FLAG,
IP_NULL,
IPMIP_BUFFER_DATA(&rep_pbuf->ipmip4.ipmip.packet),
IPMIP_BUFFER_SIZE(&rep_pbuf->ipmip4.ipmip.packet));
if (aaa->mn_fa_spi != 0)
ipdiameter_avp_add_u32(packet, DIAMETER_AVP_CODE_MIP_FA_to_MN_SPI, DIAMETER_AVP_M_FLAG, IP_NULL, aaa->mn_fa_spi);
if (aaa->fa_ha_spi != 0)
ipdiameter_avp_add_u32(packet, DIAMETER_AVP_CODE_MIP_FA_to_HA_SPI, DIAMETER_AVP_M_FLAG, IP_NULL, aaa->fa_ha_spi);
/*
if (pbuf->pktinfo.haBindingHAErrorCode != 0)
result_code = 4005;
*/
ipdiameter_avp_add_u32(packet, DIAMETER_AVP_CODE_Result_Code, DIAMETER_AVP_M_FLAG, IP_NULL, result_code);
if (req_pbuf->ipmip4.ipmip.message == IP_NULL)
req_pbuf->haBindingAAAVerified = IP_TRUE;
/* Add application id */
(void)ipdiameter_peer_pkt_send(aaa->peer, packet);
ipdiameter_answer_pkt_free(packet);
}
IP_STATIC void
ipmipha_aaa_diameter_pkt_rep_mobile_home(struct Ipmipha_data *ctx,
struct Ipmip_proc *proc,
void *global_config,
Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
struct Ipmipha_node *node,
struct Ipmipha_pktbuf *req_pbuf,
struct Ipmipha_pktbuf *pbuf)
{
Ipmipha_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&ctx->ipmip4.ipmip, &req_pbuf->ipmip4.ipmip, ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_FALSE);
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(ifp_config);
IPMIP_UNUSED_PARAMETER(node_config);
IPMIP_UNUSED_PARAMETER(node);
if (aaa)
{
Ipmip4_ext_gen_auth_t *auth = (Ipmip4_ext_gen_auth_t *)req_pbuf->ipmip4.ext.mobile.mn_aaa;
Ipmip4_ext_keyrep_ha_t *keyrep = (Ipmip4_ext_keyrep_ha_t *)proc->ntop.ntop_pbuf;
Ip_u32 aaa_spi = IP_GET_NTOHL(&auth->spi[0]);
if (aaa->mn_ha_keyreq)
{
ipcom_memset(keyrep, 0, sizeof(*keyrep));
/**/
keyrep->type = IPMIP4_EXT_TYPE_MN_HA_KEYGEN_REP;
keyrep->subtype = IPMIP4_KEYGEN_SUBTYPE_1;
IP_SET_HTONL(&keyrep->lifetime, 0xffffffff);
IP_SET_HTONS(&keyrep->alg_id, IPMIP4_AUTH_ALG_HMAC_SHA);
IP_SET_HTONS(&keyrep->replay, 2);
IP_SET_HTONL(&keyrep->aaa_spi, aaa_spi);
IP_SET_HTONS(&keyrep->length, (IPMIP4_EXT_KEYREP_HA_LENGTH + aaa->mn_ha_keyreq_nonce_len - IPMIP4_MSGEXT_LHDR_HDR_SIZE));
IP_SET_HTONL(&keyrep->spi, aaa->mn_ha_keyreq_key_spi);
/* Copy the nonce */
ipcom_memcpy(keyrep->nonce, aaa->mn_ha_keyreq_nonce, aaa->mn_ha_keyreq_nonce_len);
/* Append */
ipmip4_msgext_buffer_append_lhdr(&pbuf->ipmip4.ipmip.packet, (void *)proc->ntop.ntop_pbuf);
}
if (aaa->mn_fa_keyreq)
{
ipcom_memset(keyrep, 0, sizeof(*keyrep));
keyrep->type = IPMIP4_EXT_TYPE_MN_FA_KEYGEN_REP;
keyrep->subtype = IPMIP4_KEYGEN_SUBTYPE_1;
IP_SET_HTONL(&keyrep->lifetime, 0xffffffff);
IP_SET_HTONS(&keyrep->alg_id, IPMIP4_AUTH_ALG_HMAC_SHA);
IP_SET_HTONL(&keyrep->aaa_spi, aaa_spi);
IP_SET_HTONL(&keyrep->spi, aaa->mn_fa_keyreq_key_spi);
/**/
IP_SET_HTONS(&keyrep->length, (IPMIP4_EXT_KEYREP_FA_LENGTH + aaa->mn_fa_keyreq_nonce_len - IPMIP4_MSGEXT_LHDR_HDR_SIZE));
/* Copy the nonce */
ipcom_memcpy(keyrep->nonce, aaa->mn_fa_keyreq_nonce, aaa->mn_fa_keyreq_nonce_len);
/* Append */
ipmip4_msgext_buffer_append_lhdr(&pbuf->ipmip4.ipmip.packet, (void *)proc->ntop.ntop_pbuf);
}
}
}
IP_STATIC void
ipmipha_aaa_diamater_mn_ha_keyreq_create(Ipmipha_data_t *data,
Ipmip_proc_t *proc,
Ipmipha_aaa_diameter_pktbuf_data_t *aaa,
Ipmipha_node_t *node,
Ipmipha_pktbuf_t *pbuf)
{
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(pbuf);
if (node->haBindingHomeSA)
ipmip4_auth_spi_free(node->haBindingHomeSA);
node->haBindingHomeSA = ipmip4_auth_spi_create(proc, aaa->mn_ha_keyreq_key_spi, aaa->mn_ha_keyreq_key, aaa->mn_ha_keyreq_key_len, IPMIP4_AUTH_METHOD_MD5_HMAC);
}
IP_STATIC void
ipmipha_aaa_diameter_parse_mn_ha_keyreq(Ipmipha_data_t *data,
Ipmip_proc_t *proc,
Ipmipha_aaa_diameter_pktbuf_data_t *aaa,
Ipmipha_pktbuf_t *pbuf,
struct Ipdiameter_header_struct *response_packet_v)
{
Ip_u32 len;
Ip_u8 *val;
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(proc);
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_MN_to_HA_MSA, &len, &val) == IPCOM_SUCCESS)
{
Ip_u32 avp_len;
Ip_u8 *avp;
Ip_u32 nonce_len;
Ip_u8 *nonce_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");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-MN-to-HA-MSA is missing");
return;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Replay_Mode, &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 Timestamp (2) Replay-Mode is supported");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Replay-Mode AVP in MIP-MN-to-HA-MSA is missing or truncated");
return;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Nonce, &nonce_len, &nonce_avp) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-Nonce AVP in MIP-MN-to-HA-MSA is missing");
return;
}
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_HA_to_MN_MSA, &len, &val) == IPCOM_SUCCESS)
{
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");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-HA-to-MN-MSA is missing or truncated");
return;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Replay_Mode, &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 Timestamp (2) Replay Type is supported");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Replay-Mode AVP in MIP-HA-to-MN-MSA is missing or truncated");
return;
}
/**/
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-HA-to-MN-MSA is missing");
return;
}
else
{
Ipmip4_ext_keyreq_t *keyreq = (Ipmip4_ext_keyreq_t *)pbuf->ipmip4.ext.mobile.mn_ha_keyreq;
aaa->mn_ha_keyreq = IP_TRUE;
aaa->mn_ha_keyreq_nonce_len = nonce_len;
ipmip_util_dup(&aaa->mn_ha_keyreq_nonce, nonce_avp, nonce_len);
aaa->mn_ha_keyreq_key_len = key_len;
ipmip_util_dup(&aaa->mn_ha_keyreq_key, key_avp, key_len);
if (keyreq != IP_NULL)
aaa->mn_ha_keyreq_key_spi = IP_GET_NTOHL(&keyreq->spi);
else
{
aaa->mn_ha_keyreq_key_spi = ipcom_random() + 256;
aaa->mn_ha_keyreq_key_spi = IP_MAX(256, aaa->mn_ha_keyreq_key_spi);
}
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-HA-to-MN-MSA is missing but MIP-MN-to-HA-MSA was specified");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-MN-to-HA-MSA is missing but KEYREQ was present in registration");
return;
}
}
IP_STATIC void
ipmipha_aaa_diameter_parse_mn_fa_keyreq(Ipmipha_data_t *data,
Ipmip_proc_t *proc,
Ipmipha_aaa_diameter_pktbuf_data_t *aaa,
Ipmipha_pktbuf_t *pbuf,
struct Ipdiameter_header_struct *response_packet_v)
{
Ip_u32 len;
Ip_u8 *val;
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(proc);
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_MN_to_FA_MSA, &len, &val) == IPCOM_SUCCESS)
{
Ip_u32 avp_len;
Ip_u8 *avp;
Ip_u32 nonce_len;
Ip_u8 *nonce_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");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-MN-to-FA-MSA is missing");
return;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_FA_to_MN_SPI, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
aaa->mn_fa_keyreq_key_spi = IP_GET_NTOHL(avp);
}
else
{
Ipmip4_ext_keyreq_t *keyreq = (Ipmip4_ext_keyreq_t *)pbuf->ipmip4.ext.mobile.mn_fa_keyreq;
if (keyreq != IP_NULL)
aaa->mn_fa_keyreq_key_spi = IP_GET_NTOHL(&keyreq->spi);
else
{
aaa->mn_fa_keyreq_key_spi = ipcom_random() + 256;
aaa->mn_fa_keyreq_key_spi = IP_MAX(256, aaa->mn_fa_keyreq_key_spi);
}
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_Nonce, &nonce_len, &nonce_avp) != IPCOM_SUCCESS)
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-Nonce AVP in MIP-MN-to-FA-MSA is missing");
return;
}
aaa->mn_fa_keyreq = IP_TRUE;
aaa->mn_fa_keyreq_nonce_len = nonce_len;
ipmip_util_dup(&aaa->mn_fa_keyreq_nonce, nonce_avp, nonce_len);
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-MN-to-FA-MSA is missing, but flagged in feature vector");
return;
}
}
IP_STATIC void
ipmipha_aaa_diameter_parse_fa_ha_keyreq(Ipmipha_data_t *data,
Ipmip_proc_t *proc,
Ipmipha_aaa_diameter_pktbuf_data_t *aaa,
Ipmipha_pktbuf_t *pbuf,
struct Ipdiameter_header_struct *response_packet_v)
{
Ip_u32 len;
Ip_u8 *val;
IPMIP_UNUSED_PARAMETER(data);
IPMIP_UNUSED_PARAMETER(proc);
if (ipdiameter_get_avp(response_packet_v, DIAMETER_AVP_CODE_MIP_HA_to_FA_MSA, &len, &val) == IPCOM_SUCCESS)
{
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");
return;
}
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Algorithm Type AVP in MIP-HA-to-FA-MSA is missing");
return;
}
if (ipdiameter_grouped_avp_get_avp(val, len, DIAMETER_AVP_CODE_MIP_HA_to_FA_SPI, &avp_len, &avp) == IPCOM_SUCCESS && avp_len >= 4)
{
aaa->fa_ha_keyreq_key_spi = IP_GET_NTOHL(avp);
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER Ha-to-FA-SPI in MIP-HA-to-FA-MSA is missing");
return;
}
/**/
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");
return;
}
aaa->fa_ha_keyreq = IP_TRUE;
ipmip_util_dup(&aaa->fa_ha_keyreq_key, key_avp, key_len);
aaa->fa_ha_keyreq_key_len = key_len;
}
else
{
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"AAA DIAMETER MIP-FA-to-HA-MSA is missing but KEYREQ was present in registration");
return;
}
}
IP_STATIC void
ipmipha_aaa_diameter_AMA(int result,
Ipmipha_data_t *data,
Ipmip_proc_t *proc,
struct Ipmip4_diameter_context *diameter,
Ipmipha_pktbuf_t *pbuf,
Ipmipha_node_t *node,
struct Ipdiameter_request_struct *request_v,
struct Ipdiameter_header_struct *request_packet_v,
struct Ipdiameter_header_struct *response_packet_v)
{
Ipmipha_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&data->ipmip4.ipmip, &pbuf->ipmip4.ipmip, ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_TRUE);
if(IP_NULL == aaa)
return;
IPMIP_UNUSED_PARAMETER(diameter);
IPMIP_UNUSED_PARAMETER(request_v);
IPMIP_UNUSED_PARAMETER(request_packet_v);
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->pktinfo.haBindingResolvedHomeAgentAddress = IP_GET_32ON8((val + 2));
IPMIP4_EVENT_IF(DEBUG2, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Node %s Diameter Extension: Mip-Home-Agent-Address = %s",
ipmipha_node_describe(proc, node, IP_NULL),
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingResolvedHomeAgentAddress)));
/* 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->pktinfo.haBindingResolvedHomeAddress = IP_GET_32ON8((val + 2));
IPMIP4_EVENT_IF(DEBUG2, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Node %s Diameter Extension: Mip-Mobile-Node-Address = %s",
ipmipha_node_describe(proc, node, pbuf->binding),
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingResolvedHomeAddress)));
/* Parse the keyreq */
if (pbuf->ipmip4.ext.mobile.mn_ha_keyreq != IP_NULL)
{
ipmipha_aaa_diameter_parse_mn_ha_keyreq(data, proc, aaa, pbuf, response_packet_v);
if (pbuf->ipmip4.ipmip.message == IP_NULL)
ipmipha_aaa_diamater_mn_ha_keyreq_create(data, proc, aaa, node, pbuf);
}
}
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)
{
if (node->nai_aaah == IP_NULL && aaa->origin_host != IP_NULL)
node->nai_aaah = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_aaah_create(aaa->origin_host, aaa->origin_host_length);
pbuf->haBindingAAAVerified = IP_TRUE;
}
ipmip_timer_execute(&data->ipmip4.ipmip, &node->service);
}
IP_STATIC Ip_bool
ipmipha_aaa_diameter_access_request(struct Ipmipha_data *data,
struct Ipmip_proc *proc,
Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
struct Ipmipha_node *node,
Ipmipha_pktbuf_t *pbuf)
{
Ipdiameter_header *packet;
Ipdiameter_request request;
Ip_u32 feature = IPMIP4_DIAMETER_FEATURE_CO_LOCATED_MN;
if (!ipmip4_diameter_request_alloc(&data->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.haBindingHomeAddress != 0)
{
union Ip_sockaddr_union s_un;
ipcom_memset(&s_un, 0, sizeof(s_un));
s_un.sin.sin_addr.s_addr = pbuf->pktinfo.haBindingHomeAddress;
s_un.sin.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&s_un.sin, sizeof(s_un.sin));
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.haBindingHomeAgentAddress == 0)
feature |= IPMIP4_DIAMETER_FEATURE_HA_REQ;
else if (pbuf->pktinfo.haBindingHomeAgentAddress == 0xffffffff)
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.haBindingHomeAgentAddress;
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)
feature |= IPMIP4_DIAMETER_FEATURE_MN_HA_KEYREQ;
ipdiameter_avp_add_u32(packet,
DIAMETER_AVP_CODE_MIP_Feature_Vector,
DIAMETER_AVP_M_FLAG,
IP_NULL,
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(&data->ipmip4,
proc,
ifp_config->diameter,
(Ipmip4_diameter_func_t)ipmipha_aaa_diameter_AMA,
&pbuf->ipmip4,
node,
&request,
packet,
0);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmipha_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
* Returns: One of IPMIP4_RETCODE_CONTINUE, IPMIP4_RETCODE_SKIPPED or
* IPMIP4_RETCODE_PENDING
*/
IP_STATIC Ip_bool
ipmipha_aaa_diameter_pkt_req_verify(struct Ipmipha_data *ctx,
struct Ipmip_proc *proc,
void *global_config,
Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
struct Ipmipha_node *node,
struct Ipmipha_pktbuf *pbuf)
{
Ipmipha_aaa_diameter_pktbuf_data_t *aaa = ipmip_pktbuf_pktaux_data_get(&ctx->ipmip4.ipmip, &pbuf->ipmip4.ipmip, ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_FALSE);
IPMIP_UNUSED_PARAMETER(global_config);
IPMIP_UNUSED_PARAMETER(node_config);
if (aaa)
{
if (aaa->mn_ha_keyreq)
ipmipha_aaa_diamater_mn_ha_keyreq_create(ctx, proc, aaa, node, pbuf);
if (aaa->fa_ha_keyreq)
pbuf->haBindingForeignSA = ipmip4_auth_spi_create(proc, aaa->fa_ha_keyreq_key_spi, aaa->fa_ha_keyreq_key, aaa->fa_ha_keyreq_key_len, IPMIP4_AUTH_METHOD_MD5_HMAC);
/* Are we satisfied? */
if (node->nai_aaah == IP_NULL && aaa->origin_host != IP_NULL)
node->nai_aaah = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_aaah_create(aaa->origin_host, aaa->origin_host_length);
return IP_FALSE;
}
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();
pbuf->pktinfo.haBindingSPIMobileAAA = spi;
/**/
if ((now - pbuf->node->haNodeAAAVerificationTime) < 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)
{
/* If not keygen; there has to be security association's that correspond to the overall security policy */
IPMIP4_EVENT_IF(DEBUG2, proc,
ipmip_log_event_add(&ctx->ipmip4.ipmip,
proc,
"Node %s previous diameter authorization still valid",
ipmipha_node_describe(proc, pbuf->node, pbuf->binding)));
if (pbuf->pktinfo.haBindingForeignHomeSAPolicyOK != 0 && pbuf->pktinfo.haBindingMobileHomeSAPolicyOK != 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,
"HA required MN-AAA, but it was not provided");
return IP_FALSE;
}
else
{
/* Continue */
return IP_FALSE;
}
/* OK; we've setup the message structure; time to invoke the access request */
if (!ipmipha_aaa_diameter_access_request(ctx, proc, ifp_config, node, pbuf))
{
if (pbuf->ipmip4.ipmip.message == IP_NULL)
ipmip_pktbuf_error(&pbuf->ipmip4.ipmip,
0,
"HA not able to communicate with DIAMETER server");
return IP_FALSE;
}
return IP_TRUE;
}
return IP_FALSE;
}
/*
*===========================================================================
* ipmipha_diameter_HAR_recv
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmipha_aaa_diameter_HAR_recv(Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
void *req,
void *peer)
{
Ipdiameter_header *hdr = req;
Ipmipha_data_t *data = ifp_config->data;
/* Do we have diameter enabled? */
if (data->conf != IP_NULL)
{
/* Time to resolve the AVP's */
Ip_u32 len;
Ip_u8 *val;
Ipmipha_aaa_diameter_pktbuf_data_t *aaa;
Ipmip_proc_t *proc = ipmip4_diameter_proc(ifp_config->diameter);
Ipmipha_pktbuf_t *pbuf = IP_NULL;
Ipmip4_regreq_t *regreq;
Ip_u32 addr;
/**/
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_MIP_Reg_Request, &len, &val) != IPCOM_SUCCESS)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER Registration-Request AVP not present. Poorly formed"));
goto error_out;
}
pbuf = (Ipmipha_pktbuf_t *)ipmip_pktbuf_alloc(&data->ipmip4.ipmip, proc, 0);
aaa = ipmip_pktbuf_pktaux_data_get(&data->ipmip4.ipmip, &pbuf->ipmip4.ipmip, ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_index, IP_TRUE);
if(IP_NULL == aaa)
goto error_out;
/* Add the registration request */
ipmip_buffer_append(&pbuf->ipmip4.ipmip.packet, val, len);
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_MIP_Feature_Vector, &len, &val) != IPCOM_SUCCESS || len < 4)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER Feature Vector not present. Poorly formed"));
goto error_out;
}
aaa->feature = IP_GET_HTONL(val);
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_MIP_Mobile_Node_Address, &len, &val) == IPCOM_SUCCESS && len >= 4)
pbuf->pktinfo.haBindingResolvedHomeAddress = IP_GET_32ON8((val + 2));
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_MIP_Home_Agent_Address, &len, &val) == IPCOM_SUCCESS && len >= 4)
pbuf->pktinfo.haBindingResolvedHomeAgentAddress = IP_GET_32ON8((val + 2));
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_Origin_Host, &len, &val) != IPCOM_SUCCESS)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER Origin-Host AVP not present. Poorly formed"));
goto error_out;
}
ipmip_util_dup(&aaa->origin_host, val, len);
aaa->origin_host_length = len;
/* Store some values */
aaa->e2e_id = IP_GET_32ON8(&hdr->e2e_id);
aaa->hbh_id = IP_GET_32ON8(&hdr->hbh_id);
/* Retrieve the mandatory information */
if (ipdiameter_get_avp(hdr, DIAMETER_AVP_CODE_Session_Id, &len, &val) != IPCOM_SUCCESS)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER Session-ID AVP not present. Poorly formed"));
goto error_out;
}
ipmip_util_dup(&aaa->session_id, val, len);
aaa->session_id_length = len;
aaa->peer = peer;
/**/
regreq = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet);
addr = IP_GET_32ON8(&regreq->home_agent);
/**/
if (addr == 0 || addr == 0xffffffff)
addr = pbuf->pktinfo.haBindingResolvedHomeAgentAddress;
if (addr == 0)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER home agent not properly specified"));
goto error_out;
}
/* Try locate the interface */
pbuf->iff.pub = ipmip4_if_findbyaddr(&data->conf->if_head, addr);
if ((IP_NULL == pbuf->iff.pub) || (pbuf->iff.priv == IP_NULL))
{
/* Failure */
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to AAA DIAMETER home agent %s unknown", ipmip_ntop_inet(proc, addr)));
goto error_out;
}
else
{
/* Create a workable pktinfo */
struct Ip_in_pktinfo pktinfo;
struct Ip_sockaddr_in src;
pktinfo.ipi_addr.s_addr = addr;
pktinfo.ipi_ifindex = pbuf->iff.pub->ipmip.ifindex;
ipmip_pktbuf_srcinfo_dst_inet(&pbuf->ipmip4.ipmip, &pktinfo);
ipcom_memset(&src, 0, sizeof(src));
addr = IP_GET_32ON8(&regreq->care_of_addr);
src.sin_addr.s_addr = addr;
src.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&src, sizeof(src));
src.sin_port = ip_htons(IPMIP4_PORT);
ipmip_util_dup(&pbuf->ipmip4.ipmip.srcinfo.src, &src, sizeof(src));
}
/* Retrieve the first byte */
pbuf->pktinfo.haBindingRegType = *(Ip_u8 *)IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet);
pbuf->haBindingTimeStamp = ipmip_util_time();
/* Mark the security policies as fullfilled */
pbuf->pktinfo.haBindingForeignHomeSAPolicyOK = IP_TRUE;
pbuf->pktinfo.haBindingMobileHomeSAPolicyOK = IP_TRUE;
pbuf->reply_transport = &ipmipha_aaa_diameter_srv;
if (!ipmipha_reg_input_parse_request(data, proc, pbuf))
goto error_out;
/* OK; */
if (IP_BIT_ISTRUE(aaa->feature, IPMIP4_DIAMETER_FEATURE_MN_HA_KEYREQ))
{
ipmipha_aaa_diameter_parse_mn_ha_keyreq(data, proc, aaa, pbuf, hdr);
if (pbuf->ipmip4.ipmip.message != IP_NULL)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to %s", pbuf->ipmip4.ipmip.message));
goto error_out;
}
}
/* OK; */
if (IP_BIT_ISTRUE(aaa->feature, IPMIP4_DIAMETER_FEATURE_MN_FA_KEYREQ))
{
ipmipha_aaa_diameter_parse_mn_fa_keyreq(data, proc, aaa, pbuf, hdr);
if (pbuf->ipmip4.ipmip.message != IP_NULL)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to %s", pbuf->ipmip4.ipmip.message));
goto error_out;
}
}
/* OK; */
if (IP_BIT_ISTRUE(aaa->feature, IPMIP4_DIAMETER_FEATURE_FA_HA_KEYREQ))
{
ipmipha_aaa_diameter_parse_fa_ha_keyreq(data, proc, aaa, pbuf, hdr);
if (pbuf->ipmip4.ipmip.message != IP_NULL)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"Registration request silently discarded due to %s", pbuf->ipmip4.ipmip.message));
goto error_out;
}
}
if (pbuf->ipmip4.ext.mobile.mn_aaa != IP_NULL)
pbuf->pktinfo.haBindingSPIMobileAAA = IP_GET_NTOHL(&((Ipmip4_ext_gen_auth_t *)pbuf->ipmip4.ext.mobile.mn_aaa)->spi[0]);
/* Update pending information */
IPMIP4_EVENT_IF(DEBUG2, proc,
ipmip_log_event_add(&data->ipmip4.ipmip,
proc,
"DIAMETER Registration Request received with id=0x%08x",
pbuf->pktinfo.haBindingRegIDLow));
/* Try locate the mobile node */
ipmipha_node_lookup(data,
proc,
pbuf->iff.priv,
pbuf->pktinfo.haBindingHomeAddress,
&pbuf->ipmip4.ipmip.timeout,
(Ipmip_timer_func_t)ipmipha_reg_request_process,
pbuf);
return;
error_out:
/* Need to deal with a failed request */
/* Send a HAR error */
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
}
}
IP_STATIC void
ipmipha_aaa_diameter_config_ifp(struct Ipmipha_data *ctx,
struct Ipmip_proc *proc,
int action,
struct Ipmipha_iff *ifp,
void *gcfg,
Ipmipha_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, "ipmipha.aaa.diameter.enable"), "ipmipha.if.%s.aaa.diameter.enable", ifp->iff.ipmip.ifname))
{
cfg->diameter = ipmip4_diameter_context_create(&ctx->ipmip4, proc, "ipmipha.aaa.diameter", "ipmipha.if.%s.aaa.diametr", ifp->iff.ipmip.ifname);
cfg->access = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.aaa.diameter.access"), "ipmipha.if.%s.aaa.diameter.access", ifp->iff.ipmip.ifname);
cfg->access_require = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.aaa.diameter.access.required"), "ipmipha.if.%s.aaa.diameter.access.required", ifp->iff.ipmip.ifname);
cfg->access_timeout = ipmip_sysvar_ulong(ipmip_sysvar_ulong(0, "ipmipha.aaa.diameter.access.time_interval"), "ipmipha.if.%s.aaa.diameter.access.time_interval", ifp->iff.ipmip.ifname);
cfg->data = ctx;
ipmip4_diameter_HAR_callback(cfg, (Ipmip4_diameter_HAR_recv_t)ipmipha_aaa_diameter_HAR_recv);
}
}
else if (action == IPMIP_CALLBACK_CONFIG_FREE)
{
if (cfg->diameter)
{
ipmip4_diameter_HAR_callback(IP_NULL, (Ipmip4_diameter_HAR_recv_t)IP_NULL);
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,
"ipmipha.if.%s.aaa.diameter.enable=enabled",
ifp->iff.ipmip.ifname);
ipmip_cli_config_printf(&request->message,
"ipmipha.if.%s.aaa.diameter.access=%s",
ifp->iff.ipmip.ifname, cfg->access? "enabled" : "disabled");
ipmip_cli_config_printf(&request->message,
"ipmipha.if.%s.aaa.diameter.access.required=%s",
ifp->iff.ipmip.ifname, cfg->access_require? "enabled" : "disabled");
ipmip_cli_config_printf(&request->message,
"ipmipha.if.%s.aaa.diameter.access.time_interval=%d",
ifp->iff.ipmip.ifname, cfg->access_timeout);
ipmip4_diameter_context_dump(&ctx->ipmip4, proc, cfg->diameter, request, "ipmipha.if.%s.aaa.diameter", ifp->iff.ipmip.ifname);
}
else
{
ipmip_cli_config_printf(&request->message,
"ipmipha.if.%s.aaa.diameter.enable=disabled",
ifp->iff.ipmip.ifname);
}
}
}
IP_STATIC Ip_bool
ipmipha_aaa_diameter_setup(struct Ipmipha_data *ctx,
struct Ipmip_proc *proc,
int action,
void *global_config,
Ipmipha_aaa_diameter_config_ifp_t *ifp_config,
void *node_config,
struct Ipmipha_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;
}
IP_GLOBAL void ipmipha_aaa_diameter_install(void);
IP_GLOBAL void
ipmipha_aaa_diameter_install(void)
{
ipcom_memset(&ipmipha_aaa_diameter_srv, 0, sizeof(ipmipha_aaa_diameter_srv));
ipmipha_aaa_diameter_srv.name = IPMIPHA_AAA_DIAMETER;
ipmipha_aaa_diameter_srv.ifp_data_size = sizeof(Ipmipha_aaa_diameter_config_ifp_t);
ipmipha_aaa_diameter_srv.config_ifp = (Ipmipha_extension_config_ifp_t)ipmipha_aaa_diameter_config_ifp;
ipmipha_aaa_diameter_srv.pkt_req_validate = (Ipmipha_extension_pkt_req_validate_t)ipmipha_aaa_diameter_pkt_req_verify;
ipmipha_aaa_diameter_srv.pkt_rep_transport = (Ipmipha_extension_pkt_rep_transport_t)ipmipha_aaa_diameter_HAA;
ipmipha_aaa_diameter_srv.pkt_rep_mobile_home = (Ipmipha_extension_pkt_req_mobile_home_t)ipmipha_aaa_diameter_pkt_rep_mobile_home;
ipmipha_aaa_diameter_srv.setup = (Ipmipha_extension_setup_t)ipmipha_aaa_diameter_setup;
/**/
ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_size = sizeof(Ipmipha_aaa_diameter_pktbuf_data_t);
ipmipha_aaa_diameter_srv.pktaux.pktbuf_data_free = (Ipmip_pktbuf_free_data_t)ipmipha_aaa_diameter_pktaux_free;
ipmipha_context_register_extension(&ipmipha_aaa_diameter_srv, IPMIPHA_FUNCTION_AAA);
}
#else
IP_GLOBAL void ipmipha_aaa_diameter_install(void);
IP_GLOBAL void
ipmipha_aaa_diameter_install(void)
{
/* Do nothing */
}
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/