Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/diameap_server.c b/extensions/app_diameap/diameap_server.c
new file mode 100644
index 0000000..b93f6bb
--- /dev/null
+++ b/extensions/app_diameap/diameap_server.c
@@ -0,0 +1,3419 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************************************/
+
+#include "diameap_common.h"
+
+/* handler for DiamEAP server callback */
+static struct disp_hdl * handle;
+
+/* session handler for DiamEAP sessions state machine */
+static struct session_handler * diameap_server_reg = NULL;
+
+
+struct avp_max_occurences auth_avps[] =
+{
+{ "Service-Type", 1 },
+{ "Callback-Number", 1 },
+{ "Callback-Id", 1 },
+{ "Idle-Timeout", 1 },
+{ "Port-Limit", 1 },
+{ "NAS-Filter-Rule" - 1 },
+{ "Filter-Id", -1 },
+{ "Configuration-Token", -1 },
+{ "QoS-Filter-Rule", -1 },
+{ "Framed-Protocol", 1 },
+{ "Framed-Routing", 1 },
+{ "Framed-MTU", 1 },
+{ "Framed-Compression", -1 },
+{ "Framed-IP-Address", 1 },
+{ "Framed-IP-Netmask", 1 },
+{ "Framed-Route", -1 },
+{ "Framed-Pool", 1 },
+{ "Framed-Interface-Id", 1 },
+{ "Framed-IPv6-Prefix", -1 },
+{ "Framed-IPv6-Pool", 1 },
+{ "Framed-IPv6-Route", -1 },
+{ "Framed-IPX-Network", 1 },
+{ "Framed-Appletalk-Link", 1 },
+{ "Framed-Appletalk-Network", -1 },
+{ "Framed-Appletalk-Zone", 1 },
+{ "NAS-IPv6-Address", 0 },
+{ "NAS-Identifier", 0 },
+{ "NAS-IP-Address", 0 },
+{ "NAS-Port", 0 },
+{ "NAS-Port-Id", 0 },
+{ "NAS-Port-Type", 0 },
+{ "Called-Station-Id", 0 },
+{ "Calling-Station-Id", 0 },
+{ "Connect-Info", 0 },
+{ "Originating-Line-Info", 0 } };
+
+
+
+void diameap_cli_sess_cleanup(struct sess_state * diameap_sess_data, os0_t sid, void * opaque)
+{
+
+ CHECK_PARAMS_DO( diameap_sess_data, return );
+
+ if (diameap_sess_data != NULL)
+ {
+ if (diameap_sess_data->methodData != NULL)
+ {
+ struct plugin * cplugin;
+ if (diameap_plugin_get(diameap_sess_data->currentVendor,
+ diameap_sess_data->currentMethod, &cplugin))
+ {
+ TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sess_data->currentMethod,diameap_sess_data->currentVendor);
+ }
+
+ if (cplugin->eap_method_free)
+ {
+ (*cplugin->eap_method_free)(diameap_sess_data->methodData);
+ diameap_sess_data->methodData = NULL;
+ }
+ else
+ {
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname);
+ if (diameap_sess_data->methodData != NULL)
+ {
+ free(diameap_sess_data->methodData);
+ diameap_sess_data->methodData = NULL;
+ }
+ }
+ if (diameap_sess_data->methodData)
+ {
+ TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION);
+ }
+ }
+
+ if (diameap_sess_data->user.password != NULL)
+ {
+ free(diameap_sess_data->user.password);
+ diameap_sess_data->user.password = NULL;
+ }
+
+ if (diameap_sess_data->user.userid != NULL)
+ {
+ free(diameap_sess_data->user.userid);
+ diameap_sess_data->user.userid = NULL;
+ }
+ free(diameap_sess_data);
+ diameap_sess_data = NULL;
+ }
+}
+
+static int diameap_initialize_diameap_sm(
+ struct diameap_state_machine * diameap_sm,
+ struct sess_state * diameap_sess_data)
+{
+ TRACE_ENTRY("%p %p", diameap_sm, diameap_sess_data);
+
+ int i;
+
+ /* Initialize Long Term Variables */
+ if (diameap_sess_data != NULL)
+ {
+ diameap_sm->invalid_eappackets = diameap_sess_data->invalid_eappackets;
+
+ /* Initialize eap state machine variables */
+ /*User*/
+ diameap_sm->eap_sm.user.id = diameap_sess_data->user.id;
+
+ if ((diameap_sess_data->user.userid != NULL)
+ && (diameap_sess_data->user.useridLength > 0))
+ {
+ diameap_sm->eap_sm.user.useridLength
+ = diameap_sess_data->user.useridLength;
+ CHECK_MALLOC(diameap_sm->eap_sm.user.userid= malloc(diameap_sm->eap_sm.user.useridLength+1));
+ U8COPY(diameap_sm->eap_sm.user.userid,0,diameap_sm->eap_sm.user.useridLength+1,diameap_sess_data->user.userid);
+ free(diameap_sess_data->user.userid);
+ diameap_sess_data->user.userid = NULL;
+
+ }
+ else
+ {
+ TRACE_DEBUG(INFO,"%s user not identified yet.",DIAMEAP_EXTENSION);
+ diameap_sm->eap_sm.user.useridLength = 0;
+ diameap_sm->eap_sm.user.userid = NULL;
+ }
+
+ if ((diameap_sess_data->user.password != NULL)
+ && (diameap_sess_data->user.passwordLength > 0))
+ {
+ diameap_sm->eap_sm.user.passwordLength
+ = diameap_sess_data->user.passwordLength;
+ CHECK_MALLOC(diameap_sm->eap_sm.user.password = malloc(diameap_sm->eap_sm.user.passwordLength+1));
+ U8COPY(diameap_sm->eap_sm.user.password,0,diameap_sm->eap_sm.user.passwordLength+1, diameap_sess_data->user.password);
+ free(diameap_sess_data->user.password);
+ diameap_sess_data->user.password = NULL;
+ }
+ else
+ {
+ diameap_sm->eap_sm.user.passwordLength = 0;
+ diameap_sm->eap_sm.user.password = NULL;
+ }
+
+ diameap_sm->eap_sm.user.methodId = diameap_sess_data->user.methodId;
+ for (i = 0; i < MAXMETHODS; i++)
+ {
+ diameap_sm->eap_sm.user.methods[i].method
+ = diameap_sess_data->user.methods[i].method;
+ diameap_sm->eap_sm.user.methods[i].vendor
+ = diameap_sess_data->user.methods[i].vendor;
+ }
+ for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+ {
+ diameap_sm->eap_sm.user.proposedmethods[i].method
+ = diameap_sess_data->user.proposedmethods[i].method;
+ diameap_sm->eap_sm.user.proposedmethods[i].vendor
+ = diameap_sess_data->user.proposedmethods[i].vendor;
+ }
+
+ diameap_sm->eap_sm.user.pmethods = diameap_sess_data->user.pmethods;
+ diameap_sm->eap_sm.user.proposed_eap_method
+ = diameap_sess_data->user.proposed_eap_method;
+ diameap_sm->eap_sm.user.proposed_eap_method_vendor
+ = diameap_sess_data->user.proposed_eap_method_vendor;
+ diameap_sm->eap_sm.user.success = diameap_sess_data->user.success;
+
+ diameap_sm->eap_sm.currentId = diameap_sess_data->currentId;
+ diameap_sm->eap_sm.currentVendor = diameap_sess_data->currentVendor;
+ diameap_sm->eap_sm.lastId = diameap_sess_data->lastId;
+ diameap_sm->eap_sm.methodState = diameap_sess_data->methodState;
+ diameap_sm->eap_sm.currentMethod = diameap_sess_data->currentMethod;
+
+ diameap_sm->eap_sm.methodData = diameap_sess_data->methodData;
+ diameap_sess_data->methodData = NULL;
+
+ if (diameap_sm->eap_sm.currentMethod != TYPE_NONE)
+ {
+ diameap_plugin_get(diameap_sm->eap_sm.currentVendor,
+ diameap_sm->eap_sm.currentMethod,
+ &diameap_sm->eap_sm.selectedMethod);
+ }
+
+ /* free session data*/
+ free(diameap_sess_data);
+ diameap_sess_data = NULL;
+
+ }
+ else
+ {
+ diameap_sm->invalid_eappackets = 0;
+
+ /* Initialize eap state machine variables */
+ /*User*/
+ diameap_sm->eap_sm.user.id = 0;
+ diameap_sm->eap_sm.user.userid = NULL;
+ diameap_sm->eap_sm.user.useridLength = 0;
+ diameap_sm->eap_sm.user.password = NULL;
+ diameap_sm->eap_sm.user.passwordLength = 0;
+ diameap_sm->eap_sm.user.methodId = -1;
+ for (i = 0; i < MAXMETHODS; i++)
+ {
+ diameap_sm->eap_sm.user.methods[i].method = TYPE_NONE;
+ diameap_sm->eap_sm.user.methods[i].vendor = VENDOR_IETF;
+ }
+ for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+ {
+ diameap_sm->eap_sm.user.proposedmethods[i].method = TYPE_NONE;
+ diameap_sm->eap_sm.user.proposedmethods[i].vendor = VENDOR_IETF;
+ }
+
+ diameap_sm->eap_sm.user.pmethods = -1;
+ diameap_sm->eap_sm.user.proposed_eap_method = TYPE_NONE;
+ diameap_sm->eap_sm.user.proposed_eap_method_vendor = VENDOR_IETF;
+ diameap_sm->eap_sm.user.success = FALSE;
+
+ diameap_sm->eap_sm.currentId = -1;
+ diameap_sm->eap_sm.currentVendor = VENDOR_IETF;
+ diameap_sm->eap_sm.lastId = -1;
+ diameap_sm->eap_sm.methodState = EAP_M_PROPOSED;
+
+ diameap_sm->eap_sm.currentMethod = TYPE_NONE;
+
+ diameap_sm->eap_sm.methodData = NULL;
+
+ }
+
+ diameap_sm->result_code = 0;
+ fd_list_init(&diameap_sm->attributes, NULL);
+ fd_list_init(&diameap_sm->req_attributes, NULL);
+ fd_list_init(&diameap_sm->ans_attributes, NULL);
+ diameap_sm->failedavp = NULL;
+ diameap_sm->auth_request_val = AUTHENTICATE_ONLY;
+ diameap_sm->verify_authorization = FALSE;
+ diameap_sm->authSuccess = FALSE;
+ diameap_sm->authFailure = FALSE;
+ diameap_sm->lastReqEAPavp = NULL;
+ diameap_sm->privateUser = FALSE;
+ diameap_sm->authorized = FALSE;
+
+ diameap_sm->eap_sm.rxResp = FALSE;
+ diameap_sm->eap_sm.respId = -1;
+ diameap_sm->eap_sm.respMethod = TYPE_NONE;
+ diameap_sm->eap_sm.respVendor = VENDOR_IETF;
+ diameap_sm->eap_sm.respVendorMethod = TYPE_NONE;
+
+ return 0;
+}
+
+static int diameap_initialize_diameap_eap_interface(
+ struct diameap_eap_interface * eap_i)
+{
+ TRACE_ENTRY("%p", eap_i);
+
+ //Initialize AAA-EAP Interface
+ eap_i->aaaEapResp = FALSE;
+ eap_i->aaaEapRespData.data = NULL;
+ //Initialize EAP-AAA Interface
+ eap_i->aaaEapReq = FALSE;
+ eap_i->aaaEapNoReq = FALSE;
+ eap_i->aaaSuccess = FALSE;
+ eap_i->aaaFail = FALSE;
+ eap_i->aaaEapReqData.data = NULL;
+ eap_i->aaaEapMSKData = NULL;
+ eap_i->aaaEapEMSKData = NULL;
+ eap_i->aaaEapKeyAvailable = FALSE;
+ eap_i->aaaMethodTimeout = 0;
+
+ return 0;
+}
+
+static int diameap_failed_avp(struct diameap_state_machine * diameap_sm,
+ struct avp * invalidavp)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,invalidavp);
+ if (!invalidavp)
+ return EINVAL;
+
+ if (!diameap_sm)
+ return EINVAL;
+
+ if (diameap_sm->failedavp == NULL)
+ {
+ CHECK_FCT( fd_msg_avp_new( dataobj_failed_avp, 0, &diameap_sm->failedavp) );
+
+ CHECK_FCT( fd_msg_avp_add( diameap_sm->failedavp, MSG_BRW_LAST_CHILD, invalidavp ) );
+
+ }
+ else
+ {
+ //add multiple AVPs in Failed-AVP
+ }
+ return 0;
+}
+
+static int diameap_parse_eap_resp(struct eap_state_machine * eap_sm,
+ struct eap_packet *eappacket)
+{
+ TRACE_ENTRY("%p %p",eap_sm, eappacket)
+
+ eap_sm->rxResp = FALSE;
+ eap_sm->respId = -1;
+ eap_sm->respMethod = TYPE_NONE;
+ eap_sm->respVendor = VENDOR_IETF;
+ eap_sm->respVendorMethod = TYPE_NONE;
+
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%s Empty EAP packet",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ u16 plength;
+ CHECK_FCT(diameap_eap_get_packetlength(eappacket,&plength));
+ if ((int) plength < EAP_HEADER)
+ {
+ TRACE_DEBUG(INFO,"%s EAP packet length less than EAP header.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ u16 length;
+ CHECK_FCT(diameap_eap_get_length(eappacket,&length));
+ if ((int) length < EAP_HEADER)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length field less than EAP header.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ if (plength < length)
+ {
+ TRACE_DEBUG(INFO,"%sLength of received EAP packet is less than the value of the length field.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ eap_code code;
+ CHECK_FCT(diameap_eap_get_code(eappacket,&code));
+ if (code == EAP_REQUEST || code == EAP_SUCCESS || code == EAP_FAILURE)
+ {
+ TRACE_DEBUG(INFO,"%sOnly EAP Responses are accepted at EAP server side.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ u8 id;
+ CHECK_FCT(diameap_eap_get_identifier(eappacket,&id));
+ eap_sm->respId = id;
+
+ CHECK_FCT(diameap_eap_get_type(eappacket,&eap_sm->respMethod));
+ if ((eap_sm->methodState != EAP_M_PROPOSED) && (eap_sm->respMethod
+ == TYPE_NAK || eap_sm->respMethod == TYPE_EXPANDED_TYPES))
+ {
+ TRACE_DEBUG(INFO,"%sNAK or EXPANDED_NAK received after an EAP TYPE been selected",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ if ((eap_sm->respMethod == TYPE_EXPANDED_TYPES) && (length < 20))
+ {
+ TRACE_DEBUG(INFO,"%s Truncated EAP Packet received.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ if ((eap_sm->respMethod == TYPE_NAK) && (eap_sm->currentMethod < 4))
+ {
+ TRACE_DEBUG(INFO,"%sNAK response not expected at this step (Only EAP type = 4 and above are accepted).",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ if (eap_sm->respMethod == TYPE_EXPANDED_TYPES)
+ {
+ u8 *data = (u8 *) eappacket->data;
+ //int len = 0;
+ //u32 respVendor, respVendorMethod;
+ data += 5;
+ eap_sm->respVendor = G24BIGE(data);
+ data += 3;
+ eap_sm->respVendorMethod = G32BIGE(data);
+ data += 4;
+ /* while ((length - 12) > (len * 8))
+ {
+ if (((eap_type) G8(data)) != TYPE_EXPANDED_TYPES)
+ {
+ return FALSE;
+ }
+ data += 1;
+ respVendor = G24BIGE(data);
+ data += 3;
+ respVendorMethod = G32BIGE(data);
+ eap_sm->user.proposedmethods[len].method = respVendor;
+ eap_sm->user.proposedmethods[len].vendor = respVendorMethod;
+ len++;
+ data += 4;
+ }
+ eap_sm->user.methodId = 0;*/
+ }
+
+ if((eap_sm->respMethod == TYPE_IDENTITY) && (length < 6)){
+ TRACE_DEBUG(INFO,"%sUser Identity missing",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ eap_sm->rxResp = TRUE;
+ return 0;
+}
+
+static int diameap_eappacket_new(struct eap_packet * eappacket,
+ struct avp_hdr * avpdata)
+{
+ TRACE_ENTRY("%p %p",eappacket,avpdata);
+ eappacket->ulength = (u16) avpdata->avp_value->os.len;
+ eappacket->data = (u8 *) avpdata->avp_value->os.data;
+ diameap_eap_get_packetlength(eappacket, &eappacket->length);
+ return 0;
+}
+
+static int diameap_parse_avps(struct diameap_state_machine * diameap_sm,
+ struct msg * req, struct diameap_eap_interface * eap_i)
+{
+ TRACE_ENTRY("%p %p %p",diameap_sm,req,eap_i);
+ struct avp * avp, *avp2;
+ struct avp_hdr * avpdata;
+ int ret;
+ int depth;
+
+ /* EAP-Payload data*/
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ CHECK_FCT(diameap_eappacket_new(&eap_i->aaaEapRespData, avpdata));
+ eap_i->aaaEapResp = TRUE;
+ u16 length;
+ diameap_eap_get_length(&eap_i->aaaEapRespData, &length);
+ if (length >= 4)
+ {
+ eap_code code;
+ CHECK_FCT(diameap_eap_get_code(&eap_i->aaaEapRespData,&code));
+
+ if (code != EAP_RESPONSE)
+ {
+ diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */
+ struct avp * invalidavp;
+ union avp_value val;
+ CHECK_FCT( fd_msg_avp_new ( dataobj_eap_payload, 0, &invalidavp));
+ val.os.data = eap_i->aaaEapRespData.data;
+ val.os.len = eap_i->aaaEapRespData.length;
+ CHECK_FCT( fd_msg_avp_setvalue( invalidavp, &val ))
+ CHECK_FCT( diameap_failed_avp(diameap_sm, invalidavp));
+ TRACE_DEBUG(INFO,"%sIncorrect EAP Packet. EAP Code != Response.",DIAMEAP_EXTENSION);
+ return 0;
+ }
+ else
+ {
+ CHECK_FCT(diameap_parse_eap_resp(&diameap_sm->eap_sm, &eap_i->aaaEapRespData));
+ if (diameap_sm->eap_sm.rxResp == FALSE)
+ {
+ diameap_sm->result_code = 1001; /*DIAMETER_MULTI_ROUND_AUTH*/
+ eap_i->aaaEapNoReq = TRUE;
+ eap_i->aaaEapResp = FALSE;
+ }
+ }
+ }
+ else
+ {
+ if (diameap_sm->eap_sm.currentMethod != TYPE_NONE)
+ {
+ diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */
+ CHECK_FCT(diameap_failed_avp(diameap_sm, avp));
+ TRACE_DEBUG(INFO,"%sEAP packet length < Minimum EAP packet length.",DIAMEAP_EXTENSION);
+ return 1;
+ }
+ //EAP start received
+
+ }
+ }
+
+ /* User-Name AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_user_name, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "User-Name";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* EAP-Key-Name AVP */
+
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_key_name, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "EAP-Key-Name";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Auth-Request-Type AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_request_type, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ diameap_sm->auth_request_val = avpdata->avp_value->i32;
+ }
+
+ /* Authorization-Lifetime AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_authorization_lifetime, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Authorization-Lifetime";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Auth-Grace-Period AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_grace_period, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Auth-Grace-Period";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Auth-Session-State AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_session_state, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Auth-Session-State";
+ attribute->value.i32 = avpdata->avp_value->i32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Origin-state-Id AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_origin_state_id, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Origin-state-Id AVP";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* NAS-Port AVP*/
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-Port";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* NAS-Port-Id AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_id, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-Port-Id";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* NAS-Port-Type AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_type, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-Port-Type";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Called-Station-Id AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_called_station_id, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Called-Station-Id";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Calling-Station-Id AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_calling_station_id, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Calling-Station-Id";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Connect-Info AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_connect_info, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Connect-Info";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Originating-Line-Info AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_originating_line_info, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Originating-Line-Info";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Service-Type AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_service_type, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Service-Type";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Callback-Number AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_callback_number, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Callback-Number";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Port-Limit AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_port_limit, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Port-Limit";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-Protocol AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_protocol, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-Protocol";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-MTU AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_mtu, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-MTU";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-Compression AVP */
+ avp = NULL;
+ avp2 = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_compression, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ u32 Pi_Code = avpdata->avp_code;
+ int depth;
+ do
+ {
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-Compression";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes,
+ &attribute->chain);
+ ret = 0;
+ depth = 0;
+ ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+ if (avp2 != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+ }
+ avp = avp2;
+ } while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+ && (avpdata->avp_code == Pi_Code));
+ }
+
+ /* Framed-IP-Address AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_address, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-IP-Address";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-IP-Netmask AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_netmask, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-IP-Netmask";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-Interface-Id AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_interface_id, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-Interface-Id";
+ attribute->value.u64 = avpdata->avp_value->u64;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* Framed-IPv6-Prefix AVP */
+ avp = NULL;
+ avp2 = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ipv6_prefix, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ u32 Pi_Code = avpdata->avp_code;
+ do
+ {
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Framed-IPv6-Prefix";
+ attribute->value.u32 = avpdata->avp_value->u32;
+ fd_list_insert_before(&diameap_sm->req_attributes,
+ &attribute->chain);
+ ret = 0;
+ depth = 0;
+ ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+ if (avp2 != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+ }
+ avp = avp2;
+ } while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+ && (avpdata->avp_code == Pi_Code));
+ }
+
+ /* Tunneling AVP */
+ avp = NULL;
+ avp2 = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_tunneling, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ u32 Pi_Code = avpdata->avp_code;
+ int depth;
+ do
+ {
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "Tunneling";
+ //grouped AVP
+ fd_list_insert_before(&diameap_sm->req_attributes,
+ &attribute->chain);
+ ret = 0;
+ depth = 0;
+ ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+ if (avp2 != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata));
+ }
+ avp = avp2;
+ } while ((avp2 != NULL) && (ret == 0) && (ret == 0)
+ && (avpdata->avp_code == Pi_Code));
+ }
+
+ /* NAS-Identifier AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_identifier, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-Identifier";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* NAS-IP-Address AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ip_address, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-IP-Address";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* NAS-IPv6-Address AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ipv6_address, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "NAS-IPv6-Address";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ /* State AVP */
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_state, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ struct avp_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute)));
+ memset(attribute, 0, sizeof(struct avp_attribute));
+ fd_list_init(&attribute->chain, attribute);
+ attribute->attrib = "State";
+ attribute->value.os.data = avpdata->avp_value->os.data;
+ attribute->value.os.len = avpdata->avp_value->os.len;
+ fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain);
+ }
+
+ return 0;
+}
+
+
+static int diameap_sess_data_new(
+ struct sess_state *diameap_sess_data,
+ struct diameap_state_machine *diameap_sm)
+{
+ if (!diameap_sm)
+ return EINVAL;
+
+ int i;
+
+ diameap_sess_data->invalid_eappackets = diameap_sm->invalid_eappackets;
+
+ diameap_sess_data->user.id = diameap_sm->eap_sm.user.id;
+
+ if ((diameap_sm->eap_sm.user.userid != NULL)
+ && (diameap_sm->eap_sm.user.useridLength > 0))
+ {
+ diameap_sess_data->user.useridLength
+ = diameap_sm->eap_sm.user.useridLength;
+ CHECK_MALLOC(diameap_sess_data->user.userid= malloc(diameap_sess_data->user.useridLength+1));
+ U8COPY(diameap_sess_data->user.userid,0,diameap_sess_data->user.useridLength+1,diameap_sm->eap_sm.user.userid);
+ free(diameap_sm->eap_sm.user.userid);
+ diameap_sm->eap_sm.user.userid = NULL;
+
+ }
+ else
+ {
+ diameap_sess_data->user.useridLength = 0;
+ diameap_sess_data->user.userid = NULL;
+ }
+
+ if ((diameap_sm->eap_sm.user.password != NULL)
+ && (diameap_sm->eap_sm.user.passwordLength > 0))
+ {
+ diameap_sess_data->user.passwordLength
+ = diameap_sm->eap_sm.user.passwordLength;
+ CHECK_MALLOC(diameap_sess_data->user.password = malloc(diameap_sess_data->user.passwordLength+1));
+ U8COPY(diameap_sess_data->user.password,0,diameap_sess_data->user.passwordLength+1,diameap_sm->eap_sm.user.password);
+ free(diameap_sm->eap_sm.user.password);
+ diameap_sm->eap_sm.user.password = NULL;
+ }
+ else
+ {
+ diameap_sess_data->user.passwordLength = 0;
+ diameap_sess_data->user.password = NULL;
+ }
+
+ diameap_sess_data->user.methodId = diameap_sm->eap_sm.user.methodId;
+ for (i = 0; i < MAXMETHODS; i++)
+ {
+ diameap_sess_data->user.methods[i].method
+ = diameap_sm->eap_sm.user.methods[i].method;
+ diameap_sess_data->user.methods[i].vendor
+ = diameap_sm->eap_sm.user.methods[i].vendor;
+ }
+
+ for (i = 0; i < MAXPROPOSEDMETHODS; i++)
+ {
+ diameap_sess_data->user.proposedmethods[i].method
+ = diameap_sm->eap_sm.user.proposedmethods[i].method;
+ diameap_sess_data->user.proposedmethods[i].vendor
+ = diameap_sm->eap_sm.user.proposedmethods[i].vendor;
+ }
+
+ diameap_sess_data->user.pmethods = diameap_sm->eap_sm.user.pmethods;
+ diameap_sess_data->user.proposed_eap_method
+ = diameap_sm->eap_sm.user.proposed_eap_method;
+ diameap_sess_data->user.proposed_eap_method_vendor
+ = diameap_sm->eap_sm.user.proposed_eap_method_vendor;
+ diameap_sess_data->user.success = diameap_sm->eap_sm.user.success;
+
+ diameap_sess_data->currentId = diameap_sm->eap_sm.currentId;
+ diameap_sess_data->currentMethod = diameap_sm->eap_sm.currentMethod;
+ diameap_sess_data->currentVendor = diameap_sm->eap_sm.currentVendor;
+ diameap_sess_data->lastId = diameap_sm->eap_sm.lastId;
+ diameap_sess_data->methodState = diameap_sm->eap_sm.methodState;
+
+ diameap_sess_data->methodData = diameap_sm->eap_sm.methodData;
+ diameap_sm->eap_sm.methodData = NULL;
+
+ return 0;
+}
+
+static void free_attrib(struct auth_attribute * auth_attrib)
+{
+ if (auth_attrib == NULL)
+ {
+ return;
+ }
+ if (auth_attrib->attrib != NULL)
+ {
+ free(auth_attrib->attrib);
+ auth_attrib->attrib = NULL;
+ }
+ if (auth_attrib->op != NULL)
+ {
+ free(auth_attrib->op);
+ auth_attrib->op = NULL;
+ }
+ if (auth_attrib->value != NULL)
+ {
+ free(auth_attrib->value);
+ auth_attrib->value = NULL;
+ }
+ free(auth_attrib);
+ auth_attrib = NULL;
+}
+
+static void free_avp_attrib(struct avp_attribute * avp_attrib)
+{
+ if(avp_attrib){
+ free(avp_attrib);
+ avp_attrib = NULL;
+ }
+}
+
+static void free_ans_attrib(struct avp_attribute * ans_attrib)
+{
+ if(ans_attrib){
+ if (ans_attrib->tofree == 1)
+ {
+ if(ans_attrib->value.os.data){
+ free(ans_attrib->value.os.data);
+ ans_attrib->value.os.data = NULL;
+ }
+ }
+ free(ans_attrib);
+ ans_attrib = NULL;
+ }
+}
+
+static int diameap_unlink_attributes_lists(
+ struct diameap_state_machine * diameap_sm)
+{
+ TRACE_ENTRY("%p ", diameap_sm);
+ if (diameap_sm == NULL)
+ {
+ return EINVAL;
+ }
+
+ while (!FD_IS_LIST_EMPTY(&diameap_sm->attributes))
+ {
+ struct fd_list * item = (struct fd_list *) diameap_sm->attributes.next;
+ struct auth_attribute * auth = (struct auth_attribute *) item;
+ fd_list_unlink(item);
+ free_attrib(auth);
+ }
+
+ while (!FD_IS_LIST_EMPTY(&diameap_sm->req_attributes))
+ {
+ struct fd_list * item =
+ (struct fd_list *) diameap_sm->req_attributes.next;
+ struct avp_attribute * avp = (struct avp_attribute *) item;
+ fd_list_unlink(item);
+ free_avp_attrib(avp);
+ }
+
+ while (!FD_IS_LIST_EMPTY(&diameap_sm->ans_attributes))
+ {
+ struct fd_list * item =
+ (struct fd_list *) diameap_sm->ans_attributes.next;
+ struct avp_attribute * avp_ans = (struct avp_attribute *) item;
+ fd_list_unlink(item);
+ free_ans_attrib(avp_ans);
+ }
+
+ return 0;
+}
+
+static void diameap_free(struct diameap_state_machine * diameap_sm)
+{
+
+ if (diameap_sm != NULL)
+ {
+ if (diameap_sm->eap_sm.user.userid != NULL)
+ {
+ free(diameap_sm->eap_sm.user.userid);
+ diameap_sm->eap_sm.user.userid = NULL;
+ }
+
+ if (diameap_sm->eap_sm.user.password != NULL)
+ {
+ free(diameap_sm->eap_sm.user.password);
+ diameap_sm->eap_sm.user.password = NULL;
+ }
+
+ diameap_sm->eap_sm.selectedMethod = NULL;
+
+ if (diameap_sm->eap_sm.methodData != NULL)
+ {
+
+ struct plugin * cplugin;
+ if (diameap_plugin_get(diameap_sm->eap_sm.currentVendor,
+ diameap_sm->eap_sm.currentMethod, &cplugin))
+ {
+ TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sm->eap_sm.currentMethod,diameap_sm->eap_sm.currentVendor);
+ }
+
+ if (cplugin->eap_method_free)
+ {
+ (*cplugin->eap_method_free)(diameap_sm->eap_sm.methodData);
+ diameap_sm->eap_sm.methodData = NULL;
+ }
+ else
+ {
+ TRACE_DEBUG(INFO,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname);
+ if (diameap_sm->eap_sm.methodData != NULL)
+ {
+ free(diameap_sm->eap_sm.methodData);
+ diameap_sm->eap_sm.methodData = NULL;
+ }
+ }
+ if (diameap_sm->eap_sm.methodData)
+ {
+ TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION);
+ }
+ }
+
+ if (diameap_sm->failedavp != NULL)
+ {
+ CHECK_FCT_DO(fd_msg_free(diameap_sm->failedavp), );
+ }
+
+ if (diameap_sm->lastReqEAPavp != NULL)
+ {
+ CHECK_FCT_DO(fd_msg_free(diameap_sm->lastReqEAPavp), );
+ }
+
+ CHECK_FCT_DO(diameap_unlink_attributes_lists(diameap_sm), );
+
+ free(diameap_sm);
+ diameap_sm = NULL;
+ }
+
+}
+
+static int diameap_get_avp_attribute(struct fd_list * avp_attributes,
+ char * attribute, struct avp_attribute ** avp_attrib, int unlink,
+ int *ret)
+{
+ TRACE_ENTRY("%p %p %p %d %p", avp_attributes, attribute, avp_attrib, unlink, ret);
+ if (avp_attributes == NULL)
+ {
+ return EINVAL;
+ }
+ if (attribute == NULL)
+ {
+ return EINVAL;
+ }
+ struct fd_list * attrib;
+ for (attrib = avp_attributes->next; attrib != avp_attributes; attrib
+ = attrib->next)
+ {
+ *avp_attrib = (struct avp_attribute *) attrib;
+ if (strcmp((*avp_attrib)->attrib, attribute) == 0)
+ {
+ *ret = 0;
+ if (unlink == 1)
+ {
+ fd_list_unlink(&(*avp_attrib)->chain);
+ }
+ return 0;
+ }
+ }
+ *avp_attrib = NULL;
+ *ret = 1;
+ return 0;
+}
+
+static int diameap_get_auth_attribute(struct fd_list * auth_attributes,
+ char * attribute, struct auth_attribute ** auth_attrib, int unlink,
+ int *ret)
+{
+
+ TRACE_ENTRY("%p %p %p %d %p", auth_attributes, attribute, auth_attrib, unlink, ret);
+
+ if (auth_attributes == NULL)
+ {
+ return EINVAL;
+ }
+ if (attribute == NULL)
+ {
+ return EINVAL;
+ }
+
+ struct fd_list * attrib;
+
+ for (attrib = auth_attributes->next; attrib != auth_attributes; attrib
+ = attrib->next)
+ {
+ *auth_attrib = (struct auth_attribute *) attrib;
+ if (strcmp((*auth_attrib)->attrib, attribute) == 0)
+ {
+ *ret = 0;
+ if (unlink == 1)
+ {
+ fd_list_unlink(&(*auth_attrib)->chain);
+ }
+ return 0;
+ }
+ }
+ *auth_attrib = NULL;
+ *ret = 1;
+ return 0;
+}
+
+static int diameap_get_ans_attribute(struct fd_list * ans_attributes,
+ char * attribute, struct avp_attribute ** ans_attrib, int unlink,
+ int *ret)
+{
+ TRACE_ENTRY("%p %p %p %d %p", ans_attributes, attribute, ans_attrib, unlink, ret);
+ if (ans_attributes == NULL)
+ {
+ return EINVAL;
+ }
+ if (attribute == NULL)
+ {
+ return EINVAL;
+ }
+ struct fd_list * attrib;
+ for (attrib = ans_attributes->next; attrib != ans_attributes; attrib
+ = attrib->next)
+ {
+ *ans_attrib = (struct avp_attribute *) attrib;
+ if (strcmp((*ans_attrib)->attrib, attribute) == 0)
+ {
+ *ret = 0;
+ if (unlink == 1)
+ {
+ fd_list_unlink(&(*ans_attrib)->chain);
+ }
+ return 0;
+ }
+ }
+ *ans_attrib = NULL;
+ *ret = 1;
+ return 0;
+}
+
+static int diameap_answer_avp_attributes(
+ struct diameap_state_machine * diameap_sm)
+{
+ TRACE_ENTRY("%p",diameap_sm);
+
+ if (diameap_sm == NULL)
+ {
+ return EINVAL;
+ }
+ int ret1, ret2;
+ struct avp_attribute * avp_attrib;
+ struct avp_attribute * ans_attrib;
+ struct auth_attribute * auth_attrib;
+
+ /* Authorization-Lifetime */
+ {
+ CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Authorization-Lifetime", &avp_attrib,1, &ret1));
+
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Authorization-Lifetime", &auth_attrib,1, &ret2));
+
+ if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL))
+ {
+
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+
+ fd_list_init(&ans_attrib->chain, NULL);
+
+ ans_attrib->attrib = "Authorization-Lifetime";
+
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+
+ free_attrib(auth_attrib);
+
+ }
+ if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL))
+ {
+
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+
+ fd_list_init(&ans_attrib->chain, NULL);
+
+ ans_attrib->attrib = "Authorization-Lifetime";
+
+ ans_attrib->value.u32 = avp_attrib->value.u32;
+
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+
+ free_avp_attrib(avp_attrib);
+
+ }
+ if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib
+ != NULL))
+ {
+
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Authorization-Lifetime";
+ if (avp_attrib->value.u32 < atoi(auth_attrib->value))
+ {
+ ans_attrib->value.u32 = avp_attrib->value.u32;
+ }
+ else
+ {
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ }
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_avp_attrib(avp_attrib);
+ free_attrib(auth_attrib);
+ }
+ }
+
+ /* Auth-Grace-Period */
+ {
+ CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Auth-Grace-Period", &avp_attrib,1, &ret1));
+
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Grace-Period", &auth_attrib,1, &ret2));
+
+ if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Auth-Grace-Period";
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Auth-Grace-Period";
+ ans_attrib->value.u32 = avp_attrib->value.u32;
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_avp_attrib(avp_attrib);
+ }
+ if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib
+ != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Auth-Grace-Period";
+ if (avp_attrib->value.u32 < atoi(auth_attrib->value))
+ {
+ ans_attrib->value.u32 = avp_attrib->value.u32;
+ }
+ else
+ {
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ }
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ free_avp_attrib(avp_attrib);
+ }
+ }
+
+ /* Auth-Session-State */
+ {
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Session-State", &auth_attrib,1, &ret2));
+ if ((ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Auth-Session-State";
+ ans_attrib->value.i32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ }
+
+ /* Re-Auth-Request-Type */
+ {
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Re-Auth-Request-Type", &auth_attrib,1, &ret2));
+ if ((ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Re-Auth-Request-Type";
+ ans_attrib->value.i32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ else
+ {
+ ans_attrib = NULL;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes, "Authorization-Lifetime", &ans_attrib,0, &ret1));
+ if ((ret1 == 0) && (ans_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Re-Auth-Request-Type";
+ ans_attrib->value.i32 = 0;
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ }
+ }
+ }
+
+ /* Session-Timeout */
+ {
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Session-Timeout", &auth_attrib,1, &ret2));
+ if ((ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Session-Timeout";
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ }
+
+ /* Multi-Round-Time-Out */
+ {
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Multi-Round-Time-Out", &auth_attrib,1, &ret2));
+ if ((ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Multi-Round-Time-Out";
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ }
+
+ /* Acct-Interim-Interval */
+ {
+ CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Acct-Interim-Interval", &auth_attrib,1, &ret2));
+ if ((ret2 == 0) && (auth_attrib != NULL))
+ {
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = "Acct-Interim-Interval";
+ ans_attrib->value.u32 = atoi(auth_attrib->value);
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ free_attrib(auth_attrib);
+ }
+ }
+
+ return 0;
+}
+
+#define DIAMEAP_STR 1
+#define DIAMEAP_NUM 2
+
+#define DIAMEAP_OP_NO 0 //Not supported operator
+#define DIAMEAP_OP_EQ 1 //==
+#define DIAMEAP_OP_GT 2 //>
+#define DIAMEAP_OP_LT 3 //<
+#define DIAMEAP_OP_GE 4 //>=
+#define DIAMEAP_OP_LE 5 //<=
+#define DIAMEAP_OP_NE 6 //!=
+#define DIAMEAP_OP_EX 7 //~=
+#define EQ(A,B) A==B ? TRUE : FALSE
+#define GT(A,B) A>B ? TRUE : FALSE
+#define GE(A,B) A>=B ? TRUE : FALSE
+#define LT(A,B) A<B ? TRUE : FALSE
+#define LE(A,B) A<=B ? TRUE : FALSE
+#define NE(A,B) A!=B ? TRUE : FALSE
+
+int diameap_get_operator(char *operator)
+{
+ TRACE_ENTRY("%p",operator);
+ if (strcmp(operator, "==") == 0)
+ {
+ return DIAMEAP_OP_EQ;
+ }
+ if (strcmp(operator, ">") == 0)
+ {
+ return DIAMEAP_OP_GT;
+ }
+ if (strcmp(operator, "<") == 0)
+ {
+ return DIAMEAP_OP_LT;
+ }
+ if (strcmp(operator, ">=") == 0)
+ {
+ return DIAMEAP_OP_GE;
+ }
+ if (strcmp(operator, "<=") == 0)
+ {
+ return DIAMEAP_OP_LE;
+ }
+ if (strcmp(operator, "!=") == 0)
+ {
+ return DIAMEAP_OP_NE;
+ }
+ if (strcmp(operator, "~=") == 0)
+ {
+ return DIAMEAP_OP_EX;
+ }
+ return DIAMEAP_OP_NO;
+}
+
+boolean is_operator(int format_type, char * operator)
+{
+ TRACE_ENTRY("%d %p",format_type,operator);
+ if ((format_type == DIAMEAP_STR) && (strcmp(operator, "==") == 0 || strcmp(
+ operator, "~=") == 0 || strcmp(operator, "!=") == 0))
+ {
+ return TRUE;
+ }
+ if ((format_type == DIAMEAP_NUM) && (strcmp(operator, "~=") != 0))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+union avp_value diameap_get_num(char * num, enum dict_avp_basetype datatype)
+{
+ TRACE_ENTRY("%p %d",num,datatype);
+ union avp_value val;
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ val.i32 = atoi(num);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ val.i64 = atoll(num);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ val.u32 = strtoul(num, NULL, 10);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ val.u64 = strtoull(num, NULL, 10);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ val.f32 = atof(num);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ val.f64 = strtod(num, NULL);
+ break;
+ default:
+ TRACE_DEBUG(INFO, "%sUnknown AVP Base Type.",DIAMEAP_EXTENSION)
+ ;
+ }
+ return val;
+}
+
+boolean diameap_check(union avp_value *A, char * B, char * operator,
+ enum dict_avp_basetype datatype)
+{
+ TRACE_ENTRY("%p %p %p %d",A,B,operator,datatype);
+ if (((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+ operator) == TRUE)) || ((datatype != AVP_TYPE_OCTETSTRING)
+ && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM,
+ operator) == TRUE)))
+ {
+ switch (diameap_get_operator(operator))
+ {
+ case DIAMEAP_OP_EQ:
+ if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+ operator) == TRUE))
+ {
+ if (strcmp((char *)A->os.data, B) == 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return EQ(A->i32,diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return EQ(A->i64,diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return EQ(A->u32,diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return EQ(A->u64,diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return EQ(A->f32,diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return EQ(A->f64,diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case DIAMEAP_OP_EX:
+ {
+ //string only
+ boolean authorized = FALSE;
+ if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+ operator) == TRUE))
+ {
+ regex_t rule_regexp;
+ regcomp(&rule_regexp, B, REG_EXTENDED | REG_NOSUB | REG_ICASE);
+ if (regexec(&rule_regexp, (char *)A->os.data, 0, NULL, 0) != 0)
+ {
+ authorized = FALSE;
+ }
+ else
+ {
+ authorized = TRUE;
+ }
+ regfree(&rule_regexp);
+ }
+ return authorized;
+ }
+ case DIAMEAP_OP_GT:
+
+ if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return GT(A->i32, diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return GT(A->i64, diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return GT(A->u32, diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return GT(A->u64, diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return GT(A->f32, diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return GT(A->f64, diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case DIAMEAP_OP_GE:
+ if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return GE(A->i32,diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return GE(A->i64,diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return GE(A->u32,diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return GE(A->u64,diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return GE(A->f32,diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return GE(A->f64,diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case DIAMEAP_OP_LT:
+ if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return LT(A->i32, diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return LT(A->i64, diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return LT(A->u32, diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return LT(A->u64, diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return LT(A->f32, diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return LT(A->f64, diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case DIAMEAP_OP_LE:
+ if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return LE(A->i32, diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return LE(A->i64, diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return LE(A->u32, diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return LE(A->u64, diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return LE(A->f32, diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return LE(A->f64, diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case DIAMEAP_OP_NE:
+ if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR,
+ operator) == TRUE))
+ {
+ if (strcmp((char *)A->os.data, B) != 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype
+ != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator)
+ == TRUE))
+ {
+ switch (datatype)
+ {
+ case AVP_TYPE_INTEGER32://i32
+ return NE(A->i32, diameap_get_num(B, datatype).i32);
+ break;
+ case AVP_TYPE_INTEGER64://i64
+ return NE(A->i64, diameap_get_num(B, datatype).i64);
+ break;
+ case AVP_TYPE_UNSIGNED32://u32
+ return NE(A->u32, diameap_get_num(B, datatype).u32);
+ break;
+ case AVP_TYPE_UNSIGNED64://u64
+ return NE(A->u64, diameap_get_num(B, datatype).u64);
+ break;
+ case AVP_TYPE_FLOAT32://f32
+ return NE(A->f32, diameap_get_num(B, datatype).f32);
+ break;
+ case AVP_TYPE_FLOAT64://f64
+ return NE(A->f64, diameap_get_num(B, datatype).f64);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+char * diameap_attribute_operator(char * op, int * toadd, boolean *isrule)
+{
+ TRACE_ENTRY("%p %p %p",op,toadd,isrule);
+ char * attribute_op;
+
+ if (op[0] == '+')
+ {
+ *toadd = 1;
+ }
+ else if (op[strlen(op) - 1] == '+')
+ {
+ *toadd = 2;
+ }
+ else
+ {
+ *toadd = 0;
+ }
+
+ switch (*toadd)
+ {
+ case 1:
+ attribute_op = malloc(strlen(op));
+ memset(attribute_op, 0, strlen(op));
+ strncpy(attribute_op, op + 1, strlen(op) - 1);
+ attribute_op[strlen(op)] = '\0';
+ break;
+ case 2:
+ attribute_op = malloc(strlen(op));
+ memset(attribute_op, 0, strlen(op));
+ strncpy(attribute_op, op, strlen(op) - 1);
+ attribute_op[strlen(op)] = '\0';
+ break;
+ default:
+ attribute_op = malloc(strlen(op) + 1);
+ memset(attribute_op, 0, strlen(op) + 1);
+ strcpy(attribute_op, op);
+ attribute_op[strlen(op) + 1] = '\0';
+ }
+ if (strcmp(attribute_op, "=") == 0)
+ {
+ *isrule = FALSE;
+ *toadd = 2;
+ }
+ else
+ {
+ *isrule = TRUE;
+ }
+
+ return attribute_op;
+}
+
+int diameap_answer_set_attribute_valueA(union avp_value *A, int *tofree,
+ enum dict_avp_basetype datatype, union avp_value * rval)
+{
+ TRACE_ENTRY("%p %p %d %p",A,tofree,datatype,rval);
+ if (datatype == AVP_TYPE_OCTETSTRING)
+ {
+ CHECK_MALLOC(rval->os.data=malloc(A->os.len));
+ memcpy(rval->os.data,A->os.data,A->os.len);
+ rval->os.len = A->os.len;
+ *tofree = 1;
+ }
+ else
+ {
+ *rval = *A;
+ }
+ return 0;
+}
+int diameap_answer_set_attribute_valueB(char * B, int *tofree,
+ enum dict_avp_basetype datatype, union avp_value * rval)
+{
+ TRACE_ENTRY("%p %p %d %p",B,tofree,datatype,rval);
+ if (datatype == AVP_TYPE_OCTETSTRING)
+ {
+ CHECK_MALLOC(rval->os.data=malloc(strlen(B)));
+ memcpy(rval->os.data,B,strlen(B));
+ rval->os.len = strlen(B);
+
+ *tofree = 1;
+ }
+ else
+ {
+
+ *rval = diameap_get_num(B, datatype);
+ }
+
+ return 0;
+}
+
+static int diameap_attribute_limits(char * attrib, int * max, int *ret)
+{
+ TRACE_ENTRY("%p %p %p",attrib,max,ret);
+ if (attrib == NULL)
+ {
+ return EINVAL;
+ }
+ int i;
+ for (i = 0; i < sizeof(auth_avps); i++)
+ {
+ if (strcmp(auth_avps[i].avp_attribute, attrib) == 0)
+ {
+ *max = auth_avps[i].max;
+ *ret = 0;
+ return 0;
+ }
+ }
+ *max = 0;
+ *ret = 1;
+ return 0;
+}
+
+static int diameap_answer_authorization_attributes(
+ struct diameap_state_machine * diameap_sm)
+{
+ TRACE_ENTRY("%p",diameap_sm);
+
+ if (diameap_sm == NULL)
+ {
+ return EINVAL;
+ }
+ boolean checked = TRUE;
+
+ struct fd_list * attrib;
+ struct auth_attribute * auth_attrib;
+ struct avp_attribute * avp_attrib;
+ int ret;
+
+ for (attrib = (&diameap_sm->attributes)->next; attrib
+ != (&diameap_sm->attributes); attrib = attrib->next)
+ {
+ avp_attrib = NULL;
+ auth_attrib = (struct auth_attribute *) attrib;
+
+ int toadd = 0;
+ boolean isrule = FALSE;
+ char * op;
+
+ op = diameap_attribute_operator(auth_attrib->op, &toadd, &isrule);
+
+ struct dict_object * dobj;
+ struct dict_avp_data avpdata;
+ fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ auth_attrib->attrib, &dobj, ENOENT);
+ fd_dict_getval(dobj, &avpdata);
+
+ checked = TRUE;
+ if (isrule == TRUE)
+ {
+ CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,auth_attrib->attrib,&avp_attrib,0,&ret));
+ if (ret == 0)
+ {
+ checked = diameap_check(&avp_attrib->value, auth_attrib->value,
+ op, avpdata.avp_basetype);
+ }
+ }
+ if (checked == TRUE && toadd != 0)
+ {
+
+ struct avp_attribute * ans_attrib;
+ int max = 0;
+ diameap_attribute_limits(auth_attrib->attrib, &max, &ret);
+ if ((ret == 0) && (max != 0))
+ {
+ if (max == 1)//only one
+ {
+ int ret = 0;
+ diameap_get_ans_attribute(&diameap_sm->ans_attributes,
+ auth_attrib->attrib, &ans_attrib, 0, &ret);
+ if (ret == 1)
+ {
+ ans_attrib = NULL;
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = strdup(auth_attrib->attrib);
+ if (toadd == 1)
+ {
+ diameap_answer_set_attribute_valueA(
+ &avp_attrib->value, &ans_attrib->tofree,
+ avpdata.avp_basetype, &ans_attrib->value);
+ }
+ else
+ {
+ diameap_answer_set_attribute_valueB(
+ auth_attrib->value, &ans_attrib->tofree,
+ avpdata.avp_basetype, &ans_attrib->value);
+ }
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+
+ }
+ else
+ {
+ //an answer avp is already added
+ }
+ }
+ else
+ {
+ ans_attrib = NULL;
+ CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute)));
+ memset(ans_attrib, 0, sizeof(struct avp_attribute));
+ fd_list_init(&ans_attrib->chain, NULL);
+ ans_attrib->attrib = auth_attrib->attrib;
+ if (toadd == 1)
+ {
+ diameap_answer_set_attribute_valueA(&avp_attrib->value,
+ &ans_attrib->tofree, avpdata.avp_basetype,
+ &ans_attrib->value);
+ }
+ else
+ {
+ diameap_answer_set_attribute_valueB(auth_attrib->value,
+ &ans_attrib->tofree, avpdata.avp_basetype,
+ &ans_attrib->value);
+ }
+ fd_list_insert_before(&diameap_sm->ans_attributes,
+ &ans_attrib->chain);
+ }
+ }
+ }
+ if (checked == FALSE)
+ {
+
+ diameap_sm->authorized = FALSE;
+ return 0;
+ }
+ }
+ diameap_sm->authorized = checked;
+ return 0;
+
+ return 0;
+}
+
+
+
+static int diameap_policy_decision(struct diameap_state_machine * diameap_sm,
+ struct diameap_eap_interface *eap_i)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,eap_i);
+
+ if ((eap_i->aaaFail == TRUE) && (eap_i->aaaSuccess == TRUE))
+ {
+ TRACE_DEBUG(INFO,"%s Incorrect EAP decision. EAP process should not return both success and failure for the same session.(please report this problem.)",DIAMEAP_EXTENSION);
+ return -1;
+ }
+
+ if (eap_i->aaaFail == TRUE)
+ {
+ diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */
+ diameap_sm->authFailure = TRUE;
+ TRACE_DEBUG(FULL+1,"%s Auth failure: Authentication Rejected ",DIAMEAP_EXTENSION);
+ return 0;
+ }
+
+ if (eap_i->aaaSuccess == FALSE)
+ {
+ diameap_sm->result_code = 1001; /* DIAMETER_MULTI_ROUND_AUTH 1001 */
+ return 0;
+ }
+
+ if (eap_i->aaaSuccess == TRUE)
+ {
+ if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE)
+ {
+ if ((diameap_sm->verify_authorization == TRUE)
+ && (diameap_sm->result_code == 0))
+ {
+ diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */
+ diameap_sm->authSuccess = TRUE;
+ TRACE_DEBUG(FULL+1,"%s Auth success: Authorization and Authentication ",DIAMEAP_EXTENSION);
+ return 0;
+ }
+ else
+ {
+ //
+ }
+ }
+ if (diameap_sm->auth_request_val == AUTHENTICATE_ONLY)
+ {
+ diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */
+ diameap_sm->authSuccess = TRUE;
+ TRACE_DEBUG(FULL+1,"%s Auth success: Authentication Only ",DIAMEAP_EXTENSION);
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int diameap_add_avps(struct diameap_state_machine * diameap_sm,
+ struct msg * ans, struct msg * req)
+{
+ TRACE_ENTRY("%p %p %p",diameap_sm,ans,req);
+
+ struct avp * avp, *avp2;
+ struct avp_hdr * avpdata;
+ union avp_value avp_val;
+ int ret = 0;
+
+ /* Origin-Host AVP and Origin-Realm AVP */
+ {
+ CHECK_FCT( fd_msg_add_origin ( ans, 0 ) );
+ }
+
+ /* Auth-Application-Id AVP */
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_auth_application_id, 0, &avp));
+ avp_val.u32 = diameap_config->application_id;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+ }
+
+ /* Auth-Request-Type AVP
+ * Enumerated values:
+ * AUTHENTICATE_ONLY 1
+ * AUTHORIZE_ONLY 2
+ * AUTHORIZE_AUTHENTICATE 3 */
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_auth_request_type, 0, &avp));
+ if (!diameap_config->authorize)
+ {
+ //AUTHENTICATE ONLY
+ avp_val.i32 = AUTHENTICATE_ONLY;
+ }
+ else
+ {
+ if (diameap_sm->auth_request_val == 3)
+ {
+ //AUTHORIZE_AUTHENTICATE
+ avp_val.i32 = AUTHORIZE_AUTHENTICATE;
+ }
+ else
+ {
+ //AUTHENTICATE_ONLY
+ avp_val.i32 = AUTHENTICATE_ONLY;
+ }
+ }
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+ }
+
+ /* Proxy-Info AVP */
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_proxy_info, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) );
+ u32 proxy_info_code = avpdata->avp_code;
+ int depth;
+ do
+ {
+ ret = 0;
+ depth = 0;
+ CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) );
+ if (avpdata->avp_code == proxy_info_code)
+ {
+ CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp));
+ }
+ ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth);
+ avp = avp2;
+ } while ((avp != NULL) && (ret == 0) && (ret == 0));
+ }
+
+ if (diameap_sm->eap_sm.user.userid)
+ {
+ /* User-Name AVP */
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_user_name, 0, &avp));
+
+ if (diameap_sm->privateUser == FALSE)
+ {
+
+ avp_val.os.data = diameap_sm->eap_sm.user.userid;
+ avp_val.os.len = diameap_sm->eap_sm.user.useridLength;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ }
+ else
+ {
+
+ }
+
+ }
+ }
+ return 0;
+}
+
+static int diameap_add_user_sessions_avps(
+ struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,ans);
+
+ struct avp * avp;
+ union avp_value avp_val;
+ int ret;
+
+ /* Authorization-Lifetime AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Authorization-Lifetime",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_authorization_lifetime, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Auth-Grace-Period AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Grace-Period",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_auth_grace_period, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Auth-Session-State AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Session-State",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_auth_session_state, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Re-Auth-Request-Type AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Re-Auth-Request-Type",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_re_auth_request_type, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Session-Timeout AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Session-Timeout",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_session_timeout, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Acct-Interim-Interval AVP */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Acct-Interim-Interval",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_acct_interim_interval, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+ return 0;
+}
+
+static int diameap_add_authorization_avps(
+ struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+
+ TRACE_ENTRY("%p %p",diameap_sm, ans);
+
+ struct avp * avp;
+ union avp_value avp_val;
+ int ret;
+
+ if (diameap_sm == NULL)
+ {
+ return EINVAL;
+ }
+ if (ans == NULL)
+ {
+ return EINVAL;
+ }
+
+ /* Reply-Message */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_reply_message, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret));
+ }
+
+ }
+
+ /* Service-Type */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Service-Type",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_service_type, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Callback-Number */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Number",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_callback_number, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Callback-Id */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Id",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_callback_id, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Idle-Timeout */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Idle-Timeout",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_idle_timeout, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* NAS-Filter-Rule */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Filter-Rule",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_nas_filter_rule, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Filter-Id */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_filter_id, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret));
+ }
+
+ }
+
+ /* Configuration-Token */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_configuration_token, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret));
+ }
+ }
+
+ /* QoS-Filter-Rule */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_qos_filter_rule, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret));
+ }
+
+ }
+
+ /* Framed-Protocol */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Protocol",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_protocol, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-Routing */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Routing",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_routing, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+
+ }
+
+ /* Framed-MTU */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_mtu, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-Compression */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_compression, 0, &avp));
+ avp_val.i32 = ans_attrib->value.i32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret));
+ }
+
+ }
+ /* Framed-IP-Address */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Address",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_address, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-IP-Netmask */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Netmask",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_netmask, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-Route */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_route, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret));
+ }
+ }
+
+ /* Framed-Pool */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Pool",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_pool, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-Interface-Id */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Interface-Id",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_interface_id, 0, &avp));
+ avp_val.u64 = ans_attrib->value.u64;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-IPv6-Prefix */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_prefix, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret));
+ }
+ }
+
+ /* Framed-IPv6-Route */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_route, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret));
+ }
+ }
+
+ /* Framed-IPv6-Pool */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Pool",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_pool, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Framed-IPX-Network */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPX-Network",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipx_network, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+
+ }
+ /* Framed-AppleTalk-Link */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Link",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_link, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+
+ }
+
+ /* Framed-AppleTalk-Network */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret));
+ while ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_network, 0, &avp));
+ avp_val.u32 = ans_attrib->value.u32;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret));
+ }
+
+ }
+
+ /* Framed-AppleTalk-Zone */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Zone",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_zone, 0, &avp));
+ avp_val.os.data = ans_attrib->value.os.data;
+ avp_val.os.len = ans_attrib->value.os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_ans_attrib(ans_attrib);
+ }
+ }
+
+ /* Tunneling */
+ //
+
+ /* State */
+ //
+ return 0;
+}
+
+static int diameap_add_result_code(struct diameap_state_machine * diameap_sm,
+ struct msg * ans, struct session * sess)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,ans);
+ struct avp * avp;
+ union avp_value avp_val;
+ int ret;
+
+ /* Result-Code AVP */
+ CHECK_FCT(fd_msg_avp_new(dataobj_result_code, 0, &avp));
+ avp_val.u32 = diameap_sm->result_code;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ /* Add Result-Code AVP to the message */
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+ /* Multi_Round_Time_Out AVP */
+ if (diameap_sm->result_code == 1001)
+ {
+ struct timespec sess_timeout;
+ CHECK_FCT(fd_msg_avp_new(dataobj_multi_round_time_out, 0, &avp));
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Multi-Round-Time-Out",&ans_attrib,1,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ avp_val.u32 = ans_attrib->value.u32;
+ /* Update the session timeout with multi-round-time-out value */
+ CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout));
+ sess_timeout.tv_sec += diameap_config->multi_round_time_out;
+ CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout));
+ free_ans_attrib(ans_attrib);
+ }
+ else
+ {
+ avp_val.u32 = diameap_config->multi_round_time_out;
+ /* Update the session timeout with multi-round-time-out value */
+ CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout));
+ sess_timeout.tv_sec += diameap_config->multi_round_time_out;
+ CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout));
+ }
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ }
+ return 0;
+}
+
+static int diameap_add_eap_payload(struct diameap_state_machine * diameap_sm,
+ struct msg * ans, struct diameap_eap_interface *eap_i)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,ans);
+ struct avp * avp;
+ union avp_value avp_val;
+ int ret;
+ u32 Framed_MTU = 1500; //1500 default value
+ u32 NAS_Port_Type_HeaderLength = 4;
+ int EAP_Max_Length = 0;
+
+ /* get Framed-MTU AVP value */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,0,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ Framed_MTU = ans_attrib->value.u32;
+ }
+ }
+
+ /* get NAS-Port-Type AVP value */
+ {
+ struct avp_attribute * ans_attrib;
+ CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Port-Type",&ans_attrib,0,&ret));
+ if ((ret == 0) && (ans_attrib != NULL))
+ {
+ // = ans_attrib->value.i32;
+ }
+ }
+
+ //TD take the link type into consideration when calculating EAP_MAX_Length
+ EAP_Max_Length = Framed_MTU - NAS_Port_Type_HeaderLength;
+
+ if (eap_i->aaaEapReqData.length <= EAP_Max_Length)
+ {
+
+ /* EAP-Payload AVP */
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &avp));
+ avp_val.os.data = eap_i->aaaEapReqData.data;
+ avp_val.os.len = eap_i->aaaEapReqData.length;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+ if (diameap_sm->lastReqEAPavp != NULL)
+ {
+ fd_msg_free(diameap_sm->lastReqEAPavp);
+ diameap_sm->lastReqEAPavp = NULL;
+ }
+
+ CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &diameap_sm->lastReqEAPavp));
+ avp_val.os.data = eap_i->aaaEapReqData.data;
+ avp_val.os.len = eap_i->aaaEapReqData.length;
+ CHECK_FCT(fd_msg_avp_setvalue(diameap_sm->lastReqEAPavp, &avp_val));
+
+ }
+ }
+ else
+ {
+ //if EAP Packet length > EAP_Max_Length
+ }
+ return 0;
+}
+
+static int diameap_send(struct msg ** rmsg)
+{
+ TRACE_ENTRY("%p",rmsg);
+ CHECK_FCT( fd_msg_send( rmsg, NULL, NULL));
+ return 0;
+}
+
+static int diameap_add_eap_success_avps(
+ struct diameap_state_machine * diameap_sm, struct msg * ans,
+ struct diameap_eap_interface *eap_i)
+{
+ TRACE_ENTRY("%p %p %p",diameap_sm,ans,eap_i);
+ struct avp * avp;
+ union avp_value avp_val;
+ int ret;
+
+ /* EAP-Master-Session-Key AVP */
+ if (eap_i->aaaEapKeyAvailable == TRUE)
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_eap_master_session_key, 0, &avp));
+ avp_val.os.data = eap_i->aaaEapMSKData;
+ avp_val.os.len = eap_i->aaaEapMSKLength;
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+
+ }
+
+ /* EAP-Key-Name AVP */
+ struct avp_attribute * avp_attrib = NULL;
+
+ CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,"EAP-Key-Name",&avp_attrib,1,&ret))
+ if ((avp_attrib != NULL) && (ret != 1))
+ {
+ if (avp_attrib->value.os.len == 0)
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_eap_key_name, 0, &avp));
+ avp_val.os.data = NULL;//
+ avp_val.os.len = 0;//
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ free_avp_attrib(avp_attrib);
+ }
+ }
+
+ return 0;
+}
+
+int diameap_authorize(struct diameap_state_machine * diameap_sm)
+{
+ TRACE_ENTRY("%p",diameap_sm);
+
+ CHECK_FCT(diameap_authorization_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes));
+
+ diameap_sm->authorized = TRUE;
+
+ CHECK_FCT_DO(diameap_answer_authorization_attributes(diameap_sm),
+ );
+ if (diameap_sm->authorized == FALSE)
+ {
+ diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */
+ }
+ return 0;
+}
+
+static int diameap_add_accounting_eap_auth_method(
+ struct diameap_state_machine * diameap_sm, struct msg * ans)
+{
+ TRACE_ENTRY("%p %p",diameap_sm,ans);
+ int i = 0;
+ struct avp * avp;
+ union avp_value avp_val;
+ /* Accounting-EAP-Auth-Method AVP */
+ while (i < diameap_sm->eap_sm.user.methodId)
+ {
+ CHECK_FCT(fd_msg_avp_new(dataobj_accounting_eap_auth_method, 0, &avp));
+
+ avp_val.u64 = (u64) (((diameap_sm->eap_sm.user.methods[i].vendor)
+ * pow((double) 2, (double) 32))
+ + diameap_sm->eap_sm.user.methods[i].method);
+ CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+ i++;
+ }
+ return 0;
+}
+
+static int diameap_add_eap_reissued_payload(struct msg * ans, struct msg * req)
+{
+ TRACE_ENTRY("%p %p", ans, req);
+ struct avp * avp, *re_avp;
+ union avp_value avp_val;
+ struct avp_hdr * avphdr;
+
+ if ((ans == NULL) || (req == NULL))
+ {
+ return EINVAL;
+ }
+ avp = NULL;
+ CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp));
+ if (avp != NULL)
+ {
+ CHECK_FCT( fd_msg_avp_hdr(avp, &avphdr));
+ CHECK_FCT( fd_msg_avp_new(dataobj_eap_reissued_payload, 0, &re_avp));
+ CHECK_MALLOC(avp_val.os.data=malloc(avphdr->avp_value->os.len));
+ memcpy(avp_val.os.data,avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+ avp_val.os.len = avphdr->avp_value->os.len;
+ CHECK_FCT(fd_msg_avp_setvalue(re_avp, &avp_val));
+ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, re_avp ) );
+ }
+ else
+ {
+ TRACE_DEBUG(INFO,"%sUnable to find EAP-Payload AVP in received Diameter-EAP-Request.",DIAMEAP_EXTENSION);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+
+static int diameap_server_callback(struct msg ** rmsg, struct avp * ravp,
+ struct session * sess, void * opaque, enum disp_action * action)
+{
+ TRACE_ENTRY("%p %p %p %p", rmsg, ravp, sess, action);
+
+ struct sess_state * diameap_sess_data = NULL;
+ struct diameap_state_machine * diameap_sm = NULL;
+ struct diameap_eap_interface eap_i;
+ struct msg *req, *ans;
+ boolean non_fatal_error = FALSE;
+
+ if (rmsg == NULL)
+ return EINVAL;
+
+ req = *rmsg;
+
+ CHECK_FCT_DO(fd_sess_state_retrieve(diameap_server_reg, sess, &diameap_sess_data),
+ { TRACE_DEBUG(INFO,"%s retrieving session state failed.",DIAMEAP_EXTENSION); goto s_end;});
+
+ CHECK_MALLOC_DO(diameap_sm = malloc(sizeof(struct diameap_state_machine)),
+ goto s_end);
+ memset(diameap_sm, 0, sizeof(struct diameap_state_machine));
+
+ if (diameap_sess_data)
+ {
+ diameap_sm->state = DIAMEAP_RECEIVED;
+ diameap_sm->eap_sm.eap_state = EAP_IDLE;
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_DISABLED;
+ diameap_sm->eap_sm.eap_state = EAP_INITIALIZE;
+ }
+
+ while (diameap_sm->state != DIAMEAP_IDLE && diameap_sm->state
+ != DIAMEAP_END)
+ {
+ switch (diameap_sm->state)
+ {
+ case DIAMEAP_DISABLED:
+ if (rmsg)
+ {
+ diameap_sm->state = DIAMEAP_INITIALIZE;
+ }
+ else
+ {
+ TRACE_DEBUG(INFO,"%sReceived empty Diameter EAP Request message.",DIAMEAP_EXTENSION);
+ goto s_end;
+ }
+ break;
+
+ case DIAMEAP_INITIALIZE:
+
+ CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data),
+ { TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i),
+ { TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION))
+ ;
+
+ if ((diameap_sm->result_code != 0))
+ {
+ diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY;
+ }
+ break;
+
+ case DIAMEAP_RECEIVED:
+
+ CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data),
+ { TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i),
+ { TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION))
+ ;
+
+ if (diameap_sm->result_code != 0)
+ {
+ diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY;
+ }
+ break;
+
+ case DIAMEAP_AUTHENTICATION_VERIFY:
+ {
+
+ TRACE_DEBUG(FULL+1,"%sVerify authentication",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_eap_statemachine(&diameap_sm->eap_sm, &eap_i,&non_fatal_error),
+ { TRACE_DEBUG(INFO,"%s EAP process failed.",DIAMEAP_EXTENSION); goto s_end;});
+
+ if (non_fatal_error == TRUE)
+ {
+ TRACE_DEBUG(FULL+1,"%sAuthentication verify finished with a non-fatal-error.",DIAMEAP_EXTENSION);
+ diameap_sm->state = DIAMEAP_SEND_ERROR_MSG;
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_SELECT_DECISION;
+
+ }
+ }
+ break;
+
+ case DIAMEAP_SELECT_DECISION:
+
+ CHECK_FCT_DO( diameap_policy_decision(diameap_sm,&eap_i),
+ goto s_end)
+ ;
+
+ if ((eap_i.aaaSuccess == TRUE) && (diameap_sm->auth_request_val
+ == AUTHORIZE_AUTHENTICATE)
+ && (diameap_sm->verify_authorization == FALSE))
+ {
+ diameap_sm->state = DIAMEAP_AUTHORIZATION_VERIFY;
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_DIAMETER_EAP_ANSWER;
+ }
+ break;
+
+ case DIAMEAP_AUTHORIZATION_VERIFY:
+ diameap_sm->verify_authorization = TRUE;
+ TRACE_DEBUG(FULL+1,"%sVerify authorization",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(diameap_authorize(diameap_sm),
+ { TRACE_DEBUG(INFO,"%s Authorization check process failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ diameap_sm->state = DIAMEAP_SELECT_DECISION;
+
+ break;
+
+ case DIAMEAP_DIAMETER_EAP_ANSWER:
+ TRACE_DEBUG(FULL+1,"%screate Diameter EAP Answer",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0),
+ goto s_end)
+ ;
+ ans = *rmsg;
+ TRACE_DEBUG(FULL+1,"%sAdding AVPs to Diameter EAP Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req),
+ { TRACE_DEBUG(INFO,"%s Unable to add AVPs to Diameter-EAP-Answer message.",DIAMEAP_EXTENSION);goto s_end;})
+ ;
+ if (diameap_sm->authFailure == FALSE)
+ {
+ if (diameap_sm->eap_sm.user.id != 0)
+ {
+ TRACE_DEBUG(FULL+1,"%sSelect authentication attributes.",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_authentication_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes),
+ { TRACE_DEBUG(INFO,"%s Unable to get user's session attributes.",DIAMEAP_EXTENSION); goto s_end;});
+ TRACE_DEBUG(FULL+1,"%sCreate answer authentication attributes.",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_answer_avp_attributes(diameap_sm),
+ { TRACE_DEBUG(INFO,"%s Unable to generate answer attributes.",DIAMEAP_EXTENSION); goto s_end;});
+ }
+
+ if (diameap_sm->authSuccess == FALSE)
+ {
+ diameap_sm->state = DIAMEAP_SEND_REQUEST;
+ }
+ else
+ {
+
+ diameap_sm->state = DIAMEAP_SEND_SUCCESS;
+ }
+ }
+ else
+ {
+ diameap_sm->state = DIAMEAP_SEND_FAILURE;
+ }
+ break;
+
+ case DIAMEAP_SEND_REQUEST:
+ TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+ { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+ { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sStoring DiamEAP session data.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_MALLOC(diameap_sess_data = malloc(sizeof(struct sess_state)))
+ ;
+ memset(diameap_sess_data, 0, sizeof(struct sess_state));
+ diameap_sess_data_new(diameap_sess_data, diameap_sm);
+
+ CHECK_FCT_DO(fd_sess_state_store(diameap_server_reg, sess, &diameap_sess_data),
+ { TRACE_DEBUG(INFO,"%s Storing session state failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+
+ CHECK_FCT_DO( diameap_send(rmsg),
+ goto s_end)
+ ;
+
+ diameap_sm->state = DIAMEAP_IDLE;
+ break;
+
+ case DIAMEAP_SEND_FAILURE:
+ TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+ { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+ { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+
+ LOG_N("%s Auth FAIL: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid);
+
+ CHECK_FCT_DO( diameap_send(rmsg),
+ goto s_end)
+ ;
+ diameap_sm->state = DIAMEAP_END;
+ break;
+
+ case DIAMEAP_SEND_SUCCESS:
+ TRACE_DEBUG(FULL+1,"%sAdding User session AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(diameap_add_user_sessions_avps(diameap_sm,ans),
+ { TRACE_DEBUG(INFO,"%s Adding user's session AVPs failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+
+ if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE)
+ {
+ TRACE_DEBUG(FULL+1,"%sAdding Authorization AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_add_authorization_avps(diameap_sm,ans),
+ { TRACE_DEBUG(INFO,"%s Adding Authorization AVPs failed.",DIAMEAP_EXTENSION); goto s_end;});
+ }
+ TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess),
+ { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i),
+ { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+ TRACE_DEBUG(FULL+1,"%sAdding EAP success AVPs AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO( diameap_add_eap_success_avps(diameap_sm, ans, &eap_i),
+ goto s_end)
+ ;
+ TRACE_DEBUG(FULL+1,"%sAdding Accounting-EAP-Auth-Method AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION)
+ ;
+ CHECK_FCT_DO(diameap_add_accounting_eap_auth_method(diameap_sm, ans),
+ { TRACE_DEBUG(INFO,"%s Adding accounting AVP failed",DIAMEAP_EXTENSION); goto s_end;})
+ ;
+
+ LOG_N("%s Auth Success: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid);
+
+ CHECK_FCT_DO( diameap_send(rmsg),
+ goto s_end)
+ ;
+ diameap_sm->state = DIAMEAP_END;
+ break;
+
+ case DIAMEAP_SEND_ERROR_MSG:
+ diameap_sm->invalid_eappackets++;
+ if (diameap_sm->invalid_eappackets
+ == diameap_config->max_invalid_eap_packet)
+ {
+ diameap_sm->result_code = 4001;//DIAMETER_AUTHENTICATION_REJECTED
+ TRACE_DEBUG(FULL,"%s Maximum permitted invalid EAP Packet reached. Diameter Authentication Rejected.",DIAMEAP_EXTENSION);
+ }
+
+ CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0),
+ goto s_end)
+ ;
+
+ ans = *rmsg;
+ CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req),
+ { TRACE_DEBUG(INFO,"%s Adding AVPs to Diameter-EAP-Answer message failed.",DIAMEAP_EXTENSION);goto s_end;})
+ ;
+ if ((non_fatal_error == TRUE) && (diameap_sm->result_code == 0))
+ {
+ diameap_sm->result_code = 1001;
+ }
+
+ if (diameap_sm->result_code == 1001)
+ {
+ CHECK_FCT_DO( diameap_add_eap_reissued_payload(ans,req), goto s_end);
+ }
+
+ if (diameap_sm->result_code == 5004)
+ {
+ CHECK_FCT_DO( fd_msg_avp_add( ans , MSG_BRW_LAST_CHILD, diameap_sm->failedavp ),goto s_end );
+ }
+
+ CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), goto s_end)
+ ;
+
+ CHECK_FCT_DO( diameap_send(rmsg), goto s_end)
+ ;
+ diameap_sm->state = DIAMEAP_IDLE;
+ break;
+
+ case DIAMEAP_END:
+ break;
+
+ case DIAMEAP_IDLE:
+ break;
+ }
+ }
+
+ diameap_free(diameap_sm);
+
+ s_end: return 0;
+}
+
+int diameap_start_server(void)
+{
+ struct disp_when when;
+
+ /*create handler for sessions */
+ CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL, NULL));
+
+ /* Register the callback */
+ memset(&when, 0, sizeof(when));
+ when.command = dataobj_diameap_cmd;
+ when.app = dataobj_diameap_app;
+
+ /* Register the callback for EAP Application */
+ CHECK_FCT(fd_disp_register(diameap_server_callback, DISP_HOW_CC, &when, NULL,
+ &handle));
+
+ if (handle == NULL)
+ {
+ TRACE_DEBUG(INFO, "%sCannot register the callback !!!",DIAMEAP_EXTENSION);
+ return 1;
+ }
+ return 0;
+}
+
+int diameap_stop_server(void)
+{
+ CHECK_FCT(fd_sess_handler_destroy(&diameap_server_reg, NULL));
+ CHECK_FCT(fd_disp_unregister(&handle, NULL));
+
+ return 0;
+}