From: Marco d'Itri <md@linux.it>
Date: Sat, 14 May 2022 02:57:49 +0800
Subject: match_port

---
 hosts_access.5 |  2 +-
 hosts_access.c | 34 ++++++++++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/hosts_access.5 b/hosts_access.5
index bd8903a..044d0e0 100644
--- a/hosts_access.5
+++ b/hosts_access.5
@@ -51,7 +51,7 @@ being optional:
 daemon_list : client_list [ : shell_command ]
 .PP
 \fIdaemon_list\fR is a list of one or more daemon process names
-(argv[0] values) or wildcards (see below).  
+(argv[0] values) or server port numbers or wildcards (see below).  
 .PP
 \fIclient_list\fR is a list
 of one or more host names, host addresses, patterns or wildcards (see
diff --git a/hosts_access.c b/hosts_access.c
index a2c6abf..7ef0554 100644
--- a/hosts_access.c
+++ b/hosts_access.c
@@ -231,6 +231,36 @@ int   (*match_fn) ();
     return (NO);
 }
 
+/*
+ * daemon_or_port_match - match server information: if the server endpoint
+ * pattern is a port number, match against port number of connection;
+ * otherwise match against daemon executable name
+ */
+
+static int daemon_or_port_match(char *tok, struct request_info *request) {
+    unsigned int port, sin_port;
+    char junk;
+
+    /* daemon name */
+    if (sscanf(tok, "%u%c", &port, &junk) != 1 || port > 65535)
+	return (string_match(tok, eval_daemon(request)));
+
+    /* port number */
+    if (!request->server->sin)
+	return (NO);
+
+#ifdef INET6
+    sin_port = ntohs(((struct sockaddr_in *)request->server->sin)->sin_port);
+#else
+    sin_port = ntohs(request->server->sin->sin_port);
+#endif
+
+    if (port == sin_port)
+	return (YES);
+    else
+	return (NO);
+}
+
 /* server_match - match server information */
 
 static int server_match(tok, request)
@@ -240,9 +270,9 @@ struct request_info *request;
     char   *host;
 
     if ((host = split_at(tok + 1, '@')) == 0) {	/* plain daemon */
-	return (string_match(tok, eval_daemon(request)));
+	return (daemon_or_port_match(tok, request));
     } else {					/* daemon@host */
-	return (string_match(tok, eval_daemon(request))
+	return (daemon_or_port_match(tok, request)
 		&& host_match(host, request->server));
     }
 }
