2017-04-04 156 views
2

我正在lua編寫一個Wireshark協議解析器。它解析的協議包含crc16校驗和。解剖員應該檢查crc是否正確。計算lua中bytearray/userdata的crc16

我發現用C編寫的crc16實現已經與lua包裝代碼here。我已成功編譯並運行它(例如crc16.compute("test"))。問題是它期望一個字符串作爲輸入。從wireshark,我得到一個似乎是lua類型的緩衝區userdata。所以當我做

crc16.compute(buffer(5, 19)) 

Lua抱怨bad argument #1 to compute (string expected, got userdata)

crc16 implementationcompute()看起來是這樣的:

static int compute(lua_State *L) 
{ 
    const char *data; 
    size_t len = 0; 
    unsigned short r, crc = 0; 

    data = luaL_checklstring(L, 1, &len); 

    for (; len > 0; len--) 
    { 
     r = (unsigned short)(crc >> 8); 
     crc <<= 8; 
     crc ^= crc_table[r^*data]; 
     data ++; 
    } 

    lua_pushinteger(L, crc); 
     return 1; 
} 

看來luaL_checklstring失敗。所以我想我可能需要將輸入轉換成一個lua字符串,我不確定它是否有效,因爲我輸入的所有字節都不一定是可打印的字符。或者我需要調整上面的代碼,以便它接受類型userdata的輸入。我發現lua_touserdata(),但這似乎返回像一個指針。所以我需要第二個參數的長度,對吧?

我不一定需要使用此實現。任何接受用戶數據的lua的crc16實現都可以很好地解決問題。

+0

也許wireshark提供了一種將緩衝區轉換爲Lua字符串的方法?也許'__tostring'?如果是這樣,你可以使用'lua_tostring'而不是'luaL_checklstring'。 – lhf

+0

如果我做'uint8_t * data =(uint8_t *)lua_tostring(L,1); lua_pushinteger(L,data [0]);'然後wireshark崩潰。如果我做'uint8_t * data =(uint8_t *)lua_tolstring(L,1,&len); lua_pushinteger(L,len);'那麼我會得到'0'長度 –

+0

另外,我的數據可能包含多個零字節,而lua字符串在第一個零終止,對嗎?不會在第一個零終止嗎? –

回答

0

您從Wireshark的得到緩衝,可以用作ByteArray這樣的:

byte_array = Buffer(5,19):bytes(); 

的ByteArray具有_toString功能字節轉換成表示爲十六進制字節的字符串表示。所以,你可以調用CRC功能是這樣的:

crc16.compute(tostring(byte_array)) 

「表示爲十六進制字節的表示」是指與位11111111將轉成ASCII字符串FF輸入字節。 ASCII字符串FF的位數是01000110 01000110或十六進制的46 46。這意味着你在C中得到的不是原始字節數組。在計算crc之前,您需要將ascii表示解碼回原始字節,否則我們顯然會得到不同的crc。

static char ascii2char(char c) { 
    c = tolower(c); 
    if(c >= '0' && c <= '9') 
     return c - '0'; 
    else if(c >= 'a' && c <= 'f') 
     return c - 'a' + 10; 
} 

的計算功能,我們遍歷字符串表示現在,總是兩個字符組合成一個字節: 首先,此功能包含一個ASCII十六進制字符回它所代表的價值單個字符c轉換。

int compute(lua_State *L) { 
    size_t len; 
    const char * str = lua_tolstring(L, 1, &len); 
    uint8_t * data = (uint8_t *) malloc(len/2); 

    for(int n=0; n<len/2; n++) { 
     data[n] = ascii2char(str[2*n]) << 4; 
     data[n] |= ascii2char(str[2*n+1]); 
    } 

    crc16_t crc = crc16_init(); 
    crc = crc16_update(crc, data, len/2); 
    crc = crc16_finalize(crc); 

    lua_pushinteger(L, crc); 
    free(data); 
    return 1; 
} 

在本例中,我使用的CRC函數crc16_initcrc16_updatecrc16_finalize生成使用pycrc,而不是CRC實施的問題聯繫起來。問題是你需要使用與生成crc時相同的polynom等。 Pycrc允許您根據需要生成crc函數。 我的數據包還包含一個crc32。 Pycrc也可以生成crc32的代碼,所以它對crc32的工作方式都是一樣的。