From d5be6983b58172b01e077988df3cc6f2e86e3cd8 Mon Sep 17 00:00:00 2001 From: Job Snijders Date: Wed, 1 Feb 2023 14:30:09 +0000 Subject: [PATCH] Bugfix: don't echo the router's session_id back to the router, instead report an error Previously StayRTR would copy the client's Session ID back into the Cache Response send to the router, even though the cache's internal Session ID was something different. The purpose of the Session ID is to help both router and cache understand whether they are synchronized or not. There are two opportunities to fix desyncs: if the cache recognises the router is desynced, the cache informs the router (through an Error Report) to reconnect and send a Reset Query. If the router recognises it is out of sync with the cache, the router can send a Reset Query. According to RFC 8210 section 5.1 the cache should send "Corrupt Data" when a router sends a Serial Query with an unknown Session ID: ``` Session ID: A 16-bit unsigned integer. When a cache server is started, it generates a Session ID to identify the instance of the cache and to bind it to the sequence of Serial Numbers that cache instance will generate. This allows the router to restart a failed session knowing that the Serial Number it is using is commensurate with that of the cache. If, at any time after the protocol version has been negotiated (Section 7), either the router or the cache finds that the value of the Session ID is not the same as the other's, the party which detects the mismatch MUST immediately terminate the session with an Error Report PDU with code 0 ("Corrupt Data"), and the router MUST flush all data learned from that cache. ``` Reformat with gofmt from Ties --- lib/server.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/server.go b/lib/server.go index 094e72f..8be354f 100644 --- a/lib/server.go +++ b/lib/server.go @@ -78,6 +78,15 @@ func (e *DefaultRTREventHandler) RequestNewVersion(c *Client, sessionId uint16, if e.Log != nil { e.Log.Debugf("%v > Request New Version", c) } + server_SessionId := e.vrpManager.GetSessionId() + if sessionId != server_SessionId { + c.SendCorruptData() + if e.Log != nil { + e.Log.Debugf("%v < Invalid request (client asked for session %d but server is at %d)", c, sessionId, server_SessionId) + } + c.Disconnect() + return + } serial, valid := e.vrpManager.GetCurrentSerial(sessionId) if !valid { c.SendNoDataError() @@ -914,6 +923,14 @@ func (c *Client) SendNoDataError() { c.SendPDU(pdu) } +func (c *Client) SendCorruptData() { + pdu := &PDUErrorReport{ + ErrorCode: PDU_ERROR_CORRUPTDATA, + ErrorMsg: "Session ID mismatch: client is desynchronized", + } + c.SendPDU(pdu) +} + func (c *Client) SendWrongVersionError() { pdu := &PDUErrorReport{ ErrorCode: PDU_ERROR_BADPROTOVERSION,