Skip to content
Snippets Groups Projects
Commit 5c2b2e91 authored by Marcus Weiner's avatar Marcus Weiner
Browse files

Implement handling of OSPFv3 packets

parent f1d8ea62
No related branches found
No related tags found
1 merge request!2Packet/ospfv3
Showing
with 3767 additions and 1 deletion
...@@ -4,7 +4,9 @@ require ( ...@@ -4,7 +4,9 @@ require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 // indirect github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 // indirect
github.com/bio-routing/tflow2 v0.0.0-20181230153523-2e308a4a3c3a github.com/bio-routing/tflow2 v0.0.0-20181230153523-2e308a4a3c3a
github.com/gogo/protobuf v1.3.0 // indirect
github.com/golang/protobuf v1.4.0 github.com/golang/protobuf v1.4.0
github.com/google/gopacket v1.1.17
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.8.0
...@@ -15,7 +17,7 @@ require ( ...@@ -15,7 +17,7 @@ require (
github.com/urfave/cli v1.21.0 github.com/urfave/cli v1.21.0
github.com/vishvananda/netlink v1.0.0 github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
golang.org/x/text v0.3.2 // indirect golang.org/x/text v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36 // indirect google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36 // indirect
......
...@@ -27,6 +27,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V ...@@ -27,6 +27,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
...@@ -48,12 +50,16 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw ...@@ -48,12 +50,16 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
...@@ -110,6 +116,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r ...@@ -110,6 +116,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
...@@ -125,6 +132,8 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h ...@@ -125,6 +132,8 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
...@@ -133,6 +142,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= ...@@ -133,6 +142,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
......
package packetv3
import (
"bytes"
"encoding/binary"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/tflow2/convert"
"github.com/pkg/errors"
)
// Serializable represents any packet which can be serialized
// to bytes to be on the wire
type Serializable interface {
Serialize(buf *bytes.Buffer)
}
// ID is a common type used for 32-bit IDs in OSPF
type ID uint32
func DeserializeID(buf *bytes.Buffer) (ID, int, error) {
var id uint32
if err := binary.Read(buf, binary.BigEndian, &id); err != nil {
return ID(id), 0, errors.Wrap(err, "unable to read ID from buffer")
}
return ID(id), 4, nil
}
func (i ID) Serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint32Byte(uint32(i)))
}
// bitmasks for flags in RouterOptions
const (
RouterOptV6 uint16 = 1 << iota
RouterOptE
_
RouterOptN
RouterOptR
RouterOptDC
_
_
RouterOptAF
)
type RouterOptions struct {
_ uint8
Flags uint16
}
func (r *RouterOptions) Serialize(buf *bytes.Buffer) {
buf.WriteByte(0)
buf.Write(convert.Uint16Byte(uint16(r.Flags)))
}
type LSType uint16
func (t LSType) Serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint16Byte(uint16(t)))
}
type deserializableIP struct {
Higher uint64
Lower uint64
}
func (ip deserializableIP) ToNetIP() net.IP {
return *(net.IPv6(ip.Higher, ip.Lower))
}
func serializeIPv6(ip net.IP, buf *bytes.Buffer) {
if ip.IsIPv4() {
for i := 0; i < 16; i++ {
buf.WriteByte(0)
}
return
}
buf.Write(ip.Bytes())
}
File added
File added
File added
This diff is collapsed.
This diff is collapsed.
package packets
import "github.com/bio-routing/bio-rd/protocols/ospf/packetv3"
// Packets by source file
var Packets = make(map[string][]*packetv3.OSPFv3Message)
package main
import (
"bytes"
"fmt"
"io"
"net"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"text/template"
"github.com/bio-routing/bio-rd/protocols/ospf/packetv3"
"github.com/bio-routing/bio-rd/protocols/ospf/packetv3/fixtures"
"github.com/google/gopacket/pcapgo"
)
func main() {
cwd := ""
var filename string
for depth := 0; filename != "gen.go"; depth++ {
_, currentPath, _, ok := runtime.Caller(depth)
if !ok {
return
}
filename = filepath.Base(currentPath)
cwd = currentPath
}
dir := filepath.Dir(cwd) + "/../"
files := []string{
"OSPFv3_multipoint_adjacencies.cap",
"OSPFv3_broadcast_adjacency.cap",
"OSPFv3_NBMA_adjacencies.cap",
}
for _, path := range files {
fmt.Printf("Processing infile %s\n", path)
f, err := os.Open(dir + "/../" + path)
if err != nil {
panic(err)
}
defer f.Close()
r, err := pcapgo.NewReader(f)
if err != nil {
panic(err)
}
var packetCount int
tempBuf := bytes.NewBufferString("")
funcs := make([]string, 0)
for {
data, _, err := r.ReadPacketData()
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
pl, src, dst, err := fixtures.Payload(data)
if err != nil {
panic(err)
}
funcName := serializePacket(tempBuf, path, pl, src, dst, packetCount)
funcs = append(funcs, funcName)
packetCount++
}
args := &GenTemplArgs{File: path, PacketFuncs: funcs}
outBuf := bytes.NewBufferString("")
if err := genTemplate.Execute(outBuf, args); err != nil {
panic(err)
}
tempBuf.WriteTo(outBuf)
file, err := os.Create(dir + path + ".go")
defer file.Close()
if err != nil {
panic(err)
}
outBuf.WriteTo(file)
}
}
var genTemplate = template.Must(template.New("Gen").Parse(`
// GENERATED FILE - do not edit!
// to regenerate this, run "go run ./protocols/ospf/packetv3/fixtures/packets/gen/"
package packets
import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/ospf/packetv3"
)
func init() {
filePkts := make([]*packetv3.OSPFv3Message, {{ len .PacketFuncs }})
{{ range $index, $func := .PacketFuncs -}}
filePkts[{{ $index }}] = {{ $func }}()
{{ end -}}
Packets["{{ .File }}"] = filePkts
}
`))
type GenTemplArgs struct {
File string
PacketFuncs []string
}
var packetTemplate = template.Must(template.New("packet").Parse(`
func {{ .FuncName }}() *packetv3.OSPFv3Message {
packet := {{ .Msg }}
body := {{ .Body }}
{{ $lsafield := .LSAField -}}
{{ if gt (len .LSAs) 0 -}}
body.{{ $lsafield }} = make([]*packetv3.LSA, {{ len .LSAs }})
{{ range $index, $lsa := .LSAs -}}
body.{{ $lsafield }}[{{ $index }}] = {{ $lsa }}
{{ end -}}
{{ end -}}
packet.Body = body
return packet
}
`))
type PacketTemplArgs struct {
FuncName string
Msg string
Body string
LSAField string
LSAs []string
}
var pointerRegex = regexp.MustCompile(`\(\*packetv3\.\w+\)\(0x[0-9a-f]+\)`)
var netRegex = regexp.MustCompile(`net.IP\{higher:(0x[0-9a-f]+), lower:(0x[0-9a-f]+), isLegacy:false\}`)
func cleanSerialized(in string) string {
clean := pointerRegex.ReplaceAllString(in, "nil")
clean = strings.ReplaceAll(clean, "_:0x0, ", "")
clean = netRegex.ReplaceAllString(clean, "net.IPv6($1, $2)")
return clean
}
func serializeLSAs(items []*packetv3.LSA) []string {
out := make([]string, len(items))
for i := range items {
ser := fmt.Sprintf("%#v", items[i])
bodyStr := "nil"
if items[i].Body != nil {
bodyStr = cleanSerialized(fmt.Sprintf("%#v", items[i].Body))
}
ser = pointerRegex.ReplaceAllString(ser, bodyStr)
out[i] = cleanSerialized(ser)
}
return out
}
func serializePacket(out *bytes.Buffer, file string, payload []byte, src, dst net.IP, count int) string {
buf := bytes.NewBuffer(payload)
msg, _, err := packetv3.DeserializeOSPFv3Message(buf, src, dst)
if err != nil {
panic(err)
}
args := &PacketTemplArgs{}
args.FuncName = fmt.Sprintf("packet_%s_%03d", strings.ReplaceAll(file, ".cap", ""), count+1)
args.Msg = cleanSerialized(fmt.Sprintf("%#v", msg))
args.Body = cleanSerialized(fmt.Sprintf("%#v", msg.Body))
switch t := msg.Body.(type) {
case *packetv3.DatabaseDescription:
args.LSAField = "LSAHeaders"
args.LSAs = serializeLSAs(t.LSAHeaders)
case *packetv3.LinkStateUpdate:
args.LSAField = "LSAs"
args.LSAs = serializeLSAs(t.LSAs)
case *packetv3.LinkStateAcknowledgement:
args.LSAField = "LSAHeaders"
args.LSAs = serializeLSAs(t.LSAHeaders)
}
if err := packetTemplate.Execute(out, args); err != nil {
panic(err)
}
return args.FuncName
}
package fixtures
import (
"net"
"os"
"testing"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
)
func PacketReader(t *testing.T, path string) (*pcapgo.Reader, *os.File) {
f, err := os.Open(path)
if err != nil {
t.Error(err)
}
r, err := pcapgo.NewReader(f)
if err != nil {
t.Error(err)
}
return r, f
}
func Payload(raw []byte) (pl []byte, src, dst net.IP, err error) {
packet := gopacket.NewPacket(raw, layers.LayerTypeEthernet, gopacket.Default)
if perr := packet.ErrorLayer(); perr != nil {
// fallback to handling of FrameRelay (cut-off header)
packet = gopacket.NewPacket(raw[4:], layers.LayerTypeIPv6, gopacket.Default)
if perr = packet.ErrorLayer(); perr != nil {
err = perr.Error()
return
}
}
flowSrc, flowDst := packet.NetworkLayer().NetworkFlow().Endpoints()
src = net.IP(flowSrc.Raw())
dst = net.IP(flowDst.Raw())
pl = packet.NetworkLayer().LayerPayload()
return
}
package packetv3
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/bio-routing/tflow2/convert"
"github.com/pkg/errors"
)
type OSPFLSAType uint8
// OSPF LSA types
const (
LSATypeUnknown OSPFLSAType = iota
LSATypeRouter
LSATypeNetwork
LSATypeInterAreaPrefix
LSATypeInterAreaRouter
LSATypeASExternal
LSATypeDeprecated
LSATypeNSSA
LSATypeLink
LSATypeIntraAreaPrefix
)
type LSA struct {
Age uint16
Type LSType
ID ID
AdvertisingRouter ID
SequenceNumber uint32
Checksum uint16
Length uint16
Body Serializable
}
const LSAHeaderLength = 20
func (x *LSA) SerializeHeader(buf *bytes.Buffer) {
buf.Write(convert.Uint16Byte(x.Age))
x.Type.Serialize(buf)
x.ID.Serialize(buf)
x.AdvertisingRouter.Serialize(buf)
buf.Write(convert.Uint32Byte(x.SequenceNumber))
buf.Write(convert.Uint16Byte(x.Checksum))
buf.Write(convert.Uint16Byte(x.Length))
}
func (x *LSA) Serialize(buf *bytes.Buffer) {
x.SerializeHeader(buf)
x.Body.Serialize(buf)
}
func DeserializeLSAHeader(buf *bytes.Buffer) (*LSA, int, error) {
pdu := &LSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.Age,
&pdu.Type,
&pdu.ID,
&pdu.AdvertisingRouter,
&pdu.SequenceNumber,
&pdu.Checksum,
&pdu.Length,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 20
return pdu, readBytes, nil
}
func DeserializeLSA(buf *bytes.Buffer) (*LSA, int, error) {
pdu, readBytes, err := DeserializeLSAHeader(buf)
if err != nil {
return nil, 0, err
}
n, err := pdu.ReadBody(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode LSA body")
}
readBytes += n
return pdu, readBytes, nil
}
func (x *LSA) ReadBody(buf *bytes.Buffer) (int, error) {
code := OSPFLSAType(x.Type & 8191) // Bitmask excludes top three bits
bodyLength := x.Length - LSAHeaderLength
var body Serializable
var readBytes int
var err error
switch code {
case LSATypeRouter:
body, readBytes, err = DeserializeRouterLSA(buf, bodyLength)
case LSATypeNetwork:
body, readBytes, err = DeserializeNetworkLSA(buf, bodyLength)
case LSATypeInterAreaPrefix:
body, readBytes, err = DeserializeInterAreaPrefixLSA(buf)
case LSATypeInterAreaRouter:
body, readBytes, err = DeserializeInterAreaRouterLSA(buf)
case LSATypeASExternal:
body, readBytes, err = DeserializeASExternalLSA(buf)
case LSATypeNSSA: // NSSA-LSA special case
body, readBytes, err = DeserializeASExternalLSA(buf)
case LSATypeLink:
body, readBytes, err = DeserializeLinkLSA(buf)
case LSATypeIntraAreaPrefix:
body, readBytes, err = DeserializeIntraAreaPrefixLSA(buf)
default:
return 0, fmt.Errorf("unknown LSA type: %x", x.Type)
}
if err != nil {
return 0, err
}
x.Body = body
return readBytes, nil
}
// InterfaceMetric is the metric of a link
// This is supposed to be 24-bit long
type InterfaceMetric struct {
High uint8
Low uint16
}
// Value returns the numeric value of this metric field
func (m InterfaceMetric) Value() uint32 {
return uint32(m.High<<16) + uint32(m.Low)
}
func (x InterfaceMetric) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.High)
buf.Write(convert.Uint16Byte(x.Low))
}
type AreaLinkDescription struct {
Type uint8
Metric InterfaceMetric
InterfaceID ID
NeighborInterfaceID ID
NeighborRouterID ID
}
func (x *AreaLinkDescription) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.Type)
x.Metric.Serialize(buf)
x.InterfaceID.Serialize(buf)
x.NeighborInterfaceID.Serialize(buf)
x.NeighborRouterID.Serialize(buf)
}
func DeserializeAreaLinkDescription(buf *bytes.Buffer) (AreaLinkDescription, int, error) {
pdu := AreaLinkDescription{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.Type,
&pdu.Metric,
&pdu.InterfaceID,
&pdu.NeighborInterfaceID,
&pdu.NeighborRouterID,
}
err = decode.Decode(buf, fields)
if err != nil {
return pdu, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 16
return pdu, readBytes, nil
}
type RouterLSA struct {
Flags uint8
Options RouterOptions
LinkDescriptions []AreaLinkDescription
}
func (x *RouterLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.Flags)
x.Options.Serialize(buf)
for i := range x.LinkDescriptions {
x.LinkDescriptions[i].Serialize(buf)
}
}
func DeserializeRouterLSA(buf *bytes.Buffer, bodyLength uint16) (*RouterLSA, int, error) {
pdu := &RouterLSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.Flags,
&pdu.Options,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 4
for i := readBytes; i < int(bodyLength); {
tlv, n, err := DeserializeAreaLinkDescription(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode LinkDescription")
}
pdu.LinkDescriptions = append(pdu.LinkDescriptions, tlv)
i += n
readBytes += n
}
return pdu, readBytes, nil
}
type NetworkLSA struct {
Options RouterOptions
AttachedRouter []ID
}
func (x *NetworkLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(0) // 1 byte reserved
x.Options.Serialize(buf)
for i := range x.AttachedRouter {
x.AttachedRouter[i].Serialize(buf)
}
}
func DeserializeNetworkLSA(buf *bytes.Buffer, bodyLength uint16) (*NetworkLSA, int, error) {
pdu := &NetworkLSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
new(uint8), // 1 byte reserved
&pdu.Options,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 4
for i := readBytes; i < int(bodyLength); {
tlv, n, err := DeserializeID(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "Unable to decode AttachedRouterID")
}
pdu.AttachedRouter = append(pdu.AttachedRouter, tlv)
i += n
readBytes += n
}
return pdu, readBytes, nil
}
type InterAreaPrefixLSA struct {
Metric InterfaceMetric
Prefix LSAPrefix
}
func (x *InterAreaPrefixLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(0) // 1 byte reserved
x.Metric.Serialize(buf)
x.Prefix.Serialize(buf)
}
func DeserializeInterAreaPrefixLSA(buf *bytes.Buffer) (*InterAreaPrefixLSA, int, error) {
pdu := &InterAreaPrefixLSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
new(uint8), // 1 byte reserved
&pdu.Metric,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 4
pfx, n, err := DeserializeLSAPrefix(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode prefix")
}
pdu.Prefix = pfx
readBytes += n
return pdu, readBytes, nil
}
type InterAreaRouterLSA struct {
Options RouterOptions
Metric InterfaceMetric
DestinationRouterID ID
}
func (x *InterAreaRouterLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(0) // 1 byte reserved
x.Options.Serialize(buf)
buf.WriteByte(0) // 1 byte reserved
x.Metric.Serialize(buf)
x.DestinationRouterID.Serialize(buf)
}
func DeserializeInterAreaRouterLSA(buf *bytes.Buffer) (*InterAreaRouterLSA, int, error) {
pdu := &InterAreaRouterLSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
new(uint8), // 1 byte reserved
&pdu.Options,
new(uint8), // 1 byte reserved
&pdu.Metric,
&pdu.DestinationRouterID,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 12
return pdu, readBytes, nil
}
// Bitmasks for flags used in ASExternalLSA
const (
ASExtLSAFlagT uint8 = 1 << iota
ASExtLSAFlagF
ASExtLSAFlagE
)
type ASExternalLSA struct {
Flags uint8
Metric InterfaceMetric
Prefix LSAPrefix
ForwardingAddress net.IP // optional
ExternalRouteTag uint32 // optional
ReferencedLinkStateID ID // optional
}
func (a *ASExternalLSA) FlagE() bool {
return (a.Flags & ASExtLSAFlagE) != 0
}
func (a *ASExternalLSA) FlagF() bool {
return (a.Flags & ASExtLSAFlagF) != 0
}
func (a *ASExternalLSA) FlagT() bool {
return (a.Flags & ASExtLSAFlagT) != 0
}
func (x *ASExternalLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.Flags)
x.Metric.Serialize(buf)
x.Prefix.Serialize(buf)
if x.FlagF() {
serializeIPv6(x.ForwardingAddress, buf)
}
if x.FlagT() {
buf.Write(convert.Uint32Byte(x.ExternalRouteTag))
}
if x.Prefix.Special != 0 {
x.ReferencedLinkStateID.Serialize(buf)
}
}
func DeserializeASExternalLSA(buf *bytes.Buffer) (*ASExternalLSA, int, error) {
pdu := &ASExternalLSA{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.Flags,
&pdu.Metric,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 4
pfx, n, err := DeserializeLSAPrefix(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode prefix")
}
pdu.Prefix = pfx
readBytes += n
if pdu.FlagF() {
ip := deserializableIP{}
err := binary.Read(buf, binary.BigEndian, &ip)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode ForwardingAddress")
}
pdu.ForwardingAddress = ip.ToNetIP()
readBytes += 16
}
if pdu.FlagT() {
err := binary.Read(buf, binary.BigEndian, &pdu.ExternalRouteTag)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode ExternalRouteTag")
}
readBytes += 4
}
if pdu.Prefix.Special != 0 {
id, n, err := DeserializeID(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode ReferencedLinkStateID")
}
pdu.ReferencedLinkStateID = id
readBytes += n
}
return pdu, readBytes, nil
}
type LinkLSA struct {
RouterPriority uint8
Options RouterOptions
LinkLocalInterfaceAddress net.IP
PrefixNum uint32
Prefixes []LSAPrefix
}
func (x *LinkLSA) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.RouterPriority)
x.Options.Serialize(buf)
serializeIPv6(x.LinkLocalInterfaceAddress, buf)
buf.Write(convert.Uint32Byte(x.PrefixNum))
for i := range x.Prefixes {
x.Prefixes[i].Serialize(buf)
}
}
func DeserializeLinkLSA(buf *bytes.Buffer) (*LinkLSA, int, error) {
pdu := &LinkLSA{}
var readBytes int
var err error
var fields []interface{}
llintfAddr := deserializableIP{}
fields = []interface{}{
&pdu.RouterPriority,
&pdu.Options,
&llintfAddr,
&pdu.PrefixNum,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
pdu.LinkLocalInterfaceAddress = llintfAddr.ToNetIP()
readBytes += 24
for i := 0; i < int(pdu.PrefixNum); i++ {
tlv, n, err := DeserializeLSAPrefix(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "Unable to decode")
}
pdu.Prefixes = append(pdu.Prefixes, tlv)
readBytes += n
}
return pdu, readBytes, nil
}
type IntraAreaPrefixLSA struct {
ReferencedLSType LSType
ReferencedLinkStateID ID
ReferencedAdvertisingRouter ID
Prefixes []LSAPrefix
}
func (x *IntraAreaPrefixLSA) Serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint16Byte(uint16(len(x.Prefixes))))
x.ReferencedLSType.Serialize(buf)
x.ReferencedLinkStateID.Serialize(buf)
x.ReferencedAdvertisingRouter.Serialize(buf)
for i := range x.Prefixes {
x.Prefixes[i].Serialize(buf)
}
}
func DeserializeIntraAreaPrefixLSA(buf *bytes.Buffer) (*IntraAreaPrefixLSA, int, error) {
pdu := &IntraAreaPrefixLSA{}
var prefixNum uint16
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&prefixNum,
&pdu.ReferencedLSType,
&pdu.ReferencedLinkStateID,
&pdu.ReferencedAdvertisingRouter,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 12
for i := 0; i < int(prefixNum); i++ {
tlv, n, err := DeserializeLSAPrefix(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "Unable to decode")
}
pdu.Prefixes = append(pdu.Prefixes, tlv)
readBytes += n
}
return pdu, readBytes, nil
}
package packetv3
import (
"bytes"
"fmt"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/bio-routing/tflow2/convert"
"github.com/pkg/errors"
)
// Prefix Option Bits
const (
NUBIT = 1
LABIT = 2
PBIT = 8
DNBIT = 16
)
type PrefixOptions struct {
NoUnicast bool // NU-bit
LocalAddress bool // LA-bit
Propagate bool // P-bit
DN bool // DN-bit
}
func (o PrefixOptions) Serialize(buf *bytes.Buffer) {
var rawOptions uint8
if o.NoUnicast {
rawOptions = rawOptions | NUBIT
}
if o.LocalAddress {
rawOptions = rawOptions | LABIT
}
if o.Propagate {
rawOptions = rawOptions | PBIT
}
if o.DN {
rawOptions = rawOptions | DNBIT
}
buf.WriteByte(rawOptions)
}
type LSAPrefix struct {
PrefixLength uint8
Options PrefixOptions
// this may represent different things
// used for metric or referenced LSType
Special uint16
Address net.IP
}
func DeserializeLSAPrefix(buf *bytes.Buffer) (LSAPrefix, int, error) {
pdu := LSAPrefix{}
var readBytes int
var err error
var rawOptions uint8
fields := []interface{}{
&pdu.PrefixLength,
&rawOptions,
&pdu.Special,
}
err = decode.Decode(buf, fields)
if err != nil {
return pdu, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 4
// read Options
pdu.Options.NoUnicast = (rawOptions & NUBIT) != 0
pdu.Options.LocalAddress = (rawOptions & LABIT) != 0
pdu.Options.Propagate = (rawOptions & PBIT) != 0
pdu.Options.DN = (rawOptions & DNBIT) != 0
// read AddressPrefix
numBytes := int((pdu.PrefixLength+31)/32) * 4
pfxBytes := buf.Next(numBytes)
ipBytes := make([]byte, 16)
copy(ipBytes[:len(pfxBytes)], pfxBytes)
addr, err := net.IPFromBytes(ipBytes)
if err != nil {
return pdu, readBytes, errors.Wrap(err, "unable to decode AddressPrefix")
}
pdu.Address = *addr
readBytes += len(pfxBytes)
return pdu, readBytes, nil
}
func (x *LSAPrefix) Serialize(buf *bytes.Buffer) {
buf.WriteByte(x.PrefixLength)
x.Options.Serialize(buf)
buf.Write(convert.Uint16Byte(x.Special))
// serialize AddressPrefix
numBytes := int((x.PrefixLength+31)/32) * 4
buf.Write(x.Address.Bytes()[:numBytes])
}
package packetv3
import (
"bytes"
"encoding/binary"
"fmt"
gonet "net"
"github.com/bio-routing/bio-rd/util/checksum"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/bio-routing/tflow2/convert"
"github.com/pkg/errors"
)
const OSPFProtocolNumber = 89
const expectedVersion = 3
type OSPFMessageType uint8
// OSPF message types
const (
MsgTypeUnknown OSPFMessageType = iota
MsgTypeHello
MsgTypeDatabaseDescription
MsgTypeLinkStateRequest
MsgTypeLinkStateUpdate
MsgTypeLinkStateAcknowledgment
)
type OSPFv3Message struct {
Version uint8
Type OSPFMessageType
PacketLength uint16
RouterID ID
AreaID ID
Checksum uint16
InstanceID uint8
Body Serializable
}
const OSPFv3MessageHeaderLength = 16
const OSPFv3MessagePacketLengthAtByte = 2
const OSPFv3MessageChecksumAtByte = 12
func (x *OSPFv3Message) Serialize(out *bytes.Buffer, src, dst gonet.IP) {
buf := bytes.NewBuffer(nil)
buf.WriteByte(x.Version)
buf.WriteByte(uint8(x.Type))
buf.Write(convert.Uint16Byte(x.PacketLength))
x.RouterID.Serialize(buf)
x.AreaID.Serialize(buf)
buf.Write(convert.Uint16Byte(x.Checksum))
buf.WriteByte(x.InstanceID)
buf.WriteByte(0) // 1 byte reserved
x.Body.Serialize(buf)
data := buf.Bytes()
length := uint16(len(data))
putUint16(data, OSPFv3MessagePacketLengthAtByte, length)
checksum := checksum.IPv6UpperLayerChecksum(src, dst, OSPFProtocolNumber, data, OSPFv3MessageChecksumAtByte)
putUint16(data, OSPFv3MessageChecksumAtByte, checksum)
out.Write(data)
}
func putUint16(b []byte, p int, v uint16) {
binary.BigEndian.PutUint16(b[p:p+2], v)
}
func DeserializeOSPFv3Message(buf *bytes.Buffer, src, dst gonet.IP) (*OSPFv3Message, int, error) {
pdu := &OSPFv3Message{}
data := buf.Bytes()
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.Version,
&pdu.Type,
&pdu.PacketLength,
&pdu.RouterID,
&pdu.AreaID,
&pdu.Checksum,
&pdu.InstanceID,
new(uint8), // 1 byte reserved
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 16
if pdu.Version != expectedVersion {
return nil, readBytes, fmt.Errorf("Invalid OSPF version: %d", pdu.Version)
}
expectedChecksum := checksum.IPv6UpperLayerChecksum(src, dst, OSPFProtocolNumber, data, OSPFv3MessageChecksumAtByte)
if pdu.Checksum != expectedChecksum {
return nil, readBytes, fmt.Errorf("Checksum mismatch. Expected %#04x, got %#04x", expectedChecksum, pdu.Checksum)
}
n, err := pdu.ReadBody(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode message body")
}
readBytes += n
return pdu, readBytes, nil
}
func (m *OSPFv3Message) ReadBody(buf *bytes.Buffer) (int, error) {
bodyLength := m.PacketLength - OSPFv3MessageHeaderLength
var body Serializable
var readBytes int
var err error
switch m.Type {
case MsgTypeHello:
body, readBytes, err = DeserializeHello(buf, bodyLength)
case MsgTypeDatabaseDescription:
body, readBytes, err = DeserializeDatabaseDescription(buf, bodyLength)
case MsgTypeLinkStateRequest:
body, readBytes, err = DeserializeLinkStateRequestMsg(buf, bodyLength)
case MsgTypeLinkStateUpdate:
body, readBytes, err = DeserializeLinkStateUpdate(buf)
case MsgTypeLinkStateAcknowledgment:
body, readBytes, err = DeserializeLinkStateAcknowledgement(buf, bodyLength)
default:
return 0, fmt.Errorf("unknown message type: %d", m.Type)
}
if err != nil {
return 0, err
}
m.Body = body
return readBytes, nil
}
type Hello struct {
InterfaceID ID
RouterPriority uint8
Options RouterOptions
HelloInterval uint16
RouterDeadInterval uint16
DesignatedRouterID ID
BackupDesignatedRouterID ID
Neighbors []ID
}
func (x *Hello) Serialize(buf *bytes.Buffer) {
x.InterfaceID.Serialize(buf)
buf.WriteByte(x.RouterPriority)
x.Options.Serialize(buf)
buf.Write(convert.Uint16Byte(x.HelloInterval))
buf.Write(convert.Uint16Byte(x.RouterDeadInterval))
x.DesignatedRouterID.Serialize(buf)
x.BackupDesignatedRouterID.Serialize(buf)
for i := range x.Neighbors {
x.Neighbors[i].Serialize(buf)
}
}
func DeserializeHello(buf *bytes.Buffer, bodyLength uint16) (*Hello, int, error) {
pdu := &Hello{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
&pdu.InterfaceID,
&pdu.RouterPriority,
&pdu.Options,
&pdu.HelloInterval,
&pdu.RouterDeadInterval,
&pdu.DesignatedRouterID,
&pdu.BackupDesignatedRouterID,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 20
for i := readBytes; i < int(bodyLength); {
id, n, err := DeserializeID(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode neighbor id")
}
pdu.Neighbors = append(pdu.Neighbors, id)
i += n
readBytes += n
}
return pdu, readBytes, nil
}
type DBFlags uint8
// database description flags
const (
DBFlagInit DBFlags = 1 << iota
DBFlagMore
DBFlagMS
)
type DatabaseDescription struct {
Options RouterOptions
InterfaceMTU uint16
DBFlags DBFlags
DDSequenceNumber uint32
LSAHeaders []*LSA
}
func (x *DatabaseDescription) Serialize(buf *bytes.Buffer) {
buf.WriteByte(0) // 1 byte reserved
x.Options.Serialize(buf)
buf.Write(convert.Uint16Byte(x.InterfaceMTU))
buf.WriteByte(0) // 1 byte reserved
buf.WriteByte(uint8(x.DBFlags))
buf.Write(convert.Uint32Byte(x.DDSequenceNumber))
for i := range x.LSAHeaders {
x.LSAHeaders[i].SerializeHeader(buf)
}
}
func DeserializeDatabaseDescription(buf *bytes.Buffer, bodyLength uint16) (*DatabaseDescription, int, error) {
pdu := &DatabaseDescription{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
new(uint8),
&pdu.Options,
&pdu.InterfaceMTU,
new(uint8),
&pdu.DBFlags,
&pdu.DDSequenceNumber,
}
err = decode.Decode(buf, fields)
if err != nil {
return nil, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 12
for i := readBytes; i < int(bodyLength); {
tlv, n, err := DeserializeLSAHeader(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "Unable to decode")
}
pdu.LSAHeaders = append(pdu.LSAHeaders, tlv)
i += n
readBytes += n
}
return pdu, readBytes, nil
}
type LinkStateRequestMsg struct {
Requests []LinkStateRequest
}
func (x *LinkStateRequestMsg) Serialize(buf *bytes.Buffer) {
for i := range x.Requests {
x.Requests[i].Serialize(buf)
}
}
func DeserializeLinkStateRequestMsg(buf *bytes.Buffer, bodyLength uint16) (*LinkStateRequestMsg, int, error) {
pdu := &LinkStateRequestMsg{}
var readBytes int
for readBytes < int(bodyLength) {
req, n, err := DeserializeLinkStateRequest(buf)
if err != nil {
return nil, readBytes, errors.Wrap(err, "unable to decode LinkStateRequest")
}
pdu.Requests = append(pdu.Requests, req)
readBytes += n
}
return pdu, readBytes, nil
}
type LinkStateRequest struct {
LSType LSType
LinkStateID ID
AdvertisingRouter ID
}
func (x *LinkStateRequest) Serialize(buf *bytes.Buffer) {
buf.Write([]byte{0, 0}) // 2 bytes reserved
x.LSType.Serialize(buf)
x.LinkStateID.Serialize(buf)
x.AdvertisingRouter.Serialize(buf)
}
func DeserializeLinkStateRequest(buf *bytes.Buffer) (LinkStateRequest, int, error) {
pdu := LinkStateRequest{}
var readBytes int
var err error
var fields []interface{}
fields = []interface{}{
new(uint16), // 2 bytes reserved
&pdu.LSType,
&pdu.LinkStateID,
&pdu.AdvertisingRouter,
}
err = decode.Decode(buf, fields)
if err != nil {
return pdu, readBytes, fmt.Errorf("Unable to decode fields: %v", err)
}
readBytes += 12
return pdu, readBytes, nil
}
type LinkStateUpdate struct {
LSAs []*LSA
}
func (x *LinkStateUpdate) Serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint32Byte(uint32(len(x.LSAs))))
for i := range x.LSAs {
x.LSAs[i].Serialize(buf)
}
}
func DeserializeLinkStateUpdate(buf *bytes.Buffer) (*LinkStateUpdate, int, error) {
pdu := &LinkStateUpdate{}
var lsaCount uint32
if err := binary.Read(buf, binary.BigEndian, &lsaCount); err != nil {
return nil, 0, errors.Wrap(err, "unable to decode LSA count")
}
readBytes := 4
for i := 0; i < int(lsaCount); i++ {
tlv, n, err := DeserializeLSA(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "unable to decode LSA")
}
pdu.LSAs = append(pdu.LSAs, tlv)
readBytes += n
}
return pdu, readBytes, nil
}
type LinkStateAcknowledgement struct {
LSAHeaders []*LSA
}
func (x *LinkStateAcknowledgement) Serialize(buf *bytes.Buffer) {
for i := range x.LSAHeaders {
x.LSAHeaders[i].SerializeHeader(buf)
}
}
func DeserializeLinkStateAcknowledgement(buf *bytes.Buffer, bodyLength uint16) (*LinkStateAcknowledgement, int, error) {
pdu := &LinkStateAcknowledgement{}
var readBytes int
for i := 0; i < int(bodyLength); {
tlv, n, err := DeserializeLSAHeader(buf)
if err != nil {
return nil, 0, errors.Wrap(err, "Unable to decode")
}
pdu.LSAHeaders = append(pdu.LSAHeaders, tlv)
i += n
readBytes += n
}
return pdu, readBytes, nil
}
package packetv3_test
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"testing"
ospf "github.com/bio-routing/bio-rd/protocols/ospf/packetv3"
"github.com/bio-routing/bio-rd/protocols/ospf/packetv3/fixtures"
"github.com/bio-routing/bio-rd/protocols/ospf/packetv3/fixtures/packets"
"github.com/stretchr/testify/assert"
)
var files = []string{
"OSPFv3_multipoint_adjacencies.cap",
"OSPFv3_broadcast_adjacency.cap",
"OSPFv3_NBMA_adjacencies.cap",
}
var dir string
func init() {
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
dir = cwd + "/fixtures/"
}
func TestDecode(t *testing.T) {
for _, path := range files {
t.Run(path, func(t *testing.T) {
testDecodeFile(t, dir+path)
})
}
}
func testDecodeFile(t *testing.T, path string) {
fmt.Printf("Testing on file: %s\n", path)
r, f := fixtures.PacketReader(t, path)
defer f.Close()
var packetCount int
for {
data, _, err := r.ReadPacketData()
if err == io.EOF {
break
}
if err != nil {
t.Error(err)
return
}
t.Run(fmt.Sprintf("Packet_%03d", packetCount+1), func(t *testing.T) {
payload, src, dst, err := fixtures.Payload(data)
if err != nil {
t.Error(err)
return
}
buf := bytes.NewBuffer(payload)
if _, _, err := ospf.DeserializeOSPFv3Message(buf, src, dst); err != nil {
t.Error(err)
}
})
packetCount++
}
}
func TestEncode(t *testing.T) {
for _, path := range files {
t.Run(path, func(t *testing.T) {
testEncodeFile(t, dir+path)
})
}
}
func testEncodeFile(t *testing.T, path string) {
fmt.Printf("Testing on file: %s\n", path)
r, f := fixtures.PacketReader(t, path)
defer f.Close()
packets, ok := packets.Packets[filepath.Base(path)]
if !ok {
t.Errorf("Raw Go values not found for file %s", filepath.Base(path))
}
var packetCount int
for {
data, _, err := r.ReadPacketData()
if err == io.EOF {
break
}
if err != nil {
t.Error(err)
return
}
pl, src, dst, err := fixtures.Payload(data)
if err != nil {
t.Error(err)
return
}
t.Run(fmt.Sprintf("Packet_%03d", packetCount+1), func(t *testing.T) {
buf := &bytes.Buffer{}
msg := packets[packetCount]
msg.Serialize(buf, src, dst)
assert.Equal(t, buf.Bytes(), pl)
})
packetCount++
}
}
// taken from https://go.googlesource.com/net/+/refs/changes/17/112817/2/ipv4/header.go#102
//
// Copyright (c) 2009 The Go Authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package checksum
import (
"encoding/binary"
"net"
"github.com/bio-routing/tflow2/convert"
"golang.org/x/net/icmp"
)
func IPv6PseudoHeader(src, dst net.IP, lenght uint32, proto uint8) []byte {
header := icmp.IPv6PseudoHeader(src, dst)
lenBytes := convert.Uint32Byte(uint32(lenght))
copy(header[32:36], lenBytes)
header[len(header)-1] = proto // next header
return header
}
// IPv6UpperLayerChecksum calculates the checksum for
// an upper layer payload in IPv6 according to RFC 2460 Section 8.1
//
// Specify the position of the checksum using sumAt.
// Use a value lower than 0 to not skip a checksum field.
func IPv6UpperLayerChecksum(src, dst net.IP, proto uint8, pl []byte, sumAt int) uint16 {
header := IPv6PseudoHeader(src, dst, uint32(len(pl)), proto)
b := append(header, pl...)
// Algorithm taken from: https://en.wikipedia.org/wiki/IPv4_header_checksum.
// "First calculate the sum of each 16 bit value within the header,
// skipping only the checksum field itself."
var chk uint32
for i := 0; i < len(b); i += 2 {
if sumAt > 0 && i == len(header)+sumAt {
continue
}
chk += uint32(binary.BigEndian.Uint16(b[i : i+2]))
}
// "The first 4 bits are the carry and will be added to the rest of
// the value."
carry := uint16(chk >> 16)
sum := carry + uint16(chk&0x0ffff)
// "Next, we flip every bit in that value, to obtain the checksum."
return uint16(^sum)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment