Skip to content
This repository was archived by the owner on Feb 29, 2024. It is now read-only.

Commit 8f6f16d

Browse files
committed
RTRdump: dump the content of a RTR server in JSON format
1 parent 6835dfe commit 8f6f16d

9 files changed

+346
-6
lines changed

Dockerfile Dockerfile.gortr

File renamed without changes.
File renamed without changes.

Dockerfile.rtrdump

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
ARG src_dir="/go/src/github.com/cloudflare/gortr"
2+
3+
FROM golang:alpine as builder
4+
ARG src_dir
5+
6+
RUN apk --update --no-cache add git && \
7+
mkdir -p ${src_dir}
8+
9+
WORKDIR ${src_dir}
10+
COPY . .
11+
12+
RUN go get -u github.com/golang/dep/cmd/dep && \
13+
dep ensure && \
14+
go build cmd/rtrdump/rtrdump.go
15+
16+
FROM alpine:latest
17+
ARG src_dir
18+
19+
RUN apk --update --no-cache add ca-certificates && \
20+
adduser -S -D -H -h / rtr
21+
USER rtr
22+
23+
COPY --from=builder ${src_dir}/rtrdump /
24+
ENTRYPOINT ["./rtrdump"]

Dockerfile.rtrdump.prod

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ARG src_uri=github.com/cloudflare/gortr/cmd/rtrdump
2+
3+
FROM golang:alpine as builder
4+
ARG src_uri
5+
6+
RUN apk --update --no-cache add git && \
7+
go get -u $src_uri
8+
9+
FROM alpine:latest
10+
ARG src_uri
11+
12+
RUN apk --update --no-cache add ca-certificates && \
13+
adduser -S -D -H -h / rtr
14+
USER rtr
15+
16+
COPY --from=builder /go/bin/rtrdump /
17+
ENTRYPOINT ["./rtrdump"]

cmd/rtrdump/rtrdump.go

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
rtr "github.com/cloudflare/gortr/lib"
7+
"github.com/cloudflare/gortr/prefixfile"
8+
log "github.com/sirupsen/logrus"
9+
"os"
10+
"runtime"
11+
"encoding/json"
12+
"time"
13+
"io"
14+
"crypto/tls"
15+
)
16+
17+
const AppVersion = "RTRdump 0.9.4"
18+
19+
var (
20+
Connect = flag.String("connect", "127.0.0.1:8282", "Connection address")
21+
OutFile = flag.String("file", "output.json", "Output file")
22+
23+
UseTLS = flag.Bool("tls.enable", false, "Use TLS")
24+
ValidateCert = flag.Bool("tls.validate", true, "Validate TLS")
25+
26+
RefreshInterval = flag.Int("refresh", 600, "Refresh interval in seconds")
27+
28+
LogLevel = flag.String("loglevel", "info", "Log level")
29+
Version = flag.Bool("version", false, "Print version")
30+
)
31+
32+
type Client struct {
33+
Data prefixfile.ROAList
34+
}
35+
36+
func (c *Client) HandlePDU(cs *rtr.ClientSession, pdu rtr.PDU) {
37+
log.Debugf("Received: %v", pdu)
38+
switch pdu := pdu.(type) {
39+
case *rtr.PDUIPv4Prefix:
40+
rj := prefixfile.ROAJson{
41+
Prefix: pdu.Prefix.String(),
42+
ASN: fmt.Sprintf("AS%v", pdu.ASN),
43+
Length: pdu.MaxLen,
44+
}
45+
c.Data.Data = append(c.Data.Data, rj)
46+
c.Data.Metadata.Counts++
47+
case *rtr.PDUIPv6Prefix:
48+
rj := prefixfile.ROAJson{
49+
Prefix: pdu.Prefix.String(),
50+
ASN: fmt.Sprintf("AS%v", pdu.ASN),
51+
Length: pdu.MaxLen,
52+
}
53+
c.Data.Data = append(c.Data.Data, rj)
54+
c.Data.Metadata.Counts++
55+
case *rtr.PDUEndOfData:
56+
t := time.Now().UTC().UnixNano()/1000000000
57+
c.Data.Metadata.Generated = int(t)
58+
c.Data.Metadata.Valid = int(pdu.SerialNumber)
59+
cs.Disconnect()
60+
}
61+
}
62+
63+
func (c *Client) Connected(cs *rtr.ClientSession) {
64+
cs.SendResetQuery()
65+
}
66+
67+
func (c *Client) Disconnected(cs *rtr.ClientSession) {
68+
69+
}
70+
71+
func main() {
72+
runtime.GOMAXPROCS(runtime.NumCPU())
73+
74+
flag.Parse()
75+
if *Version {
76+
fmt.Println(AppVersion)
77+
os.Exit(0)
78+
}
79+
80+
lvl, _ := log.ParseLevel(*LogLevel)
81+
log.SetLevel(lvl)
82+
83+
84+
cc := rtr.ClientConfiguration{
85+
ProtocolVersion: rtr.PROTOCOL_VERSION_0,
86+
Log: log.StandardLogger(),
87+
}
88+
89+
client := &Client{
90+
Data: prefixfile.ROAList{
91+
Metadata: prefixfile.MetaData{
92+
},
93+
Data: make([]prefixfile.ROAJson, 0),
94+
},
95+
}
96+
97+
clientSession := rtr.NewClientSession(cc, client)
98+
99+
config := &tls.Config{
100+
InsecureSkipVerify: !*ValidateCert,
101+
}
102+
err := clientSession.Start(*Connect, *UseTLS, config)
103+
if err != nil {
104+
log.Fatal(err)
105+
}
106+
107+
var f io.Writer
108+
if *OutFile != "" {
109+
ff, err := os.Create(*OutFile)
110+
defer ff.Close()
111+
if err != nil {
112+
log.Fatal(err)
113+
}
114+
f = ff
115+
} else {
116+
f = os.Stdout
117+
}
118+
119+
enc := json.NewEncoder(f)
120+
err = enc.Encode(client.Data)
121+
if err != nil {
122+
log.Fatal(err)
123+
}
124+
}

