--- 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;