Introduction
Let us see with example How to decode IPv6 header. We will get to know the structure of IPv6 header and number/string manipulation in Python. I will try to keep it simple and easy to understand code it might not be efficiently optimized.
In gray box i have a IPv6 byte array to decode The purpose of this example is to decode Byte Array marked in Red in the wireshark log shown below and then compare the program output with Wireshark.
Wireshark Log
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 ……..}&….
Python Script
# 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")
Output
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
Python Script Function to decode IPv6 Header
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()
Output
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)