Only in sendmail-8.13.8-dnsmap/devtools/Site: site.config.m4
Only in sendmail-8.13.8-dnsmap/: obj.Linux.2.6.12.3686-smp-0.1.0.i686
diff -urw sendmail-8.13.8-orig/sendmail/conf.c sendmail-8.13.8-dnsmap/sendmail/conf.c
--- sendmail-8.13.8-orig/sendmail/conf.c	2006-03-22 17:49:33.000000000 -0500
+++ sendmail-8.13.8-dnsmap/sendmail/conf.c	2006-11-02 23:52:07.000000000 -0500
@@ -6055,6 +6055,11 @@
 	/* DefaultAuthInfo doesn't really work in 8.13 anymore. */
 	"_FFR_ALLOW_SASLINFO",
 #endif /* _FFR_ALLOW_SASLINFO */
+#if _FFR_BESTMX_MULTI_BEST
+	/* allow -B map switch to specify return of all MX's which are best
+	 * Best used in conjuction with -z */
+	"_FFR_BESTMX_MULTI_BEST",
+#endif /* _FFR_BESTMX_MULTI_BEST */
 #if _FFR_BESTMX_BETTER_TRUNCATION
 	/* Better truncation of list of MX records for dns map. */
 	"_FFR_BESTMX_BETTER_TRUNCATION",
@@ -6128,6 +6133,14 @@
 	/* Limit number of return values for DNS map. */
 	"_FFR_DNSMAP_MULTILIMIT",
 # endif /* _FFR_DNSMAP_MULTILIMIT */
+# if _FFR_DNSMAP_MULTI_SAMENAME
+	/* restrict matches to the ones with the same domain name */
+	"_FFR_DNSMAP_SAMENAME",
+# endif /* _FFR_DNSMAP_MULTI_SAMENAME */
+# if _FFR_DNSMAP_MULTI_BEST
+	/* Limit multiple DNS map results to the most preffered */
+	"_FFR_DNSMAP_MULTI_BEST",
+# endif /* _FFR_DNSMAP_MULTI_BEST */
 #endif /* _FFR_DNSMAP_MULTI */
 #if _FFR_DONTLOCKFILESFORREAD_OPTION
 	/* Enable DontLockFilesForRead option. */
Only in sendmail-8.13.8-dnsmap/sendmail: conf.c.orig
Only in sendmail-8.13.8-dnsmap/sendmail: conf.c.rej
diff -urw sendmail-8.13.8-orig/sendmail/domain.c sendmail-8.13.8-dnsmap/sendmail/domain.c
--- sendmail-8.13.8-orig/sendmail/domain.c	2006-04-17 20:00:34.000000000 -0400
+++ sendmail-8.13.8-dnsmap/sendmail/domain.c	2006-11-02 23:13:44.000000000 -0500
@@ -637,6 +637,25 @@
 		sm_dprintf(" = %d\n", hfunc);
 	return hfunc;
 }
+
+#if _FFR_BESTMX_MULTI_BEST
+struct dns_names_prefs {
+	char * name;
+	unsigned pref;
+};
+
+static int 
+cmp_names_prefs(a, b)
+	struct dns_names_prefs *a;
+	struct dns_names_prefs *b;
+{
+	if (a->pref < b->pref)
+		return -1;
+	if (a->pref > b->pref)
+		return 1;
+	return 0;
+}
+#endif /* _FFR_BESTMX_MULTI_BEST */
 /*
 **  BESTMX -- find the best MX for a name
 **
@@ -658,6 +677,7 @@
 	ssize_t len = 0;
 	char *result;
 	char *mxhosts[MAXMXHOSTS + 1];
+	unsigned short mxprefs[MAXMXHOSTS + 1];
 #if _FFR_BESTMX_BETTER_TRUNCATION
 	char *buf;
 #else /* _FFR_BESTMX_BETTER_TRUNCATION */
@@ -666,7 +686,7 @@
 #endif /* _FFR_BESTMX_BETTER_TRUNCATION */
 
 	_res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
-	nmx = getmxrr(name, mxhosts, NULL, false, statp, false, NULL);
+	nmx = getmxrr(name, mxhosts, mxprefs, false, statp, false, NULL);
 	_res.options = saveopts;
 	if (nmx <= 0)
 		return NULL;
@@ -679,7 +699,26 @@
 	**  We were given a -z flag (return all MXs) and there are multiple
 	**  ones.  We need to build them all into a list.
 	*/
-
+#if _FFR_BESTMX_MULTI_BEST
+	if (bitset(MF_MULTBEST, map->map_mflags))
+	{
+		struct dns_names_prefs name_pref[MAXMXHOSTS + 1];
+		for (i = 0; i < nmx; i++)
+		{
+			name_pref[i].name = mxhosts[i];
+			name_pref[i].pref = mxprefs[i];
+		}
+		qsort(name_pref, nmx, sizeof name_pref[0], cmp_names_prefs);
+		for (i = 0; i < nmx; i++)
+		{
+			if (name_pref[i].pref != name_pref[0].pref)
+				break;
+			mxhosts[i] = name_pref[i].name;
+			mxprefs[i] = name_pref[i].pref;
+		}
+		nmx = i; /* trunc for only best ones */
+	}
+#endif /* _FFR_BESTMX_MULTI_BEST */
 #if _FFR_BESTMX_BETTER_TRUNCATION
 	for (i = 0; i < nmx; i++)
 	{
Only in sendmail-8.13.8-dnsmap/sendmail: domain.c.orig
diff -urw sendmail-8.13.8-orig/sendmail/map.c sendmail-8.13.8-dnsmap/sendmail/map.c
--- sendmail-8.13.8-orig/sendmail/map.c	2006-04-17 21:26:41.000000000 -0400
+++ sendmail-8.13.8-dnsmap/sendmail/map.c	2006-11-02 23:52:25.000000000 -0500
@@ -194,6 +194,14 @@
 			map->map_mflags |= MF_APPEND;
 			break;
 
+#if (_FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST) || _FFR_BESTMX_MULTI_BEST
+		 /* XXX: Mostly this is here because I dont want to hack in
+		  * a special map for bestmx just to add this */
+		  case 'B':
+			map->map_mflags |= MF_MULTBEST;
+			break;
+			
+#endif /* (_FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST) || _FFR_BESTMX_MULTI_BEST */
 		  case 'q':
 			map->map_mflags |= MF_KEEPQUOTES;
 			break;
@@ -979,6 +987,12 @@
 		  case 'A':
 			map->map_mflags |= MF_APPEND;
 			break;
+#  if _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST
+
+		  case 'B':
+			map->map_mflags |= MF_MULTBEST;
+			break;
+#  endif /*  _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST */
 
 		  case 'q':
 			map->map_mflags |= MF_KEEPQUOTES;
@@ -1112,6 +1126,25 @@
 	return true;
 }
 
+#  if _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST
+struct dns_names_prefs {
+	char * name;
+	unsigned pref;
+};
+
+static int 
+cmp_names_prefs(a, b)
+	struct dns_names_prefs *a;
+	struct dns_names_prefs *b;
+{
+	if (a->pref < b->pref)
+		return -1;
+	if (a->pref > b->pref)
+		return 1;
+	return 0;
+}
+#  endif /* _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST */
+
 /*
 **  DNS_MAP_LOOKUP -- perform dns map lookup.
 **
@@ -1134,12 +1167,17 @@
 	int *statp;
 {
 #  if _FFR_DNSMAP_MULTI
-#   if _FFR_DNSMAP_MULTILIMIT
 	int resnum = 0;
-#   endif /* _FFR_DNSMAP_MULTILIMIT */
+#   if _FFR_DNSMAP_MULTI_SAMENAME
+	char *vp_name = NULL;
+#   endif /* _FFR_DNSMAP_MULTI_SAMENAME */
+#   if _FFR_DNSMAP_MULTI_BEST
+	struct dns_names_prefs * name_pref = NULL;
+	int name_prefs = 16;
+#   endif /* _FFR_DNSMAP_MULTI_BEST */
 #  endif /* _FFR_DNSMAP_MULTI */
 	char *vp = NULL, *result = NULL;
-	size_t vsize;
+	size_t vsize = 0;
 	struct dns_map *map_p;
 	RESOURCE_RECORD_T *rr = NULL;
 	DNS_REPLY_T *r = NULL;
@@ -1275,10 +1313,36 @@
 			vp = newstr(value);
 			break;
 		}
