Commit ae0991fe authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Added test for modified message parsing

parent fb9b064d
......@@ -19,6 +19,7 @@ SET(FD_COMMON_SRC
messages.c
queues.c
peers.c
p_ce.c
p_expiry.c
p_out.c
p_psm.c
......
......@@ -242,6 +242,9 @@ int fd_p_sr_store(struct sr_list * srlist, struct msg **req, uint32_t *hbhloc);
int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req);
void fd_p_sr_failover(struct sr_list * srlist);
/* Capabilities Exchange */
int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer);
/* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
extern struct fd_list fd_g_activ_peers;
extern pthread_rwlock_t fd_g_activ_peers_rw; /* protect the list */
......
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* 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: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * 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. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* 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 "fD.h"
/* This file contains code to handle Capabilities Exchange messages (CER and CEA) */
int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer)
{
/* Save all information from the CER into the peer structure, after cleaning old information if any */
return ENOTSUP;
}
......@@ -154,7 +154,13 @@ int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer)
cnx = peer->p_cnxctx;
/* Do send the message */
CHECK_FCT( do_send(msg, cnx, hbh, peer ? &peer->p_sr : NULL) );
CHECK_FCT_DO( do_send(msg, cnx, hbh, peer ? &peer->p_sr : NULL),
{
fd_log_debug("An error occurred while sending this message, it is lost:\n");
fd_msg_dump_walk(NONE, *msg);
fd_msg_free(*msg);
*msg = NULL;
} );
}
return 0;
......
......@@ -358,11 +358,23 @@ psm_loop:
}
/* Link-local message: They must be understood by our dictionary */
{
int ret;
CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msg ),
{
if ((ret == EBADMSG) && (msg != NULL)) {
/* msg now contains an answer message to send back */
CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ );
}
if (msg) {
CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
}
goto psm_loop;
} );
}
TODO("Check if it is a local message (CER, DWR, ...)");
TODO("If not, check we are in OPEN state");
TODO("Update expiry timer if needed");
TODO("Handle the message");
/* Handle the LL message and update the expiry timer appropriately */
TODO("...");
}
/* The connection object is broken */
......@@ -400,6 +412,12 @@ psm_loop:
case STATE_CLOSED:
TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
/* In case of error : DIAMETER_UNKNOWN_PEER */
CHECK_FCT_DO( fd_p_ce_merge(peer, params->cer),
{
} );
break;
case STATE_WAITCNXACK:
......
......@@ -282,7 +282,14 @@ int main(int argc, char *argv[])
ADD_RULE(gavp, 73565, "AVP Test - os", RULE_REQUIRED, 2, 3, 0);
ADD_RULE(gavp, 73565, "AVP Test - enumos", RULE_OPTIONAL, 0, 1, 0);
ADD_RULE(gavp, 73565, "AVP Test - grouped", RULE_FIXED_TAIL, -1, 1, 1);
/* ABNF :
< no vendor - f32 >
< i64 >
< enumi32 >
2*3 { os }
*1 [ enumos ]
< grouped >
*/
#if 0
fd_dict_dump_object ( gavp );
#endif
......@@ -727,9 +734,9 @@ int main(int argc, char *argv[])
/* Now test the msg_parse_rule function */
{
struct dict_object * rule;
struct fd_pei pei;
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
/* Use the "AVP Test - rules" AVP to test the rules */
{
......@@ -748,38 +755,50 @@ int main(int argc, char *argv[])
ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - grouped" );
/* Check the message is still conform */
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
/* The first avp is optional in fixed position, so remove it and check the message is still OK */
CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &childavp, NULL) );
CHECK( 0, fd_msg_free ( childavp ) );
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
ADD_AVP( tavp, MSG_BRW_FIRST_CHILD, childavp, 0, "AVP Test - no vendor - f32" );
/* Now break some rules and check it is detected */
#define CHECK_CONFLICT( _msg, _ruleavp, _avpvendor ) { \
struct dict_object * _rule; \
CHECK( EBADMSG, fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_rule ) ); \
if ((_ruleavp) == NULL) { \
CHECK( NULL, _rule); \
#define CHECK_CONFLICT( _msg, _error, _conflictavp_name, _conflictavp_vnd ) { \
struct fd_pei _pei; \
CHECK( EBADMSG, fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_pei ) ); \
if (_error) { \
CHECK( 0, strcmp( _error, _pei.pei_errcode ) ); \
} \
if ((_conflictavp_name) == NULL) { \
CHECK( NULL, _pei.pei_avp); \
} else { \
struct dict_rule_data _ruledata; \
struct dict_avp_request _req = { (_conflictavp_vnd), 0, (_conflictavp_name) }; \
struct dict_object * _avp; \
struct dict_avp_request _req = { (_avpvendor), 0, (_ruleavp) }; \
struct dict_object * _conflict; \
CHECK( 1, (_pei.pei_avp) ? 1 : 0 ); \
CHECK( 0, fd_msg_model( _pei.pei_avp, &_conflict ) ); \
CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT)); \
CHECK( 0, fd_dict_getval( _rule, &_ruledata ) ); \
CHECK( _avp, _ruledata.rule_avp ); \
CHECK( _avp, _conflict ); \
} \
}
/* ABNF :
< no vendor - f32 >
< i64 >
< enumi32 >
2*3 { os }
*1 [ enumos ]
< grouped >
*/
{
/* Test the FIXED_HEAD rules positions: add another AVP before the third */
CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &tempavp, NULL) ); /* tempavp is the novendor avp */
CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &tempavp, NULL) ); /* tempavp is the i64 avp */
ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - os" );
CHECK_CONFLICT( msg, "AVP Test - enumi32", 73565 );
CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
/* Now remove this AVP */
CHECK( 0, fd_msg_free ( childavp ) );
......@@ -789,7 +808,7 @@ int main(int argc, char *argv[])
CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &childavp, NULL) ); /* childavp is the enumi32 avp */
CHECK( 0, fd_msg_free ( childavp ) );
CHECK_CONFLICT( msg, "AVP Test - enumi32", 73565 );
CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
/* Add the AVP back */
ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - enumi32" );
......@@ -800,7 +819,7 @@ int main(int argc, char *argv[])
CHECK( 0, fd_msg_browse ( childavp, MSG_BRW_NEXT, &tempavp, NULL) ); /* tempavp is the os avp */
CHECK( 0, fd_msg_free ( tempavp ) );
CHECK_CONFLICT( msg, "AVP Test - os", 73565 ); /* The rule requires at least 2 AVP, we have only 1 */
CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - os", 73565 ); /* The rule requires at least 2 AVP, we have only 1 */
/* Now add this AVP */
ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
......@@ -810,7 +829,7 @@ int main(int argc, char *argv[])
ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
CHECK_CONFLICT( msg, "AVP Test - os", 73565 ); /* The rule requires at most 3 AVP, we have 4 */
CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - os", 73565 ); /* The rule requires at most 3 AVP, we have 4 */
/* Now delete these AVP */
CHECK( 0, fd_msg_free ( tempavp ) );
......@@ -823,12 +842,12 @@ int main(int argc, char *argv[])
ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
/* The message is still conform */
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
/* Now break the rule */
ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
CHECK_CONFLICT( msg, "AVP Test - enumos", 73565 ); /* The rule requires at most 3 AVP, we have 4 */
CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - enumos", 73565 );
/* Now delete this AVP */
CHECK( 0, fd_msg_free ( tempavp ) );
......@@ -838,7 +857,7 @@ int main(int argc, char *argv[])
/* Test the RULE_FIXED_TAIL rules positions: add another AVP at the end */
ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - os" );
CHECK_CONFLICT( msg, "AVP Test - grouped", 73565 );
CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - grouped", 73565 );
/* Now remove this AVP */
CHECK( 0, fd_msg_free ( childavp ) );
......
......@@ -1864,8 +1864,34 @@ struct parserules_data {
/* Create an empty AVP of a given model (to use in Failed-AVP) */
static struct avp * empty_avp(struct dict_object * model_avp)
{
TODO("Create the AVP instance and set a 0 value");
return NULL;
struct avp * avp = NULL;
struct dict_avp_data avp_info;
union avp_value val;
char os[1] = { '\0' };
/* Create an instance */
CHECK_FCT_DO( fd_msg_avp_new(model_avp, 0, &avp ), return NULL );
/* Type of the AVP */
CHECK_FCT_DO( fd_dict_getval(model_avp, &avp_info), return NULL );
/* 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);
case AVP_TYPE_INTEGER32:
case AVP_TYPE_INTEGER64:
case AVP_TYPE_UNSIGNED32:
case AVP_TYPE_UNSIGNED64:
case AVP_TYPE_FLOAT32:
case AVP_TYPE_FLOAT64:
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), return NULL );
/* For AVP_TYPE_GROUPED we don't do anything */
}
return avp;
}
/* Check that a list of AVPs is compliant with a given rule -- will be iterated on the list of rules */
......@@ -2055,12 +2081,12 @@ int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct f
{
TRACE_ENTRY("%p %p %p", object, dict, error_info);
/* Resolve the dictionary objects when missing. This also validates the object. */
CHECK_FCT( fd_msg_parse_dict ( object, dict ) );
if (error_info)
memset(error_info, 0, sizeof(struct fd_pei));
/* Resolve the dictionary objects when missing. This also validates the object. */
CHECK_FCT( fd_msg_parse_dict ( object, dict ) );
/* Call the recursive function */
return parserules_do ( dict, object, error_info, 1 ) ;
}
......@@ -2186,7 +2212,7 @@ int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_act
if (app == NULL) {
/* In that case, maybe we should answer a DIAMETER_APPLICATION_UNSUPPORTED error ? Do we do this here ? */
TRACE_DEBUG(NONE, "Reply DIAMETER_APPLICATION_UNSUPPORTED if it's a request ?");
TODO("Reply DIAMETER_APPLICATION_UNSUPPORTED if it's a request ?");
}
/* So start browsing the message */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment