ports/64566: [PATCH] add socketmap support to ports/mail/sendmail

Michael O. Boev mike at tric.tomsk.gov.ru
Mon Mar 22 11:50:20 UTC 2004


>Number:         64566
>Category:       ports
>Synopsis:       Add socket map support to the sendmail port (from 8.13.0)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 22 03:50:19 PST 2004
>Closed-Date:
>Last-Modified:
>Originator:     Michael O. Boev
>Release:        FreeBSD 4.9-RELEASE-p3 i386
>Organization:
Tomsk Regional Information Center
>Environment:
System: FreeBSD isrv.tric.ru 4.9-RELEASE-p3 FreeBSD 4.9-RELEASE-p3 #0: Wed
Mar 3 14:04:51 NOVT 2004 root at isrv.tric.ru:/usr/obj/usr/src/sys/ISRV i386


>Description:
	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).
	2) the knob adds SITE+=	${FILESDIR}/site.config.m4.socketmap and
		EXTRA_PATCHES+=	${FILESDIR}/extra-patch-socketmap.patch
	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).


>How-To-Repeat:

>Fix:
	Please apply the following diff...
diff -ruN sendmail.orig/Makefile sendmail/Makefile
--- sendmail.orig/Makefile	Wed Mar  3 02:41:14 2004
+++ sendmail/Makefile	Mon Mar 22 17:27:09 2004
@@ -7,6 +7,7 @@

 PORTNAME=	sendmail
 PORTVERSION=	8.12.11
+PORTREVISION=	1
 CATEGORIES=	mail ipv6
 MASTER_SITES=	ftp://ftp.sendmail.org/pub/sendmail/ \
 		${MASTER_SITE_RINGSERVER:S,%SUBDIR%,net/mail/sendmail/&,}
@@ -96,6 +97,10 @@
 .endif
 .if defined(SENDMAIL_WITH_TLS) || defined(WITH_TLS)
 USE_OPENSSL=	yes
+.endif
+.if defined(SENDMAIL_WITH_SOCKETMAP)
+SITE+=	${FILESDIR}/site.config.m4.socketmap
+EXTRA_PATCHES+=	${FILESDIR}/extra-patch-socketmap.patch
 .endif

 # install directly if no mailwrapper support
diff -ruN sendmail.orig/files/extra-patch-socketmap.patch
sendmail/files/extra-patch-socketmap.patch
--- sendmail.orig/files/extra-patch-socketmap.patch	Thu Jan  1 07:00:00 1970
+++ sendmail/files/extra-patch-socketmap.patch	Mon Mar 22 16:02:53 2004
@@ -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 at 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 at 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 at 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 at host */
++		at = strchr(colon, '@');
++		if (at == NULL)
++		{
++			syserr("socket map \"%s\": bad address %s (expected port at 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:
diff -ruN sendmail.orig/files/site.config.m4.socketmap
sendmail/files/site.config.m4.socketmap
--- sendmail.orig/files/site.config.m4.socketmap	Thu Jan  1 07:00:00 1970
+++ sendmail/files/site.config.m4.socketmap	Mon Mar 22 17:13:48 2004
@@ -0,0 +1 @@
+APPENDDEF(`conf_sendmail_ENVDEF', `-DSOCKETMAP')



>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list