+#   if _FFR_DNSMAP_MULTI_BEST
+		else if (bitset(MF_MULTBEST, map->map_mflags) && (
+			  rr->rr_type == T_MX ||
+		    	  rr->rr_type == T_SRV )
+			)
+		{
+			if (!name_pref)	
+			{
+				name_pref = (void *)xalloc(name_prefs * (sizeof *name_pref));
+			}
+			else if (resnum >= (name_prefs - 2))
+			{
+				name_pref = sm_realloc(name_pref, (name_prefs *= 2) * (sizeof *name_pref));
+			}
+			
+			name_pref[resnum].name = newstr(value); 
+			
+			if (rr->rr_type == T_MX)
+				name_pref[resnum].pref = rr->rr_u.rr_mx->mx_r_preference;
+			else if (rr->rr_type == T_SRV)
+				name_pref[resnum].pref = rr->rr_u.rr_srv->srv_r_priority;
+		}
+#   endif /* _FFR_DNSMAP_MULTI_BEST */
 		else if (vp == NULL)
 		{
 			/* First result */
 			vp = newstr(value);
+#    if _FFR_DNSMAP_MULTI_SAMENAME
+			vp_name = rr->rr_domain;
+#    endif /* _FFR_DNSMAP_MULTI_SAMENAME */
 		}
 		else
 		{
@@ -1286,23 +1350,74 @@
 			int sz;
 			char *new;
 
+#    if _FFR_DNSMAP_MULTI_SAMENAME
+			if(strcasecmp(vp_name, rr->rr_domain))
+				continue;
+#    endif /* _FFR_DNSMAP_MULTI_SAMENAME */
+
 			sz = strlen(vp) + strlen(value) + 2;
 			new = xalloc(sz);
 			(void) sm_snprintf(new, sz, "%s%c%s",
 					   vp, map->map_coldelim, value);
 			sm_free(vp);
 			vp = new;
+		}
+		
+		resnum++;
 #   if _FFR_DNSMAP_MULTILIMIT
 			if (map->map_sizelimit > 0 &&
-			    ++resnum >= map->map_sizelimit)
+		    resnum >= map->map_sizelimit)
 				break;
 #   endif /* _FFR_DNSMAP_MULTILIMIT */
-		}
 #  else /* _FFR_DNSMAP_MULTI */
 		vp = value;
 		break;
 #  endif /* _FFR_DNSMAP_MULTI */
+	}/*loop stops here*/
+
+
+#  if _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST
+	/* post processing */
+	if (name_pref)
+	{
+		int i;
+		int vpsize = 1024;
+		char *p;
+
+		vp = xalloc(vpsize);
+		vp[0] = '\0';
+		p = vp;
+
+		qsort(name_pref, resnum, sizeof *name_pref, cmp_names_prefs);
+		for (i = 0; i <= resnum; i++)
+		{
+			if (name_pref[0].pref != name_pref[i].pref)
+				break;
+			
+			while (1)
+			{
+				int pvp_diff = (p - vp);
+				int num_chars = sm_snprintf(p, vpsize - pvp_diff - 1, "%s%c",
+						name_pref[i].name,
+						map->map_coldelim );
+					
+				if (num_chars > vpsize - pvp_diff - 1)
+				{
+					while (num_chars > (vpsize*=2) - pvp_diff - 1)
+						;
+					vp = sm_realloc(vp, vpsize);
+					p = vp + pvp_diff;
+					continue;
+				}
+				p += num_chars;	
+				break;
 	}
+		}
+		/* erase trailing delim */
+		*(p-1) = '\0';
+	}
+#  endif /* _FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST */
+
 	if (vp == NULL)
 	{
 		result = NULL;
@@ -1331,6 +1446,15 @@
 #  if _FFR_DNSMAP_MULTI
 	if (vp != NULL)
 		sm_free(vp);
+#   if _FFR_DNSMAP_MULTI_BEST
+	if (name_pref != NULL)
+	{
+		int i = 0;
+		for (;i < resnum; i++)
+			sm_free(name_pref[i].name);
+		sm_free(name_pref);
+	}
+#   endif /* _FFR_DNSMAP_MULTI_BEST */
 #  endif /* _FFR_DNSMAP_MULTI */
 	if (r != NULL)
 		dns_free_data(r);
diff -urw sendmail-8.13.8-orig/sendmail/sendmail.h sendmail-8.13.8-dnsmap/sendmail/sendmail.h
--- sendmail-8.13.8-orig/sendmail/sendmail.h	2006-05-22 21:32:07.000000000 -0400
+++ sendmail-8.13.8-dnsmap/sendmail/sendmail.h	2006-11-02 23:13:44.000000000 -0500
@@ -1218,6 +1218,9 @@
 #define MF_FILECLASS	0x00400000	/* this is a file class map */
 #define MF_OPENBOGUS	0x00800000	/* open failed, don't call map_close */
 #define MF_CLOSING	0x01000000	/* map is being closed */
+#if (_FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST) || _FFR_BESTMX_MULTI_BEST
+#  define MF_MULTBEST	0x02000000	/* return multiple BEST values only */
+#endif /* (_FFR_DNSMAP_MULTI && _FFR_DNSMAP_MULTI_BEST) || _FFR_BESTMX_MULTI_BEST */
 
 #define DYNOPENMAP(map) if (!bitset(MF_OPEN, (map)->map_mflags)) \
 	{	\
Only in sendmail-8.13.8-dnsmap/sendmail: sendmail.h.orig
