2017-04-04 155 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的工作方式都是一样的。