proc getOneLine {} { global convertBuffer global convertLine if {[string length $convertLine] > 0} { set a $convertLine set convertLine "" return $a } set i [string first "\n" $convertBuffer] set o [string length $convertBuffer] if {$o < 1} { return "" } set o [expr $o + 32] if {$i < 0} { set i $o } set a [string range $convertBuffer 0 [expr $i - 1]] set convertBuffer [string range $convertBuffer [expr $i + 1] $o] return $a } proc putBackLine {a} { global convertLine set convertLine $a } proc getNextLine {} { global convertBuffer for {set a ""} {[string length $a] < 1} {} { if {[string length $convertBuffer] < 1} { return "" } set a [getOneLine] } return $a } proc testHeadingLine {a} { set b [string range $a 2 2] if {[string compare $b ":"] != 0} { return 0 } set b [string range $a 5 5] if {[string compare $b ":"] != 0} { return 0 } set b [string range $a 8 8] if {[string compare $b "."] != 0} { return 0 } return 1 } proc testDataLine {a} { set b [string range $a 8 8] if {[string compare $b ":"] != 0} { return 0 } return 1 } proc readUpOnePacket {} { for {set a ""} {[testHeadingLine $a] != 1} {} { set a [getNextLine] if {[string length $a] < 1} { return "" } } set a [string range $a 0 7] set ret "" for {} {1==1} {} { set a [getNextLine] if {[string length $a] < 1} { break } if {[testDataLine $a] != 1} { putBackLine $a break } set a [string range $a 9 45] regsub -all " " $a "" b set b [string tolower $b] for {} {[string length $b] > 1} {} { set a [string range $b 0 1] set b [string range $b 2 99] set ret "$ret$a" } } return "$ret" } proc readByte {a o} { set o [expr $o*2] set a [string range $a $o 6666] if {[string length $a] < 1} {set a "0"} set a "0x[string range $a 0 1]" set a [expr $a] return $a } proc readWord {a o} { set o [expr $o*2] set a [string range $a $o 6666] if {[string length $a] < 1} {set a "0"} set a "0x[string range $a 0 3]" set a [expr $a] return $a } proc readLong {a o} { set o [expr $o*2] set a [string range $a $o 6666] if {[string length $a] < 1} {set a "0"} set a "0x[string range $a 0 7]" set a [expr $a] return $a } proc readAddr4 {a o} { set o [expr $o*2] set a [string range $a $o 6666] return "[readByte $a 0].[readByte $a 1].[readByte $a 2].[readByte $a 3]" } proc readAddr6 {a o} { set o [expr $o*2] set a [string range $a $o 6666] set b "[string range $a 0 3]:[string range $a 4 7]:" set b "$b[string range $a 8 11]:[string range $a 12 15]:" set b "$b[string range $a 16 19]:[string range $a 20 23]:" set b "$b[string range $a 24 27]:[string range $a 28 31]" return $b } proc addFlagsValue {flg val nam} { global packetVerb set flg [expr $flg & $val] if {$flg == 0} { set nam [string tolower $nam] } else { set nam [string toupper $nam] } set packetVerb "$packetVerb$nam " } proc doDisTCPpack {pack} { global packetSimp global packetVerb set a [readWord $pack 0] set b [readWord $pack 2] set packetSimp "$packetSimp tcp: $a --> $b" set packetVerb "$packetVerb\TCP header\n source=$a\n destination=$b\n" set a [readLong $pack 4] set b [readLong $pack 8] set offs [readByte $pack 12] set offs [expr ($offs >> 4)*4] set data [string length $pack] set data [expr ($data/2) - $offs] set packetVerb "$packetVerb sequence=0x[format "%08x" $a] (next=0x[format "%08x" [expr $data+$a]])\n" set packetVerb "$packetVerb acknowledge=0x[format "%08x" $b]\n" set packetVerb "$packetVerb data offset=$offs (data size=$data)\n flags=" set flg [readWord $pack 12] addFlagsValue $flg 0x01 fin addFlagsValue $flg 0x02 syn addFlagsValue $flg 0x04 rst addFlagsValue $flg 0x08 psh addFlagsValue $flg 0x10 ack addFlagsValue $flg 0x20 urg addFlagsValue $flg 0x40 ece addFlagsValue $flg 0x80 cwr set a [readWord $pack 14] set b [readWord $pack 16] set c [readWord $pack 18] set packetVerb "$packetVerb\n window size=$a\n" set packetVerb "$packetVerb checksum=0x[format "%04x" $b]\n" set packetVerb "$packetVerb urgent pointer=$c\n" set packetSimp "$packetSimp data: $data" set a "" if {[expr $flg & 1] !=0} { set a "$a fin" } if {[expr $flg & 2] !=0} { set a "$a syn" } if {[expr $flg & 4] !=0} { set a "$a rst" } set packetSimp "$packetSimp$a" } proc doDisUDPpack {pack} { global packetSimp global packetVerb set a [readWord $pack 0] set b [readWord $pack 2] set c [readWord $pack 4] set d [readWord $pack 6] set e [expr $c - 8] set packetSimp "$packetSimp udp: $a --> $b data: $e" set packetVerb "$packetVerb\UDP header\n source=$a\n destination=$b\n" set packetVerb "$packetVerb length=$c\n checksum=0x[format "%04x" $d]\n" } proc doDisICMP4pack {pack} { global packetSimp global packetVerb set a [readByte $pack 0] set b [readByte $pack 1] set c [readWord $pack 2] if {$a == 8} {set a "echo-request"} if {$a == 0} {set a "echo-reply"} set packetSimp "$packetSimp icmp: type=$a" set packetVerb "$packetVerb\ICMPv4 header\n type=$a\n code=$b\n checksum=0x[format "%04x" $c]\n" } proc doDisICMP6pack {pack} { global packetSimp global packetVerb set a [readByte $pack 0] set b [readByte $pack 1] set c [readWord $pack 2] if {$a == 128} {set a "echo-request"} if {$a == 129} {set a "echo-reply"} if {$a == 135} {set a "neighbor solicit"} if {$a == 136} {set a "neighbor advertise"} set packetSimp "$packetSimp icmp: type=$a" set packetVerb "$packetVerb\ICMPv6 header\n type=$a\n code=$b\n checksum=0x[format "%04x" $c]\n" } proc doDisUPPERpack {prot pack} { if {$prot == 17 } { doDisUDPpack $pack return } if {$prot == 6 } { doDisTCPpack $pack return } if {$prot == 1 } { doDisICMP4pack $pack return } if {$prot == 58 } { doDisICMP6pack $pack return } } proc doDisIP4pack {pack} { global packetSimp global packetVerb set packetSimp "$packetSimp ip4:" set a [readByte $pack 0] set b [expr $a >> 4] set head [expr ($a & 15)*4] set packetVerb "$packetVerb\IPv4 header\n version=$b\n header length=$head\n" if {$b != 4} return set a [readByte $pack 1] set packetVerb "$packetVerb type of service=0x[format "%02x" $a]\n" set a [readWord $pack 2] set c [readWord $pack 4] set packetVerb "$packetVerb total length=$a\n identification=0x[format "%04x" $c]\n" set b [expr ($a*2)-1] set pack [string range $pack 0 $b] set a [readWord $pack 6] set packetVerb "$packetVerb fragment offset=[expr $a & 0x1fff]\n flags=" addFlagsValue $a 0x4000 dontfrag addFlagsValue $a 0x2000 morefrag set a [readByte $pack 8] set prot [readByte $pack 9] set c [readWord $pack 10] set packetVerb "$packetVerb\n time to live=$a\n protocol=$prot\n checksum=0x[format "%04x" $c]\n" set a [readAddr4 $pack 12] set b [readAddr4 $pack 16] set packetVerb "$packetVerb source=$a\n destination=$b\n" set packetSimp "$packetSimp $a --> $b" set a [expr $head*2] set a [string range $pack $a 6666] doDisUPPERpack $prot $a } proc doDisIP6pack {pack} { global packetSimp global packetVerb set packetSimp "$packetSimp ip6:" set a [readByte $pack 0] set a [expr $a >> 4] set packetVerb "$packetVerb\IPv6 header\n version=$a\n" if {$a != 6} return set a [readWord $pack 0] set a [expr ($a >> 4) & 0xff] set packetVerb "$packetVerb traffic class=0x[format "%02x" $a]\n" set a [readLong $pack 0] set a [expr $a & 0xfffff] set packetVerb "$packetVerb flow label=0x[format "%05x" $a]\n" set a [readWord $pack 4] set packetVerb "$packetVerb payload length=$a\n" set a [expr (($a+40)*2)-1] set pack [string range $pack 0 $a] set prot [readByte $pack 6] set a [readByte $pack 7] set packetVerb "$packetVerb next header=$prot\n hop limit=$a\n" set a [readAddr6 $pack 8] set b [readAddr6 $pack 24] set packetVerb "$packetVerb source=$a\n destination=$b\n" set packetSimp "$packetSimp $a --> $b" set a [string range $pack 80 6666] doDisUPPERpack $prot $a } proc doDisOnePack {pack} { global packetSimp global packetVerb set packetSimp "" set packetVerb "" # ethernet starts at 24, serial starts at 2... set pack [string range $pack 24 6666] set a [readWord $pack 0] if {$a == 0x8100} { set a [readWord $pack 2] set a [expr $a & 0xfff] set packetVerb "$packetVerb\802.1q header\n vlan=$a\n" set pack [string range $pack 8 6666] set a [readWord $pack 0] } if {$a == 0x800} { doDisIP4pack [string range $pack 4 6666] return } if {$a == 0x86dd} { doDisIP6pack [string range $pack 4 6666] return } if {$a < 0x800} { set packetSimp "llc" return } if {$a < 0x806} { set packetSimp "arp" return } set packetSimp "unknown ethertype: 0x[format "%04x" $a]" return } proc doDissectBuffer {dataIn verb} { global convertBuffer global convertLine global packetSimp global packetVerb set convertBuffer $dataIn set convertLine "" set dataOut "" for {} {1==1} {} { set a [readUpOnePacket] if {[string length $a] < 1} { break } doDisOnePack $a if {[string length $packetSimp] < 1} { continue } puts $packetSimp if {$verb != 0} { puts $packetVerb } } return $dataOut } proc doDissectFile {ni verb} { puts "reading file $ni..." set f [open "$ni" "r"] set di [read $f] close $f puts "dissecting data..." doDissectBuffer $di $verb } proc doDissectShow {bi verb} { puts "reading buffer $bi..." set di [exec show monitor capture buffer $bi dump] puts "dissecting data..." doDissectBuffer $di $verb } # doDissectShow b1 0 doDissectFile cap.in 1