4 namespace eval excentis {
14 namespace eval basic {
26 proc Frame.Udpv6.Set { DMAC SMAC DIP SIP DP SP dataOrLength {params DEFAULT} } {
69 if { ![ string equal -nocase $params "DEFAULT" ]} {
70 foreach {item value} $params {
71 switch -- [
string tolower $item ] {
73 -ethernet { set Ethernet $value }
74 default { error "Frame.Udpv6.Set: Invalid param '${item}'" }
81 set dataLength [
llength $data ]
84 set length [
expr ( 8 + $dataLength ) ]
88 set PH [
concat $PH1 $PH2 $PH3 ]
91 set PHH [
concat $PH $H1 $H2 ]
92 set H [
concat $H1 $H2 ]
93 set myContent [
concat $PHH $data ]
94 if { [ expr ( [ llength $myContent ] % 2 ) ]} {
95 lappend myContent 0x00
98 set myContent [
concat $H $data ]
99 set myContent [
eval lreplace {$myContent} 6 7 $checkSum ]
102 set myContent [
Frame.Ipv6.Set $DMAC $SMAC $DIP $SIP 17 $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
110 proc Frame.Udp.Set {DMAC SMAC DIP SIP DP SP dataOrLength { params DEFAULT }} {
151 if { ![ string equal -nocase $params "DEFAULT" ]} {
152 foreach {item value} $params {
153 switch -- [
string tolower $item ] {
154 -ip { set IP $value }
155 -ethernet { set Ethernet $value }
156 default { error "Frame.Udp.Set: Invalid param '${item}'" }
163 set dataLength [
llength $data ]
164 if { $dataLength < 4} {
165 error "Frame.Udp.Set: data length must be > 4"
169 set length [
expr ( 8 + $dataLength ) ]
173 set PH [
concat $PH1 $PH2 $PH3 ]
176 set PHH [
concat $PH $H1 $H2 ]
177 set H [
concat $H1 $H2 ]
178 set myContent [
concat $PHH $data ]
179 if { [ expr ( $length % 2 ) ]} {
180 lappend myContent 0x00
183 set myContent [
concat $H $data ]
184 set myContent [
eval lreplace {$myContent} 6 7 $checkSum ]
187 set myContent [
Frame.Ipv4.Set $DMAC $SMAC $DIP $SIP 17 $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
195 proc Frame.Tcp.Set { DMAC SMAC DIP SIP DP SP dataOrLength { params DEFAULT } } {
241 set TCPSeq [ list 0x10 0x00 0x01 0xa3 ]
242 set TCPAck [ list 0x10 0x00 0x01 0xa0 ]
244 set TCPByte1314 [ list 0x50 0x00 ]
245 set TCPUrgent [ list 0x00 0x00 ]
247 if { ![ string equal -nocase $params "DEFAULT" ]} {
248 foreach {item value} $params {
249 switch -- [
string tolower $item ] {
250 -tcp { set TCP $value }
251 -ip { set IP $value }
252 -ethernet { set Ethernet $value }
253 default { error "Frame.Tcp.Set: Invalid param '${item}'" }
258 if { ![ string equal -nocase $TCP "DEFAULT" ]} {
259 foreach {item value} $TCP {
260 switch -- [
string tolower $item ] {
261 -tcpseq { set TCPSeq $value }
262 -tcpack { set TCPAck $value }
263 -tcpwindow { set TCPWindow $value }
264 -tcpbyte1314 { set TCPByte1314 $value }
265 -tcpurgent { set TCPUrgent $value }
266 default { error "Frame.Tcp.Set: Invalid TCP option '${item}'" }
273 error "Frame.Tcp.Set: Invalid TCPSeq '$TCPSeq', expecting 4 bytes"
278 error "Frame.Tcp.Set: Invalid TCPAck '$TCPAck', expecting 4 bytes"
282 if { [ string equal $TCPWindow "" ] || ![
string is integer $TCPWindow ] || $TCPWindow < 0 || $TCPWindow > 0xFFFF} {
283 error "Frame.Tcp.Set: Invalid TCPWindow value '$TCPWindow', MUST be <= 0xFFFF"
287 if { [ llength $TCPByte1314 ] != 2 || ![
ByteList.Check $TCPByte1314 ]} {
288 error "Frame.Tcp.Set: Invalid TCPByte1314 '$TCPByte1314', expecting 2 bytes"
292 if { [ llength $TCPUrgent ] != 2 || ![
ByteList.Check $TCPUrgent ]} {
293 error "Frame.Tcp.Set: Invalid TCPUrgent '$TCPUrgent', expecting 2 bytes"
299 set length [
expr ( 20 + [
llength $data ] ) ]
304 set PH [
concat $PH1 $PH2 $PH3 ]
309 set H4 [
concat $TCPByte1314 [
Short.To.Hex $TCPWindow ] ]
310 set H5 [
concat 0x00 0x00 $TCPUrgent ]
312 set PHH [
concat $PH $H1 $H2 $H3 $H4 $H5 ]
313 set H [
concat $H1 $H2 $H3 $H4 $H5 ]
314 set myContent [
concat $PHH $data ]
315 if { [ expr ( $length % 2 ) ]} {
316 lappend myContent 0x00
319 set myContent [
concat $H $data ]
320 set myContent [
eval lreplace {$myContent} 16 17 $checkSum ]
322 set myContent [
Frame.Ipv4.Set $DMAC $SMAC $DIP $SIP 6 $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
330 proc Frame.Tcpv6.Set { DMAC SMAC DIP SIP DP SP dataOrLength { params DEFAULT } } {
377 set TCPSeq [ list 0x10 0x00 0x01 0xa3 ]
378 set TCPAck [ list 0x10 0x00 0x01 0xa0 ]
380 set TCPByte1314 [ list 0x50 0x00 ]
381 set TCPUrgent [ list 0x00 0x00 ]
383 if { ![ string equal -nocase $params "DEFAULT" ]} {
384 foreach {item value} $params {
385 switch -- [
string tolower $item ] {
386 -tcp { set TCP $value }
387 -ip { set IP $value }
388 -ethernet { set Ethernet $value }
389 default { error "Frame.Tcpv6.Set : Invalid param '${item}'" }
394 if { ![ string equal -nocase $TCP "DEFAULT" ]} {
395 foreach {item value} $TCP {
396 switch -- [
string tolower $item ] {
397 -tcpseq { set TCPSeq $value }
398 -tcpack { set TCPAck $value }
399 -tcpwindow { set TCPWindow $value }
400 -tcpbyte1314 { set TCPByte1314 $value }
401 -tcpurgent { set TCPUrgent $value }
402 default { error "Frame.Tcpv6.Set: Invalid TCP option '${item}'" }
409 error "Frame.Tcpv6.Set: Invalid TCPSeq '$TCPSeq', expecting 4 bytes"
414 error "Frame.Tcpv6.Set: Invalid TCPAck '$TCPAck', expecting 4 bytes"
418 if { [ string equal $TCPWindow "" ] || ![
string is integer $TCPWindow ] || $TCPWindow < 0 || $TCPWindow > 0xFFFF} {
419 error "Frame.Tcpv6.Set: Invalid TCPWindow value '$TCPWindow', MUST be <= 0xFFFF"
423 if { [ llength $TCPByte1314 ] != 2 || ![
ByteList.Check $TCPByte1314 ]} {
424 error "Frame.Tcpv6.Set: Invalid TCPByte1314 '$TCPByte1314', expecting 2 bytes"
428 if { [ llength $TCPUrgent ] != 2 || ![
ByteList.Check $TCPUrgent ]} {
429 error "Frame.Tcpv6.Set: Invalid TCPUrgent '$TCPUrgent', expecting 2 bytes"
435 set length [
expr ( 20 + [
llength $data ] ) ]
439 set PH [
concat $PH1 $PH2 $PH3 ]
444 set H4 [
concat $TCPByte1314 [
Short.To.Hex $TCPWindow ] ]
445 set H5 [
concat 0x00 0x00 $TCPUrgent ]
447 set PHH [
concat $PH $H1 $H2 $H3 $H4 $H5 ]
448 set H [
concat $H1 $H2 $H3 $H4 $H5 ]
449 set myContent [
concat $PHH $data ]
450 if { [ expr ( $length % 2 ) ]} {
451 lappend myContent 0x00
454 set myContent [
concat $H $data ]
455 set myContent [
eval lreplace {$myContent} 16 17 $checkSum ]
457 set myContent [
Frame.Ipv6.Set $DMAC $SMAC $DIP $SIP 6 $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
465 proc Frame.Igmp.Set { SMAC SIP Type GroupAddress { params DEFAULT } } {
566 if { ![ string equal -nocase $params "DEFAULT" ]} {
567 foreach {item value} $params {
568 switch -- [
string tolower $item ] {
569 -igmp { set IGMP $value }
570 -ip { set IP $value }
571 -ethernet { set Ethernet $value }
572 default { error "Frame.Igmp.Set: Invalid param '${item}'" }
577 set maxResponseTime 0
578 set sourceAddressList [ list ]
579 if { ![ string equal -nocase $IGMP "DEFAULT" ]} {
580 foreach {item value} $IGMP {
581 switch -- [
string tolower $item ] {
582 -maxresptime { set maxResponseTime $value }
583 -sourceaddresslist { set sourceAddressList $value }
584 default { error "Frame.Igmp.Set: Invalid IGMP option '${item}'" }
590 0 { set DIP $GroupAddress }
591 1 { set DIP $GroupAddress }
592 2 { set DIP 224.0.0.2 }
593 3 { set DIP 224.0.0.1 }
594 4 { set DIP $GroupAddress }
595 5 { set DIP 224.0.0.22 }
596 6 { set DIP 224.0.0.22 }
597 7 { set DIP 224.0.0.1 }
598 8 { set DIP $GroupAddress }
621 set IgmpIpOptions [ list -TTL 1 -IPOptions [ list 0x94 0x04 0x00 0x00 ] ]
622 if { [ string equal -nocase $IP "DEFAULT" ]} {
623 set IP $IgmpIpOptions
625 set IP [
eval list $IgmpIpOptions $IP ]
644 set IGMPPart1 { 0x12 0x00 }
645 set IGMPPart2 [
IP.To.Hex $GroupAddress ]
649 set IGMPPart1 { 0x16 0x00 }
650 set IGMPPart2 [
IP.To.Hex $GroupAddress ]
653 set IGMPPart1 { 0x17 0x00 }
654 set IGMPPart2 [
IP.To.Hex $GroupAddress ]
657 set IGMPPart1 [ list 0x11 [
Byte.To.Hex $maxResponseTime ] ]
658 set IGMPPart2 [ list 0x00 0x00 0x00 0x00 ]
661 set IGMPPart1 [ list 0x11 [
Byte.To.Hex $maxResponseTime ] ]
662 set IGMPPart2 [
IP.To.Hex $GroupAddress ]
665 # --- IGMPv3 Membership Report message
666 set IGMPPart1 [ list 0x22 0x00 ]
667 set nrOfGroupRecords 1
668 if { [
llength $sourceAddressList ] > 0 } { set recordType 0x05 } else { set recordType 0x02 }
672 # --- IGMPv3 Leave Group message
673 set IGMPPart1 [ list 0x22 0x00 ]
674 if { [
llength $sourceAddressList ] > 0 } { set recordType 0x06 } else { set recordType 0x01 }
675 set nrOfGroupRecords 1
679 # --- IGMPv3 General Membership Query
680 set IGMPPart1 [ list 0x11 [
Byte.To.Hex $maxResponseTime ] ]
681 set IGMPPart2 " 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 "
684 # --- IGMPv3 Group-Specific Membership Query and Group-and-Source-Specific Membership Query
685 set IGMPPart1 [ list 0x11 [
Byte.To.Hex $maxResponseTime ] ]
686 set IGMPPart2 " [
IP.To.Hex $GroupAddress ] 0x00 0x00 [
Short.To.Hex [
llength $sourceAddressList ] ]"
690 set myContent [
concat $IGMPPart1 { 0x00 0x00 } $IGMPPart2 ]
691 set sourceSpecificAdresses [ list ]
692 foreach sourceAddress $sourceAddressList {
693 eval lappend myContent [
IP.To.Hex $address ]
698 set myContent [
eval lreplace { $myContent } 2 3 $checkSum ]
699 puts "IGMP : $myContent"
701 set myContent [
Frame.Ipv4.Set $DMAC $SMAC $DIP $SIP $ipProtocol $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
708 proc Frame.Icmp.Echo.Set { DMAC SMAC DIP SIP ID seqNr dataOrLength { params DEFAULT } } {
755 if { ![ string equal -nocase $params "DEFAULT" ]} {
756 foreach {item value} $params {
757 switch -- [
string tolower $item ] {
758 -icmp { set ICMP $value }
759 -ip { set IP $value }
760 -ethernet { set Ethernet $value }
761 default { error "Frame.Icmp.Echo.Set : Invalid param '${item}'" }
766 if { ![ string equal -nocase $ICMP "DEFAULT" ]} {
767 foreach {item value} $ICMP {
768 switch -- [
string tolower $item ] {
769 -type { set icmpType $value }
770 -code { set icmpCode $value }
771 default { error "Frame.Icmp.Echo.Set: Invalid ICMP option '${item}'" }
777 if { [ string equal $ID "" ] || ![
string is integer $ID ] || $ID < 0 || $ID > 0xFFFF} {
778 error "Frame.Icmp.Echo.Set : Invalid ID value '$ID', MUST be <= 0xFFFF"
782 if { [ string equal $seqNr "" ] || ![
string is integer $seqNr ] || $seqNr < 0 || $seqNr > 0xFFFF} {
783 error "Frame.Icmp.Echo.Set : Invalid seqNr value '$seqNr', MUST be <= 0xFFFF"
792 set H [
concat $H1 $H2 ]
793 set myContent [
concat $H $data ]
795 set myContent [
Frame.Icmp.Set $DMAC $SMAC $DIP $SIP $icmpType $icmpCode $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
803 proc Frame.Icmp.Set { DMAC SMAC DIP SIP Type Code dataOrLength { params DEFAULT } } {
843 if { ![ string equal -nocase $params "DEFAULT" ]} {
844 foreach {item value} $params {
845 switch -- [
string tolower $item ] {
846 -ip { set IP $value }
847 -ethernet { set Ethernet $value }
848 default { error "Frame.Icmp.Set : Invalid param '${item}'" }
854 if { [ string equal $Type "" ] || ![
string is integer $Type ] || $Type < 0 || $Type > 0xFF} {
855 error "Frame.Icmp.Set : Invalid Type value '$Type', MUST be <= 0xFF"
859 if { [ string equal $Code "" ] || ![
string is integer $Code ] || $Code < 0 || $Code > 0xFF} {
860 error "Frame.Icmp.Set : Invalid Code value '$Code', MUST be <= 0xFF"
869 set H [
concat $H1 $H2 ]
870 set PlaceHolder [ list 0x00 0x00 ]
871 set myContent [
concat $H $PlaceHolder $data ]
873 set myContent [
eval lreplace {$myContent} 2 3 $checkSum ]
875 set myContent [
Frame.Ipv4.Set $DMAC $SMAC $DIP $SIP 0x01 $myContent [ list -IP $IP -Ethernet $Ethernet ] ]
883 proc Frame.Ipv4.Set { DMAC SMAC DIP SIP protocol dataOrLength { params DEFAULT } } {
915 set IPIdentif [ list 0x00 0x00 ]
916 set FF [ list 0x00 0x00 ]
918 set IPOptions [ list ]
920 if { ![ string equal -nocase $params "DEFAULT" ]} {
921 foreach { item value } $params {
922 switch -- [
string tolower $item ] {
923 -ip { set IP $value }
924 -ethernet { set Ethernet $value }
925 default { error "Frame.Ipv4.Set: Invalid param '${item}'" }
931 if { ![ string equal -nocase $IP "DEFAULT" ]} {
932 foreach {item value} $IP {
933 switch -- [
string tolower $item ] {
934 -version { set Version $value }
935 -ihl { set IHL $value; set overrideIHL 1 }
936 -ipidentif { set IPIdentif $value }
937 -ttl { set TTL $value }
938 -ff { set FF $value }
939 -tos { set ToS $value }
940 -ipoptions { set IPOptions $value }
941 default { error "Frame.Ipv4.Set: Invalid param '$item'" }
947 if { [ string equal $Version "" ] || ![
string is integer $Version ] || $Version < 0 || $Version > 0xF} {
948 error "Frame.Ipv4.Set: Invalid Version value '$Version', MUST be <= 0xF"
952 if { [ expr ( [ llength $IPOptions ] % 4 ) ] != 0 || ![
ByteList.Check $IPOptions ]} {
953 error "Frame.Ipv4.Set: Invalid IPOptions \`$IPOptions', expecting multiple of 4 bytes"
957 if { $overrideIHL != 1} {
958 set IHL [
expr 5 + ( [
llength $IPOptions ] / 4 ) ]
960 if { [ string equal $IHL "" ] || ![
string is integer $IHL ] || $IHL < 0 || $IHL > 0xF} {
961 error "Frame.Ipv4.Set: Invalid IHL value '$IHL', MUST be <= 0xF"
965 if { [ llength $IPIdentif ] != 2 || ![
ByteList.Check $IPIdentif ]} {
966 error "Frame.Ipv4.Set: Invalid IPIdentif '$IPIdentif', expecting 2 bytes"
970 if { [ string equal $TTL "" ] || ![
string is integer $TTL ] || $TTL < 0 || $TTL > 0xFF} {
971 error "Frame.Ipv4.Set: Invalid TTL value '$TTL', MUST be <= 0xFF"
976 error "Frame.Ipv4.Set: Invalid FF '$FF', expecting 2 bytes"
980 if { [ string equal $ToS "" ] || ![
string is integer $ToS ] || $ToS < 0 || $ToS > 0xFF} {
981 error "Frame.Ipv4.Set: Invalid ToS value '$Tos', MUST be <= 0xFF"
983 set ToS [
format "0x%02x" [
expr $ToS * 1 ] ]
987 set length [
Short.To.Hex [
expr ( 4 * $IHL + [
llength $data ] ) ] ]
989 set H1 [
concat [
format "0x%02x" [
expr ( $Version << 4 ) & 0xF0 | ( $IHL & 0x0F ) ] ] "$ToS" $length ]
990 set H2 [
concat $IPIdentif $FF ]
995 set myContent [
concat $H1 $H2 $H3 $H4 $H5 $H6 ]
998 set myContent [
eval lreplace {$myContent} 10 11 $IPCheckSum ]
999 set myContent [
concat $myContent $data ]
1001 set myContent [
Frame.Mac.Set $DMAC $SMAC 0x0800 $myContent $Ethernet ]
1009 proc Frame.Ipv6.Set {DMAC SMAC DIP SIP nextHeader dataOrLength {params DEFAULT}} {
1035 set Ethernet DEFAULT
1040 set flowLabel [ list 0x00 0x00 0x00 ]
1044 if { ![ string equal -nocase $params "DEFAULT" ]} {
1045 foreach {item value} $params {
1046 switch -- [
string tolower $item ] {
1047 -ip { set IP $value }
1048 -ethernet { set Ethernet $value }
1049 default { error "Frame.Ipv6.Set : Invalid param '${item}'" }
1054 if { ![ string equal -nocase $IP "DEFAULT" ]} {
1055 foreach {item value} $IP {
1056 switch -- [
string tolower $item ] {
1057 -version { set version $value }
1058 -trafclass { set trafClass $value }
1059 -flowlabel { set flowLabel $value }
1060 -hoplimit { set hopLimit $value }
1061 -jumbo { set jumbo $value }
1062 default { error "Frame.Ipv6.Set: Invalid param '$item'" }
1068 if { [ string equal $version "" ] || ![
string is integer $version ] || $version < 0 || $version > 0xF} {
1069 error "Frame.Ipv6.Set: Invalid version value '$version', MUST be <= 0xF"
1073 if { [ string equal $trafClass "" ] || ![
string is integer $trafClass ] || $trafClass < 0 || $trafClass > 0xFF} {
1074 error "Frame.Ipv6.Set: Invalid trafClass value '$trafClass', MUST be <= 0xFF"
1078 if { [ llength $flowLabel ] != 3 || ![
ByteList.Check $flowLabel ] || [
lindex $flowLabel 0 ] > 0xF} {
1079 error "Frame.Ipv6.Set: Invalid flowLabel '$flowLabel', expecting 20 bits"
1083 if { [ string equal $hopLimit "" ] || ![
string is integer $hopLimit ] || $hopLimit < 0 || $hopLimit > 0xFF} {
1084 error "Frame.Ipv6.Set: Invalid hopLimit value '$hopLimit', MUST be <= 0xFF"
1091 lappend H1 [
format "0x%02x" [
expr ( ( $version << 4 ) & 0xF0 ) | ( ( $trafClass >> 4 ) & 0x0F ) ] ]
1092 lappend H1 [
format "0x%02x" [
expr ( ( $trafClass << 4 ) & 0xF0 ) | [
lindex $flowLabel 0 ] & 0x0F ] ]
1093 eval lappend H1 [
lrange $flowLabel 1 end ]
1105 set myContent [
concat $H1 $H2 $H3 $H4 ]
1106 set myContent [
concat $myContent $data ]
1108 set myContent [
Frame.Mac.Set $DMAC $SMAC 0x86dd $myContent $Ethernet ]
1116 proc Frame.Mac.Set { DMAC SMAC EtherType data { params DEFAULT } } {
1145 if { ![ string equal -nocase $params "DEFAULT" ]} {
1146 foreach {item value} $params {
1147 switch -- [
string tolower $item ] {
1148 -mft { set EMFT $value }
1149 -length { set ELength $value }
1150 default { error "Frame.Mac.Set : Invalid Ethernet param '$item'" }
1155 switch -- [
string tolower $EMFT ] {
1156 snap { set myContent [
x.Frame.SNAP.Set $DMAC $SMAC $EtherType $data $ELength ] }
1159 default { error "Frame.Mac.Set : Invalid Ethernet MFT (Media Frame Type) '$EMFT'" }
1168 proc Frame.Pad { frame {length 64} {padByte 0x00} } {
1184 if { ![ ByteList.Check $frame ]} {
1185 error "Frame.Pad: Invalid frame ByteList: '${frame}'"
1188 set frameLength [
llength $frame ]
1189 while { $frameLength < $length} {
1190 lappend frame $padByte
1200 proc Frame.Vlan.Tag.Create { id priority dropeligable tpid } {
1232 if { [ string equal $id "" ] || ![
string is integer $id ] || $id < 0 || $id > 0xFFF} {
1233 error "Frame.Vlan.Insert: Invalid id value '$id', MUST be <= 4095 (0xFFF)"
1237 if { [ string equal $priority "" ] || ![
string is integer $priority ] || $priority < 0 || $priority > 7} {
1238 error "Frame.Vlan.Insert: Invalid priority value '$priority', MUST be <= 7"
1242 if { [ string equal $dropeligable "" ] || ![
string is integer $dropeligable ] || $dropeligable < 0 || $dropeligable > 1} {
1243 error "Frame.Vlan.Insert: Invalid dropeligable value '$dropeligable', MUST be 0 or 1"
1247 if { [ string equal $tpid "" ] || ![
string is integer $tpid ] || $tpid < 0 || $tpid > 0xFFFF} {
1248 error "Frame.Vlan.Insert: Invalid tpid value '$tpid', MUST be 0x8100 or 0x88a8"
1250 if { $tpid != 0x8100 && $tpid != 0x88a8} {
1251 puts stderr "Frame.Vlan.Insert: WARNING: Using unsupported tpid value '$tpid', should be 0x8100 or 0x88a8."
1256 set T1 [
format "0x%02x" [
expr ( ( $priority << 5 ) & 0xE0 ) | ( ( $dropeligable << 4 ) & 0x10 ) | ( ( $id >> 8 ) & 0x0F ) ] ]
1257 set T2 [
format "0x%02x" [
expr ( $id % 256 ) ] ]
1259 return [
concat [
eval list [
Short.To.Hex $tpid ] $T1 $T2 ] ]
1264 proc Frame.Vlan.Insert { frame id priority dropeligable { tpid 0x8100 } } {
1291 if { ![ ByteList.Check $frame ]} {
1292 error "Frame.Vlan.Insert: Invalid frame ByteList: '${frame}'"
1296 if { [ llength $frame ] < 14} {
1297 error "Frame.Vlan.Insert: Could not insert Tag. ByteList is shorter than a MAC header (14 bytes)."
1304 return [
join [
linsert $frame 12 $tag ] ]
1309 proc Frame.PPP.ProtocolId.FromEtherType { ethernetEtherType } {
1313 switch -- [
string tolower $ethernetEtherType ] {
1314 0x0800 { return 0x0021 }
1315 0x86dd { return 0x0057 }
1318 error "Unsupported conversion from Ethernet EtherType '${ethernetEtherType}' to PPP Protocol ID"
1323 proc Frame.PPPoE.Session.Header.Create { sessionId payloadLength ethernetEtherType } {
1357 set PppHeaderLength 2
1360 if { [ string equal $sessionId "" ] || ![
string is integer $sessionId ] || $sessionId < 0 || $sessionId > 0xFFFF} {
1361 error "Frame.PPPoE.Session.Tag.Create: Invalid sessionId value '$sessionId', MUST be <= 65635 (0xffff)"
1365 if { [ string equal $payloadLength "" ] || ![
string is integer $payloadLength ] || $payloadLength < 0 || $payloadLength > ( 0xFFFF - $PppHeaderLength )} {
1366 error "Frame.PPPoE.Session.Tag.Create: Invalid payloadLength value '$payloadLength', MUST be <= [
expr 0xFFFF - $PppHeaderLength ] (0xffff - $PppHeaderLength)"
1370 if { [ catch { Frame.PPP.ProtocolId.FromEtherType $ethernetEtherType } pppProtocolId ]} {
1374 error "LinkLayer.AutoComplete: ${pppProtocolId}"
1380 set versionAndType [
format "0x%02x" [
expr ( ( $Version << 4 ) & 0xF0 ) | ( $Type & 0x0F ) ] ]
1381 set Code [
format "0x%02x" [
expr ( $Code % 256 ) ] ]
1385 set payloadLength [
Short.To.Hex [
expr $payloadLength + $PppHeaderLength ] ]
1390 return [
concat [
eval list $versionAndType $Code $sessionId $payloadLength $pppProtocolHeader ] ]
1395 proc x.Frame.EtherII.Set { DMAC SMAC type data {length auto} } {
1413 set myContent [ list ]
1415 if { $type <= 0x5dc} {
1416 error "x.Frame.EtherII.Set: EtherType '$type' must be higher than 0x5dc"
1419 eval lappend myContent $data
1421 if { [ string equal -nocase $length "auto" ]} {
1422 set myContent [
Frame.Pad $myContent 60 ]
1424 if { [ string equal $length "" ] || ![
string is integer $length ] || $length < 0} {
1425 error "x.Frame.EtherII.Set: Invalid integer value length='$length'"
1427 if { [ llength $myContent ] > $length} {
1428 error "x.Frame.EtherII.Set: Can't reduce length to '$length', data already exceeds this value <[
llength $myContent ]>"
1430 set myContent [
Frame.Pad $myContent $length ]
1444 proc x.Frame.SNAP.Set { DMAC SMAC type data {length auto} } {
1465 set myContent [ list ]
1467 lappend myContent 0x00 0x00
1468 lappend myContent 0xaa 0xaa 0x03 0x00 0x00 0x00
1470 eval lappend myContent $data
1471 set frameWithoutDataLength [
expr [
llength $myContent ] - 8 - [
llength $data ] ]
1473 if { [ string equal -nocase $length "auto" ]} {
1474 set myContent [
Frame.Pad $myContent 64 ]
1476 if { [ string equal $length "" ] || ![
string is integer $length ] || $length < 0} {
1477 error "x.Frame.SNAP.Set: Invalid integer value length='$length'"
1479 if { [ llength $myContent ] > $length} {
1480 error "x.Frame.SNAP.Set: Can't set Length to '$length', data already exceeds this value '[
llength $myContent ]'"
1482 set myContent [
Frame.Pad $myContent $length ]
1485 set finalLength [
expr ( [
llength $myContent ] - $frameWithoutDataLength ) ]
1487 set myContent [
eval lreplace {$myContent} 12 13 $finalLengthHex ]
1490 if { $finalLength > $MTU - $frameWithoutDataLength} {
1491 error "x.Frame.802.3.Set: MTU exceeded, length was '[
expr $finalLength + $frameWithoutDataLength ]', maximum is ${MTU}"
1500 proc x.Frame.802.3.Set { DMAC SMAC data {length auto} } {
1515 set myContent [ list ]
1517 lappend myContent 0x00 0x00
1518 eval lappend myContent $data
1519 set frameWithoutDataLength [
expr [
llength $myContent ] - [
llength $data ] ]
1521 if { [ string equal -nocase $length "auto" ]} {
1522 set myContent [
Frame.Pad $myContent 64 ]
1524 if { [ string equal $length "" ] || ![
string is integer $length ] || $length < 0} {
1525 error "x.Frame.802.3.Set: Invalid integer value length='$length'"
1527 if { [ llength $myContent ] > $length} {
1528 error "x.Frame.802.3.Set: Can't set Length to '$length', data already exceeds this value '[
llength $myContent ]'"
1530 set myContent [
Frame.Pad $myContent $length ]
1533 set finalLength [
expr ( [
llength $myContent ] - $frameWithoutDataLength ) ]
1535 set myContent [
eval lreplace {$myContent} 12 13 $finalLengthHex ]
1538 if { $finalLength > $MTU - $frameWithoutDataLength} {
1539 error "x.Frame.802.3.Set: MTU exceeded, length was '[
expr $finalLength + $frameWithoutDataLength ]', maximum is ${MTU}"
1548 proc x.Frame.DataOrLength.Parse { dataOrLength } {
1560 if { [ string equal -nocase [ lindex $dataOrLength 0 ] "-length" ]} {
1561 if { [ llength $dataOrLength ] != 2} {
1562 error "x.Frame.DataOrLength.Parse: dataOrLength MUST be '-length <integer length>' OR ByteList of data"
1565 set length [
lindex $dataOrLength 1 ]
1567 if { [ string equal $length "" ] || ![
string is integer $length ] || $length < 0} {
1568 error "x.Frame.DataOrLength.Parse: Invalid length '${length}'"
1570 while { [ llength $data ] < $length} {
1574 if { ![ ByteList.Check $dataOrLength ]} {
1575 error "x.Frame.DataOrLength.Parse: Invalid ByteList data == '${dataOrLength}"
1577 set data [
string tolower $dataOrLength ]