rocco
rocco

Reputation: 25

How to pack with variable bit order and length in python

I need to create a IP Packet in Python, but the length of the fields are different. Every time I have a field bigger than 1 byte I need to change the byte order to big endian. So what I did was to pack each variable separately and save everything in a file. I'm saving in a file because I need to do the checksum after packing and then pack all over again with the checksum (If someone has a better idea is more than welcome).

I'm having two problems:

1) The packet that I generate is bigger than the original one from were I parsed the information (the IP packet I generate only change in one field that is the TTL, but it should remain the same size)

2) When I parse my packet (stream of data in the file), some information has change (I didn't change it).

This is the original packet information:

Ver: 4
HL: 12
TOS: 0
LEN: 50
ID= 456
OFF: 16384
TTL: 5
PROT: 6
CHSUM: 30512
SRC: 16885952
DST: 167880896
rem_head: ['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
data: ['A', 'A']

This result is from parsing the packet. Then I verify the check sum and decrease the TTL by one and reassemble the packet like this:

pk_cksum=0
    arch= open('packet.out', 'w')
    arch.write( struct.pack('B',frstb) )
    arch.write( struct.pack('>B', pk_tos) )
    arch.write( struct.pack('>H', pk_len) )
    arch.write( struct.pack('>H', pk_id) )
    arch.write( struct.pack('>H',pk_off) )
    arch.write( struct.pack('B', pk_ttl) )
    arch.write( struct.pack('B', pk_p) )
    arch.write( struct.pack('>H', pk_cksum) )
    arch.write( struct.pack('>I', pk_src) )
    arch.write( struct.pack('>I', pk_dst) )
    if (pk_hl>5):
        for i in range(len(pk_head)):
            arch.write(struct.pack('c', pk_head[i])[0])
    if (pk_len>(pk_hl*4)):
        for j in range(len(pk_data)):
            arch.write(struct.pack('c', pk_data[j])[0])
    arch.close()

To verify if the packing was successful I use my same code to parse this last packet and then I get this information:

Ver: 4
HL: 0
TOS: 0
LEN: 50
ID= 456
OFF: 16384
TTL: 4
PROT: 6
CHSUM: 0
SRC: 3232235777
DST: 2818640397
data: ['@', '\x00', '\x00', '2', '\x01', '\xc8', '@', '\x00', '\x04', '\x06', '\x00', '\x00', '\x01', '\x01', '\xa8', '\xc0', '\r', '\n', '\x01', '\xa8', '\xc0', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'A']

As you see, some of the variables have another value and I don't know why.

Can someone tell me what I'm doing wrong?

Thanks

Upvotes: 0

Views: 468

Answers (1)

John La Rooy
John La Rooy

Reputation: 304473

You can control the endianess by prefixing the format string with "<"(little) or ">"(big)

Upvotes: 1

Related Questions