/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmipfa_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #ifdef IPMIPFA_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 "ipmipfa_h.h" #include "ipmipfa_h.h" #include "ipmipfa_reg.h" #include "ipmipfa_node.h" #include "ipmipfa_pktbuf.h" #include /* **************************************************************************** * 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 **************************************************************************** */