ASNで1コンパイルツールasn 1 c生成LTE-RRCメッセージ復号プログラム

5575 ワード

最近、iPhoneからLTE-RRC通信パケットを入手するには、LTE-RRC通信パケットを詳細に復号する必要がある.RRCプロトコルはすべてASNです.1文法的に記述され、PER符号化されている.ASNで1記載のプロトコルの復号化作業は、比較的煩雑である.かつて3 Gシグナリングシステムプロジェクトで、ASNを開発したことがある.1文法はC++文法の符号化規範に変換されるが、まだ複雑で、新人がこの符号化規範に基づいてプロトコル復号を実現するのは比較的難しく、メンテナンスが困難である.asnを利用できることが望ましい.1文法コンパイラ、LTE-RRCプロトコルのasn.1ファイルを記述し、対応するC/C++ファイルにコンパイルし、C/C++コンパイラでLTE-RRCプロトコルコーデックプログラムをコンパイルする.
asn 1 cはこのようなオープンソースの文法コンパイルツールである.アドレスはクリックしてリンクを開きます.最新版0.9.24を取り出してLTE-RRC復号プログラムを生成する.手順は次のとおりです.
1、asn 1 cソースコードをダウンロードし、asn 1 cをコンパイルする:
asn 1をダウンロードします.1ソース:wgethttp://lionet.info/soft/asn1c-0.9.24.tar.gz
解凍:tar xvf asn 1 c-0.9.24.tar.gz
ソースディレクトリへ:cd asn 1 c-0.9.24
構成:./configure
コンパイル:make
インストール:make install
asn 1 cツールがインストールされており、asn 1 c-hを実行して使い方を確認できます
2.LTE-RRCプロトコルのASNを準備する.1説明ファイル36331-c 00.asn :
LTE-RRCの仕様(3 gpp 36331-xx.doc)を3 gppサイトからダウンロードし、例えば最新のRel 12版を取り、解凍し、wordドキュメントを開くが、LTEのRRCドキュメントは完全なASNを持っていないことに気づいた.1記述は完全に一緒に書かれているが、各IEの記述に分散されている.イメージの3 GのRRC仕様は一緒に書いてあります.そこでwordドキュメントをtxtテキストファイルとして保存する、次のコードでasn記述テキストを取り出し、36331-c 00に保存する.asn:
#include 
#include 
#include 
#include 

int main(int argc, char* argv[])
{
    if (argc != 2)
	{
        return 1;
    }

    std::string output_file;
    std::string input_file = argv[1];

    int pos = input_file.find('.');
    if (pos == std::string::npos )
	{
        output_file = input_file + ".asn";
    }
    else
	{
        output_file = input_file.substr(0,pos) + ".asn";
    }

    std::fstream input;
    input.open(input_file.c_str(), std::fstream::in );
    if ( input.fail() == true)
	{
        std::cout< vec_asn;
    std::vector<:string>::iterator itr;

    const unsigned long cul_asn_idle  = 0x0;
    const unsigned long cul_asn_start = 0x1;

    unsigned long asn_state = cul_asn_idle;

    while ( std::getline(input, input_line) ) 
	{
        if ( cul_asn_idle == asn_state )
		{
            if ( input_line.find("-- ASN1START") != std::string::npos )
			{
                asn_state |=  cul_asn_start;
            }

            continue;
        }

        if ( 0 != (cul_asn_start & asn_state) )
		{
            if ( input_line.find("-- ASN1STOP") != std::string::npos )
			{
                asn_state = cul_asn_idle;
            }
            else
			{
                vec_asn.push_back(input_line);
            }
        }
    }

    for ( itr  = vec_asn.begin(); itr != vec_asn.end(); ++itr )
	{
        output<

3、Cコードを生成する:
コマンドasn 1 c-S/usr/local/share/asn 1 c-fcompound-names-fskeletons-copy-gen-PER-pdu=auto 36331-c 00を実行する.asnは一連のCコードを生成する.注意:-f compound-namesを追加しないと、後続のcコードのコンパイル時に重量挙げ定義エラーが多数報告されます.-fskeleton-copyは-Sで指定されたディレクトリからasnベースタイプの復号ファイルをコピーし、依存がないように加算する必要があります.-pdu=autoを付けないと、pdu_は発生しませんcolletion.cファイル.このファイルには、すべてのメッセージPDUが定義されている.
4、生成したCコードを修正する:
生成されたファイルディレクトリの下に、converter-sampleというメインプログラムファイルがあります.cとmakefileファイル:Makefile.am.sample.生成したメインプログラムファイルを直接使用する場合はconverter-sample.cに2行の定義を追加:#define PDU BCCH_BCH_Messageと#define ASN_PDU_COLLECTION:下の赤い行を見て
converter-sample.c
 
     21 #include 
     22 #include        /* for _ASN_DEFAULT_STACK_MAX */
     23 
     24 #define PDU BCCH_BCH_Message  //       pdu_collection.c     ,       
     25 #define ASN_PDU_COLLECTION    //       windows   ,linux  Makefile.am.sample      
     26 
     27 /* Convert "Type" defined by -DPDU into "asn_DEF_Type" */
     28 #define ASN_DEF_PDU(t)  asn_DEF_ ## t
     29 #define DEF_PDU_Type(t) ASN_DEF_PDU(t)
     30 #define PDU_Type        DEF_PDU_Type(PDU)
     31 
     32 extern asn_TYPE_descriptor_t PDU_Type;  /* ASN.1 type to be decoded */
     33 #ifdef  ASN_PDU_COLLECTION              /* Generated by asn1c: -pdu=... */
     34 extern asn_TYPE_descriptor_t *asn_pdu_collection[];
     35 #endif

もう一つの注意点は、
PER符号化はビットベースであるため、PER符号化されたPDUデータは、ちょうどバイト単位で開始および終了しない可能性がある.ファイルが見つかりましたper_opentype.cファイル、赤い部分を変更する:
per_opentype.c:
117		FREEMEM(buf);
118		if(padding >= 8) {
119			ASN_DEBUG("Too large padding %d in open type", (int)padding);
120			padding = padding % 8;  //     
121			// _ASN_DECODE_FAILED;  //      
122		} else {
123			ASN_DEBUG("Non-zero padding");
124			_ASN_DECODE_FAILED;
125		}
修正しないと、ほとんどのデータに対して復号エラーが発生する可能性があります.
5、生成したCコードをコンパイルする:
make-f Makefileを実行します.am.sampleはLTE-RRCのコーデックプログラムを生成することができ、プログラム名はprognameである.
Windowsの下で、空のVCコンソールプロジェクトを作成し、すべてのファイルを追加し、windowsバージョンをコンパイルすることもできます.
6、prognameを実行すればLTE-RRCデータを復号でき、progname-hはヘルプ情報を表示できる.このプログラムはasn 1 cとはもう関係ありません.LTE-RRCは多くのPDUを定義しているため、すべての復号はパラメータ-p[UDタイプ]を持たなければならず、progname-p listでサポートされているPDUタイプを表示することができます.
例えば、PDUはBCCH-DL-SCH-Message、データファイルはBCCH-DL-SCHであるデータがある.dat,内容は16進数(00 80 1 C 31 18 6 F E 1 22 B 8 35 84 96 E 2 D 0 02 00 7 D 0 E 77 2 C B 5 50 9 B 98 50 28 64 90 99 E 9 3 C 05 04 EE 94 8 A 80 00):
実行:./progname -p BCCH-DL-SCH-Message BCCH-DL-SCH.Dataは、詳細な復号結果をXML形式で出力することができる.
一般に、自動的に生成するconverter-sampleを用いる必要はない.cメインプログラムは、自分で書き直す必要があります.入手したLTE-RRC層のデータファイルには,PDUが1つしか含まれていないのではなく,異なるPUDタイプが含まれているためである.復号化のために異なるPUDタイプのオブジェクトを呼び出す必要がある.これで、定義#define PDU xxxxも不要になります.例えば、本人が現在入手しているデータファイルは、RRCレイヤごとにPDUの前に、PDUタイプとPDUのデータ長をそれぞれ識別するために数バイト加算される.
これにより,LTE−RRCを解析するメッセージデコーダが作成される.