Index: sendmail/sendmail/sendmail/README
diff -u sendmail/sendmail/sendmail/README:1.1.1.2 sendmail/sendmail/sendmail/README:1.3
--- sendmail/sendmail/sendmail/README:1.1.1.2	Thu Jan 23 11:50:26 2003
+++ sendmail/sendmail/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/sendmail/sendmail/conf.c:1.1.1.2	Thu Jan 23 11:50:27 2003
+++ sendmail/sendmail/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/sendmail/sendmail/map.c:1.1.1.2	Thu Jan 23 11:50:27 2003
+++ sendmail/sendmail/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/sendmail/sendmail.h:1.1.1.2	Thu Jan 23 11:50:27 2003
+++ sendmail/sendmail/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/sendmail/sendmail/stab.c:1.1.1.1	Fri Oct 11 14:44:04 2002
+++ sendmail/sendmail/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:
