/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmipha_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #ifdef IPMIPHA_DIAMETER_ENABLE #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 /* **************************************************************************** * 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(®req->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(®req->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 **************************************************************************** */