cluster/identd/ident: add basic ident protocol server
This adds an ident protocol server and tests for it.
Change-Id: I830f85faa7dce4220bd7001635b20e88b4a8b417
diff --git a/cluster/identd/ident/request.go b/cluster/identd/ident/request.go
index 9727893..9c94e75 100644
--- a/cluster/identd/ident/request.go
+++ b/cluster/identd/ident/request.go
@@ -2,6 +2,9 @@
import (
"fmt"
+ "net"
+ "regexp"
+ "strconv"
)
// Request is an ident protocol request, as seen by the client or server.
@@ -12,9 +15,44 @@
// ServerPort is the port number on the server side of the ident protocol,
// ie. the port local to the ident server.
ServerPort uint16
+
+ // ClientAddress is the address of the ident protocol client. This is set
+ // by the ident Server before invoking handlers, and is ignored by the
+ // ident protocol Client.
+ // In handlers this can be used to ensure that responses are only returned
+ // to clients who are running on the remote side of the connection that
+ // they are querying about.
+ ClientAddress net.Addr
}
// encode encodes ths Request as per RFC1413, including the terminating \r\n.
func (r *Request) encode() []byte {
return []byte(fmt.Sprintf("%d,%d\r\n", r.ServerPort, r.ClientPort))
}
+
+var (
+ // reRequest matches request from RFC1413, but allows extra whitespace
+ // between significant tokens.
+ reRequest = regexp.MustCompile(`^\s*(\d{1,5})\s*,\s*(\d{1,5})\s*$`)
+)
+
+// decodeRequest parses the given bytes as an ident request. The data must be
+// stripped of the trailing \r\n.
+func decodeRequest(data []byte) (*Request, error) {
+ match := reRequest.FindStringSubmatch(string(data))
+ if match == nil {
+ return nil, fmt.Errorf("unparseable request")
+ }
+ serverPort, err := strconv.ParseUint(match[1], 10, 16)
+ if err != nil {
+ return nil, fmt.Errorf("invalid server port: %w", err)
+ }
+ clientPort, err := strconv.ParseUint(match[2], 10, 16)
+ if err != nil {
+ return nil, fmt.Errorf("invalid client port: %w", err)
+ }
+ return &Request{
+ ClientPort: uint16(clientPort),
+ ServerPort: uint16(serverPort),
+ }, nil
+}