📄 ethernet.tcl
字号:
switch -- $type { 0 { append icmpv4_msg "network" } 1 { append icmpv4_msg "host" } 2 { append icmpv4_msg "tos & network" } 3 { append icmpv4_msg "tos & host" } default { append icmpv4_msg "unknown" } } set error 1 } 8 { append icmpv4_msg "ping request" if { [string length $packet] >= 8 } { binary scan $packet {iss} junk id seq append icmpv4_msg [format " id %u, seq %u" [expr $id & 0x0FFFF] [expr $seq & 0x0FFFF]] set data 1 set packet [string range $packet 8 end] } } 9 { append icmpv4_msg "router advertisement" } 10 { append icmpv4_msg "router solicitation" } 11 { append icmpv4_msg "time exceeded/" switch -- $type { 0 { append icmpv4_msg "transit" } 1 { append icmpv4_msg "reassembly" } default { append icmpv4_msg "unknown" } } set error 1 } 12 { append icmpv4_msg "parameter problem/" switch -- $type { 0 { append icmpv4_msg "IP header bad" } 1 { append icmpv4_msg "required option missing" } default { append icmpv4_msg "unknown" } } set error 1 } 13 { append icmpv4_msg "timestamp request" } 14 { append icmpv4_msg "timestamp reply" } 15 { append icmpv4_msg "information request" } 16 { append icmpv4_msg "information reply" } 17 { append icmpv4_msg "address mask request" } 18 { append icmpv4_msg "address mask reply" } default { append icmpv4_msg "unknown" } } if { $error && ([string length $packet] >= 36) } { # The ICMP message contains an IP header and hopefully the TCP or UDP ports as well # Only deal with the simple cases. binary scan $packet {iiccSiccSIISS} icmp_junk1 icmp_junk2 ip_lenver ip_junk1 ip_junk2 ip_junk3 ip_junk4 ip_protocol ip_junk5 \ ip_source ip_dest ip_source_port ip_dest_port if { (5 == ($ip_lenver & 0x0F)) && ((6 == $ip_protocol) || (17 == $ip_protocol)) } { if { 6 == $ip_protocol } { append icmpv4_msg ", tcp" } else { append icmpv4_msg ", udp" } append icmpv4_msg " >[ethernet::inet_ipv4_ntoa $ip_dest]:$ip_dest_port <[ethernet::inet_ipv4_ntoa $ip_source]:$ip_source_port" } } append icmpv4_msg "\n" synth::output $icmpv4_msg "eth_icmpv4" # Only some of the requests contain additional data that should be displayed if { !$data } { return } } elseif { 58 == $ip_protocol } { # ipv6 ICMP if { [string length $packet] < 4 } { return } binary scan $packet {ccS} code type checksum set icmpv6_msg "$device $direction: ICMPv6 " set error 0 set data 0 switch -- $code { 1 { append icmpv6_msg "unreachable/" switch -- $type { 0 { append icmpv6_msg "no route" } 1 { append icmpv6_msg "prohibited" } 2 { append icmpv6_msg "not a neighbour" } 3 { append icmpv6_msg "any other reason" } 4 { append icmpv6_msg "UDP port unreachable" } default { append icmpv6_msg "unknown" } } set error 1 } 2 { append icmpv6_msg "packet too big" set error 1 } 3 { append icmpv6_msg "time exceeded/" switch -- $type { 0 { append icmpv6_msg "hop limit" } 1 { append icmpv6_msg "fragment reassembly" } default { append icmpv6_msg "unknown" } } set error 1 } 4 { append icmpv6_msg "parameter problem" switch -- $type { 0 { append icmpv6_msg "erroneous header" } 1 { append icmpv6_msg "unrecognized next header" } 2 { append icmpv6_msg "unrecognized option" } default { append icmpv6_msg "unknown" } } set error 1 } 128 { append icmpv6_msg "ping request" # FIXME: is this the same format as for icmpv4? } 129 { append icmpv6_msg "ping reply" # FIXME: is this the same format as for icmpv4? } 130 { append icmpv6_msg "group membership query" } 131 { append icmpv6_msg "group membership report" } 132 { append icmpv6_msg "group membership reduction" } 133 { append icmpv6_msg "router solicitation" } 134 { append icmpv6_msg "router advertisement" } 135 { append icmpv6_msg "neighbour solicitation" } 136 { append icmpv6_msg "neighbour advertisement" } 137 { append icmpv6_msg "redirect" } } if { $error && ([string length $packet] >= 44) } { # The ICMP message contains an IPv6 header and hopefully the TCP or UDP ports as well binary scan $packet {isccH16H16SS} icmp_junk1 icmp_junk2 ip_protocol icmp_junk3 ip_source ip_dest ip_source_port ip_dest_port if { 6 == $ip_protocol } { append icmpv6_msg ", tcp" } elseif { 17 == $ip_protocol } { append icmpv6_msg ", udp" } append icmpv6_msg " >[ethernet::inet_ipv4_ntoa $ip_dest]:$ip_dest_port <[ethernet::inet_ipv6_ntoa $ip_source]:$ip_source_port" } append icmpv6_msg "\n" synth::output $icmpv6_msg "eth_icmpv6" if { !$data } { return } } elseif { 6 == $ip_protocol } { # TCP if { [string length $packet] < 20 } { return } binary scan $packet {SSIIccSSS} source_port dest_port seq ack hdrsize flags winsize checksum urg set source_port [expr $source_port & 0x0FFFF] set dest_port [expr $dest_port & 0x0FFFF] set hdrsize [expr ($hdrsize >> 4) & 0x0F] set winsize [expr $winsize & 0x0FFFF] set urg [expr $urg & 0x0FFFF] set tcp_msg "$device $direction tcp: " append tcp_msg " >${dest_name}:${dest_port}" if { [info exists ethernet::services($dest_port,udp)] } { append tcp_msg "($ethernet::services($dest_port,udp))" } append tcp_msg "<${source_name}:$source_port" if { [info exists ethernet::services($source_port,udp)] } { append tcp_msg "($ethernet::services($source_port,udp))" } append tcp_msg ", " if { $flags & 0x08 } { append tcp_msg "PSH " } if { $flags & 0x04 } { append tcp_msg "RST " } if { $flags & 0x02 } { append tcp_msg "SYN " } if { $flags & 0x01 } { append tcp_msg "FIN " } append tcp_msg [format "seq %u" $seq] if { 0 != ($flags & 0x010) } { append tcp_msg [format ", ACK %u" $ack] } append tcp_msg ", win $winsize" if { 0 != ($flags & 0x020) } { append tcp_msg ", URG $urg" } append tcp_msg "\n" synth::output $tcp_msg "eth_tcp" set packet [string range $packet [expr 4 * $hdrsize] end] } elseif { 17 == $ip_protocol } { # UDP if { [string length $packet] < 8 } { return } set udp_msg "$device $direction: udp " binary scan $packet {SSSS} source_port dest_port len checksum set source_port [expr $source_port & 0x0FFFF] set dest_port [expr $dest_port & 0x0FFFF] append udp_msg [format "%d bytes, " [expr $len & 0x0FFFF]] append udp_msg " >${dest_name}:$dest_port" if { [info exists ethernet::services($dest_port,udp)] } { append udp_msg "($ethernet::services($dest_port,udp))" } append udp_msg "<${source_name}:$source_port" if { [info exists ethernet::services($source_port,udp)] } { append udp_msg "($ethernet::services($source_port,udp))" } append udp_msg "\n" synth::output $udp_msg "eth_udp" set packet [string range $packet 8 end] } else { # Unknown protocol, so no way of knowing where the data starts. return } # At this point we may have a payload. This should be # dumped in both hex and ascii. The code tries to preserve # alignment. if { [string length $packet] == 0 } { return } set hexdata_msg "$device $direction: data [format_hex_data $packet]\n" set asciidata_msg "$device $direction: data " set len [string length $packet] if { $len > $ethernet::max_show } { set len $ethernet::max_show } for { set i 0 } { $i < $len } { incr i } { set char [string index $packet $i] if { "\r" == $char } { append asciidata_msg "\\r" } elseif { "\n" == $char } { append asciidata_msg "\\n" } elseif { "\t" == $char } { append asciidata_msg "\\t" } elseif { [string is print -strict $char] } { append asciidata_msg " $char" } else { append asciidata_msg "??" } if { 3 == ($i % 4) } { append asciidata_msg " " } } append asciidata_msg "\n" synth::output $hexdata_msg "eth_hexdata" synth::output $asciidata_msg "eth_asciidata" return } # A utility for handling the ethernet record button on the toolbar proc logging_button_toggle { } { if { $ethernet::logging_enabled } { set ethernet::logging_enabled 0 .toolbar.ethernet_logging configure -relief flat } else { set ethernet::logging_enabled 1 .toolbar.ethernet_logging configure -relief sunken } } # A dummy procedure for initialization. All of this could execute at # the toplevel, but there are lots of locals. proc filters_initialize { } { ethernet::read_services ethernet::read_protocols ethernet::read_hosts # Add a button on the toolbar for enabling/disabling logging. # Also add an entry to the help menu if { $synth::flag_gui } { button .toolbar.ethernet_logging -image $ethernet::image_netrecord -borderwidth 2 -relief flat -command ethernet::logging_button_toggle pack .toolbar.ethernet_logging -side left -padx 2 synth::register_balloon_help .toolbar.ethernet_logging "Record ethernet traffic" if { [synth::tdf_has_option "ethernet" "logging"] } { set ethernet::logging_enabled [synth::tdf_get_option "ethernet" "logging"] } else { # Default to logging ethernet traffic. This may not be the right thing to do # because users may see too much output by default, but it is easy enough # to disable. set ethernet::logging_enabled 1 } if { $ethernet::logging_enabled } { .toolbar.ethernet_logging configure -relief sunken } set ethernet_help [file join $synth::device_src_dir "doc" "devs-eth-synth-ecosynth.html"] if { ![file readable $ethernet_help] } { synth::report_warning "Failed to locate synthetic ethernet documentation $ethernet_help\n \ Help->Ethernet target menu option disabled.\n" set ethernet_help "" } if { "" == $ethernet_help } { .menubar.help add command -label "Ethernet" -state disabled } else { .menubar.help add command -label "Ethernet" -command [list synth::handle_help "file://$ethernet_help"] } } if { [synth::tdf_has_option "ethernet" "max_show"] } { set ethernet::max_show [synth::tdf_get_option "ethernet" "max_show"] if { ! [string is integer -strict $ethernet::max_show] } { synth::report_error "Ethernet device, invalid value in target definition file $synth::target_definition\n \ Entry max_show should be a simple integer, not $ethernet::max_show\n" set ethernet::init_ok 0 } } # Filters. First, perform some validation. set known_filters [list "ether" "arp" "ipv4" "ipv6" "icmpv4" "icmpv6" "udp" "tcp" "hexdata" "asciidata"] set tdf_filters [synth::tdf_get_options "ethernet" "filter"] array set filter_options [list] foreach filter $tdf_filters { if { 0 == [llength $filter] } { synth::report_error "Ethernet device, invalid value in target definition file $synth::target_definition\n \ Option \"filter\" requires the name of a known filters.\n" set ethernet::init_ok 0 continue } set name [lindex $filter 0] if { [info exists filter_options($name)] } { synth::report_error "Ethernet device, invalid value in target definition file $synth::target_definition\n \ \"filter $name\" should be defined only once.\n" set ethernet::init_ok 0 continue } if { -1 == [lsearch -exact $known_filters $name] } { synth::report_error "Ethernet device, invalid value in target definition file $synth::target_definition\n \ Unknown filter \"$name\".\n \ Known filters are $known_filters\n" set ethernet::init_ok 0 continue } set filter_options($name) [lrange $filter 1 end] } # We now know about all the filter entries in the target definition file. # Time to create the filters themselves, provided we are running in GUI mode. if { $synth::flag_gui } { foreach filter $known_filters { if { ! [info exists filter_options($filter)] } { synth::filter_add "eth_$filter" -text "ethernet $filter" } else { array set parsed_options [list] set message "" if { ![synth::filter_parse_options $filter_options($filter) parsed_options message] } { synth::report_error \ "Invalid entry in target definition file $synth::target_definition\n \ Ethernet filter $filter\n $message" set ethernet::init_ok 0 } else { set parsed_options("-text") "ethernet $filter" synth::filter_add_parsed "eth_$filter" parsed_options } } } } } ethernet::filters_initialize}return ethernet::instantiate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -