Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/diameap_eappacket.c b/extensions/app_diameap/diameap_eappacket.c
new file mode 100644
index 0000000..a696161
--- /dev/null
+++ b/extensions/app_diameap/diameap_eappacket.c
@@ -0,0 +1,310 @@
+/*****************************************************************************************************
+ * 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 "libdiameap.h"
+
+int diameap_eap_get_code(struct eap_packet *eappacket, eap_code * eapcode)
+{
+ TRACE_ENTRY("%p %p",eappacket,eapcode);
+
+ if (eappacket->data == NULL)
+ {
+ *eapcode = ERROR;
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Code to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 1)
+ {
+ *eapcode = ERROR;
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Code to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *eapcode = G8(eappacket->data);
+ return 0;
+}
+
+int diameap_eap_get_identifier(struct eap_packet *eappacket, u8 * identifier)
+{
+ TRACE_ENTRY("%p %p",eappacket,identifier);
+ *identifier = 0;
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Identifier field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 2)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no Identifier field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *identifier = G8(eappacket->data + 1);
+ return 0;
+}
+
+int diameap_eap_get_length(struct eap_packet *eappacket, u16 *length)
+{
+ TRACE_ENTRY("%p %p",eappacket,length);
+ *length = 0;
+
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->ulength < 4)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no Length field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *length = (u16) G16BIGE((eappacket->data + 2));
+ return 0;
+}
+
+int diameap_eap_get_packetlength(struct eap_packet *eappacket, u16 *length)
+{
+ TRACE_ENTRY("%p %p",eappacket,length);
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ *length = eappacket->ulength;
+ return 0;
+}
+
+int diameap_eap_get_type(struct eap_packet *eappacket, eap_type * eaptype)
+{
+ TRACE_ENTRY("%p %p",eappacket,eaptype);
+ *eaptype = 0;
+
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Type field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 5)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Type field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *eaptype = (u32) G8(eappacket->data + 4);
+ return 0;
+}
+
+boolean diameap_eap_check_code(eap_code code)
+{
+ TRACE_ENTRY("%d",code);
+ if (code != EAP_REQUEST && code != EAP_RESPONSE && code != EAP_SUCCESS
+ && code != EAP_FAILURE)
+ {
+ TRACE_DEBUG(FULL,"%sIncorrect EAP Code (%d).",DIAMEAP_EXTENSION,code);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int diameap_eap_get_packetdata(struct eap_packet *eappacket, u8 ** data,
+ int *len)
+{
+ TRACE_ENTRY("%p %p",eappacket,data);
+ if (eappacket->length > 0)
+ {
+ *data = malloc(sizeof(u8) * eappacket->length);
+ U8COPY(*data,0,eappacket->length,eappacket->data);
+ *len = eappacket->length;
+ return 0;
+ }
+ TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+ *data = NULL;
+ *len = 0;
+ return EINVAL;
+}
+
+int diameap_eap_get_data(struct eap_packet *eappacket, u8 ** data, int * len)
+{
+ TRACE_ENTRY("%p %p",eappacket,data);
+ if (eappacket->length > 5)
+ {
+ CHECK_MALLOC( *data = malloc(sizeof(u8) * (eappacket->length - 5)) );
+ U8COPY(*data,0,(eappacket->length-5),(eappacket->data+5));
+ *len = eappacket->length - 5;
+ return 0;
+ }
+ TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+ *data = NULL;
+ *len = 0;
+
+ return EINVAL;
+}
+
+void diameap_eap_dump(int level, struct eap_packet *eappacket)
+{
+ TRACE_ENTRY("%d %p",level,eappacket);
+ if (!TRACE_BOOL(level))
+ return;
+
+ if (eappacket->data == NULL)
+ return;
+ if (eappacket->length < 5)
+ return;
+ if (eappacket->ulength < 5)
+ return;
+
+ fd_log_debug("------------- Dump EAP Packet-------------");
+ int i;
+ fd_log_debug("\t -Code : ");
+ eap_code code;
+ CHECK_FCT_DO(diameap_eap_get_code(eappacket,&code),return);
+ switch (code)
+ {
+ case 1:
+ fd_log_debug("Request");
+ break;
+ case 2:
+ fd_log_debug("Response");
+ break;
+ case 3:
+ fd_log_debug("Success");
+ break;
+ case 4:
+ fd_log_debug("Failure");
+ break;
+ default:
+ fd_log_debug("Error (EAP Code value [%d] not allowed)",code);
+ break;
+ }
+ u8 id;
+ CHECK_FCT_DO(diameap_eap_get_identifier(eappacket,&id),return);
+ fd_log_debug("\t -Identifier : %x ", id);
+ u16 length;
+ CHECK_FCT_DO(diameap_eap_get_length(eappacket,&length),return);
+ fd_log_debug("\t -Length : %d ", (unsigned int)length);
+ if (eappacket->length > 4)
+ {
+ eap_type type;
+ CHECK_FCT_DO(diameap_eap_get_type(eappacket,&type),return);
+ fd_log_debug("\t -Type : %d ", type);
+ }
+ if (eappacket->length > 5)
+ {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "\t -Data : ");
+ for (i = 5; i < eappacket->length && i < 30; i++)
+ {
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02x ", G8(eappacket->data + i));
+ }
+ if(i+1<eappacket->length)
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "[...] (len=%d)",(unsigned int) length);
+ fd_log_debug("%s", buf);
+ }
+ fd_log_debug("-------------End Dump EAP Packet-------------");
+}
+
+int diameap_eap_new(eap_code code, u8 id, eap_type type, u8 * data,
+ u16 dataLength, struct eap_packet *eappacket)
+{
+
+ TRACE_ENTRY("%d %hhu %d %p %hu %p", code, id, type, data, dataLength,eappacket);
+
+ int length = 0;
+
+ //Initialize EAP Packet
+ eappacket->length = 0;
+ eappacket->ulength = 0;
+ eappacket->data = NULL;
+
+ if (diameap_eap_check_code(code) == FALSE)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%sWrong EAP Code. Only Request, Response, Success or Failure are permitted.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+
+ length += EAP_HEADER;
+ if (code == EAP_REQUEST || code == EAP_RESPONSE)
+ { // EAP Packet code is either Request or Response
+ if (type == TYPE_NONE)
+ {
+ TRACE_DEBUG(INFO,
+ "%sUnable to create a new EAP Packet (Request or Response) without EAP Type field.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ length += EAP_TYPE; // EAP Packet code
+ if (data != NULL)
+ {
+ length += dataLength;
+
+ if (length > (int) MAX_EAP_PACKET)
+ {
+
+ TRACE_DEBUG(INFO,
+ "%sUnable to add Data to EAP Packet. Data field length exceed allowed data size.", DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ else
+ {
+
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ U8COPY(eappacket->data, 5, dataLength, data);
+ }
+ }
+ else
+ {
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ }
+ P8(eappacket->data + 4, type);
+ }
+ else
+ { //EAP Packet code is SUCCESS or FAILURE
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ //No Data filed
+ //No Type field
+ }
+ //Add Code and Identifier fields
+ P8(eappacket->data, code);
+ P8(eappacket->data + 1, id);
+ //Add length field
+ P16BIGE(eappacket->data + 2, length);
+ eappacket->length = length;
+ eappacket->ulength = length;
+ return 0;
+}