Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compute CRC of struct in Python

I have the following struct, from the NRPE daemon code in C:

typedef struct packet_struct {
  int16_t packet_version;
  int16_t packet_type;
  uint32_t crc32_value;
  int16_t result_code;
  char buffer[1024];
} packet;

I want to send this data format to the C daemon from Python. The CRC is calculated when crc32_value is 0, then it is put into the struct. My Python code to do this is as follows:

cmd = '_NRPE_CHECK'
pkt = struct.pack('hhIh1024s', 2, 1, 0, 0, cmd)
# pkt has length of 1034, as it should
checksum = zlib.crc32(pkt) & 0xFFFFFFFF
pkt = struct.pack('hhIh1024s', 2, 1, checksum, 0, cmd)
socket.send(....)

The daemon is receiving these values: version=2 type=1 crc=FE4BBC49 result=0

But it is calculating crc=3731C3FD

The actual C code to compute the CRC is:

https://github.com/KristianLyng/nrpe/blob/master/src/utils.c

and it is called via:

calculate_crc32((char *)packet, sizeof(packet));

When I ported those two functions to Python, I get the same as what zlib.crc32 returns.

Is my struct.pack call correct? Why is my CRC computation differing from the server's?

like image 711
verideskstar Avatar asked Nov 04 '22 18:11

verideskstar


1 Answers

From the Python struct documentation:

To handle platform-independent data formats or omit implicit pad bytes, use standard size and alignment instead of native size and alignment: see Byte Order, Size, and Alignment for details.

Use '!' as the first format character to make the packed structure platform-independent. It forces big-endian, standard type sizes, and no pad bytes. Then the CRCs should be consistent.

like image 69
Mark Adler Avatar answered Nov 12 '22 11:11

Mark Adler