lib/client.go

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package rtrlib
2+
3+
import (
4+
"net"
5+
"time"
6+
"crypto/tls"
7+
)
8+
9+
type RTRClientSessionEventHandler interface {
10+
//RequestCache(*ClientSession)
11+
HandlePDU(*ClientSession, PDU)
12+
}
13+
14+
type Logger interface{
15+
Debugf(string, ...interface{})
16+
Printf(string, ...interface{})
17+
Errorf(string, ...interface{})
18+
Infof(string, ...interface{})
19+
}
20+
21+
type ClientSession struct {
22+
version uint8
23+
24+
connected bool
25+
26+
curserial uint32
27+
transmits chan PDU
28+
quit chan bool
29+
30+
tcpconn net.Conn
31+
32+
handler RTRClientSessionEventHandler
33+
34+
log Logger
35+
}
36+
37+
type ClientConfiguration struct {
38+
ProtocolVersion uint8
39+
EnforceVersion bool
40+
41+
RefreshInterval uint32
42+
RetryInterval uint32
43+
ExpireInterval uint32
44+
45+
Log Logger
46+
}
47+
48+
func NewClientSession(configuration ClientConfiguration, handler RTRClientSessionEventHandler) *ClientSession {
49+
return &ClientSession{
50+
transmits: make(chan PDU, 256),
51+
quit: make(chan bool),
52+
log: configuration.Log,
53+
handler: handler,
54+
}
55+
}
56+
57+
func (c *ClientSession) SendResetQuery() {
58+
pdu := &PDUResetQuery{}
59+
c.SendPDU(pdu)
60+
}
61+
62+
func (c *ClientSession) SendSerialQuery(serial uint32) {
63+
pdu := &PDUSerialQuery{
64+
// to fill
65+
}
66+
c.SendPDU(pdu)
67+
}
68+
69+
func (c *ClientSession) SendPDU(pdu PDU) {
70+
pdu.SetVersion(c.version)
71+
c.SendRawPDU(pdu)
72+
}
73+
74+
func (c *ClientSession) SendRawPDU(pdu PDU) {
75+
c.transmits <- pdu
76+
}
77+
78+
func (c *ClientSession) sendLoop() {
79+
for c.connected {
80+
select {
81+
case pdu := <-c.transmits:
82+
c.tcpconn.Write(pdu.Bytes())
83+
case <-c.quit:
84+
break
85+
}
86+
}
87+
}
88+
89+
func (c *ClientSession) refreshLoop() {
90+
for c.connected {
91+
select {
92+
case <-time.After(20*time.Second):
93+
// send refresh
94+
}
95+
}
96+
}
97+
98+
func (c *ClientSession) Disconnect() {
99+
c.connected = false
100+
//log.Debugf("Disconnecting client %v", c.String())
101+
//if c.handler != nil {
102+
// c.handler.ClientDisconnected(c)
103+
//}
104+
select {
105+
case c.quit <- true:
106+
default:
107+
108+
}
109+
110+
c.tcpconn.Close()
111+
}
112+
113+
func (c *ClientSession) StartWithConn(tcpconn net.Conn) error {
114+
c.tcpconn = tcpconn
115+
c.connected = true
116+
//if c.handler != nil {
117+
// c.handler.ClientConnected(c)
118+
//}
119+
120+
go c.sendLoop()
121+
c.SendResetQuery()
122+
for c.connected {
123+
dec, err := Decode(c.tcpconn)
124+
if err != nil || dec == nil {
125+
if c.log != nil {
126+
c.log.Errorf("Error %v", err)
127+
}
128+
c.Disconnect()
129+
return err
130+
}
131+
if c.handler != nil {
132+
c.handler.HandlePDU(c, dec)
133+
}
134+
}
135+
136+
return nil
137+
}
138+
139+
func (c *ClientSession) Start(addr string, useTls bool, config *tls.Config) error {
140+
addrTCP, err := net.ResolveTCPAddr("tcp", addr)
141+
if err != nil {
142+
return err
143+
}
144+
if useTls {
145+
tcpconn, err := tls.Dial("tcp", addr, config)
146+
if err != nil {
147+
return err
148+
}
149+
return c.StartWithConn(tcpconn)
150+
} else {
151+
tcpconn, err := net.DialTCP("tcp", nil, addrTCP)
152+
if err != nil {
153+
return err
154+
}
155+
return c.StartWithConn(tcpconn)
156+
}
157+
return nil
158+
}

lib/server.go

+1
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ func (c *Client) Start() {
631631

632632
buf := make([]byte, 8000)
633633
for c.connected {
634+
// Remove this?
634635
length, err := c.tcpconn.Read(buf)
635636
if err != nil || length == 0 {
636637
log.Debugf("Error %v", err)

lib/structs.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -598,14 +598,30 @@ func Decode(rdr io.Reader) (PDU, error) {
598598
Prefix: ipnet,
599599
}, nil
600600
case PDU_ID_END_OF_DATA:
601-
if len(toread) != 4 {
602-
return nil, errors.New(fmt.Sprintf("Wrong length for End of Data PDU: %v != 4", len(toread)))
601+
if len(toread) != 4 && len(toread) != 16 {
602+
return nil, errors.New(fmt.Sprintf("Wrong length for End of Data PDU: %v != 4 or != 16", len(toread)))
603603
}
604-
serial := binary.BigEndian.Uint32(toread)
604+
605+
var serial uint32
606+
var refreshInterval uint32
607+
var retryInterval uint32
608+
var expireInterval uint32
609+
if len(toread) == 4 {
610+
serial = binary.BigEndian.Uint32(toread)
611+
} else if len(toread) == 16 {
612+
serial = binary.BigEndian.Uint32(toread[0:4])
613+
refreshInterval = binary.BigEndian.Uint32(toread[4:8])
614+
retryInterval = binary.BigEndian.Uint32(toread[8:12])
615+
expireInterval = binary.BigEndian.Uint32(toread[12:16])
616+
}
617+
605618
return &PDUEndOfData{
606619
Version: pver,
607620
SessionId: sessionId,
608621
SerialNumber: serial,
622+
RefreshInterval: refreshInterval,
623+
RetryInterval: retryInterval,
624+
ExpireInterval: expireInterval,
609625
}, nil
610626
case PDU_ID_CACHE_RESET:
611627
if len(toread) != 0 {

prefixfile/prefixfile.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,19 @@ type ROAJson struct {
8080
Prefix string `json:"prefix"`
8181
Length uint8 `json:"maxLength"`
8282
ASN string `json:"asn"`
83-
TA string `json:"ta"`
83+
TA string `json:"ta,omitempty"`
8484
}
8585

8686
type MetaData struct {
8787
Counts int `json:"counts"`
8888
Generated int `json:"generated"`
89-
Valid int `json:"valid"`
89+
Valid int `json:"valid,omitempty"`
9090
Signature string `json:"signature,omitempty"`
9191
SignatureDate string `json:"signatureDate,omitempty"`
9292
}
9393

9494
type ROAList struct {
95-
Metadata MetaData `json:"metadata"`
95+
Metadata MetaData `json:"metadata,omitempty"`
9696
Data []ROAJson `json:"roas"`
9797
}
9898

0 commit comments

Comments
 (0)