Initial import
This commit is contained in:
70
protocol/detect_postgres.go
Normal file
70
protocol/detect_postgres.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerPostgreSQL()
|
||||
}
|
||||
|
||||
func registerPostgreSQL() {
|
||||
Register(Server, "R\x00???", detectPostgreSQLServer) // Authentication request
|
||||
Register(Server, "K\x00???", detectPostgreSQLServer) // BackendKeyData
|
||||
Register(Server, "S\x00???", detectPostgreSQLServer) // ParameterStatus
|
||||
Register(Server, "Z\x00???", detectPostgreSQLServer) // ReadyForQuery
|
||||
Register(Server, "E\x00???", detectPostgreSQLServer) // ErrorResponse
|
||||
Register(Server, "N\x00???", detectPostgreSQLServer) // NoticeResponse
|
||||
Register(Client, "????\x00\x02\x00\x00", detectPostgreSQLClient) // Startup packet, protocol 2.0
|
||||
Register(Client, "????\x00\x03\x00\x00", detectPostgreSQLClient) // Startup packet, protocol 3.0
|
||||
}
|
||||
|
||||
func detectPostgreSQLClient(dir Direction, data []byte) *Protocol {
|
||||
// A client startup message needs at least 8 bytes (length + protocol version).
|
||||
if len(data) < 8 {
|
||||
return nil
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint32(data[0:]))
|
||||
if len(data) != length {
|
||||
log.Printf("not postgres %q: %d != %d", data, len(data), length)
|
||||
return nil
|
||||
}
|
||||
|
||||
major := int(binary.BigEndian.Uint16(data[4:]))
|
||||
minor := int(binary.BigEndian.Uint16(data[6:]))
|
||||
if major == 2 || major == 3 {
|
||||
return &Protocol{
|
||||
Name: ProtocolPostgreSQL,
|
||||
Version: Version{
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Patch: -1,
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func detectPostgreSQLServer(dir Direction, data []byte) *Protocol {
|
||||
// A server message needs at least 5 bytes (type + length).
|
||||
if len(data) < 5 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// All server messages (and subsequent client messages) are tagged with a single-byte type.
|
||||
firstByte := data[0]
|
||||
switch firstByte {
|
||||
case 'R', // Authentication request
|
||||
'K', // BackendKeyData
|
||||
'S', // ParameterStatus
|
||||
'Z', // ReadyForQuery
|
||||
'E', // ErrorResponse
|
||||
'N': // NoticeResponse
|
||||
return &Protocol{Name: ProtocolPostgreSQL}
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user