Repository: scionproto/scion
Pull request #3774 (2020-05-20 14:40:34)

braccept: add scmp bad host error from scmp packet
Add a test for SCMP error BAD_HOST of SCMP packets, ie. SCMP ECHO

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/scionproto/scion/3774)
<!-- Reviewable:end -->



Patch:
diff --git a/go/border/braccept/parser/helper.go b/go/border/braccept/parser/helper.go
index 5d06bd389..7f113badb 100644
--- a/go/border/braccept/parser/helper.go
+++ b/go/border/braccept/parser/helper.go
@@ -66,6 +66,14 @@ func StrToInt(s string) int {
 	return i
 }
 
+func StrToUint64(s string) uint64 {
+	u64, err := strconv.ParseUint(s, 10, 0)
+	if err != nil {
+		panic(fmt.Sprintf("StrToUint64 error converting '%s'\n", s))
+	}
+	return u64
+}
+
 func HexToInt(s string) uint {
 	i, err := strconv.ParseUint(s, 16, 64)
 	if err != nil {
diff --git a/go/border/braccept/parser/scmp.go b/go/border/braccept/parser/scmp.go
index 82e1ee2e7..8b99751ff 100644
--- a/go/border/braccept/parser/scmp.go
+++ b/go/border/braccept/parser/scmp.go
@@ -107,6 +107,10 @@ func (s *SCMPTaggedLayer) Update(lines []string) {
 			info := &InfoExtIdx{}
 			skip = info.parse(lines[i:])
 			s.Info = info
+		case "InfoEcho":
+			info := &InfoEcho{}
+			skip = info.parse(lines[i:])
+			s.Info = info
 		default:
 			panic(fmt.Errorf("Unknown SCMP sub layer type '%s'\n", layerType))
 		}
@@ -217,6 +221,28 @@ func (i *InfoExtIdx) parse(lines []string) int {
 	return 0
 }
 
+type InfoEcho struct {
+	scmp.InfoEcho
+}
+
+func (i *InfoEcho) parse(lines []string) int {
+	if len(lines) < 1 {
+		panic(fmt.Sprintf("Bad InfoEcho layer!\n%s\n", lines))
+	}
+	_, _, kvStr := decodeLayerLine(lines[0])
+	for k, v := range getKeyValueMap(kvStr) {
+		switch k {
+		case "Id":
+			i.Id = uint64(StrToUint64(v))
+		case "Seq":
+			i.Seq = uint16(StrToInt(v))
+		default:
+			panic(fmt.Sprintf("Invalid InfoEcho field: %s=%v", k, v))
+		}
+	}
+	return 0
+}
+
 func (s *SCMPTaggedLayer) updateHeaderFields(kvs propMap) {
 	for k, v := range kvs {
 		switch k {
@@ -454,7 +480,7 @@ func (qr *quoteRaw) getRaw(blk scmp.RawBlock) common.RawBytes {
 		return scnPld[:extLen]
 	case scmp.RawL4Hdr:
 		if s, ok := qr.l4.(*layers.SCMP); ok {
-			return qr.l4.LayerContents()[:scmp.HdrLen+s.Meta.InfoLen*common.LineLen]
+			return qr.l4.LayerContents()[:scmp.HdrLen+scmp.MetaLen+s.Meta.InfoLen*common.LineLen]
 		}
 		return qr.l4.LayerContents()
 	}


Test patch:
diff --git a/go/border/braccept/br_tests.go b/go/border/braccept/br_tests.go
index 97d0313a6..affda1430 100644
--- a/go/border/braccept/br_tests.go
+++ b/go/border/braccept/br_tests.go
@@ -117,7 +117,8 @@ func br_parent() int {
 	failures += ohp_udp_internal_bs_to_parent()
 	failures += ohp_internal_bs_to_parent()
 
-	failures += parent_scmp_routing_bad_host()
+	failures += parent_scmp_routing_bad_host_udp()
+	failures += parent_scmp_routing_bad_host_scmp()
 
 	return failures
 }
diff --git a/go/border/braccept/parent_tests.go b/go/border/braccept/parent_tests.go
index 398ec2efc..f7a447786 100644
--- a/go/border/braccept/parent_tests.go
+++ b/go/border/braccept/parent_tests.go
@@ -281,7 +281,7 @@ func ohp_internal_bs_to_parent() int {
 	return ExpectedPackets("one-hop-path internal/bs to parent", defaultTimeout, pkt1)
 }
 
-func parent_scmp_routing_bad_host() int {
+func parent_scmp_routing_bad_host_udp() int {
 	pkt0 := AllocatePacket()
 	pkt0.ParsePacket(`
 		Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4
@@ -321,5 +321,50 @@ func parent_scmp_routing_bad_host() int {
 
 	SendPackets(pkt0)
 
-	return ExpectedPackets("parent scmp routing bad host", defaultTimeout, pkt1)
+	return ExpectedPackets("parent scmp routing bad host - udp pakcet", defaultTimeout, pkt1)
+}
+
+func parent_scmp_routing_bad_host_scmp() int {
+	pkt0 := AllocatePacket()
+	pkt0.ParsePacket(`
+		Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4
+		IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF
+		UDP: Src=40000 Dst=50000
+		SCION: NextHdr=SCMP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC
+			ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=0009
+			IF_1: ISD=1 Hops=2 Flags=ConsDir
+				HF_1: ConsIngress=0   ConsEgress=311
+				HF_2: ConsIngress=131 ConsEgress=0
+		SCMP: Class=GENERAL Type=ECHO_REQUEST Timestamp=now
+			META: InfoLen=2
+			InfoEcho: Id=1234 Seq=5678
+	`)
+	pkt0.SetDev("veth_131")
+	pkt0.SetChecksum("UDP", "IP4")
+	pkt0.SetChecksum("SCMP", "SCION")
+	pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1")
+
+	pkt1 := AllocatePacket()
+	pkt1.ParsePacket(fmt.Sprintf(`
+		Ethernet: SrcMAC=f0:0d:ca:fe:00:13 DstMAC=f0:0d:ca:fe:be:ef EthernetType=IPv4
+		IP4: Src=192.168.13.2 Dst=192.168.13.3 NextHdr=UDP Flags=DF Checksum=0
+		UDP: Src=50000 Dst=40000 Checksum=0
+		SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4
+			ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.11 DstIA=1-ff00:0:3 Dst=172.16.3.1
+			IF_1: ISD=1 Hops=2
+				HF_1: ConsIngress=131 ConsEgress=0
+				HF_2: ConsIngress=0   ConsEgress=311
+		HBH: NextHdr=SCMP Type=SCMP
+			HBH.SCMP: Flags=Error,HBH
+		SCMP: Class=ROUTING Type=BAD_HOST Checksum=0
+			QUOTED: RawPkt=%s
+	`, pkt0.Serialize()))
+	pkt1.SetDev("veth_131")
+	pkt1.SetChecksum("UDP", "IP4")
+	pkt1.SetChecksum("SCMP", "SCION")
+	pkt1.GenerateMac("SCION", "IF_1", "HF_1", "HF_2")
+
+	SendPackets(pkt0)
+
+	return ExpectedPackets("parent scmp routing bad host - scmp packet", defaultTimeout, pkt1)
 }