diff options
author | dinoex <dinoex@FreeBSD.org> | 2004-03-26 22:05:33 +0800 |
---|---|---|
committer | dinoex <dinoex@FreeBSD.org> | 2004-03-26 22:05:33 +0800 |
commit | 70d6020bf55876721c0c2a1c5e7bce8cd55b0d4f (patch) | |
tree | c20e5779b0d476a1bacb1daf19c46e0dbf89c4e3 /mail/sendmail | |
parent | 212ef0364720e0c757be48690d600f798830e1f9 (diff) | |
download | freebsd-ports-gnome-70d6020bf55876721c0c2a1c5e7bce8cd55b0d4f.tar.gz freebsd-ports-gnome-70d6020bf55876721c0c2a1c5e7bce8cd55b0d4f.tar.zst freebsd-ports-gnome-70d6020bf55876721c0c2a1c5e7bce8cd55b0d4f.zip |
Add socket map support to the sendmail port (from 8.13.0)
This will allow for easier integration with e.g. ports/mail/cyrus-imapd22,
which already includes smmapd for realtime checking whether the mailbox
exists and is not over quota.
The patch adds
1) an extra knob in Makefile (WITH_SENDMAIL_SOCKETMAP).
3) the extra-patch-socketmap.patch is actually
http://www.sendmail.org/~ca/email/patches/sendmail-8.12.7-socketmap-v4.patch
slightly hacked (the pathnames) so it cleanly applies through ports(7).
PR: 64566
Submitted by: Michael O. Boev
- change PKGNAMESUFFIX
- merge 1-line site.config.m4.* files into Makefile
- update CONFLICTS
Diffstat (limited to 'mail/sendmail')
-rw-r--r-- | mail/sendmail/Makefile | 69 | ||||
-rw-r--r-- | mail/sendmail/files/site.config.m4.smtps | 1 | ||||
-rw-r--r-- | mail/sendmail/files/socketmap.patch | 798 |
3 files changed, 855 insertions, 13 deletions
diff --git a/mail/sendmail/Makefile b/mail/sendmail/Makefile index 5ca67264de40..7d6bf1b37ce7 100644 --- a/mail/sendmail/Makefile +++ b/mail/sendmail/Makefile @@ -10,13 +10,14 @@ PORTVERSION= 8.12.11 CATEGORIES= mail ipv6 MASTER_SITES= ftp://ftp.sendmail.org/pub/sendmail/ \ ${MASTER_SITE_RINGSERVER:S,%SUBDIR%,net/mail/sendmail/&,} +PKGNAMESUFFIX?= ${TLS_SUFFIX}${SASL_SUFFIX}${LDAP_SUFFIX}${PKGNAMESUFFIX2} DISTNAME= ${PORTNAME}.${PORTVERSION} MAINTAINER= dinoex@FreeBSD.org COMMENT= Reliable, highly configurable mail transfer agent with utilities -CONFLICTS?= courier-0.* postfix-1.* postfix-2.* sendmail-8.11.* sendmail-*-8.11.* \ - smail-3.* zmailer-2.* +CONFLICTS?= courier-0.* postfix-1.* postfix-2.* smail-3.* zmailer-2.* +CONFLICTS+= sendmail-8.11.* sendmail-*-8.11.* sendmail+*-8.11.* WRKSRC= ${WRKDIR}/${PORTNAME}-${PORTVERSION} WCONF= ${WRKSRC}/devtools/Site @@ -43,6 +44,7 @@ PKGMESSAGE= ${WRKSRC}/pkg-message # SENDMAIL_WITH_SASL=yes # SENDMAIL_WITH_SASL2=yes # SENDMAIL_WITH_LDAP=yes +# SENDMAIL_WITH_SOCKETMAP=yes # SENDMAIL_WITH_PICKY_HELO_CHECK=yes .if defined(SENDMAIL_WITH_SMTPS) @@ -54,25 +56,61 @@ pre-configure: .endif .if defined(SENDMAIL_WITH_LDAP) -PKGNAMESUFFIX?= -ldap +LDAP_SUFFIX?= +ldap +CONFLICTS+= sendmail+tls-8.* \ + sendmail+tls+sasl1-8.* \ + sendmail+tls+sasl2-8.* \ + sendmail+sasl1-8.* \ + sendmail+sasl2-8.* CONFLICTS+= sendmail-sasl-8.* sendmail-sasl2-8.* sendmail-tls-8.* LIB_DEPENDS+= ldap.2:${PORTSDIR}/${LDAP_PORT} LIB_DEPENDS+= lber.2:${PORTSDIR}/${LDAP_PORT} +.else +CONFLICTS+= sendmail*+ldap*-8.* .endif .if defined(SENDMAIL_WITH_SASL) -LIB_DEPENDS+= sasl.8:${PORTSDIR}/security/cyrus-sasl -PKGNAMESUFFIX?= -sasl +SASL_SUFFIX?= +sasl1 +CONFLICTS+= sendmail+tls-8.* \ + sendmail+tls+ldap-8.* \ + sendmail+tls+sasl2-8.* \ + sendmail+tls+sasl2+ldap-8.* \ + sendmail+sasl2-8.* \ + sendmail+sasl2+ldap-8.* \ + sendmail+ldap-8.* CONFLICTS+= sendmail-ldap-8.* sendmail-sasl2-8.* sendmail-tls-8.* +LIB_DEPENDS+= sasl.8:${PORTSDIR}/security/cyrus-sasl +.else +CONFLICTS+= sendmail*+sasl1*-8.* .endif .if defined(SENDMAIL_WITH_SASL2) +SASL_SUFFIX?= +sasl2 +CONFLICTS+= sendmail+tls-8.* \ + sendmail+tls+ldap-8.* \ + sendmail+tls+sasl-8.* \ + sendmail+tls+sasl+ldap-8.* \ + sendmail+sasl-8.* \ + sendmail+sasl+ldap-8.* \ + sendmail+ldap-8.* +CONFLICTS+= sendmail-ldap-8.* sendmail-sasl-8.* sendmail-tls-8.* +LIB_DEPENDS+= sasl.8:${PORTSDIR}/security/cyrus-sasl LIB_DEPENDS+= sasl2.2:${PORTSDIR}/security/cyrus-sasl2 RUN_DEPENDS+= ${LOCALBASE}/sbin/saslauthd:${PORTSDIR}/security/cyrus-sasl2-saslauthd -PKGNAMESUFFIX?= -sasl2 -CONFLICTS+= sendmail-ldap-8.* sendmail-sasl-8.* sendmail-tls-8.* +.else +CONFLICTS+= sendmail*+sasl2*-8.* +.endif +.if defined(SENDMAIL_WITH_SOCKETMAP) +EXTRA_PATCHES+= ${FILESDIR}/socketmap.patch .endif .if defined(SENDMAIL_WITH_TLS) || defined(WITH_TLS) -PKGNAMESUFFIX?= -tls +TLS_SUFFIX?= +tls +CONFLICTS+= sendmail+sasl-8.* \ + sendmail+sasl+ldap-8.* \ + sendmail+sasl2-8.* \ + sendmail+sasl2+ldap-8.* \ + sendmail+ldap-8.* CONFLICTS+= sendmail-ldap-8.* sendmail-sasl-8.* sendmail-sasl2-8.* +.else +CONFLICTS+= sendmail*+tls*-8.* .endif # Build site.config.m4 @@ -126,9 +164,19 @@ do-configure: ${SED} -e "s=%%PREFIX%%=${PREFIX}=g" \ -e "s=%%LOCALBASE%%=${LOCALBASE}=g" \ ${SITE} > ${WCONF}/site.config.m4 +.if defined(SENDMAIL_WITH_SMTPS) + ${ECHO_CMD} \ + 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-D_FFR_SMTP_SSL'\'') \ + >> ${WCONF}/site.config.m4 +.endif +.if defined(SENDMAIL_WITH_SOCKETMAP) + ${ECHO_CMD} \ + 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-DSOCKETMAP'\'')' \ + >> ${WCONF}/site.config.m4 +.endif .if defined(SENDMAIL_WITH_PICKY_HELO_CHECK) ${ECHO_CMD} \ - 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-DPICKY_HELO_CHECK'\'')' \ + 'APPENDDEF(`conf_sendmail_ENVDEF'\'', `-DPICKY_HELO_CHECK'\'')' \ >> ${WCONF}/site.config.m4 .endif .if defined(SENDMAIL_WITHOUT_SHMEM) @@ -283,9 +331,6 @@ tls-install: SITE+= ${FILESDIR}/site.config.m4.ssl .endif SITE+= ${FILESDIR}/site.config.m4.tls -.if defined(SENDMAIL_WITH_SMTPS) -SITE+= ${FILESDIR}/site.config.m4.smtps -.endif .endif .if exists(${FILESDIR}/site.config.m4.local) diff --git a/mail/sendmail/files/site.config.m4.smtps b/mail/sendmail/files/site.config.m4.smtps deleted file mode 100644 index f66b5fa440cd..000000000000 --- a/mail/sendmail/files/site.config.m4.smtps +++ /dev/null @@ -1 +0,0 @@ -APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_SMTP_SSL') diff --git a/mail/sendmail/files/socketmap.patch b/mail/sendmail/files/socketmap.patch new file mode 100644 index 000000000000..ea128dbace71 --- /dev/null +++ b/mail/sendmail/files/socketmap.patch @@ -0,0 +1,798 @@ +Index: sendmail/sendmail/sendmail/README +diff -u sendmail/sendmail/sendmail/README:1.1.1.2 sendmail/sendmail/sendmail/README:1.3 +--- sendmail/README Thu Jan 23 11:50:26 2003 ++++ sendmail/README Tue Jan 28 16:55:41 2003 +@@ -127,6 +127,8 @@ + PH_MAP PH map support. You will need the libphclient library from + the nph package (http://www-dev.cso.uiuc.edu/ph/nph/). + MAP_NSD nsd map support (IRIX 6.5 and later). ++SOCKETMAP Support for a trivial query protocol over UNIX domain or TCP ++ sockets. + + >>> NOTE WELL for NEWDB support: If you want to get ndbm support, for + >>> Berkeley DB versions under 2.0, it is CRITICAL that you remove +@@ -180,6 +182,50 @@ + check_* rule-set, you can block a certain range of addresses that would + otherwise be considered valid. + ++The socket map uses a simple request/reply protocol over TCP or UNIX domain ++sockets to query an external server. Both requests and replies are text ++based and encoded as D.J. Bernsteins netstrings. E.g., a string ++"hello there" becomes: ++11:hello there, ++ ++NB. neither requests nor replies end with CRLF. ++ ++The request consists of the database map name and the lookup key separated ++by a space character: ++ ++<mapname> ' ' <key> ++ ++The server responds with a status indicator and the result (if any): ++ ++<status> ' ' <result> <LF> ++ ++The status indicator is one of the following upper case words: ++OK (the key was found, result contains the looked up value) ++NOTFOUND (the key was not found, the result is empty) ++TEMP (a temporary failure occured) ++TIMEOUT (a timeout occured on the server side) ++PERM (a permanent failure occured) ++ ++In case of errors (status TEMP, TIMEOUT or PERM) the result fied may ++contain an explanatory message. ++ ++Example replies: ++30:OK resolved.addess@example.com, ++ ++in case of a successful lookup, or: ++7:NOTFOUND, ++ ++in case the key was not found, or: ++54:TEMP this text explains that we had a temporary failure, ++ ++in case of a failure. ++ ++The socket map uses the same syntax as milters the specify the remote ++endpoint. E.g.: ++Ksocket mySocketMap inet:12345@127.0.0.1 ++ ++If multiple socket maps define the same remote endpoint, they will share ++a single connection to this endpoint. + + +---------------+ + | COMPILE FLAGS | +Index: sendmail/sendmail/sendmail/conf.c +diff -u sendmail/sendmail/sendmail/conf.c:1.1.1.2 sendmail/sendmail/sendmail/conf.c:1.6 +--- sendmail/conf.c Thu Jan 23 11:50:27 2003 ++++ sendmail/conf.c Fri Jan 24 15:31:59 2003 +@@ -622,6 +622,13 @@ + dequote_init, null_map_open, null_map_close, + arith_map_lookup, null_map_store); + ++#if SOCKETMAP ++ /* arbitrary daemons */ ++ MAPDEF("socket", NULL, MCF_ALIASOK, ++ map_parseargs, socket_map_open, socket_map_close, ++ socket_map_lookup, null_map_store); ++#endif /* SOCKETMAP */ ++ + if (tTd(38, 2)) + { + /* bogus map -- always return tempfail */ +Index: sendmail/sendmail/sendmail/map.c +diff -u sendmail/sendmail/sendmail/map.c:1.1.1.2 sendmail/sendmail/sendmail/map.c:1.25 +--- sendmail/map.c Thu Jan 23 11:50:27 2003 ++++ sendmail/map.c Tue Feb 25 14:57:14 2003 +@@ -66,6 +66,9 @@ + static bool ni_getcanonname __P((char *, int, int *)); + #endif /* NETINFO */ + static bool text_getcanonname __P((char *, int, int *)); ++#ifdef SOCKETMAP ++static STAB * socket_map_findconn __P((const char*)); ++#endif /* SOCKETMAP */ + + /* default error message for trying to open a map in write mode */ + #ifdef ENOSYS +@@ -7395,3 +7398,646 @@ + *statp = EX_CONFIG; + return NULL; + } ++ ++#ifdef SOCKETMAP ++ ++# if NETINET || NETINET6 ++# include <arpa/inet.h> ++# endif /* NETINET || NETINET6 */ ++ ++#define socket_map_next map_stack[0] ++#define socket_map_previous map_stack[1] ++ ++/* ++** SOCKET_MAP_OPEN -- open socket table ++*/ ++ ++bool ++socket_map_open(map, mode) ++ MAP *map; ++ int mode; ++{ ++ STAB *s; ++ ++ int sock = 0; ++ SOCKADDR_LEN_T addrlen = 0; ++ int addrno = 0; ++ int save_errno; ++ char *p; ++ char *colon; ++ char *at; ++ struct hostent *hp = NULL; ++ SOCKADDR addr; ++ ++ if (tTd(38, 2)) ++ sm_dprintf("socket_map_open(%s, %s, %d)\n", ++ map->map_mname, map->map_file, mode); ++ ++ mode &= O_ACCMODE; ++ ++ /* sendmail doesn't have the ability to write to SOCKET (yet) */ ++ if (mode != O_RDONLY) ++ { ++ /* issue a pseudo-error message */ ++ errno = SM_EMAPCANTWRITE; ++ return false; ++ } ++ ++ if (*map->map_file == '\0') ++ { ++ syserr("socket map \"%s\": empty or missing socket information", ++ map->map_mname); ++ return false; ++ } ++ ++ s = socket_map_findconn(map->map_file); ++ if (s->s_socketmap != NULL) ++ { ++ /* Copy open connection */ ++ map->map_db1 = s->s_socketmap->map_db1; ++ ++ /* Add this map as head of linked list */ ++ map->socket_map_next = s->s_socketmap; ++ s->s_socketmap = map; ++ ++ if (tTd(38, 2)) ++ sm_dprintf("using cached connection\n"); ++ return true; ++ } ++ ++ if (tTd(38, 2)) ++ sm_dprintf("opening new connection\n"); ++ ++ ++ ++ /* following code is ripped from milter.c */ ++ ++ /* protocol:filename or protocol:port@host */ ++ memset(&addr, '\0', sizeof addr); ++ p = map->map_file; ++ colon = strchr(p, ':'); ++ if (colon != NULL) ++ { ++ *colon = '\0'; ++ ++ if (*p == '\0') ++ { ++# if NETUNIX ++ /* default to AF_UNIX */ ++ addr.sa.sa_family = AF_UNIX; ++# else /* NETUNIX */ ++# if NETINET ++ /* default to AF_INET */ ++ addr.sa.sa_family = AF_INET; ++# else /* NETINET */ ++# if NETINET6 ++ /* default to AF_INET6 */ ++ addr.sa.sa_family = AF_INET6; ++# else /* NETINET6 */ ++ /* no protocols available */ ++ syserr("socket map \"%s\": no valid socket protocols available", ++ map->map_mname); ++ return false; ++# endif /* NETINET6 */ ++# endif /* NETINET */ ++# endif /* NETUNIX */ ++ } ++# if NETUNIX ++ else if (sm_strcasecmp(p, "unix") == 0 || ++ sm_strcasecmp(p, "local") == 0) ++ addr.sa.sa_family = AF_UNIX; ++# endif /* NETUNIX */ ++# if NETINET ++ else if (sm_strcasecmp(p, "inet") == 0) ++ addr.sa.sa_family = AF_INET; ++# endif /* NETINET */ ++# if NETINET6 ++ else if (sm_strcasecmp(p, "inet6") == 0) ++ addr.sa.sa_family = AF_INET6; ++# endif /* NETINET6 */ ++ else ++ { ++# ifdef EPROTONOSUPPORT ++ errno = EPROTONOSUPPORT; ++# else /* EPROTONOSUPPORT */ ++ errno = EINVAL; ++# endif /* EPROTONOSUPPORT */ ++ syserr("socket map \"%s\": unknown socket type %s", ++ map->map_mname, p); ++ return false; ++ } ++ *colon++ = ':'; ++ } ++ else ++ { ++ /* default to AF_UNIX */ ++ addr.sa.sa_family = AF_UNIX; ++ colon = p; ++ } ++ ++# if NETUNIX ++ if (addr.sa.sa_family == AF_UNIX) ++ { ++ long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; ++ ++ at = colon; ++ if (strlen(colon) >= sizeof addr.sunix.sun_path) ++ { ++ syserr("socket map \"%s\": local socket name %s too long", ++ map->map_mname, colon); ++ return false; ++ } ++ errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, ++ S_IRUSR|S_IWUSR, NULL); ++ ++ if (errno != 0) ++ { ++ /* if not safe, don't create */ ++ syserr("socket map \"%s\": local socket name %s unsafe", ++ map->map_mname, colon); ++ return false; ++ } ++ ++ (void) sm_strlcpy(addr.sunix.sun_path, colon, ++ sizeof addr.sunix.sun_path); ++ addrlen = sizeof (struct sockaddr_un); ++ } ++ else ++# endif /* NETUNIX */ ++# if NETINET || NETINET6 ++ if (false ++# if NETINET ++ || addr.sa.sa_family == AF_INET ++# endif /* NETINET */ ++# if NETINET6 ++ || addr.sa.sa_family == AF_INET6 ++# endif /* NETINET6 */ ++ ) ++ { ++ unsigned short port; ++ ++ /* Parse port@host */ ++ at = strchr(colon, '@'); ++ if (at == NULL) ++ { ++ syserr("socket map \"%s\": bad address %s (expected port@host)", ++ map->map_mname, colon); ++ return false; ++ } ++ *at = '\0'; ++ if (isascii(*colon) && isdigit(*colon)) ++ port = htons((unsigned short) atoi(colon)); ++ else ++ { ++# ifdef NO_GETSERVBYNAME ++ syserr("socket map \"%s\": invalid port number %s", ++ map->map_mname, colon); ++ return false; ++# else /* NO_GETSERVBYNAME */ ++ register struct servent *sp; ++ ++ sp = getservbyname(colon, "tcp"); ++ if (sp == NULL) ++ { ++ syserr("socket map \"%s\": unknown port name %s", ++ map->map_mname, colon); ++ return false; ++ } ++ port = sp->s_port; ++# endif /* NO_GETSERVBYNAME */ ++ } ++ *at++ = '@'; ++ if (*at == '[') ++ { ++ char *end; ++ ++ end = strchr(at, ']'); ++ if (end != NULL) ++ { ++ bool found = false; ++# if NETINET ++ unsigned long hid = INADDR_NONE; ++# endif /* NETINET */ ++# if NETINET6 ++ struct sockaddr_in6 hid6; ++# endif /* NETINET6 */ ++ ++ *end = '\0'; ++# if NETINET ++ if (addr.sa.sa_family == AF_INET && ++ (hid = inet_addr(&at[1])) != INADDR_NONE) ++ { ++ addr.sin.sin_addr.s_addr = hid; ++ addr.sin.sin_port = port; ++ found = true; ++ } ++# endif /* NETINET */ ++# if NETINET6 ++ (void) memset(&hid6, '\0', sizeof hid6); ++ if (addr.sa.sa_family == AF_INET6 && ++ anynet_pton(AF_INET6, &at[1], ++ &hid6.sin6_addr) == 1) ++ { ++ addr.sin6.sin6_addr = hid6.sin6_addr; ++ addr.sin6.sin6_port = port; ++ found = true; ++ } ++# endif /* NETINET6 */ ++ *end = ']'; ++ if (!found) ++ { ++ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", ++ map->map_mname, at); ++ return false; ++ } ++ } ++ else ++ { ++ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", ++ map->map_mname, at); ++ return false; ++ } ++ } ++ else ++ { ++ hp = sm_gethostbyname(at, addr.sa.sa_family); ++ if (hp == NULL) ++ { ++ syserr("socket map \"%s\": Unknown host name %s", ++ map->map_mname, at); ++ return false; ++ } ++ addr.sa.sa_family = hp->h_addrtype; ++ switch (hp->h_addrtype) ++ { ++# if NETINET ++ case AF_INET: ++ memmove(&addr.sin.sin_addr, ++ hp->h_addr, INADDRSZ); ++ addr.sin.sin_port = port; ++ addrlen = sizeof (struct sockaddr_in); ++ addrno = 1; ++ break; ++# endif /* NETINET */ ++ ++# if NETINET6 ++ case AF_INET6: ++ memmove(&addr.sin6.sin6_addr, ++ hp->h_addr, IN6ADDRSZ); ++ addr.sin6.sin6_port = port; ++ addrlen = sizeof (struct sockaddr_in6); ++ addrno = 1; ++ break; ++# endif /* NETINET6 */ ++ ++ default: ++ syserr("socket map \"%s\": Unknown protocol for %s (%d)", ++ map->map_mname, at, hp->h_addrtype); ++# if NETINET6 ++ freehostent(hp); ++# endif /* NETINET6 */ ++ return false; ++ } ++ } ++ } ++ else ++# endif /* NETINET || NETINET6 */ ++ { ++ syserr("socket map \"%s\": unknown socket protocol", map->map_mname); ++ return false; ++ } ++ ++ /* nope, actually connecting */ ++ for (;;) ++ { ++ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); ++ if (sock < 0) ++ { ++ save_errno = errno; ++ if (tTd(38, 5)) ++ sm_dprintf("socket map \"%s\": error creating socket: %s\n", ++ map->map_mname, ++ sm_errstring(save_errno)); ++# if NETINET6 ++ if (hp != NULL) ++ freehostent(hp); ++# endif /* NETINET6 */ ++ return false; ++ } ++ ++ if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) ++ break; ++ ++ /* couldn't connect.... try next address */ ++ save_errno = errno; ++ p = CurHostName; ++ CurHostName = at; ++ if (tTd(38, 5)) ++ sm_dprintf("socket_open (%s): open %s failed: %s\n", ++ map->map_mname, at, sm_errstring(save_errno)); ++ CurHostName = p; ++ (void) close(sock); ++ ++ /* try next address */ ++ if (hp != NULL && hp->h_addr_list[addrno] != NULL) ++ { ++ switch (addr.sa.sa_family) ++ { ++# if NETINET ++ case AF_INET: ++ memmove(&addr.sin.sin_addr, ++ hp->h_addr_list[addrno++], ++ INADDRSZ); ++ break; ++# endif /* NETINET */ ++ ++# if NETINET6 ++ case AF_INET6: ++ memmove(&addr.sin6.sin6_addr, ++ hp->h_addr_list[addrno++], ++ IN6ADDRSZ); ++ break; ++# endif /* NETINET6 */ ++ ++ default: ++ if (tTd(38, 5)) ++ sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", ++ map->map_mname, at, ++ hp->h_addrtype); ++# if NETINET6 ++ freehostent(hp); ++# endif /* NETINET6 */ ++ return false; ++ } ++ continue; ++ } ++ p = CurHostName; ++ CurHostName = at; ++ if (tTd(38, 5)) ++ sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", ++ map->map_mname, sm_errstring(save_errno)); ++ CurHostName = p; ++# if NETINET6 ++ if (hp != NULL) ++ freehostent(hp); ++# endif /* NETINET6 */ ++ return false; ++ } ++# if NETINET6 ++ if (hp != NULL) ++ { ++ freehostent(hp); ++ hp = NULL; ++ } ++# endif /* NETINET6 */ ++ if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, ++ SM_TIME_DEFAULT, ++ (void *) &sock, ++ SM_IO_RDWR, ++ NULL)) == NULL) ++ { ++ close(sock); ++ if (tTd(38, 2)) ++ sm_dprintf("socket_open (%s): failed to create stream: %s\n", ++ map->map_mname, sm_errstring(errno)); ++ return false; ++ } ++ ++ /* Save connection for reuse */ ++ s->s_socketmap = map; ++ return true; ++} ++ ++/* ++** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server ++** ++** Cache SOCKET connections based on the connection specifier ++** and PID so we don't have multiple connections open to ++** the same server for different maps. Need a separate connection ++** per PID since a parent process may close the map before the ++** child is done with it. ++** ++** Parameters: ++** conn -- SOCKET map connection specifier ++** ++** Returns: ++** Symbol table entry for the SOCKET connection. ++*/ ++ ++static STAB * ++socket_map_findconn(conn) ++ const char *conn; ++{ ++ char *format; ++ char *nbuf; ++ STAB *SM_NONVOLATILE s = NULL; ++ ++ format = "%s%c%d"; ++ nbuf = sm_stringf_x(format, ++ conn, ++ CONDELSE, ++ (int) CurrentPid); ++ if (tTd(38, 20)) ++ sm_dprintf("socket_find_conn '%s'\n", nbuf); ++ SM_TRY ++ s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); ++ SM_FINALLY ++ sm_free(nbuf); ++ SM_END_TRY ++ return s; ++} ++ ++/* ++** SOCKET_MAP_CLOSE -- close the socket ++*/ ++ ++void ++socket_map_close(map) ++ MAP *map; ++{ ++ STAB *s; ++ MAP *smap; ++ ++ if (tTd(38, 20)) ++ sm_dprintf("socket_map_close(%s), pid=%d\n", map->map_file,(int) CurrentPid); ++ ++ /* Check if already closed */ ++ if (!map->map_db1) ++ { ++ if (tTd(38, 20)) ++ sm_dprintf("socket_map_close(%s) already closed\n", map->map_file); ++ return; ++ } ++ ++ sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); ++ ++ /* Mark all the maps that share the connection as closed */ ++ s = socket_map_findconn(map->map_file); ++ ++ smap = s->s_socketmap; ++ ++ while (smap != NULL) ++ { ++ MAP *next; ++ ++ if (tTd(38, 2) && smap != map) ++ sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", ++ map->map_mname, smap->map_mname); ++ ++ smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); ++ smap->map_db1 = NULL; ++ next = smap->socket_map_next; ++ smap->socket_map_next = NULL; ++ smap = next; ++ } ++ ++ s->s_socketmap = NULL; ++} ++ ++/* ++** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table ++*/ ++ ++char * ++socket_map_lookup(map, name, av, statp) ++ MAP *map; ++ char *name; ++ char **av; ++ int *statp; ++{ ++ size_t nettolen; ++ char *rval = NULL; ++ SM_FILE_T *f = (SM_FILE_T *)map->map_db1; ++ ++ if (tTd(38, 20)) ++ sm_dprintf("socket_map_lookup(%s, %s) %s\n", ++ map->map_mname, name, map->map_file); ++ ++ nettolen = strlen(map->map_mname) + 1 + strlen(name); ++ if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", ++ nettolen, map->map_mname, name) == SM_IO_EOF) || (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || ++ (sm_io_error(f))) ++ { ++ syserr("socket_map_lookup(%s): failed to send lookup request", ++ map->map_mname); ++ *statp = EX_TEMPFAIL; ++ socket_map_close(map); ++ } ++ else ++ { ++ size_t replylen; ++ ++ if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) ++ { ++ syserr("socket_map_lookup(%s): failed to read length parameter of reply", ++ map->map_mname); ++ *statp = EX_TEMPFAIL; ++ socket_map_close(map); ++ } ++ else ++ { ++ /* XXX arbitrary limit for sanity */ ++ if (replylen > 1000000) ++ { ++ syserr("socket_map_lookup(%s): reply too long: %u", ++ map->map_mname, replylen); ++ /* *statp = EX_PROTOCOL; */ ++ *statp = EX_TEMPFAIL; ++ socket_map_close(map); ++ } ++ else ++ { ++ if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') ++ { ++ syserr("socket_map_lookup(%s): missing ':' in reply", ++ map->map_mname); ++ /* *statp = EX_PROTOCOL; */ ++ *statp = EX_TEMPFAIL; ++ } ++ else ++ { ++ size_t recvlen; ++ char *replybuf = (char *) sm_malloc(replylen + 1); ++ recvlen = sm_io_read(f, SM_TIME_DEFAULT, ++ replybuf, replylen); ++ if (recvlen < replylen) ++ { ++ syserr("socket_map_lookup(%s): received only %u of %u reply characters", ++ map->map_mname, recvlen, replylen); ++ *statp = EX_TEMPFAIL; ++ socket_map_close(map); ++ } ++ else ++ { ++ if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') ++ { ++ syserr("socket_map_lookup(%s): missing ',' in reply", ++ map->map_mname); ++ /* *statp = EX_PROTOCOL; */ ++ *statp = EX_TEMPFAIL; ++ socket_map_close(map); ++ } ++ else ++ { ++ char *value; ++ char *status = replybuf; ++ ++ replybuf[recvlen] = '\0'; ++ value = strchr(replybuf, ' '); ++ if (value != NULL) ++ { ++ *value = '\0'; ++ value++; ++ } ++ ++ if (strcmp(status, "OK") == 0) ++ { ++ *statp = EX_OK; ++ ++ /* collect the return value */ ++ if (bitset(MF_MATCHONLY, map->map_mflags)) ++ rval = map_rewrite(map, name, strlen(name), NULL); ++ else ++ rval = map_rewrite(map, value, strlen(value), av); ++ } ++ else if(strcmp(status, "NOTFOUND") == 0) ++ { ++ *statp = EX_NOTFOUND; ++ if (tTd(38, 20)) ++ sm_dprintf("socket_map_lookup(%s): %s not found\n", ++ map->map_mname, name); ++ } ++ else ++ { ++ if (tTd(38, 5)) ++ sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", ++ map->map_mname, name, status, ++ value ? value : ""); ++ if ((strcmp(status, "TEMP") == 0) || ++ (strcmp(status, "TIMEOUT") == 0)) ++ { ++ *statp = EX_TEMPFAIL; ++ } ++ else if(strcmp(status, "PERM") == 0) ++ { ++ *statp = EX_UNAVAILABLE; ++ } ++ else ++ { ++ *statp = EX_PROTOCOL; ++ } ++ } ++ } ++ } ++ ++ sm_free(replybuf); ++ } ++ } ++ } ++ } ++ ++ return rval; ++} ++ ++ ++#endif /* SOCKETMAP */ +Index: sendmail/sendmail/sendmail/sendmail.h +diff -u sendmail/sendmail/sendmail/sendmail.h:1.1.1.2 sendmail/sendmail/sendmail/sendmail.h:1.3 +--- sendmail/sendmail.h Thu Jan 23 11:50:27 2003 ++++ sendmail/sendmail.h Thu Jan 23 11:51:38 2003 +@@ -1382,6 +1382,9 @@ + #if LDAPMAP + MAP *sv_lmap; /* Maps for LDAP connection */ + #endif /* LDAPMAP */ ++#if SOCKETMAP ++ MAP *sv_socketmap; /* Maps for SOCKET connection */ ++#endif /* SOCKETMAP */ + #if MILTER + struct milter *sv_milter; /* milter filter name */ + #endif /* MILTER */ +@@ -1413,8 +1416,12 @@ + #endif /* MILTER */ + #define ST_QUEUE 15 /* a queue entry */ + ++#if SOCKETMAP ++# define ST_SOCKETMAP 16 /* List head of maps for SOCKET connection */ ++#endif /* SOCKETMAP */ ++ + /* This entry must be last */ +-#define ST_MCI 16 /* mailer connection info (offset) */ ++#define ST_MCI 17 /* mailer connection info (offset) */ + + #define s_class s_value.sv_class + #define s_address s_value.sv_addr +@@ -1432,6 +1439,9 @@ + #if LDAPMAP + # define s_lmap s_value.sv_lmap + #endif /* LDAPMAP */ ++#if SOCKETMAP ++# define s_socketmap s_value.sv_socketmap ++#endif /* SOCKETMAP */ + #if MILTER + # define s_milter s_value.sv_milter + #endif /* MILTER */ +Index: sendmail/sendmail/sendmail/stab.c +diff -u sendmail/sendmail/sendmail/stab.c:1.1.1.1 sendmail/sendmail/sendmail/stab.c:1.2 +--- sendmail/stab.c Fri Oct 11 14:44:04 2002 ++++ sendmail/stab.c Wed Jan 22 18:57:22 2003 +@@ -173,6 +173,12 @@ + len = sizeof s->s_quegrp; + break; + ++#if SOCKETMAP ++ case ST_SOCKETMAP: ++ len = sizeof s->s_socketmap; ++ break; ++#endif /* SOCKETMAP */ ++ + default: + /* + ** Each mailer has its own MCI stab entry: |