⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethernet.tcl

📁 开放源码实时操作系统源码.
💻 TCL
📖 第 1 页 / 共 3 页
字号:
		    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 + -