Commit 757b1940 authored by gauthier's avatar gauthier

Problem decoding S1AP

parent 34ab7c37
cmake_minimum_required(VERSION 2.8)
set ( CMAKE_BUILD_TYPE "RelWithDebInfo" )
set ( ASN_DEBUG False)
set ( ADDR_CONF False )
set ( DEBUG_OMG False )
set ( DISABLE_XER_PRINT False )
set ( DRIVER2013 True )
set ( EMOS False )
set ( EMIT_ASN_DEBUG True )
set ( ENABLE_FXP True )
set ( ENABLE_ITTI True )
set ( ENABLE_NAS_UE_LOGGING True )
......
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="pdml2html.xsl"?>
<!-- You can find pdml2html.xsl in /usr/share/wireshark or at http://anonsvn.wireshark.org/trunk/wireshark/pdml2html.xsl. -->
<pdml capture_file="./attach_complete.pcapng" creator="wireshark/1.10.6" time="Wed Oct 14 15:33:08 2015" version="0">
<pdml capture_file="./attach_complete.pcapng" creator="wireshark/1.10.6" time="Mon Nov 2 09:22:48 2015" version="0">
<packet>
<proto name="frame" pos="0" showname="Frame 9: 82 bytes on wire (656 bits), 82 bytes captured (656 bits) on interface 0" size="82">
<field name="frame.interface_id" pos="0" show="0" showname="Interface id: 0" size="0"/>
......
......@@ -106,6 +106,7 @@
<xsl:template match="proto[@name='frame']">
<xsl:variable name="time_relative" select="field[@name='frame.time_relative']/@show"/>
<xsl:variable name="frame_number" select="field[@name='frame.number']/@show"/>
<xsl:variable name="ip" select="proto[@name='ip']"/>
<xsl:variable name="ip_src">
<xsl:call-template name="reverse_ip">
......@@ -131,16 +132,17 @@
<xsl:for-each select="$ip/proto[@name='sctp']">
<xsl:variable name="sctp_data_sid" select="./field/field[@name='sctp.data_sid']/@show"/>
<!-- TODO resolv problem of 2 SCTP packets in 1 IP packet: src and dst ports are not in the 2nd SCTP packet -->
<xsl:variable name="sctp_srcport" select="./field[@name='sctp.srcport']/@show"/>
<xsl:variable name="sctp_dstport" select="./field[@name='sctp.dstport']/@show"/>
<xsl:variable name="sctp_data_ssn" select="./field/field[@name='sctp.data_ssn']/@show"/>
<xsl:variable name="sctp_data_payload_proto_id" select="./field/field[@name='sctp.data_payload_proto_id']/@show"/>
<!--xsl:variable name="sctp_srcport" select="./field[@name='sctp.srcport']/@show"/-->
<!--xsl:variable name="sctp_dstport" select="./field[@name='sctp.dstport']/@show"/-->
<!--xsl:variable name="sctp_data_ssn" select="./field/field[@name='sctp.data_ssn']/@show"/-->
<!--xsl:variable name="sctp_data_payload_proto_id" select="./field/field[@name='sctp.data_payload_proto_id']/@show"/-->
<xsl:variable name="sctp_chunk_type_str">
<xsl:call-template name="chunktype2str">
<xsl:with-param name="chunk_type" select="./field/field[@name='sctp.chunk_type']/@value"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="sctp_pos_offset" select="./@pos"/>
<xsl:variable name="sctp_node" select="."/>
<xsl:choose>
<xsl:when test="$sctp_chunk_type_str='DATA'">
......@@ -148,59 +150,61 @@
<xsl:variable name="s1ap_pos_offset" select="./@pos"/>
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$s1ap_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<sctp.data_ssn value="{$sctp_data_ssn}"/>
<sctp.data_payload_proto_id value="{$sctp_data_payload_proto_id}"/>
<!--sctp.data_sid value="{$sctp_data_sid}"/-->
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<!--sctp.data_ssn value="{$sctp_data_ssn}"/-->
<!--sctp.data_payload_proto_id value="{$sctp_data_payload_proto_id}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<xsl:copy-of select="node()"/>
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:for-each>
</xsl:when>
<xsl:when test="$sctp_chunk_type_str='INIT'">
<xsl:variable name="sctp_init_nr_out_streams" select="./field/field[@name='sctp.init_nr_out_streams']/@show"/>
<xsl:variable name="sctp_init_nr_in_streams" select="./field/field[@name='sctp.init_nr_in_streams']/@show"/>
<xsl:variable name="sctp_init_initial_tsn" select="./field/field[@name='sctp.init_initial_tsn']/@show"/>
<!--xsl:variable name="sctp_init_nr_out_streams" select="./field/field[@name='sctp.init_nr_out_streams']/@show"/-->
<!--xsl:variable name="sctp_init_nr_in_streams" select="./field/field[@name='sctp.init_nr_in_streams']/@show"/-->
<!--xsl:variable name="sctp_init_initial_tsn" select="./field/field[@name='sctp.init_initial_tsn']/@show"/-->
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$sctp_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<sctp.init_nr_in_streams value="{$sctp_init_nr_in_streams}"/>
<sctp.init_nr_out_streams value="{$sctp_init_nr_out_streams}"/>
<sctp.init_initial_tsn value="{$sctp_init_initial_tsn}"/>
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<!--sctp.init_nr_in_streams value="{$sctp_init_nr_in_streams}"/-->
<!--sctp.init_nr_out_streams value="{$sctp_init_nr_out_streams}"/-->
<!--sctp.init_initial_tsn value="{$sctp_init_initial_tsn}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<!--xsl:copy-of select="node()"/-->
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:when>
<xsl:when test="$sctp_chunk_type_str='INIT_ACK'">
<xsl:variable name="sctp_initack_nr_out_streams" select="./field/field[@name='sctp.initack_nr_out_streams']/@show"/>
<xsl:variable name="sctp_initack_nr_in_streams" select="./field/field[@name='sctp.initack_nr_in_streams']/@show"/>
<xsl:variable name="sctp_initack_initial_tsn" select="./field/field[@name='sctp.initack_initial_tsn']/@show"/>
<!--xsl:variable name="sctp_initack_nr_out_streams" select="./field/field[@name='sctp.initack_nr_out_streams']/@show"/-->
<!--xsl:variable name="sctp_initack_nr_in_streams" select="./field/field[@name='sctp.initack_nr_in_streams']/@show"/-->
<!--xsl:variable name="sctp_initack_initial_tsn" select="./field/field[@name='sctp.initack_initial_tsn']/@show"/-->
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$sctp_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<sctp.initack_nr_in_streams value="{$sctp_initack_nr_in_streams}"/>
<sctp.initack_nr_out_streams value="{$sctp_initack_nr_out_streams}"/>
<sctp.initack_initial_tsn value="{$sctp_initack_initial_tsn}"/>
<!--sctp.data_sid value="{$sctp_data_sid}"/-->
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<!--sctp.initack_nr_in_streams value="{$sctp_initack_nr_in_streams}"/-->
<!--sctp.initack_nr_out_streams value="{$sctp_initack_nr_out_streams}"/-->
<!--sctp.initack_initial_tsn value="{$sctp_initack_initial_tsn}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<!--xsl:copy-of select="node()"/-->
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:when>
<!--xsl:when test="$sctp_chunk_type_str='SACK'"> </xsl:when-->
......@@ -209,44 +213,47 @@
<xsl:when test="$sctp_chunk_type_str='ABORT'">
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$sctp_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<!--sctp.data_sid value="{$sctp_data_sid}"/-->
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<xsl:copy-of select="node()"/>
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:when>
<xsl:when test="$sctp_chunk_type_str='SHUTDOWN'">
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$sctp_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<!--sctp.data_sid value="{$sctp_data_sid}"/-->
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<xsl:copy-of select="node()"/>
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:when>
<!--xsl:when test="$sctp_chunk_type_str='SHUTDOWN_ACK'"></xsl:when-->
<xsl:when test="$sctp_chunk_type_str='ERROR'">
<packet name="{$sctp_chunk_type_str}" action="{$action}">
<frame.time_relative value="{$time_relative}"/>
<frame.number value="{$frame_number}"/>
<!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)-->
<pos_offset value="{$sctp_pos_offset}"/>
<ip.src value="{$ip_src}"/>
<ip.dst value="{$ip_dst}"/>
<sctp.data_sid value="{$sctp_data_sid}"/>
<sctp.srcport value="{$sctp_srcport}"/>
<sctp.dstport value="{$sctp_dstport}"/>
<!--sctp.data_sid value="{$sctp_data_sid}"/-->
<!--sctp.srcport value="{$sctp_srcport}"/-->
<!--sctp.dstport value="{$sctp_dstport}"/-->
<sctp.chunk_type_str value="{$sctp_chunk_type_str}"/>
<xsl:copy-of select="node()"/>
<xsl:copy-of select="$sctp_node"/>
</packet>
</xsl:when>
<!--xsl:when test="$sctp_chunk_type_str='COOKIE_ECHO'"> </xsl:when-->
......
......@@ -46,6 +46,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
......@@ -53,6 +54,7 @@
#include <libxml/DOCBparser.h>
#include <libxml/xinclude.h>
#include <libxml/catalog.h>
#include <libxml/xmlreader.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
......@@ -60,9 +62,13 @@
#include "assertions.h"
#include "play_scenario.h"
#include "s1ap_eNB.h"
//#include "s1ap_eNB.h"
#include "s1ap_common.h"
#include "s1ap_ies_defs.h"
#include "s1ap_eNB_decoder.h"
#include "intertask_interface.h"
#include "enb_config.h"
#include "log.h"
//------------------------------------------------------------------------------
#define ENB_CONFIG_MAX_XSLT_PARAMS 32
#define PLAY_SCENARIO 1
......@@ -73,8 +79,100 @@ char *g_openair_dir = NULL;
//------------------------------------------------------------------------------
extern Enb_properties_array_t enb_properties;
extern int xmlLoadExtDtdDefaultValue;
extern int asn_debug;
extern int asn1_xer_print;
//------------------------------------------------------------------------------
void test_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num);
int is_file_exists ( const char const * file_nameP, const char const *file_roleP);
int strip_extension( char *in_filename);
int split_path ( char * pathP, char *** resP);
void display_node ( xmlNodePtr node, unsigned int indent);
void display_tree ( xmlNodePtr node, unsigned int indent);
//-------------------------
void free_packet(test_packet_t* packet);
void free_scenario(test_scenario_t* scenario);
//-------------------------
void display_packet_sctp_init(const sctp_inithdr_t * const sctp);
void display_packet_sctp_initack(const sctp_initackhdr_t * const sctp);
void display_packet_sctp_data(const sctp_datahdr_t * const sctp);
void display_packet_sctp(const test_sctp_hdr_t * const sctp);
void display_packet_ip(const test_ip_hdr_t * const ip);
void display_packet(const test_packet_t * const packet);
void display_scenario(const test_scenario_t * const scenario);
//-------------------------
char * test_ip2ip_str(const test_ip_t * const ip);
int hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len);
sctp_cid_t chunk_type_str2cid(const xmlChar * const chunk_type_str);
const char * const chunk_type_cid2str(const sctp_cid_t chunk_type);
test_action_t action_str2test_action_t(const xmlChar * const action);
void ip_str2test_ip(const xmlChar * const ip_str, test_ip_t * const ip);
//-------------------------
int test_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p);
int test_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p);
int test_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p);
int test_s1ap_decode_pdu(s1ap_message *message, const uint8_t * const buffer,const uint32_t length);
void test_decode_s1ap(test_s1ap_t * const s1ap);
//-------------------------
void parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, test_s1ap_t * const s1ap);
void parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr);
void parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr);
void parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr);
void parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, test_sctp_hdr_t * const sctp_hdr);
test_packet_t* parse_xml_packet(xmlDocPtr doc, xmlNodePtr node);
//-------------------------
int play_scenario(test_scenario_t* scenario);
int generate_xml_scenario(
const char const * test_dir_name,
const char const * test_scenario_filename,
const char const * enb_config_filename,
char const * play_scenario_filename /* OUT PARAM*/);
//-----------------------------------------------------------------------------
void test_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num)
//-----------------------------------------------------------------------------
{
unsigned long octet_index = 0;
if (byte_stream == NULL) {
return;
}
fprintf(stdout, "+-----+-------------------------------------------------+\n");
fprintf(stdout, "| | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
fprintf(stdout, "+-----+-------------------------------------------------+\n");
for (octet_index = 0; octet_index < num; octet_index++) {
if ((octet_index % 16) == 0) {
if (octet_index != 0) {
fprintf(stdout, " |\n");
}
fprintf(stdout, " %04ld |", octet_index);
}
/*
* Print every single octet in hexadecimal form
*/
fprintf(stdout, " %02x", byte_stream[octet_index]);
/*
* Align newline and pipes according to the octets in groups of 2
*/
}
/*
* Append enough spaces and put final pipe
*/
unsigned char index;
for (index = octet_index; index < 16; ++index) {
fprintf(stdout, " ");
}
fprintf(stdout, " |\n");
}
//------------------------------------------------------------------------------
// test if file exist in current directory
......@@ -138,9 +236,14 @@ int split_path( char * pathP, char *** resP)
return n_spaces;
}
//------------------------------------------------------------------------------
void display_node(xmlNodePtr node) {
void display_node(xmlNodePtr node, unsigned int indent)
{
int i = 0;
if (node->type == XML_ELEMENT_NODE) {
xmlChar *path = xmlGetNodePath(node);
for (i=0; i<indent; i++) {
printf(" ");
}
if (node->children != NULL && node->children->type == XML_TEXT_NODE) {
xmlChar *content = xmlNodeGetContent(node);
printf("%s -> %s\n", path, content);
......@@ -151,13 +254,229 @@ void display_node(xmlNodePtr node) {
xmlFree(path);
}
}
/**
* print_element_names:
* @node: the initial xml node to consider.
* @indent: indentation level.
*
* Prints the names of the all the xml elements
* that are siblings or children of a given xml node.
*/
//------------------------------------------------------------------------------
void display_tree(xmlNodePtr node, unsigned int indent)
{
xmlNode *cur_node = NULL;
for (cur_node = node; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
display_node(cur_node, indent);
}
display_tree(cur_node->children, indent++);
}
}
//------------------------------------------------------------------------------
void free_packet(test_packet_t* packet)
{
if (packet) {
switch (packet->sctp_hdr.chunk_type) {
case SCTP_CID_DATA:
free_pointer(packet->sctp_hdr.u.data_hdr.payload.binary_stream);
break;
default:
;
}
free_pointer(packet);
}
}
//------------------------------------------------------------------------------
void free_scenario(test_scenario_t* scenario)
{
//TODO
test_packet_t *packet = NULL;
test_packet_t *next_packet = NULL;
if (scenario) {
packet = scenario->list_packet;
while (packet) {
next_packet = packet->next;
free_packet(packet);
packet = next_packet->next;
}
free_pointer(scenario);
}
}
//------------------------------------------------------------------------------
void display_packet_sctp_init(const sctp_inithdr_t * const sctp)
{
if (sctp) {
fprintf(stdout, "\t\tSCTP.init.init_tag : %u\n", sctp->init_tag);
fprintf(stdout, "\t\tSCTP.init.a_rwnd : %u\n", sctp->a_rwnd);
fprintf(stdout, "\t\tSCTP.init.num_inbound_streams : %u\n", sctp->num_inbound_streams);
fprintf(stdout, "\t\tSCTP.init.num_outbound_streams : %u\n", sctp->num_outbound_streams);
fprintf(stdout, "\t\tSCTP.init.initial_tsn : %u\n", sctp->initial_tsn);
}
}
//------------------------------------------------------------------------------
sctp_cid_t chunk_type_str2cid(xmlChar *chunk_type_str)
void display_packet_sctp_initack(const sctp_initackhdr_t * const sctp)
{
if (sctp) {
fprintf(stdout, "\t\tSCTP.initack.init_tag : %u\n", sctp->init_tag);
fprintf(stdout, "\t\tSCTP.initack.a_rwnd : %u\n", sctp->a_rwnd);
fprintf(stdout, "\t\tSCTP.initack.num_inbound_streams : %u\n", sctp->num_inbound_streams);
fprintf(stdout, "\t\tSCTP.initack.num_outbound_streams : %u\n", sctp->num_outbound_streams);
fprintf(stdout, "\t\tSCTP.initack.initial_tsn : %u\n", sctp->initial_tsn);
}
}
//------------------------------------------------------------------------------
void display_packet_sctp_data(const sctp_datahdr_t * const sctp)
{
if (sctp) {
fprintf(stdout, "\t\tSCTP.data.tsn : %u\n", sctp->tsn);
fprintf(stdout, "\t\tSCTP.data.stream : %u\n", sctp->stream);
fprintf(stdout, "\t\tSCTP.data.ssn : %u\n", sctp->ssn);
fprintf(stdout, "\t\tSCTP.data.ppid : %u\n", sctp->ppid);
//fprintf(stdout, "\t\tSCTP.data.pdu_type : %u\n", sctp->payload.pdu_type);
//fprintf(stdout, "\t\tSCTP.data.procedure_code : %u\n", sctp->payload.procedure_code);
fprintf(stdout, "\t\tSCTP.data.binary_stream_allocated_size : %u\n", sctp->payload.binary_stream_allocated_size);
if (NULL != sctp->payload.binary_stream) {
fprintf(stdout, "\t\tSCTP.data.binary_stream :\n");
test_print_hex_octets(sctp->payload.binary_stream, sctp->payload.binary_stream_allocated_size);
} else {
fprintf(stdout, "\t\tSCTP.data.binary_stream : NULL\n");
}
}
}
//------------------------------------------------------------------------------
void display_packet_sctp(const test_sctp_hdr_t * const sctp)
{
if (sctp) {
fprintf(stdout, "\t\tSCTP.src_port : %u\n", sctp->src_port);
fprintf(stdout, "\t\tSCTP.dst_port : %u\n", sctp->dst_port);
fprintf(stdout, "\t\tSCTP.chunk_type : %s\n", chunk_type_cid2str(sctp->chunk_type));
switch (sctp->chunk_type) {
case SCTP_CID_DATA:
display_packet_sctp_data(&sctp->u.data_hdr);
break;
case SCTP_CID_INIT:
display_packet_sctp_initack(&sctp->u.init_hdr);
break;
case SCTP_CID_INIT_ACK:
display_packet_sctp_initack(&sctp->u.init_ack_hdr);
break;
default:
;
}
}
}
//------------------------------------------------------------------------------
void display_packet_ip(const test_ip_hdr_t * const ip)
{
if (ip) {
fprintf(stdout, "\t\tSource address : %s\n", test_ip2ip_str(&ip->src));
fprintf(stdout, "\t\tDestination address : %s\n", test_ip2ip_str(&ip->dst));
}
}
//------------------------------------------------------------------------------
void display_packet(const test_packet_t * const packet)
{
if (packet) {
fprintf(stdout, "\tPacket:\tnum %u | original frame number %u \n", packet->packet_number, packet->original_frame_number);
fprintf(stdout, "\tPacket:\ttime relative to 1st packet %ld.%06lu\n",
packet->time_relative_to_first_packet.tv_sec, packet->time_relative_to_first_packet.tv_usec);
fprintf(stdout, "\tPacket:\ttime relative to last tx packet %ld.%06lu\n",
packet->time_relative_to_last_sent_packet.tv_sec, packet->time_relative_to_last_sent_packet.tv_usec);
fprintf(stdout, "\tPacket:\ttime relative to last_received packet %ld.%06lu\n",
packet->time_relative_to_last_received_packet.tv_sec, packet->time_relative_to_last_received_packet.tv_usec);
switch(packet->action) {
case ACTION_S1C_SEND:
fprintf(stdout, "\tPacket:\tAction SEND\n");
break;
case ACTION_S1C_RECEIVE:
fprintf(stdout, "\tPacket:\tAction RECEIVE\n");
break;
default:
fprintf(stdout, "\tPacket:\tAction UNKNOWN\n");
}
display_packet_ip(&packet->ip_hdr);
display_packet_sctp(&packet->sctp_hdr);
}
}
//------------------------------------------------------------------------------
void display_scenario(const test_scenario_t * const scenario)
{
test_packet_t *packet = NULL;
if (scenario) {
fprintf(stdout, "Scenario: %s\n", (scenario->name != NULL) ? (char*)scenario->name:"UNKNOWN NAME");
packet = scenario->list_packet;
while (packet) {
display_packet(packet);
packet = packet->next;
}
}
}
//------------------------------------------------------------------------------
char * test_ip2ip_str(const test_ip_t * const ip)
{
static char str[INET6_ADDRSTRLEN];
sprintf(str, "ERROR");
switch (ip->address_family) {
case AF_INET6:
inet_ntop(AF_INET6, &(ip->address.ipv6), str, INET6_ADDRSTRLEN);
break;
case AF_INET:
inet_ntop(AF_INET, &(ip->address.ipv4), str, INET_ADDRSTRLEN);
break;
default:
;
}
return str;
}
//------------------------------------------------------------------------------
//convert hexstring to len bytes of data
//returns 0 on success, negative on error
//data is a buffer of at least len bytes
//hexstring is upper or lower case hexadecimal, NOT prepended with "0x"
int hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len)
{
unsigned const char *pos = hexstring;
char *endptr = NULL;
size_t count = 0;
fprintf(stdout, "%s(%s,%d)\n", __FUNCTION__, hexstring, len);
if ((len > 1) && (strlen((const char*)hexstring) % 2)) {
//or hexstring has an odd length
return -3;
}
if (len == 1) {
char buf[5] = {'0', 'x', 0, pos[0], '\0'};
data[0] = strtol(buf, &endptr, 16);
/* Check for various possible errors */
AssertFatal ((errno == 0) || (data[0] != 0), "ERROR %s() strtol: %s\n", __FUNCTION__, strerror(errno));
AssertFatal (endptr != buf, "ERROR %s() No digits were found\n", __FUNCTION__);
return 0;
}
for(count = 0; count < len/2; count++) {
char buf[5] = {'0', 'x', pos[0], pos[1], 0};
data[count] = strtol(buf, &endptr, 16);
pos += 2 * sizeof(char);
AssertFatal (endptr[0] == '\0', "ERROR %s() non-hexadecimal character encountered buf %p endptr %p buf %s count %d pos %p\n", __FUNCTION__, buf, endptr, buf, count, pos);
AssertFatal (endptr != buf, "ERROR %s() No digits were found\n", __FUNCTION__);
}
return 0;
}
//------------------------------------------------------------------------------
sctp_cid_t chunk_type_str2cid(const xmlChar * const chunk_type_str)
{
if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"DATA"))) { return SCTP_CID_DATA;}
if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"INIT"))) { return SCTP_CID_INIT;}
......@@ -178,43 +497,612 @@ sctp_cid_t chunk_type_str2cid(xmlChar *chunk_type_str)
if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"FWD_TSN"))) { return SCTP_CID_FWD_TSN;}
if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ASCONF"))) { return SCTP_CID_ASCONF;}
if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ASCONF_ACK"))) { return SCTP_CID_ASCONF_ACK;}
fprintf(stderr, "ERROR: Could not convert: %s\n", chunk_type_str);
exit(-1);
AssertFatal (0, "ERROR: %s() cannot convert: %s\n", __FUNCTION__, chunk_type_str);
}
//------------------------------------------------------------------------------
test_packet_t* parse_xml_packet(xmlNodePtr node) {
const char * const chunk_type_cid2str(const sctp_cid_t chunk_type)
{
switch (chunk_type) {
case SCTP_CID_DATA: return "DATA"; break;
case SCTP_CID_INIT: return "INIT"; break;
case SCTP_CID_INIT_ACK: return "INIT_ACK"; break;
case SCTP_CID_SACK: return "SACK"; break;
case SCTP_CID_HEARTBEAT: return "HEARTBEAT"; break;
case SCTP_CID_HEARTBEAT_ACK: return "HEARTBEAT_ACK"; break;
case SCTP_CID_ABORT: return "ABORT"; break;
case SCTP_CID_SHUTDOWN: return "SHUTDOWN"; break;
case SCTP_CID_SHUTDOWN_ACK: return "SHUTDOWN_ACK"; break;
case SCTP_CID_ERROR: return "ERROR"; break;
case SCTP_CID_COOKIE_ECHO: return "COOKIE_ECHO"; break;
case SCTP_CID_COOKIE_ACK: return "COOKIE_ACK"; break;
case SCTP_CID_ECN_ECNE: return "ECN_ECNE"; break;
case SCTP_CID_ECN_CWR: return "ECN_CWR"; break;
case SCTP_CID_SHUTDOWN_COMPLETE: return "SHUTDOWN_COMPLETE"; break;
case SCTP_CID_AUTH: return "AUTH"; break;
case SCTP_CID_FWD_TSN: return "FWD_TSN"; break;
case SCTP_CID_ASCONF: return "ASCONF"; break;
case SCTP_CID_ASCONF_ACK: return "ASCONF_ACK"; break;
default:
AssertFatal (0, "ERROR %s(): Unknown chunk_type %d!\n", __FUNCTION__, chunk_type);
}
}
//------------------------------------------------------------------------------
test_action_t action_str2test_action_t(const xmlChar * const action)
{
if ((!xmlStrcmp(action, (const xmlChar *)"SEND"))) { return ACTION_S1C_SEND;}
if ((!xmlStrcmp(action, (const xmlChar *)"RECEIVE"))) { return ACTION_S1C_RECEIVE;}
AssertFatal (0, "ERROR: %s cannot convert: %s\n", __FUNCTION__, action);
//if (NULL == action) {return ACTION_S1C_NULL;}
}
//------------------------------------------------------------------------------
void ip_str2test_ip(const xmlChar * const ip_str, test_ip_t * const ip)
{
AssertFatal (NULL != ip_str, "ERROR %s() Cannot convert null string to ip address!\n", __FUNCTION__);
AssertFatal (NULL != ip, "ERROR %s() out parameter pointer is NULL!\n", __FUNCTION__);
// store this IP address in sa:
if (inet_pton(AF_INET, (const char*)ip_str, (void*)&(ip->address.ipv4)) > 0) {
ip->address_family = AF_INET;
} else if (inet_pton(AF_INET6, (const char*)ip_str, (void*)&(ip->address.ipv6)) > 0) {
ip->address_family = AF_INET6;
} else {
ip->address_family = AF_UNSPEC;
AssertFatal (0, "ERROR %s() Could not parse ip address %s!\n", __FUNCTION__, ip_str);
}
}
//------------------------------------------------------------------------------
int test_s1ap_decode_initiating_message(s1ap_message *message,
S1ap_InitiatingMessage_t *initiating_p)
{
int ret = -1;
DevAssert(initiating_p != NULL);
message->procedureCode = initiating_p->procedureCode;
message->criticality = initiating_p->criticality;
switch(initiating_p->procedureCode) {
case S1ap_ProcedureCode_id_downlinkNASTransport:
ret = s1ap_decode_s1ap_downlinknastransporties(
&message->msg.s1ap_DownlinkNASTransportIEs,
&initiating_p->value);
break;
case S1ap_ProcedureCode_id_InitialContextSetup:
ret = s1ap_decode_s1ap_initialcontextsetuprequesties(
&message->msg.s1ap_InitialContextSetupRequestIEs, &initiating_p->value);
break;
case S1ap_ProcedureCode_id_UEContextRelease:
ret = s1ap_decode_s1ap_uecontextreleasecommandies(
&message->msg.s1ap_UEContextReleaseCommandIEs, &initiating_p->value);
break;
case S1ap_ProcedureCode_id_Paging:
ret = s1ap_decode_s1ap_pagingies(
&message->msg.s1ap_PagingIEs, &initiating_p->value);
break;
case S1ap_ProcedureCode_id_uplinkNASTransport: {
ret = s1ap_decode_s1ap_uplinknastransporties (&message->msg.s1ap_UplinkNASTransportIEs, &initiating_p->value);
}
break;
case S1ap_ProcedureCode_id_S1Setup: {
ret = s1ap_decode_s1ap_s1setuprequesties (&message->msg.s1ap_S1SetupRequestIEs, &initiating_p->value);
}
break;
case S1ap_ProcedureCode_id_initialUEMessage: {
ret = s1ap_decode_s1ap_initialuemessageies (&message->msg.s1ap_InitialUEMessageIEs, &initiating_p->value);
}
break;
case S1ap_ProcedureCode_id_UEContextReleaseRequest: {
ret = s1ap_decode_s1ap_uecontextreleaserequesties (&message->msg.s1ap_UEContextReleaseRequestIEs, &initiating_p->value);
}
break;
case S1ap_ProcedureCode_id_UECapabilityInfoIndication: {
ret = s1ap_decode_s1ap_uecapabilityinfoindicationies (&message->msg.s1ap_UECapabilityInfoIndicationIEs, &initiating_p->value);
}
break;
case S1ap_ProcedureCode_id_NASNonDeliveryIndication: {
ret = s1ap_decode_s1ap_nasnondeliveryindication_ies (&message->msg.s1ap_NASNonDeliveryIndication_IEs, &initiating_p->value);
}
break;
default:
AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n",
(int)initiating_p->procedureCode);
return -1;
}
return ret;
}
//------------------------------------------------------------------------------
int test_s1ap_decode_successful_outcome(s1ap_message *message,
S1ap_SuccessfulOutcome_t *successfullOutcome_p)
{
int ret = -1;
DevAssert(successfullOutcome_p != NULL);
message->procedureCode = successfullOutcome_p->procedureCode;
message->criticality = successfullOutcome_p->criticality;
switch(successfullOutcome_p->procedureCode) {
case S1ap_ProcedureCode_id_S1Setup:
ret = s1ap_decode_s1ap_s1setupresponseies(
&message->msg.s1ap_S1SetupResponseIEs, &successfullOutcome_p->value);
break;
case S1ap_ProcedureCode_id_InitialContextSetup: {
ret = s1ap_decode_s1ap_initialcontextsetupresponseies (&message->msg.s1ap_InitialContextSetupResponseIEs, &successfullOutcome_p->value);
}
break;
case S1ap_ProcedureCode_id_UEContextRelease: {
ret = s1ap_decode_s1ap_uecontextreleasecompleteies (&message->msg.s1ap_UEContextReleaseCompleteIEs, &successfullOutcome_p->value);
}
break;
default:
AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n",
(int)successfullOutcome_p->procedureCode);
return -1;
}
return ret;
}
//------------------------------------------------------------------------------
int test_s1ap_decode_unsuccessful_outcome(s1ap_message *message,
S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p)
{
int ret = -1;
DevAssert(unSuccessfullOutcome_p != NULL);
message->procedureCode = unSuccessfullOutcome_p->procedureCode;
message->criticality = unSuccessfullOutcome_p->criticality;
switch(unSuccessfullOutcome_p->procedureCode) {
case S1ap_ProcedureCode_id_S1Setup:
return s1ap_decode_s1ap_s1setupfailureies(
&message->msg.s1ap_S1SetupFailureIEs, &unSuccessfullOutcome_p->value);
case S1ap_ProcedureCode_id_InitialContextSetup: {
ret = s1ap_decode_s1ap_initialcontextsetupfailureies (&message->msg.s1ap_InitialContextSetupFailureIEs, &unSuccessfullOutcome_p->value);
}
break;
default:
AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n",
(int)unSuccessfullOutcome_p->procedureCode);
break;
}
return ret;
}
//------------------------------------------------------------------------------
int test_s1ap_decode_pdu(s1ap_message *message, const uint8_t * const buffer,
const uint32_t length)
{
S1AP_PDU_t pdu;
S1AP_PDU_t *pdu_p = &pdu;
asn_dec_rval_t dec_ret;
DevAssert(buffer != NULL);
memset((void *)pdu_p, 0, sizeof(S1AP_PDU_t));
dec_ret = aper_decode(NULL,
&asn_DEF_S1AP_PDU,
(void **)&pdu_p,
buffer,
length,
0,
0);
if (dec_ret.code != RC_OK) {
S1AP_ERROR("Failed to decode pdu\n");
return -1;
}
message->direction = pdu_p->present;
switch(pdu_p->present) {
case S1AP_PDU_PR_initiatingMessage:
return test_s1ap_decode_initiating_message(message,
&pdu_p->choice.initiatingMessage);
case S1AP_PDU_PR_successfulOutcome:
return test_s1ap_decode_successful_outcome(message,
&pdu_p->choice.successfulOutcome);
case S1AP_PDU_PR_unsuccessfulOutcome:
return test_s1ap_decode_unsuccessful_outcome(message,
&pdu_p->choice.unsuccessfulOutcome);
default:
AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)pdu_p->present);
break;
}
return -1;
}
//------------------------------------------------------------------------------
void test_decode_s1ap(test_s1ap_t * const s1ap)
{
if (NULL != s1ap) {
if (test_s1ap_decode_pdu(&s1ap->message, s1ap->binary_stream, s1ap->binary_stream_allocated_size) < 0) {
AssertFatal (0, "ERROR %s() Cannot decode S1AP message!\n", __FUNCTION__);
}
}
}
//------------------------------------------------------------------------------
void parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, test_s1ap_t * const s1ap)
{
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
xmlChar *xml_char2 = NULL;
unsigned int size = 0;
int rc = 0;
unsigned int go_deeper_in_tree = 1;
if ((NULL != s1ap_node) && (NULL != s1ap)) {
for (cur_node = (xmlNode *)s1ap_node; cur_node; cur_node = cur_node->next) {
go_deeper_in_tree = 1;
if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"field"))) {
// do not get hidden fields
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"hide");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"yes"))) {
xmlFree(xml_char);
return;
}
xmlFree(xml_char);
}
// first get size
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size");
if (NULL != xml_char) {
size = strtoul((const char *)xml_char, NULL, 0);
xmlFree(xml_char);
// second: try to get value (always hex)
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
if (NULL != xml_char) {
xml_char2 = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name");
fprintf(stdout, "s1ap %p field %s size %d value %s\n",s1ap, xml_char2, size, xml_char);
xmlFree(xml_char2);
// if success to get value, do not parse children
//AssertFatal ((xmlStrlen(xml_char) == size), "ERROR %s() mismatch in size %d and strlen %d\n", __FUNCTION__, size, xmlStrlen(xml_char));
//if (xmlStrlen(xml_char) == size) {
AssertFatal ((s1ap->binary_stream_pos+xmlStrlen(xml_char)/2) <= s1ap->binary_stream_allocated_size,
"ERROR %s() in buffer size: binary_stream_pos %d xmlStrlen(xml_char)/2=%d\n", __FUNCTION__, s1ap->binary_stream_pos, xmlStrlen(xml_char)/2);
rc = hex2data( &s1ap->binary_stream[s1ap->binary_stream_pos], xml_char, xmlStrlen(xml_char));
s1ap->binary_stream_pos += xmlStrlen(xml_char)/2;
display_node(cur_node, 0);
AssertFatal (rc >= 0, "ERROR %s() in converting hex string %s len %d size %d rc %d\n", __FUNCTION__, xml_char, xmlStrlen(xml_char), size, rc);
go_deeper_in_tree = 0;
//}
xmlFree(xml_char);
}
}
}
if (0 < go_deeper_in_tree) {
parse_s1ap(doc, cur_node->children, s1ap);
}
}
}
}
//------------------------------------------------------------------------------
void parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr)
{
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
xmlChar *xml_char2 = NULL;
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_payload_proto_id"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->ppid = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_sid"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->stream = strtoul((const char *)xml_char2, NULL, 16);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_tsn"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->tsn = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_ssn"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->ssn = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
}
xmlFree(xml_char);
}
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
parse_sctp_data_chunk(doc, cur_node, sctp_hdr);
}
}
}
//------------------------------------------------------------------------------
void parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr)
{
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
xmlChar *xml_char2 = NULL;
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_out_streams"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_in_streams"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_credit"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initial_tsn"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initiate_tag"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16);
xmlFree(xml_char2);
}
}
xmlFree(xml_char);
}
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
parse_sctp_init_chunk(doc, cur_node, sctp_hdr);
}
}
}
//------------------------------------------------------------------------------
void parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr)
{
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
xmlChar *xml_char2 = NULL;
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_out_streams"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_in_streams"))) {
xml_char2 = xmlGetProp((xmlNode *)(xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_credit"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initial_tsn"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initiate_tag"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
if (NULL != xml_char2) {
sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16);
xmlFree(xml_char2);
}
}
xmlFree(xml_char);
}
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
parse_sctp_init_ack_chunk(doc, cur_node, sctp_hdr);
}
}
}
//------------------------------------------------------------------------------
void parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, test_sctp_hdr_t * const sctp_hdr)
{
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
xmlChar *xml_char2 = NULL;
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
if ((!xmlStrcmp(sctp_node->name, (const xmlChar *)"proto"))) {
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"s1ap"))) {
xmlFree(xml_char);
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"size");
if (NULL != xml_char2) {
sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size = strtoul((const char *)xml_char2, NULL, 0);
sctp_hdr->u.data_hdr.payload.binary_stream = calloc(1, sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size);
xmlFree(xml_char2);
}
parse_s1ap(doc, sctp_node, &sctp_hdr->u.data_hdr.payload);
test_decode_s1ap(&sctp_hdr->u.data_hdr.payload);
return;
}
xmlFree(xml_char);
}
}
//if ((cur_node->type == XML_ATTRIBUTE_NODE) || (cur_node->type == XML_ELEMENT_NODE)) {
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.srcport"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->src_port = strtoul((const char *)xml_char2, NULL, 16);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.dstport"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->dst_port = strtoul((const char *)xml_char2, NULL, 16);
xmlFree(xml_char2);
}
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.chunk_type"))) {
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
if (NULL != xml_char2) {
sctp_hdr->chunk_type = strtoul((const char *)xml_char2, NULL, 0);
xmlFree(xml_char2);
switch (sctp_hdr->chunk_type) {
case SCTP_CID_DATA:
parse_sctp_data_chunk(doc, sctp_node->parent, &sctp_hdr->u.data_hdr);
break;
case SCTP_CID_INIT:
parse_sctp_init_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_hdr);
break;
case SCTP_CID_INIT_ACK:
parse_sctp_init_ack_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_ack_hdr);
break;
default:
;
}
}
}
}
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
parse_sctp(doc, cur_node, sctp_hdr);
}
}
}
//------------------------------------------------------------------------------
test_packet_t* parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
test_packet_t *packet = NULL;
xmlNode *cur_node = NULL;
xmlChar *xml_char = NULL;
float afloat = (float)0.0;
static struct timeval initial_time = { .tv_sec = 0, .tv_usec = 0 };
static struct timeval relative_last_sent_packet = { .tv_sec = 0, .tv_usec = 0 };
static struct timeval relative_last_received_packet = { .tv_sec = 0, .tv_usec = 0 };
static char first_packet = 1;
static char first_sent_packet = 1;
static char first_received_packet = 1;
static unsigned int packet_number = 1;
if (NULL != node) {
packet = calloc(1, sizeof(*packet));
xml_char = xmlGetProp(node, (const xmlChar *)"action");
packet->action = action_str2test_action_t(xml_char);
xmlFree(xml_char);
packet->packet_number = packet_number++;
for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
printf("node type: Element, name: %s\n", cur_node->name);
//if (cur_node->type == XML_ELEMENT_NODE) {
if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.time_relative"))) {
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
afloat = atof((const char*)xml_char);
xmlFree(xml_char);
packet->time_relative_to_first_packet.tv_sec = (int)afloat;
packet->time_relative_to_first_packet.tv_usec = (int)((afloat - packet->time_relative_to_first_packet.tv_sec)*1000000);
if (first_packet > 0) {
initial_time = packet->time_relative_to_first_packet;
packet->time_relative_to_first_packet.tv_sec = 0;
packet->time_relative_to_first_packet.tv_usec = 0;
first_packet = 0;
} else {
timersub(&packet->time_relative_to_first_packet, &initial_time,
&packet->time_relative_to_first_packet);
}
if (packet->action == ACTION_S1C_SEND) {
if (first_sent_packet > 0) {
relative_last_sent_packet = packet->time_relative_to_first_packet;
packet->time_relative_to_last_sent_packet.tv_sec = 0;
packet->time_relative_to_last_sent_packet.tv_usec = 0;
first_sent_packet = 0;
} else {
timersub(&packet->time_relative_to_first_packet, &relative_last_sent_packet,
&packet->time_relative_to_last_sent_packet);
relative_last_sent_packet = packet->time_relative_to_first_packet;
}
} else if (packet->action == ACTION_S1C_RECEIVE) {
if (first_received_packet > 0) {
relative_last_received_packet.tv_sec = packet->time_relative_to_first_packet.tv_sec;
relative_last_received_packet.tv_usec = packet->time_relative_to_first_packet.tv_usec;
packet->time_relative_to_last_received_packet.tv_sec = 0;
packet->time_relative_to_last_received_packet.tv_usec = 0;
first_received_packet = 0;
} else {
timersub(&packet->time_relative_to_first_packet, &relative_last_received_packet,
&packet->time_relative_to_last_received_packet);
relative_last_received_packet = packet->time_relative_to_first_packet;
}
}
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.number"))) {
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
packet->original_frame_number = strtoul((const char *)xml_char, NULL, 0);
xmlFree(xml_char);
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.src"))) {
xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
ip_str2test_ip(xml_char, &packet->ip_hdr.src);
xmlFree(xml_char);
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.dst"))) {
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"sctp.chunk_type_str"))) {
xml_char = xmlGetProp(cur_node, (const xmlChar *)"value");
packet->sctp_hdr.chunk_type = chunk_type_str2cid(xml_char);
fprintf(stdout, "chunk_type_str2cid: %s\n", xml_char);
xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
ip_str2test_ip(xml_char, &packet->ip_hdr.dst);
xmlFree(xml_char);
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"proto"))) {
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name");
if (NULL != xml_char) {
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp"))) {
parse_sctp(doc, cur_node, &packet->sctp_hdr);
}
xmlFree(xml_char);
}
}
//}
}
}
return packet;
}
//------------------------------------------------------------------------------
int play_scenario(test_scenario_t* scenario) {
//TODO
display_scenario(scenario);
return 0;
}
//------------------------------------------------------------------------------
test_scenario_t* generate_scenario(
const char const * play_scenario_filename )
const char * const play_scenario_filename )
{
xmlDocPtr doc = NULL;
xmlNodePtr root = NULL;
......@@ -229,6 +1117,7 @@ test_scenario_t* generate_scenario(
AssertFatal (0, "Could not parse scenario xml file %s!\n", play_scenario_filename);
} else {
fprintf(stdout, "Test scenario file to play: %s\n", play_scenario_filename);
//xmlDebugDumpDocument(NULL, doc);
}
// Get root
......@@ -242,13 +1131,13 @@ test_scenario_t* generate_scenario(
next_packet = &scenario->list_packet;
for (node = root->children; node != NULL; node = node->next) {
if ((!xmlStrcmp(node->name, (const xmlChar *)"packet"))) {
packet = parse_xml_packet(node);
packet = parse_xml_packet(doc, node);
if (NULL != packet) {
*next_packet = packet;
next_packet = &packet->next;
} else {
fprintf(stdout, "WARNING omitted packet:\n");
display_node(node);
display_node(node, 0);
}
}
}
......@@ -285,7 +1174,7 @@ int generate_xml_scenario(
if (getcwd(astring, sizeof(astring)) != NULL) {
fprintf(stdout, "working in %s directory\n", astring);
} else {
perror("getcwd() error");
perror("getcwd() ERROR");
exit(1);
}
......@@ -332,22 +1221,22 @@ int generate_xml_scenario(
if (NULL != res) {
sprintf(play_scenario_filename,"%s",test_scenario_filename);
if (strip_extension(play_scenario_filename) > 0) {
strcat(play_scenario_filename, ".tsml");
strcat((char *)play_scenario_filename, ".tsml");
play_scenario_file = fopen( play_scenario_filename, "w+");
if (NULL != play_scenario_file) {
xsltSaveResultToFile(play_scenario_file, res, cur);
fclose(play_scenario_file);
fprintf(stdout, "Wrote test scenario to %s\n", play_scenario_filename);
} else {
fprintf(stderr, "Error in fopen(%s)\n", play_scenario_filename);
fprintf(stderr, "ERROR in fopen(%s)\n", play_scenario_filename);
ret = -1;
}
} else {
fprintf(stderr, "Error in strip_extension()\n");
fprintf(stderr, "ERROR in strip_extension()\n");
ret = -1;
}
} else {
fprintf(stderr, "Error in xsltApplyStylesheet()\n");
fprintf(stderr, "ERROR in xsltApplyStylesheet()\n");
ret = -1;
}
xsltFreeStylesheet(cur);
......@@ -466,23 +1355,23 @@ config_parse_opt_line (
exit(1);
}
if (chdir(*test_dir_name) != 0) {
fprintf(stderr, "Error: chdir %s returned %s\n", *test_dir_name, strerror(errno));
fprintf(stderr, "ERROR: chdir %s returned %s\n", *test_dir_name, strerror(errno));
exit(1);
}
if (rv & PLAY_SCENARIO) {
if (NULL == *enb_config_file_name) {
fprintf(stderr, "Error: please provide the original eNB config file name that should be in %s\n", *test_dir_name);
fprintf(stderr, "ERROR: please provide the original eNB config file name that should be in %s\n", *test_dir_name);
}
if (is_file_exists(*enb_config_file_name, "eNB config file") != GS_IS_FILE) {
fprintf(stderr, "Error: original eNB config file name %s is not found in dir %s\n", *enb_config_file_name, *test_dir_name);
fprintf(stderr, "ERROR: original eNB config file name %s is not found in dir %s\n", *enb_config_file_name, *test_dir_name);
}
enb_properties_p = enb_config_init(*enb_config_file_name);
if (NULL == *scenario_file_name) {
fprintf(stderr, "Error: please provide the scenario file name that should be in %s\n", *test_dir_name);
fprintf(stderr, "ERROR: please provide the scenario file name that should be in %s\n", *test_dir_name);
}
if (is_file_exists(*scenario_file_name, "Scenario file") != GS_IS_FILE) {
fprintf(stderr, "Error: Scenario file name %s is not found in dir %s\n", *scenario_file_name, *test_dir_name);
fprintf(stderr, "ERROR: Scenario file name %s is not found in dir %s\n", *scenario_file_name, *test_dir_name);
}
}
return rv;
......@@ -503,21 +1392,29 @@ int main( int argc, char **argv )
memset(play_scenario_filename, 0, sizeof(play_scenario_filename));
g_openair_dir = getenv("OPENAIR_DIR");
if (NULL == g_openair_dir) {
fprintf(stderr, "Error: Could not get OPENAIR_DIR environment variable\n");
fprintf(stderr, "ERROR: Could not get OPENAIR_DIR environment variable\n");
exit(1);
}
// logging
logInit();
set_comp_log(S1AP, LOG_TRACE, LOG_MED,1);
set_comp_log(SCTP, LOG_TRACE, LOG_MED,1);
asn_debug = 1;
asn1_xer_print = 1;
//parameters
actions = config_parse_opt_line (argc, argv, &test_dir_name, &scenario_file_name, &enb_config_file_name); //Command-line options
if (actions & PLAY_SCENARIO) {
if (generate_xml_scenario(test_dir_name, scenario_file_name,enb_config_file_name, play_scenario_filename) == 0) {
if (NULL != (scenario = generate_scenario(play_scenario_filename))) {
ret = play_scenario(scenario);
} else {
fprintf(stderr, "Error: Could not generate scenario from tsml file\n");
fprintf(stderr, "ERROR: Could not generate scenario from tsml file\n");
ret = -1;
}
} else {
fprintf(stderr, "Error: Could not generate tsml scenario from xml file\n");
fprintf(stderr, "ERROR: Could not generate tsml scenario from xml file\n");
ret = -1;
}
free_pointer(test_dir_name);
......
......@@ -28,18 +28,22 @@
*******************************************************************************/
/*
generate_scenario.h
play_scenario.h
-------------------
AUTHOR : Lionel GAUTHIER
COMPANY : EURECOM
EMAIL : Lionel.Gauthier@eurecom.fr
*/
#ifndef GENERATE_SCENARIO_H_
#define GENERATE_SCENARIO_H_
#ifndef PLAY_SCENARIO_H_
#define PLAY_SCENARIO_H_
# include <time.h>
# include <stdint.h>
#include <libxml/tree.h>
# include <libxml/tree.h>
# include <netinet/in.h>
#include "s1ap_ies_defs.h"
/** @defgroup _enb_app ENB APP
* @ingroup _oai2
......@@ -83,13 +87,32 @@ typedef enum {
SCTP_CID_ASCONF_ACK = 0x80,
} sctp_cid_t; /* enum */
typedef enum {
TEST_S1AP_PDU_TYPE_START = 0,
TEST_S1AP_PDU_TYPE_UNKNOWN = TEST_S1AP_PDU_TYPE_START,
TEST_S1AP_PDU_TYPE_INITIATING,
TEST_S1AP_PDU_TYPE_SUCCESSFUL_OUTCOME,
TEST_S1AP_PDU_TYPE_UNSUCCESSFUL_OUTCOME,
TEST_S1AP_PDU_TYPE_END
} test_s1ap_pdu_type_t;
typedef struct test_s1ap_s {
//test_s1ap_pdu_type_t pdu_type;
uint16_t binary_stream_pos;
uint16_t binary_stream_allocated_size;
uint8_t *binary_stream;
s1ap_message message;
} test_s1ap_t;
// from kernel source file 3.19/include/linux/sctp.h, Big Endians
typedef struct sctp_datahdr_s {
uint32_t tsn;
uint16_t stream;
uint16_t ssn;
uint32_t ppid;
uint8_t payload[0];
test_s1ap_t payload;
} sctp_datahdr_t;
// from kernel source file 3.19/include/linux/sctp.h, Big Endians
......@@ -115,15 +138,28 @@ typedef struct test_sctp_hdr_s {
} u;
} test_sctp_hdr_t;
typedef struct test_ip_s {
unsigned int address_family; // AF_INET, AF_INET6
union {
struct in6_addr ipv6;
in_addr_t ipv4;
}address;
}test_ip_t;
typedef struct test_ip_hdr_s {
test_ip_t src;
test_ip_t dst;
} test_ip_hdr_t;
typedef struct test_packet_s {
test_action_t action;
struct timeval time_relative_to_first_packet;
struct timeval time_relative_to_last_packet;
struct timeval time_relative_to_last_sent_packet;
struct timeval time_relative_to_last_received_packet;
unsigned int original_frame_number;
unsigned int packet_number;
test_ip_hdr_t ip_hdr;
test_sctp_hdr_t sctp_hdr;
uint16_t s1ap_byte_stream_count;
uint8_t *s1ap_byte_stream;
xmlNodePtr *s1ap_node;
struct test_packet_s *next;
}test_packet_t;
......
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