-return DNS_FAIL;
-}
-
-
-
-/* Support for A6 records has been commented out since they were demoted to
-experimental status at IETF 51. */
-
-#if HAVE_IPV6 && defined(SUPPORT_A6)
-
-/*************************************************
-* Search DNS block for prefix RRs *
-*************************************************/
-
-/* Called from dns_complete_a6() to search an additional section or a main
-answer section for required prefix records to complete an IPv6 address obtained
-from an A6 record. For each prefix record, a recursive call to dns_complete_a6
-is made, with a new copy of the address so far.
-
-Arguments:
- dnsa the DNS answer block
- which RESET_ADDITIONAL or RESET_ANSWERS
- name name of prefix record
- yptrptr pointer to the pointer that points to where to hang the next
- dns_address structure
- bits number of bits we have already got
- bitvec the bits we have already got
-
-Returns: TRUE if any records were found
-*/
-
-static BOOL
-dns_find_prefix(dns_answer *dnsa, int which, uschar *name, dns_address
- ***yptrptr, int bits, uschar *bitvec)
-{
-BOOL yield = FALSE;
-dns_record *rr;
-dns_scan dnss;
-
-for (rr = dns_next_rr(dnsa, &dnss, which);
- rr != NULL;
- rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
- {
- uschar cbitvec[16];
- if (rr->type != T_A6 || strcmpic(rr->name, name) != 0) continue;
- yield = TRUE;
- memcpy(cbitvec, bitvec, sizeof(cbitvec));
- dns_complete_a6(yptrptr, dnsa, rr, bits, cbitvec);
- }
-
-return yield;
-}
-
-
-
-/*************************************************
-* Follow chains of A6 records *
-*************************************************/
-
-/* A6 records may be incomplete, with pointers to other records containing more
-bits of the address. There can be a tree structure, leading to a number of
-addresses originating from a single initial A6 record.
-
-Arguments:
- yptrptr pointer to the pointer that points to where to hang the next
- dns_address structure
- dnsa the current DNS answer block
- rr the RR we have at present
- bits number of bits we have already got
- bitvec the bits we have already got
-
-Returns: nothing
-*/
-
-static void
-dns_complete_a6(dns_address ***yptrptr, dns_answer *dnsa, dns_record *rr,
- int bits, uschar *bitvec)
-{
-static uschar bitmask[] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
-uschar *p = (uschar *)(rr->data);
-int prefix_len, suffix_len;
-int i, j, k;
-uschar *chainptr;
-uschar chain[264];
-dns_answer cdnsa;
-
-/* The prefix length is the first byte. It defines the prefix which is missing
-from the data in this record as a number of bits. Zero means this is the end of
-a chain. The suffix is the data in this record; only sufficient bytes to hold
-it are supplied. There may be zero bytes. We have to ignore trailing bits that
-we have already obtained from earlier RRs in the chain. */
-
-prefix_len = *p++; /* bits */
-suffix_len = (128 - prefix_len + 7)/8; /* bytes */
-
-/* If the prefix in this record is greater than the prefix in the previous
-record in the chain, we have to ignore the record (RFC 2874). */
-
-if (prefix_len > 128 - bits) return;
-
-/* In this little loop, the number of bits up to and including the current byte
-is held in k. If we have none of the bits in this byte, we can just or it into
-the current data. If we have all of the bits in this byte, we skip it.
-Otherwise, some masking has to be done. */
-
-for (i = suffix_len - 1, j = 15, k = 8; i >= 0; i--)
- {
- int required = k - bits;
- if (required >= 8) bitvec[j] |= p[i];
- else if (required > 0) bitvec[j] |= p[i] & bitmask[required];
- j--; /* I tried putting these in the "for" statement, but gcc muttered */
- k += 8; /* about computed values not being used. */
- }
-
-/* If the prefix_length is zero, we are at the end of a chain. Build a
-dns_address item with the current data, hang it onto the end of the chain,
-adjust the hanging pointer, and we are done. */
-
-if (prefix_len == 0)
- {
- dns_address *new = store_get(sizeof(dns_address) + 50);
- inet_ntop(AF_INET6, bitvec, CS new->address, 50);
- new->next = NULL;
- **yptrptr = new;
- *yptrptr = &(new->next);
- return;
- }
+ /* Try to look up the Client SMTP Authorization SRV record for the name. If
+ there isn't one, search from the top downwards for a CSA record in a parent
+ domain, which might be making assertions about subdomains. If we find a record
+ we set fully_qualified_name to whichever lookup succeeded, so that the caller
+ can tell whether to look at the explicit authorization field or the subdomain
+ assertion field. */
+ case T_CSA:
+ {
+ uschar *srvname, *namesuff, *tld;
+ int priority, weight, port;
+ int limit, rc, i;
+ BOOL ipv6;
+ dns_record *rr;
+ dns_scan dnss;
+
+ DEBUG(D_dns) debug_printf("CSA lookup of %s\n", name);
+
+ srvname = string_sprintf("_client._smtp.%s", name);
+ rc = dns_lookup(dnsa, srvname, T_SRV, NULL);
+ if (rc == DNS_SUCCEED || rc == DNS_AGAIN)
+ {
+ if (rc == DNS_SUCCEED) *fully_qualified_name = string_copy(name);
+ return rc;
+ }