ports/mail/sendmail/files/socketmap.patch
Dirk Meyer 6db91b3c94 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
2004-03-26 14:05:33 +00:00

798 lines
23 KiB
Diff

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: