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

Commit fb7be39

Browse files
authored
Merge pull request #56 from cloudflare/feature/json-serials
Serial control
2 parents 092ade0 + b4f0245 commit fb7be39

File tree

6 files changed

+149
-76
lines changed

6 files changed

+149
-76
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,18 @@ To use a data source that do not contains signatures or validity information, pa
316316

317317
Cloudflare's prefix list removes duplicates and entries that are not routed on the Internet (>/24 IPv4 and >/48 IPv6).
318318

319+
By default, the session ID will be randomly generated. The serial will start at zero.
320+
321+
You can define a serial to start with the following way:
322+
* the JSON must contain a `serial` field in `metadata`; and
323+
* the flag `-useserial` must be set to 1 or 2
324+
325+
When flag is set to 1, every change of file will increment the serial regardless of the current `serial` field.
326+
Make sure the refresh rate of GoRTR is more frequent than the refresh rate of the JSON.
327+
328+
When flag is set to 2, GoRTR will set the value of the serial in the JSON. If an ID is missed or not updated,
329+
it will cause discrepancies on the client.
330+
319331
## Configurations
320332

321333
### Compatibility matrix

cmd/gortr/gortr.go

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ const (
3838
METHOD_NONE = iota
3939
METHOD_PASSWORD
4040
METHOD_KEY
41+
42+
USE_SERIAL_DISABLE = iota
43+
USE_SERIAL_START
44+
USE_SERIAL_FULL
4145
)
4246

4347
var (
@@ -78,7 +82,9 @@ var (
7882
Verify = flag.Bool("verify", true, "Check signature using provided public key (disable by passing -verify=false)")
7983
PublicKey = flag.String("verify.key", "cf.pub", "Public key path (PEM file)")
8084

81-
CacheBin = flag.String("cache", "https://rpki.cloudflare.com/rpki.json", "URL of the cached JSON data")
85+
CacheBin = flag.String("cache", "https://rpki.cloudflare.com/rpki.json", "URL of the cached JSON data")
86+
UseSerial = flag.String("useserial", "disable", "Use serial contained in file (disable, startup, full)")
87+
8288
Etag = flag.Bool("etag", true, "Enable Etag header")
8389
UserAgent = flag.String("useragent", fmt.Sprintf("Cloudflare-%v (+https://github.com/cloudflare/gortr)", AppVersion), "User-Agent header")
8490
RefreshInterval = flag.Int("refresh", 600, "Refresh interval in seconds")
@@ -143,6 +149,11 @@ var (
143149
"password": METHOD_PASSWORD,
144150
//"key": METHOD_KEY,
145151
}
152+
serialToId = map[string]int{
153+
"disable": USE_SERIAL_DISABLE,
154+
"startup": USE_SERIAL_START,
155+
"full": USE_SERIAL_FULL,
156+
}
146157
)
147158

148159
func initMetrics() {
@@ -331,6 +342,8 @@ func (e IdenticalEtag) Error() string {
331342
}
332343

333344
func (s *state) updateFile(file string) error {
345+
sessid, _ := s.server.GetSessionId(nil)
346+
334347
log.Debugf("Refreshing cache from %s", file)
335348

336349
s.lastts = time.Now().UTC()
@@ -354,6 +367,14 @@ func (s *state) updateFile(file string) error {
354367
return err
355368
}
356369

370+
if s.useSerial == USE_SERIAL_START || s.useSerial == USE_SERIAL_FULL {
371+
//if serial, _ := s.server.GetCurrentSerial(sessid); roalistjson.Metadata.Serial != 0 && serial != roalistjson.Metadata.Serial {
372+
if _, valid := s.server.GetCurrentSerial(sessid); !valid || s.useSerial == USE_SERIAL_FULL {
373+
// Set serial at beginning
374+
s.server.SetSerial(uint32(roalistjson.Metadata.Serial))
375+
}
376+
}
377+
357378
if s.checktime {
358379
validtime := time.Unix(int64(roalistjson.Metadata.Valid), 0).UTC()
359380
if time.Now().UTC().After(validtime) {
@@ -383,12 +404,32 @@ func (s *state) updateFile(file string) error {
383404
log.Infof("Slurm filtering: %v kept, %v removed, %v asserted", len(kept), len(removed), len(asserted))
384405
roasjson = append(kept, asserted...)
385406
}
407+
408+
roas, count, countv4, countv6 := processData(roasjson)
409+
if err != nil {
410+
return err
411+
}
412+
413+
log.Infof("New update (%v uniques, %v total prefixes). %v bytes. Updating sha256 hash %x -> %x",
414+
len(roas), count, len(s.lastconverted), s.lasthash, hsum)
415+
s.lasthash = hsum
416+
417+
s.server.AddROAs(roas)
418+
419+
serial, _ := s.server.GetCurrentSerial(sessid)
420+
log.Infof("Updated added, new serial %v", serial)
421+
if s.sendNotifs {
422+
log.Debugf("Sending notifications to clients")
423+
s.server.NotifyClientsLatest()
424+
}
425+
386426
s.lockJson.Lock()
387427
s.exported = prefixfile.ROAList{
388428
Metadata: prefixfile.MetaData{
389429
Counts: len(roasjson),
390430
Generated: roalistjson.Metadata.Generated,
391431
Valid: roalistjson.Metadata.Valid,
432+
Serial: int(serial),
392433
/*Signature: roalistjson.Metadata.Signature,
393434
SignatureDate: roalistjson.Metadata.SignatureDate,*/
394435
},
@@ -406,25 +447,6 @@ func (s *state) updateFile(file string) error {
406447

407448
s.lockJson.Unlock()
408449

409-
roas, count, countv4, countv6 := processData(roasjson)
410-
if err != nil {
411-
return err
412-
}
413-
414-
log.Infof("New update (%v uniques, %v total prefixes). %v bytes. Updating sha256 hash %x -> %x",
415-
len(roas), count, len(s.lastconverted), s.lasthash, hsum)
416-
s.lasthash = hsum
417-
418-
s.server.AddROAs(roas)
419-
420-
sessid, _ := s.server.GetSessionId(nil)
421-
serial, _ := s.server.GetCurrentSerial(sessid)
422-
log.Infof("Updated added, new serial %v", serial)
423-
if s.sendNotifs {
424-
log.Debugf("Sending notifications to clients")
425-
s.server.NotifyClientsLatest()
426-
}
427-
428450
if s.metricsEvent != nil {
429451
var countv4_dup int
430452
var countv6_dup int
@@ -516,6 +538,7 @@ type state struct {
516538
userAgent string
517539
etags map[string]string
518540
enableEtags bool
541+
useSerial int
519542

520543
server *rtr.Server
521544

@@ -655,6 +678,14 @@ func main() {
655678
lockJson: &sync.RWMutex{},
656679
}
657680

681+
if serialId, ok := serialToId[*UseSerial]; ok {
682+
s.useSerial = serialId
683+
} else {
684+
log.Fatalf("Serial configuration %s is unknown", *UseSerial)
685+
}
686+
687+
server.SetManualSerial(s.useSerial == USE_SERIAL_FULL)
688+
658689
if *ExportSign != "" {
659690
keyFile, err := os.Open(*ExportSign)
660691
if err != nil {
@@ -683,6 +714,38 @@ func main() {
683714
log.Fatalf("Specify at least a bind address")
684715
}
685716

717+
err := s.updateFile(*CacheBin)
718+
if err != nil {
719+
switch err.(type) {
720+
case HttpNotModified:
721+
log.Info(err)
722+
case IdenticalFile:
723+
log.Info(err)
724+
case IdenticalEtag:
725+
log.Info(err)
726+
default:
727+
log.Errorf("Error updating: %v", err)
728+
}
729+
}
730+
731+
slurmFile := *Slurm
732+
if slurmFile != "" {
733+
err := s.updateSlurm(slurmFile)
734+
if err != nil {
735+
switch err.(type) {
736+
case HttpNotModified:
737+
log.Info(err)
738+
case IdenticalEtag:
739+
log.Info(err)
740+
default:
741+
log.Errorf("Slurm: %v", err)
742+
}
743+
}
744+
if !*SlurmRefresh {
745+
slurmFile = ""
746+
}
747+
}
748+
686749
if *Bind != "" {
687750
go func() {
688751
sessid, _ := server.GetSessionId(nil)
@@ -795,37 +858,6 @@ func main() {
795858
}()
796859
}
797860

798-
slurmFile := *Slurm
799-
if slurmFile != "" {
800-
err := s.updateSlurm(slurmFile)
801-
if err != nil {
802-
switch err.(type) {
803-
case HttpNotModified:
804-
log.Info(err)
805-
case IdenticalEtag:
806-
log.Info(err)
807-
default:
808-
log.Errorf("Slurm: %v", err)
809-
}
810-
}
811-
if !*SlurmRefresh {
812-
slurmFile = ""
813-
}
814-
}
815-
816-
err := s.updateFile(*CacheBin)
817-
if err != nil {
818-
switch err.(type) {
819-
case HttpNotModified:
820-
log.Info(err)
821-
case IdenticalFile:
822-
log.Info(err)
823-
case IdenticalEtag:
824-
log.Info(err)
825-
default:
826-
log.Errorf("Error updating: %v", err)
827-
}
828-
}
829861
s.routineUpdate(*CacheBin, *RefreshInterval, slurmFile)
830862

831863
}

cmd/rtrdump/rtrdump.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ var (
3333
Connect = flag.String("connect", "127.0.0.1:8282", "Connection address")
3434
OutFile = flag.String("file", "output.json", "Output file")
3535

36+
InitSerial = flag.Bool("serial", false, "Send serial query instead of reset")
37+
Serial = flag.Int("serial.value", 0, "Serial number")
38+
Session = flag.Int("session.id", 0, "Session ID")
39+
3640
ConnType = flag.String("type", "plain", "Type of connection: plain, tls or ssh")
3741
ValidateCert = flag.Bool("tls.validate", true, "Validate TLS")
3842

@@ -62,6 +66,10 @@ var (
6266

6367
type Client struct {
6468
Data prefixfile.ROAList
69+
70+
InitSerial bool
71+
Serial uint32
72+
SessionID uint16
6573
}
6674

6775
func (c *Client) HandlePDU(cs *rtr.ClientSession, pdu rtr.PDU) {
@@ -86,7 +94,8 @@ func (c *Client) HandlePDU(cs *rtr.ClientSession, pdu rtr.PDU) {
8694
case *rtr.PDUEndOfData:
8795
t := time.Now().UTC().UnixNano() / 1000000000
8896
c.Data.Metadata.Generated = int(t)
89-
c.Data.Metadata.Valid = int(pdu.SerialNumber)
97+
c.Data.Metadata.Valid = int(t) + int(pdu.RefreshInterval)
98+
c.Data.Metadata.Serial = int(pdu.SerialNumber)
9099
cs.Disconnect()
91100
case *rtr.PDUCacheResponse:
92101
default:
@@ -95,7 +104,11 @@ func (c *Client) HandlePDU(cs *rtr.ClientSession, pdu rtr.PDU) {
95104
}
96105

97106
func (c *Client) ClientConnected(cs *rtr.ClientSession) {
98-
cs.SendResetQuery()
107+
if c.InitSerial {
108+
cs.SendSerialQuery(c.SessionID, c.Serial)
109+
} else {
110+
cs.SendResetQuery()
111+
}
99112
}
100113

101114
func (c *Client) ClientDisconnected(cs *rtr.ClientSession) {
@@ -124,6 +137,9 @@ func main() {
124137
Metadata: prefixfile.MetaData{},
125138
Data: make([]prefixfile.ROAJson, 0),
126139
},
140+
InitSerial: *InitSerial,
141+
Serial: uint32(*Serial),
142+
SessionID: uint16(*Session),
127143
}
128144

129145
clientSession := rtr.NewClientSession(cc, client)

lib/client.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ func (c *ClientSession) SendResetQuery() {
6262
c.SendPDU(pdu)
6363
}
6464

65-
func (c *ClientSession) SendSerialQuery(serial uint32) {
65+
func (c *ClientSession) SendSerialQuery(sessionid uint16, serial uint32) {
6666
pdu := &PDUSerialQuery{
67-
// to fill
67+
SessionId: sessionid,
68+
SerialNumber: serial,
6869
}
6970
c.SendPDU(pdu)
7071
}

0 commit comments

Comments
 (0)