Define _ISOC99_SOURCE in exim.h
[exim.git] / src / src / lookups / dnsdb.c
index 2862a5bc9f95890c03291eb0ba79a2eee8735341..0bbc86a56a6f4a2c44c6b15e8971876037af77c8 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
@@ -17,6 +17,11 @@ header files. */
 #define T_TXT 16
 #endif
 
 #define T_TXT 16
 #endif
 
+/* Many systems do not have T_SPF. */
+#ifndef T_SPF
+#define T_SPF 99
+#endif
+
 /* Table of recognized DNS record types and their integer values. */
 
 static const char *type_names[] = {
 /* Table of recognized DNS record types and their integer values. */
 
 static const char *type_names[] = {
@@ -33,6 +38,7 @@ static const char *type_names[] = {
   "mxh",
   "ns",
   "ptr",
   "mxh",
   "ns",
   "ptr",
+  "spf",
   "srv",
   "txt",
   "zns"
   "srv",
   "txt",
   "zns"
@@ -52,6 +58,7 @@ static int type_values[] = {
   T_MXH,     /* Private type for "MX hostnames" */
   T_NS,
   T_PTR,
   T_MXH,     /* Private type for "MX hostnames" */
   T_NS,
   T_PTR,
+  T_SPF,
   T_SRV,
   T_TXT,
   T_ZNS      /* Private type for "zone nameservers" */
   T_SRV,
   T_TXT,
   T_ZNS      /* Private type for "zone nameservers" */
@@ -89,7 +96,8 @@ separator is newline.
 character used for multiple items of text in "TXT" records. Alternatively,
 if the next character is ';' then these multiple items are concatenated with
 no separator. With neither of these options specified, only the first item
 character used for multiple items of text in "TXT" records. Alternatively,
 if the next character is ';' then these multiple items are concatenated with
 no separator. With neither of these options specified, only the first item
-is output.
+is output.  Similarly for "SPF" records, but the default for joining multiple
+items in one SPF record is the empty string, for direct concatenation.
 
 (c) If the next sequence of characters is 'defer_FOO' followed by a comma,
 the defer behaviour is set to FOO. The possible behaviours are: 'strict', where
 
 (c) If the next sequence of characters is 'defer_FOO' followed by a comma,
 the defer behaviour is set to FOO. The possible behaviours are: 'strict', where
@@ -114,7 +122,7 @@ int size = 256;
 int ptr = 0;
 int sep = 0;
 int defer_mode = PASS;
 int ptr = 0;
 int sep = 0;
 int defer_mode = PASS;
-int type = T_TXT;
+int type;
 int failrc = FAIL;
 uschar *outsep = US"\n";
 uschar *outsep2 = NULL;
 int failrc = FAIL;
 uschar *outsep = US"\n";
 uschar *outsep2 = NULL;
@@ -190,8 +198,10 @@ if (strncmpic(keystring, US"defer_", 6) == 0)
   while (isspace(*keystring)) keystring++;
   }
 
   while (isspace(*keystring)) keystring++;
   }
 
-/* If the keystring contains an = this must be preceded by a valid type name. */
+/* Figure out the "type" value if it is not T_TXT.
+If the keystring contains an = this must be preceded by a valid type name. */
 
 
+type = T_TXT;
 if ((equals = Ustrchr(keystring, '=')) != NULL)
   {
   int i, len;
 if ((equals = Ustrchr(keystring, '=')) != NULL)
   {
   int i, len;
@@ -239,6 +249,14 @@ if (type == T_PTR && keystring[0] != '<' &&
     string_is_ip_address(keystring, NULL) != 0)
   sep = -1;
 
     string_is_ip_address(keystring, NULL) != 0)
   sep = -1;
 
+/* SPF strings should be concatenated without a separator, thus make
+it the default if not defined (see RFC 4408 section 3.1.3).
+Multiple SPF records are forbidden (section 3.1.2) but are currently
+not handled specially, thus they are concatenated with \n by default. */
+
+if (type == T_SPF && outsep2 == NULL)
+  outsep2 = US"";
+
 /* Now scan the list and do a lookup for each item */
 
 while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
 /* Now scan the list and do a lookup for each item */
 
 while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
@@ -316,7 +334,7 @@ while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
 
     if (ptr != 0) yield = string_cat(yield, &size, &ptr, outsep, 1);
 
 
     if (ptr != 0) yield = string_cat(yield, &size, &ptr, outsep, 1);
 
-    if (type == T_TXT)
+    if (type == T_TXT || type == T_SPF)
       {
       if (outsep2 == NULL)
         {
       {
       if (outsep2 == NULL)
         {