view extensions/app_diameap/diameap_eappacket.c @ 1327:82b386714795

Set callback data also when only setting expire callback (and not answer callback as well). It is used when calling the expire callback, so not setting it makes no sense.
author Thomas Klausner <tk@giga.or.at>
date Mon, 27 Nov 2017 15:21:20 +0100
parents 0117a7746b21
children
line wrap: on
line source

/*****************************************************************************************************
 * 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;
}
"Welcome to our mercurial repository"