# HG changeset patch # User Sebastien Decugis # Date 1374400659 -7200 # Node ID e72c9dad62ac83529f0cc527a1f4c8b212ee015a # Parent 4e52f009861a456e1aab5548d33d72de001f89a5 Fix issue with generating Failed-AVP when the error is DIAMETER_MISSING_AVP. Also fix a memory leak in that case diff -r 4e52f009861a -r e72c9dad62ac include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Thu Jul 18 16:08:54 2013 +0200 +++ b/include/freeDiameter/libfdproto.h Sun Jul 21 11:57:39 2013 +0200 @@ -2698,6 +2698,7 @@ struct fd_pei { char * pei_errcode; /* name of the error code to use */ struct avp * pei_avp; /* pointer to invalid (in original message) or missing AVP (to be freed) */ + int pei_avp_free; /* Set to 1 if the pei_avp must be freed */ char * pei_message; /* Overwrite default message if needed */ int pei_protoerr; /* do we set the 'E' bit in the error message ? */ }; diff -r 4e52f009861a -r e72c9dad62ac libfdcore/messages.c --- a/libfdcore/messages.c Thu Jul 18 16:08:54 2013 +0200 +++ b/libfdcore/messages.c Sun Jul 21 11:57:39 2013 +0200 @@ -388,6 +388,11 @@ /* Set the error code */ CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) ); + /* free the pei AVP to avoid memory leak */ + if (pei.pei_avp_free) { + fd_msg_free(pei.pei_avp); + } + *msg = NULL; *error = m; diff -r 4e52f009861a -r e72c9dad62ac libfdcore/p_ce.c --- a/libfdcore/p_ce.c Thu Jul 18 16:08:54 2013 +0200 +++ b/libfdcore/p_ce.c Sun Jul 21 11:57:39 2013 +0200 @@ -636,6 +636,10 @@ CHECK_FCT_DO( fd_msg_rescode_set(*cer, error->pei_errcode, error->pei_message, error->pei_avp, 1 ), goto destroy ); CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL), goto destroy ); + if (error->pei_avp_free) { + fd_msg_free(error->pei_avp); + } + /* And now destroy this connection */ destroy: fd_cnx_destroy(*recv_cnx); diff -r 4e52f009861a -r e72c9dad62ac libfdcore/routing_dispatch.c --- a/libfdcore/routing_dispatch.c Thu Jul 18 16:08:54 2013 +0200 +++ b/libfdcore/routing_dispatch.c Sun Jul 21 11:57:39 2013 +0200 @@ -609,6 +609,7 @@ if (error_info.pei_errcode) { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr)); CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) ); + if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); } return 0; } else { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Host AVP", fd_msg_pmdl_get(msgptr)); @@ -631,6 +632,7 @@ if (error_info.pei_errcode) { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr)); CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) ); + if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); } return 0; } else { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Realm AVP", fd_msg_pmdl_get(msgptr)); @@ -655,6 +657,7 @@ if (error_info.pei_errcode) { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr)); CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) ); + if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); } return 0; } else { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing User-Name AVP", fd_msg_pmdl_get(msgptr)); @@ -673,6 +676,7 @@ if (error_info.pei_errcode) { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr)); CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) ); + if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); } return 0; } else { fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Route-Record AVP", fd_msg_pmdl_get(msgptr)); @@ -931,6 +935,7 @@ { if (error_info.pei_errcode) { CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) ); + if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); } return 0; } else { return ret; diff -r 4e52f009861a -r e72c9dad62ac libfdproto/messages.c --- a/libfdproto/messages.c Thu Jul 18 16:08:54 2013 +0200 +++ b/libfdproto/messages.c Sun Jul 21 11:57:39 2013 +0200 @@ -2370,12 +2370,16 @@ /* Type of the AVP */ CHECK_FCT_DO( fd_dict_getval(model_avp, &avp_info), return NULL ); + /* Set an initial size */ + avp->avp_public.avp_len = GETAVPHDRSZ( avp->avp_public.avp_flags ) + avp_value_sizes[avp_info.avp_basetype]; + /* Prepare the empty value */ memset(&val, 0, sizeof(val)); switch (avp_info.avp_basetype) { case AVP_TYPE_OCTETSTRING: val.os.data = os; val.os.len = sizeof(os); + avp->avp_public.avp_len += val.os.len; case AVP_TYPE_INTEGER32: case AVP_TYPE_INTEGER64: case AVP_TYPE_UNSIGNED32: @@ -2439,6 +2443,7 @@ if (pr_data->pei) { pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_avp = empty_avp(rule->rule_avp); + pr_data->pei->pei_avp_free = 1; } return EBADMSG; } @@ -2452,6 +2457,7 @@ else pr_data->pei->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES"; pr_data->pei->pei_avp = empty_avp(rule->rule_avp); /* Well we are supposed to return the (max + 1)th instance of the AVP instead... Pfff... */ TODO("Improve..."); + pr_data->pei->pei_avp_free = 1; } return EBADMSG; } @@ -2471,6 +2477,7 @@ pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_message = "AVP was not in its fixed position"; pr_data->pei->pei_avp = empty_avp(rule->rule_avp); + pr_data->pei->pei_avp_free = 1; } return EBADMSG; } @@ -2484,6 +2491,7 @@ pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_message = "AVP was not in its fixed position"; pr_data->pei->pei_avp = empty_avp(rule->rule_avp); + pr_data->pei->pei_avp_free = 1; } return EBADMSG; }