Python

 

 

 

 

Python - Decoding IPv6 Header/ICMPv6/TCP Header

 

NOTE 1 : All the examples in this page are written in Python 3.x. It may not work if you use Pyton 2.x

NOTE 2 : All the examples in this page are assumed to be written/run on Windows 7 unless specifically mentioned. You MAY (or may not) need to modify the syntax a little bit if you are running on other operating system.

 

Example 01 > =============================================================

 

This example will show you the very simple and straightfoward way to decode IPv6 header. This example is designed for getting familiar with structure of IPv6 header and number/string manipulation in Python. I don't think this is very efficient code, but it would be very simple/easy to understand.

For simplicity, I gave a precaptured IPv6 byte array to decode. But if you can combine the skills explained in Raw Packet : IPv4 page, you can modify the code so that the script can decode IPv6 header directly from a network card.

 

The purpose of this example is to decode Byte Array marked in Red in the wireshark log shown below. Compare the program output with Wireshark log.

 

No.     Time            Source                Destination           Protocol Length Info

      2 16:42:34.164000 fe80::11              ff02::2               ICMPv6   62     Router Solicitation

 

Frame 2: 62 bytes on wire (496 bits), 62 bytes captured (496 bits)

    Encapsulation type: Ethernet (1)

    Arrival Time: Oct 21, 2015 12:42:34.164000000 Eastern Daylight Time

    [Time shift for this packet: 0.000000000 seconds]

    Epoch Time: 1445445754.164000000 seconds

    [Time delta from previous captured frame: 57.164000000 seconds]

    [Time delta from previous displayed frame: 57.164000000 seconds]

    [Time since reference or first frame: 57.164000000 seconds]

    Frame Number: 2

    Frame Length: 62 bytes (496 bits)

    Capture Length: 62 bytes (496 bits)

    [Frame is marked: False]

    [Frame is ignored: False]

    [Protocols in frame: eth:ipv6:icmpv6]

    [Coloring Rule Name: ICMP]

    [Coloring Rule String: icmp || icmpv6]

Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)

    Destination: 00:00:00_00:00:00 (00:00:00:00:00:00)

        Address: 00:00:00_00:00:00 (00:00:00:00:00:00)

        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)

        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)

    Source: 00:00:00_00:00:00 (00:00:00:00:00:00)

        Address: 00:00:00_00:00:00 (00:00:00:00:00:00)

        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)

        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)

    Type: IPv6 (0x86dd)

Internet Protocol Version 6, Src: fe80::11 (fe80::11), Dst: ff02::2 (ff02::2)

    0110 .... = Version: 6

        [0110 .... = This field makes the filter "ip.version == 6" possible: 6]

    .... 0000 0000 .... .... .... .... .... = Traffic class: 0x00000000

        .... 0000 00.. .... .... .... .... .... = Differentiated Services Field: Default (0x00000000)

        .... .... ..0. .... .... .... .... .... = ECN-Capable Transport (ECT): Not set

        .... .... ...0 .... .... .... .... .... = ECN-CE: Not set

    .... .... .... 0000 0000 0000 0000 0000 = Flowlabel: 0x00000000

    Payload length: 8

    Next header: ICMPv6 (58)

    Hop limit: 255

    Source: fe80::11 (fe80::11)

    Destination: ff02::2 (ff02::2)

    [Source GeoIP: Unknown]

    [Destination GeoIP: Unknown]

Internet Control Message Protocol v6

    Type: Router Solicitation (133)

    Code: 0

    Checksum: 0x7d26 [correct]

    Reserved: 00000000

 

0000  00 00 00 00 00 00 00 00 00 00 00 00 86 dd 60 00   ..............`.

0010  00 00 00 08 3a ff fe 80 00 00 00 00 00 00 00 00   ....:...........

0020  00 00 00 00 00 11 ff 02 00 00 00 00 00 00 00 00   ................

0030  00 00 00 00 00 02 85 00 7d 26 00 00 00 00         ........}&....

 

 

If you understand only a few Python syntax, you would be able to read the code directly. Followings are some syntax you may refer to if you have difficulties understanding this code.

 

# Following is the source code for this example.  Understanding this code is very simple.

 

import binascii

 

def decodeIPv6Header(pktBytes) :

    

    headerLength = 40

    headerBytes = pktBytes[0:headerLength]

    headerInt = int.from_bytes(headerBytes, 'big')

    headerBin = '{0:0{1}b}'.format(headerInt,headerLength*8)

    #print("Header in Binary = ",headerBin)

    

    version = int(headerBin[0:4],2)

    print("Version : ",version)

 

    trafficClass = int(headerBin[4:12],2)

    print("Traffic Class : ",headerBin[4:12],"(Bin)")

 

    FlowLabel = int(headerBin[12:32],2)

    print("FlowLabel : ",headerBin[12:32],"(Bin)")

 

    payloadLen = int(headerBin[32:32+16],2)

    print("Payload Length : ",payloadLen,"(Dec)")

 

    nextHeader = int(headerBin[32+16:32+24],2)

    print("Next Header : ",nextHeader,"(Dec) :", NextHeaderKeyword(nextHeader))

 

    hopLimit = int(headerBin[32+24:32+32],2)

    print("hopLimit : ",hopLimit,"(Dec)")

 

    srcAddString = '{0:X}'.format(int(headerBin[2*32:2*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[2*32+16:2*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[3*32:3*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[3*32+16:3*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[4*32:4*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[4*32+16:4*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[5*32:5*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[5*32+16:5*32+32],2))

    print("Source Address : ",srcAddString)

 

    dstAddString = '{0:X}'.format(int(headerBin[6*32:6*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[6*32+16:6*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[7*32:7*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[7*32+16:7*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[8*32:8*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[8*32+16:8*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[9*32:9*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[9*32+16:9*32+32],2))

    print("Destination Address : ",dstAddString)

    

    return nextHeader

 

def NextHeaderKeyword(headerIndex):

    switcher = {

        0: "HOPOPT",

        1: "ICMP",

        17: "UDP",

        50: "ESP",

        58: "ICMPv6",

        142 : "ROHC",

    }

    return switcher.get(headerIndex, "nothing")

 

# Beginning of Main Routine

ByteAry = b'\x60\x00\x00\x00\x00\x08\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11

\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x85'

HexStr=binascii.b2a_hex(ByteAry)

 

if((ByteAry[0] & 0xF0) == 0x60) :

   decodeIPv6Header(ByteAry)

else :

   print("The packet given is not IPv6 header")

 

 

Result :----------------------------------------------------------------

 

Version :  6

Traffic Class :  00000000 (Bin)

FlowLabel :  00000000000000000000 (Bin)

Payload Length :  8 (Dec)

Next Header :  58 (Dec) : ICMPv6

hopLimit :  255 (Dec)

Source Address :  FE80:0:0:0:0:0:0:11

Destination Address :  FF02:0:0:0:0:0:0:2

 

 

Example 02 > =============================================================

 

import binascii

import sys

import ctypes

import math

 

 

# Function to decode IPv6 Header ####################3###################

def decodeIPv6Header(pktBytes, fOut) :

    

    headerLength = 40

    headerBytes = pktBytes[0:headerLength]

    headerInt = int.from_bytes(headerBytes, 'big')

    headerBin = '{0:0{1}b}'.format(headerInt,headerLength*8)

 

    outStr = "IPv6 Header ===================================================="

    fOut.write(outStr + "\n")

    print(outStr)

    

    version = int(headerBin[0:4],2)

    outStr = "Version : " + '{0:d}'.format(version)

    fOut.write(outStr + "\n")

    print(outStr)

 

    trafficClass = int(headerBin[4:12],2)

    outStr = "Traffic Class :  " + '{0:08b}'.format(trafficClass) + "(Bin)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    FlowLabel = int(headerBin[12:32],2)

    outStr = "FlowLabel : " + '{0:020b}'.format(FlowLabel) + "(Bin)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    payloadLen = int(headerBin[32:32+16],2)

    outStr = "payloadLen : " + '{0:d}'.format(payloadLen) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    nextHeader = int(headerBin[32+16:32+24],2)

    outStr = "Next Header : " + '{0:d}'.format(nextHeader) + "(Dec) : " + NextHeaderKeyword(nextHeader)

    fOut.write(outStr + "\n")

    print(outStr)

 

    hopLimit = int(headerBin[32+24:32+32],2)

    outStr = "Hop Limit : " + '{0:d}'.format(hopLimit) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    srcAddString = '{0:X}'.format(int(headerBin[2*32:2*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[2*32+16:2*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[3*32:3*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[3*32+16:3*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[4*32:4*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[4*32+16:4*32+32],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[5*32:5*32+16],2))

    srcAddString = srcAddString + ":" + '{0:X}'.format(int(headerBin[5*32+16:5*32+32],2))

    outStr = "Source Address : " + srcAddString

    fOut.write(outStr + "\n")

    print(outStr)

 

    dstAddString = '{0:X}'.format(int(headerBin[6*32:6*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[6*32+16:6*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[7*32:7*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[7*32+16:7*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[8*32:8*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[8*32+16:8*32+32],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[9*32:9*32+16],2))

    dstAddString = dstAddString + ":" + '{0:X}'.format(int(headerBin[9*32+16:9*32+32],2))

    outStr = "Destination Address : " + dstAddString

    fOut.write(outStr + "\n")

    print(outStr)

    

    return payloadLen,nextHeader

 

# Function to return NextHeader (Protocol) String from Next Header Number ######

def NextHeaderKeyword(headerIndex):

    switcher = {

        0: "HOPOPT",

        1: "ICMP",

        6: "TCP",

        17: "UDP",

        50: "ESP",

        58: "ICMPv6",

        142 : "ROHC",

    }

    return switcher.get(headerIndex, "nothing")

 

 

# Function to return ICMPv6 String from IcmpType Number ###################

def getICMPv6TypeString(IcmpType):

    switcher = {

        1: "Destination Unreachable",

        2: "Packet Too Big",

        3: "Time Exceeded",

        4: "Parameter Problem",

        100: "Private experimentation",

        101 : "Private experimentation",

        127 : "Reserved for expansion of ICMPv6 error messages",

        128 : "Echo Request",

        129 : "Echo Reply",

        133 : "Router Solicitation (NDP)",

        134 : "Router Advertisement (NDP)",

        135 : "Neighbor Solicitation (NDP)",

        136 : "Neighbor Advertisement (NDP)",

        138 : "Redirect Message (NDP)",

        139 : "ICMP Node Information Query",

        140 : "ICMP Node Information Response",

        141 : "Inverse Neighbor Discovery Solicitation Message",

        142 : "Inverse Neighbor Discovery Advertisement Message",

        144 : "Home Agent Address Discovery Request Message",

        145 : "Home Agent Address Discovery Reply Message",

        146 : "Mobile Prefix Solicitation",

        147 : "Mobile Prefix Advertisement",

        148 : "Certification Path Solicitation (SEND)",

        149 : "Certification Path Advertisement (SEND)",

        151 : "Multicast Router Advertisement (MRD)",

        152 : "Multicast Router Solicitation (MRD)",

        153 : "Multicast Router Termination (MRD)",

        200 : "Private experimentation",

        201 : "Private experimentation",

        255 : "Reserved for expansion of ICMPv6 informational messages",

    }

    return switcher.get(IcmpType, "nothing")

 

 

# Function to decode Router Solicitation Packet ###################

def decodeRouterSolicitation(pktBytes,fOut) :

    pktLength = len(pktBytes)

    rsBytes = pktBytes[0:pktLength]

    rsInt = int.from_bytes(rsBytes, 'big')

    rsBin = '{0:0{1}b}'.format(rsInt,pktLength*8)

 

    outStr = "Router Solcitation ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsType = int(rsBin[0:8],2)

    outStr = "Type : " + '{0:d}'.format(rsType) + "(Dec) : " + getICMPv6TypeString(rsType)

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsCode = int(rsBin[8:16],2)

    outStr = "Code : " + '{0:d}'.format(rsCode) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsCheckSum = int(rsBin[16:32],2)

    outStr = "Checksum : " + '{0:#x}'.format(rsCheckSum) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsReserved = int(rsBin[32:32+32],2)

    outStr = "Reserved : " + '{0:08x}'.format(rsReserved) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

     

    return 1

 

 

# Function to decode Link Address Option in RA Packet ###################

def decodeRaOptionLinkAddress(pktBytes,fOut) :

 

    pktLength = len(pktBytes)

    raBytes = pktBytes[0:pktLength]

    raInt = int.from_bytes(raBytes, 'big')

    raBin = '{0:0{1}b}'.format(raInt,pktLength*8)

    

    outStr = "Link Address ----------------------------------------"

    fOut.write(outStr + "\n")

    print(outStr)

    

    optType = int(raBin[0:8],2)

    outStr = "Type : " + '{0:d}'.format(optType) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    linkAddressLength = int(raBin[8:16],2)

    outStr = "Length : " + '{0:d}'.format(linkAddressLength) + "(Dec) - " + '{0:d}'.format(linkAddressLength*8) + " Bytes"

    fOut.write(outStr + "\n")

    print(outStr)

 

    linkAddString = '{0:02X}'.format(int(raBin[16:24],2))

    linkAddString = linkAddString + ":" + '{0:02X}'.format(int(raBin[24:32],2))

    linkAddString = linkAddString + ":" + '{0:02X}'.format(int(raBin[32:32+8],2))

    linkAddString = linkAddString + ":" + '{0:02X}'.format(int(raBin[32+8:32+16],2))

    linkAddString = linkAddString + ":" + '{0:02X}'.format(int(raBin[32+16:32+24],2))

    linkAddString = linkAddString + ":" + '{0:02X}'.format(int(raBin[32+24:32+32],2))

    outStr = "Link Address : " + linkAddString

    fOut.write(outStr + "\n")

    print(outStr)

 

    unusedBytes = pktBytes[linkAddressLength*8 : pktLength];

    return unusedBytes

 

 

# Function to decode MTU Option in RA Packet ###################

def decodeRaOptionMTU(pktBytes,fOut) :

 

    pktLength = len(pktBytes)

    raBytes = pktBytes[0:pktLength]

    raInt = int.from_bytes(raBytes, 'big')

    raBin = '{0:0{1}b}'.format(raInt,pktLength*8)

    

    outStr = "MTU ------------------------------------------------"

    fOut.write(outStr + "\n")

    print(outStr)

    

    optType = int(raBin[0:8],2)

    outStr = "Type : MTU : " + '{0:d}'.format(optType) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    mtuByteLength = int(raBin[8:16],2)

    outStr = "Length : " + '{0:d}'.format(mtuByteLength) + "(" + '{0:d}'.format(mtuByteLength*8)+  " Bytes)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    mtuByteReserved = int(raBin[16:32],2)

    outStr = "Reserved : " + '{0:04X}'.format(mtuByteReserved) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    mtuSize = int(raBin[32*1+0:32*1+32],2)

    outStr = "MTU : " + '{0:d}'.format(mtuSize) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    unusedBytes = pktBytes[mtuByteLength*8 : pktLength];

    return unusedBytes   

 

 

# Function to decode Prefix Information Option in RA Packet ###################

def decodeRaOptionPrefixInformation(pktBytes,fOut) :

 

    pktLength = len(pktBytes)

    raBytes = pktBytes[0:pktLength]

    raInt = int.from_bytes(raBytes, 'big')

    raBin = '{0:0{1}b}'.format(raInt,pktLength*8)

 

    outStr = "Prefix Information ------------------------------------------------"

    fOut.write(outStr + "\n")

    print(outStr)

 

    optType = int(raBin[0:8],2)

    outStr = "Type : Prefix Information : " + '{0:d}'.format(optType) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    prefixLength = int(raBin[8:16],2)

    outStr = "Length : " + '{0:d}'.format(prefixLength) + "(" + '{0:d}'.format(prefixLength*8)+  " Bytes)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    prefixBitLength = int(raBin[16:24],2)

    outStr = "Prefix Length : " + '{0:d}'.format(prefixBitLength) + "bits"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(raBin[24:32],2)

    outStr = "Flags : " + '{0:08b}'.format(flag) + "(BIN)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    validLifeTime = int(raBin[32*1+0:32*1+32],2)

    outStr = "Valid Lifetime : " + '{0:d}'.format(validLifeTime) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    preferredLifeTime = int(raBin[32*2+0:32*2+32],2)

    outStr = "Preferred Lifetime : " + '{0:d}'.format(preferredLifeTime) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    reserved = int(raBin[32*3+0:32*3+32],2)

    outStr = "Reserved : " + '{0:08X}'.format(reserved) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    prefixAddString = '{0:X}'.format(int(raBin[32*4+0:32*4+16],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*4+16:32*4+32],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*5+0:32*5+16],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*5+16:32*5+32],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*6+0:32*6+16],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*6+16:32*6+32],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*7+0:32*7+16],2))

    prefixAddString = prefixAddString + ":" + '{0:X}'.format(int(raBin[32*7+16:32*7+32],2))

    outStr = "Prefix Address : " + prefixAddString

    fOut.write(outStr + "\n")

    print(outStr)

   

    unusedBytes = pktBytes[prefixLength*8 : pktLength];

    return unusedBytes

 

 

# Function to decode Router Advertisement Option Fields ##########################

def decodeRaOption(pktBytes,fOut) :

 

    pktLength = len(pktBytes)

 

    if pktLength <= 1 :

       return 1

 

    raBytes = pktBytes[0:pktLength]

    raInt = int.from_bytes(raBytes, 'big')

    raBin = '{0:0{1}b}'.format(raInt,pktLength*8)

    

    optType = int(raBin[0:8],2)

    unusedBytes = pktBytes

 

    if optType == 1 :

       unusedBytes = decodeRaOptionLinkAddress(unusedBytes,fOut)

 

    if optType == 3 :

       unusedBytes = decodeRaOptionPrefixInformation(unusedBytes,fOut)

 

    if optType == 5 :

       unusedBytes = decodeRaOptionMTU(unusedBytes,fOut)

 

    decodeRaOption(unusedBytes,fOut)

    

    return 1

 

 

# Function to decode Router Advertisement ######################################

def decodeRouterAdvertisement(pktBytes,fOut) :

    pktLength = len(pktBytes)

    rsBytes = pktBytes[0:pktLength]

    rsInt = int.from_bytes(rsBytes, 'big')

    raBin = '{0:0{1}b}'.format(rsInt,pktLength*8)

 

    outStr = "Router Advertisement ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsType = int(raBin[0:8],2)

    outStr = "Type : " + '{0:d}'.format(rsType) + "(Dec) : " + getICMPv6TypeString(rsType)

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsCode = int(raBin[8:16],2)

    outStr = "Code : " + '{0:d}'.format(rsCode) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    rsCheckSum = int(raBin[16:32],2)

    outStr = "Checksum : " + '{0:#x}'.format(rsCheckSum) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    currentHoplimit = int(raBin[32:32+8],2)

    outStr = "Current Hop Limit : " + '{0:d}'.format(currentHoplimit) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    autoConfigFlag = int(raBin[32+8:32+16],2)

    outStr = "AutoConfig Flag : " + '{0:08b}'.format(autoConfigFlag) + "(Bin)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    routerLifeTime = int(raBin[32+16:32+32],2)

    outStr = "Router Life Time : " + '{0:d}'.format(routerLifeTime) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    reachableTime = int(raBin[32*2:32*2+32],2)

    outStr = "Reachable Time : " + '{0:d}'.format(reachableTime) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    retransmissionTimer = int(raBin[32*3:32*3+32],2)

    outStr = "Retransmission Timer : " + '{0:d}'.format(retransmissionTimer) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    unusedBytes = pktBytes[4*4:pktLength]

    decodeRaOption(unusedBytes,fOut)

 

    return 1   

 

# Function to decode TCP Packet ######################################

def decodeTcpHeader(pktBytes,fOut) :

    pktLength = len(pktBytes)

    tcpBytes = pktBytes[0:pktLength]

    tcpInt = int.from_bytes(tcpBytes, 'big')

    tcpBin = '{0:0{1}b}'.format(tcpInt,pktLength*8)

 

    outStr = "TCP Header ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    sourcePort = int(tcpBin[0:16],2)

    outStr = "Source Port : " + '{0:d}'.format(sourcePort) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    destinationPort = int(tcpBin[16:32],2)

    outStr = "Destination Port : " + '{0:d}'.format(destinationPort) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    sequenceNumber = int(tcpBin[32*1+0:32*1+32],2)

    outStr = "Sequence Number : " + '{0:08X}'.format(sequenceNumber) + "(HEX) - " + '{0:d}'.format(sequenceNumber) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    acknowledgementNumber = int(tcpBin[32*2+0:32*2+32],2)

    outStr = "Acknowledgement Number : " + '{0:08X}'.format(acknowledgementNumber) + "(HEX) - " + '{0:d}'.format(acknowledgementNumber) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    dataOffset = int(tcpBin[32*3+0:32*3+4],2)

    outStr = "Data Offset (Header Length) : " + '{0:d}'.format(dataOffset * 4) + "(Bytes)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4:32*3+16],2)

    outStr = "Flags : "+'{0:03X}'.format(flag)+"(HEX) : " +'{0:012b}'.format(flag)+ "(BIN)-----"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4:32*3+4+3],2)

    outStr ="    " +  '{0:03b}'.format(flag)+". .... ...." + " = Reserved"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+3:32*3+4+4],2)

    outStr ="    " +  "..."+'{0:01b}'.format(flag)+" .... ...." + " = Nonce"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+4:32*3+4+5],2)

    outStr ="    " +  ".... "+'{0:01b}'.format(flag)+"... ...." + " = Congestion Window Reduced(CWR)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+5:32*3+4+6],2)

    outStr ="    " +  ".... ."+'{0:01b}'.format(flag)+".. ...." + " = ECN-Echo"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+6:32*3+4+7],2)

    outStr ="    " +  ".... .."+'{0:01b}'.format(flag)+". ...." + " = Urgent"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+7:32*3+4+8],2)

    outStr ="    " +  ".... ..."+'{0:01b}'.format(flag)+" ...." + " = Acknowlegment"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+8:32*3+4+9],2)

    outStr ="    " +  ".... .... "+'{0:01b}'.format(flag)+"..." + " = Push"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+9:32*3+4+10],2)

    outStr ="    " +  ".... .... ."+'{0:01b}'.format(flag)+".." + " = Reset"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+10:32*3+4+11],2)

    outStr = "    " + ".... .... .."+'{0:01b}'.format(flag)+"." + " = Syn"

    fOut.write(outStr + "\n")

    print(outStr)

 

    flag = int(tcpBin[32*3+4+11:32*3+4+12],2)

    outStr = "    " + ".... .... ..."+'{0:01b}'.format(flag)+ "" + " = Fin"

    fOut.write(outStr + "\n")

    print(outStr)

 

    windowSize = int(tcpBin[32*3+16:32*3+32],2)

    outStr = "Window Size Value : " + '{0:d}'.format(windowSize) + "(DEC)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    checkSum = int(tcpBin[32*4+0:32*4+16],2)

    outStr = "Checksum : " + '{0:04X}'.format(checkSum) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    urgentPointer = int(tcpBin[32*4+16:32*4+32],2)

    outStr = "Urgent Pointer : " + '{0:04X}'.format(urgentPointer) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    option = int(tcpBin[32*5+0:(dataOffset*4)*8],2)

    outStr = "TCP Option : " + '{0:0{1}X}'.format(option,2*(dataOffset*4-20)) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    unusedBytes = pktBytes[dataOffset*4:pktLength]

  

    return unusedBytes   

 

# Function to decode UDP Packet ######################################

def decodeUdpHeader(pktBytes,fOut) :

    pktLength = len(pktBytes)

    udpBytes = pktBytes[0:pktLength]

    udpInt = int.from_bytes(udpBytes, 'big')

    udpBin = '{0:0{1}b}'.format(udpInt,pktLength*8)

 

    outStr = "UDP Header ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    sourcePort = int(udpBin[0:16],2)

    outStr = "Source Port : " + '{0:d}'.format(sourcePort) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    destinationPort = int(udpBin[16:32],2)

    outStr = "Destination Port : " + '{0:d}'.format(destinationPort) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    udpLength = int(udpBin[32*1+0:32*1+16],2)

    outStr = "Length : " + '{0:d}'.format(udpLength) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    checkSum = int(udpBin[32*1+16:32*1+32],2)

    outStr = "Checksum : " + '{0:04X}'.format(checkSum) + "(HEX)"  

    fOut.write(outStr + "\n")

    print(outStr)

 

    unusedBytes = pktBytes[8:pktLength]

 

    return unusedBytes

 

 

# Function to decode ICMPv6\Ping Request ######################################

def decodePing6Request(pktBytes,fOut) :

    pktLength = len(pktBytes)

    icmpBytes = pktBytes[0:pktLength]

    icmpInt = int.from_bytes(icmpBytes, 'big')

    icmpBin = '{0:0{1}b}'.format(icmpInt,pktLength*8)

 

    outStr = "Ping Request ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpType = int(icmpBin[0:8],2)

    outStr = "Type : " + '{0:d}'.format(icmpType) + "(Dec) : " + getICMPv6TypeString(icmpType)

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpCode = int(icmpBin[8:16],2)

    outStr = "Code : " + '{0:d}'.format(icmpCode) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpCheckSum = int(icmpBin[16:32],2)

    outStr = "Checksum : " + '{0:04x}'.format(icmpCheckSum) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpIdentifier = int(icmpBin[32:32+16],2)

    outStr = "Identifier  : " + '{0:04x}'.format(icmpIdentifier) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

          

    icmpSequence = int(icmpBin[32+16:32+32],2)

    outStr = "Sequence : " + '{0:d}'.format(icmpSequence) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

     

    return 1

 

 

# Function to decode ICMPv6\Ping Reply ######################################

def decodePing6Reply(pktBytes,fOut) :

    pktLength = len(pktBytes)

    icmpBytes = pktBytes[0:pktLength]

    icmpInt = int.from_bytes(icmpBytes, 'big')

    icmpBin = '{0:0{1}b}'.format(icmpInt,pktLength*8)

 

    outStr = "Ping Reply ========================================="

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpType = int(icmpBin[0:8],2)

    outStr = "Type : " + '{0:d}'.format(icmpType) + "(Dec) : " + getICMPv6TypeString(icmpType)

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpCode = int(icmpBin[8:16],2)

    outStr = "Code : " + '{0:d}'.format(icmpCode) + "(Dec)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpCheckSum = int(icmpBin[16:32],2)

    outStr = "Checksum : " + '{0:04x}'.format(icmpCheckSum) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

 

    icmpIdentifier = int(icmpBin[32:32+16],2)

    outStr = "Identifier  : " + '{0:04x}'.format(icmpIdentifier) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

          

    icmpSequence = int(icmpBin[32+16:32+32],2)

    outStr = "Sequence : " + '{0:d}'.format(icmpSequence) + "(HEX)"

    fOut.write(outStr + "\n")

    print(outStr)

     

    return 1

 

 

 

# Start of Main Routine ====================================================

fHandleOut = open("IPv6_Out.txt","w")

 

#IPv6/ICMPv6/RS

testStr1 = "60 00 00 00 00 08 3A FF FE 80 00 00 00 00 00 00 00 00 00 00 00 00 10 00 FF \

            02 00 00 00 00 00 00 00 00 00 00 00 00 00 02 85 00 6D 80 00 00 00 38 3A FF \

            FE 80 00 00 00 00 00 00 02 00 00 FF FE 00 00 01 FE 80 00 00 00 00 00 00 00 \

            00 00 00 00 00 10 00 86 00 42 1F FF 00 07 08 00 00 00 00 00 00 00 00 01 01 \

            00 00 00 00 00 01 03 04 40 C0 00 27 8D 00 00 09 3A 80 00 00 00 00 20 01 04 \

            68 01 81 F1 00 00 00 00 00 00 00 00 00 6D 37 00 00 00 00"

 

#IPv6/ICMPv6/RA with 2 Options

testStr2 = "6D 80 00 00 00 38 3A FF FE 80 00 00 00 00 00 00 02 00 00 FF FE 00 00 01 FE \

            80 00 00 00 00 00 00 00 00 00 00 00 00 10 00 86 00 42 1F FF 00 07 08 00 00 \

            00 00 00 00 00 00 01 01 00 00 00 00 00 01 03 04 40 C0 00 27 8D 00 00 09 3A \

            80 00 00 00 00 20 01 04 68 01 81 F1 00 00 00 00 00 00 00 00 00"

 

#IPv6/ICMPv6/RA with 3 Options

testStr3 = "60 00 00 00 00 40 3A FF FE 80 00 00 00 00 00 00 D1 DE AE 75 2E 92 1C 33 FF \

            02 00 00 00 00 00 00 00 00 00 00 00 00 00 01 86 00 73 99 00 00 00 00 00 00 \

            00 00 00 00 00 00 01 01 90 E2 BA 2D C3 FE 05 01 00 00 00 00 05 DC 03 04 40 \

            C0 00 27 8D 00 00 09 3A 80 00 00 00 00 20 01 04 68 01 81 F1 00 00 00 00 00 \

            00 00 00 00"

 

#IPv6/TCP

testStr4 = "60 00 00 00 01 65 06 40 20 01 00 00 00 00 00 01 4C 16 9C 0F 49 86 9E 6D 20 \

            01 00 00 00 00 00 01 00 00 00 00 00 00 00 02 AF 4C 13 C4 63 CB D0 BC 2C 72 \

            30 79 80 18 00 D3 63 BF 00 00 01 01 08 0A 00 00 E9 15 00 01 CC 55"

 

#IPv6/ICMPv6/Ping Request

testStr5 = "60 00 00 00 00 6C 3A 7F 20 01 04 68 01 81 F1 00 BC AA B2 4B C7 4C D7 63 20 \

            02 04 68 01 81 F1 00 00 00 00 00 00 00 00 01 80 00 89 37 00 01 AD 90 61 62 \

            63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 \

            65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 \

            67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 \

            69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68"

 

#IPv6/ICMPv6/Ping Reply

testStr6 = "60 00 00 00 00 6C 3A 80 20 02 04 68 01 81 F1 00 00 00 00 00 00 00 00 01 20 \

            01 04 68 01 81 F1 00 BC AA B2 4B C7 4C D7 63 81 00 88 37 00 01 AD 90 61 62 \

            63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 \

            65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 \

            67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 \

            69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68"

 

#IPv6/UDP

testStr7 = "60 00 00 00 02 A5 11 40 20 01 00 00 00 00 00 02 00 00 00 00 00 00 00 01 20 \

            01 00 00 00 00 00 02 00 00 00 00 00 00 00 02 13 C4 13 C4 02 A5 46 E5"

 

 

pktStr = testStr4       

pktStr = pktStr.replace(" ","")

pktStr = pktStr.replace("\n","")

pktStrBytes = bytearray(binascii.a2b_hex(pktStr))

 

if((pktStrBytes[0] & 0xF0) == 0x60) : # Decode IPv6 Header

   payloadLength,nextHeader = decodeIPv6Header(pktStrBytes,fHandleOut)

   

if nextHeader == 6 : # Decode TCP Header if it is in the packet

   tcpByteAry = pktStrBytes[40:40+payloadLength]

   unusedBytes = decodeTcpHeader(tcpByteAry,fHandleOut)

elif nextHeader == 17 : # Decode UDPHeader if it is in the packet

   udpByteAry = pktStrBytes[40:40+payloadLength]

   unusedBytes = decodeUdpHeader(udpByteAry,fHandleOut)   

elif nextHeader == 58 : # Decode ICMPv6 Header if it is in the packet

   icmpByteAry = pktStrBytes[40:40+payloadLength]

   if icmpByteAry[0] == 133 : # Decode Router Solicitation Packet if it is in the ICMPv6 Packet

      decodeRouterSolicitation(icmpByteAry,fHandleOut)

   elif icmpByteAry[0] == 134 : # Decode Router Advertisement Packet if it is in the ICMPv6 Packet

      decodeRouterAdvertisement(icmpByteAry,fHandleOut)

   elif icmpByteAry[0] == 128 : # Decode Ping Request Packet if it is in the ICMPv6 Packet

      decodePing6Request(icmpByteAry,fHandleOut)

   elif icmpByteAry[0] == 129 : # Decode Ping Reply Packet if it is in the ICMPv6 Packet

      decodePing6Reply(icmpByteAry,fHandleOut)   

else :

    print("No further decoding for Next Header")

 

fHandleOut.close()

 

 

Result > ---------------------------------------------------------

 

IPv6 Header ====================================================

Version : 6

Traffic Class :  00000000(Bin)

FlowLabel : 00000000000000000000(Bin)

payloadLen : 357(Dec)

Next Header : 6(Dec) : TCP

Hop Limit : 64(Dec)

Source Address : 2001:0:0:1:4C16:9C0F:4986:9E6D

Destination Address : 2001:0:0:1:0:0:0:2

TCP Header =========================================

Source Port : 44876(Dec)

Destination Port : 5060(Dec)

Sequence Number : 63CBD0BC(HEX) - 1674301628(Dec)

Acknowledgement Number : 2C723079(HEX) - 745681017(Dec)

Data Offset (Header Length) : 32(Bytes)

Flags : 018(HEX) : 000000011000(BIN)-----

    000. .... .... = Reserved

    ...0 .... .... = Nonce

    .... 0... .... = Congestion Window Reduced(CWR)

    .... .0.. .... = ECN-Echo

    .... ..0. .... = Urgent

    .... ...1 .... = Acknowlegment

    .... .... 1... = Push

    .... .... .0.. = Reset

    .... .... ..0. = Syn

    .... .... ...0 = Fin

Window Size Value : 211(DEC)

Checksum : 63BF(HEX)

Urgent Pointer : 0000(HEX)

TCP Option : 0101080A0000E9150001CC55(HEX)