Martin Lopez
Martin Lopez

Reputation: 103

Converting integers to Bytes in python

I am trying to change a number of integer parameters into bytes and putting them into a byte array. I have most of the required answer but the first 2 bytes in my byte array are different from the required answer. All the if statements in the code are for errors in integer format and the for loop decides how many bytes to allocate to the parameter depending on how big the integer is.

I have tried this on my mac and also Linux computers and I still get the same answer.

def composepacket (version, hdrlen, tosdscp, totallength, identification, flags, fragmentoffset, timetolive, protocoltype, headerchecksum, sourceaddress, destinationaddress):
    if version != 4:
        return 1
    elif hdrlen < 0 or hdrlen > 15:
        return 2
    elif tosdscp < 0 or tosdscp > 63:
        return 3
    elif totallength < 0 or totallength > 65535:
        return 4
    elif identification < 0 or identification > 65535:
        return 5
    elif flags < 0 or flags > 7:
        return 6
    elif fragmentoffset < 0 or fragmentoffset > 8191:
        return 7
    elif timetolive < 0 or timetolive > 255:
        return 8
    elif protocoltype < 0 or protocoltype > 255:
        return 9
    elif headerchecksum < 0 or headerchecksum > 65535:
        return 10
    elif sourceaddress < 0 or sourceaddress > 4294967295:
        return 11
    elif destinationaddress < 0 or destinationaddress > 4294967295:
        return 12
    else:
        list1 = [version,hdrlen,tosdscp,totallength,identification,flags,fragmentoffset,timetolive,protocoltype,headerchecksum,sourceaddress,destinationaddress]
        final = bytearray()
        for element in list1:
            if element <= 255:
                x = element.to_bytes(1,byteorder='big')
                final += x
            elif element <= 65535:
                x = element.to_bytes(2,byteorder='big')
                final += x
            elif element <= 16777215:
                x = element.to_bytes(3,byteorder='big')
                final += x
            elif element <= 4294967295:
                x = element.to_bytes(4,byteorder='big')
                final += x
        return final

the test line is

print(composepacket(4,5,0,1500,24200,0,63,22,6,4711, 2190815565, 3232270145))

The expected answer is

bytearray(b'E\x00\x05\xdc^\x88\x00?\x16\x06\x12g\x82\x951M\xc0\xa8\x87A')

and the answer I get is

bytearray(b'\x04\x05\x00\x05\xdc^\x88\x00?\x16\x06\x12g\x82\x951M\xc0\xa8\x87A')

so the difference is the first two bytes where i get b'\x04\x05 where i should get b'E

Upvotes: 0

Views: 508

Answers (1)

Evan
Evan

Reputation: 1378

It looks like you're working on building out a IPv4 packet header (you should've mentioned this in your question, assuming you know this to be the case).

Your logic currently takes the version and appends it to your byte array as a whole byte (8 bits), but it should only occupy the first 4 bits (or 1 nibble).

You're likely expecting the first byte to be "E" because 0b0100_0101 (that is, 4 represented as 4 bits followed by 5 represented as 4 bits, as shown in the diagram below) is 69 in decimal, which is the ASCII character for "E". So, if you were to run strings or hexdump on a TCPv4 packet, you might see "E" as the first character. However, the first byte should actually be 0x45, so you're confusing the representations of the initial byte.

enter image description here

Your code isn't quite right because it's treating the version and hdrlen as two separate bytes when they should be in the same byte as two separate nibbles.

So, you want something like:

first_byte = version << 4 | length

This should give you enough direction. Best of luck.

Upvotes: 2

Related Questions