--- libmilter/docs/smfi_setconn.html | 1 + libmilter/listener.c | 27 ++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libmilter/docs/smfi_setconn.html b/libmilter/docs/smfi_setconn.html --- a/libmilter/docs/smfi_setconn.html +++ b/libmilter/docs/smfi_setconn.html @@ -44,6 +44,7 @@ Set the socket through which this filter
{unix|local}:/path/to/file
-- A named pipe.
inet:port@{hostname|ip-address}
-- An IPV4 socket.
inet6:port@{hostname|ip-address}
-- An IPV6 socket.
+ fd:number
-- Pre-opened file descriptor.
diff --git a/libmilter/listener.c b/libmilter/listener.c
--- a/libmilter/listener.c
+++ b/libmilter/listener.c
@@ -197,6 +197,11 @@ mi_milteropen(conn, backlog, rmsocket, n
L_socksize = sizeof addr.sin6;
}
#endif /* NETINET6 */
+ else if (strcasecmp(p, "fd") == 0)
+ {
+ addr.sa.sa_family = AF_UNSPEC;
+ L_socksize = sizeof (_SOCK_ADDR);
+ }
else
{
smi_log(SMI_LOG_ERR, "%s: unknown socket type %s",
@@ -443,7 +448,21 @@ mi_milteropen(conn, backlog, rmsocket, n
}
#endif /* NETINET || NETINET6 */
- sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ if (addr.sa.sa_family == AF_UNSPEC)
+ {
+ char *end;
+ sock = strtol(colon, &end, 10);
+ if (*end != '\0' || sock < 0)
+ {
+ smi_log(SMI_LOG_ERR, "%s: expected positive integer as fd, got %s", name, colon);
+ return INVALID_SOCKET;
+ }
+ }
+ else
+ {
+ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ }
+
if (!ValidSocket(sock))
{
smi_log(SMI_LOG_ERR,
@@ -466,6 +485,7 @@ mi_milteropen(conn, backlog, rmsocket, n
#if NETUNIX
addr.sa.sa_family != AF_UNIX &&
#endif
+ addr.sa.sa_family != AF_UNSPEC &&
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt,
sizeof(sockopt)) == -1)
{
@@ -511,7 +531,8 @@ mi_milteropen(conn, backlog, rmsocket, n
}
#endif /* NETUNIX */
- if (bind(sock, &addr.sa, L_socksize) < 0)
+ if (addr.sa.sa_family != AF_UNSPEC &&
+ bind(sock, &addr.sa, L_socksize) < 0)
{
smi_log(SMI_LOG_ERR,
"%s: Unable to bind to port %s: %s",
@@ -818,7 +839,7 @@ mi_listener(conn, dbg, smfi, timeout, ba
#ifdef BSD4_4_SOCKADDR
cliaddr.sa.sa_len == 0 ||
#endif
- cliaddr.sa.sa_family != L_family))
+ (L_family != AF_UNSPEC && cliaddr.sa.sa_family != L_family)))
{
(void) closesocket(connfd);
connfd = INVALID_SOCKET;