Expansions: New ${ipv6denorm:<string>} and ${ipv6norm:<string>} operators. Bug 1650
[exim.git] / src / src / expand.c
index fbbc68154c94811386734dd377736a14632df5fd..90ffe78c00490dcb7964e36ffe7fc35c368e7efd 100644 (file)
@@ -210,6 +210,8 @@ static uschar *op_table_main[] = {
   US"hash",
   US"hex2b64",
   US"hexquote",
+  US"ipv6denorm",
+  US"ipv6norm",
   US"l",
   US"lc",
   US"length",
@@ -248,6 +250,8 @@ enum {
   EOP_HASH,
   EOP_HEX2B64,
   EOP_HEXQUOTE,
+  EOP_IPV6DENORM,
+  EOP_IPV6NORM,
   EOP_L,
   EOP_LC,
   EOP_LENGTH,
@@ -6406,6 +6410,39 @@ while (*s != 0)
         continue;
         }
 
+      case EOP_IPV6NORM:
+      case EOP_IPV6DENORM:
+       {
+        int type = string_is_ip_address(sub, NULL);
+       int binary[4];
+       uschar buffer[44];
+
+       switch (type)
+         {
+         case 6:
+           (void) host_aton(sub, binary);
+           break;
+
+         case 4:       /* convert to IPv4-mapped IPv6 */
+           binary[0] = binary[1] = 0;
+           binary[2] = 0x0000ffff;
+           (void) host_aton(sub, binary+3);
+           break;
+
+         case 0:
+           expand_string_message =
+             string_sprintf("\"%s\" is not an IP address", sub);
+           goto EXPAND_FAILED;
+         }
+
+       yield = string_cat(yield, &size, &ptr, buffer,
+                 c == EOP_IPV6NORM
+                   ? ipv6_nmtoa(binary, buffer)
+                   : host_nmtoa(4, binary, -1, buffer, ':')
+                 );
+       continue;
+       }
+
       case EOP_ADDRESS:
       case EOP_LOCAL_PART:
       case EOP_DOMAIN: