Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -58,11 +58,11 @@ * TODO: * * - Timeouts * - Resolve with each search domain * - Iterate through name servers - * - IPv6 (for responses and for talking to the name servers) + * - IPv6 for talking to the name servers * - Fallback to TCP */ @interface OFDNSResolver_context: OFObject { @@ -182,10 +182,69 @@ *idx = i; return [components componentsJoinedByString: @"."]; } + +static OFString * +parseAAAA(const unsigned char *buffer) +{ + OFMutableString *data = [OFMutableString string]; + int_fast8_t zerosStart = -1, maxZerosStart = -1; + uint_fast8_t zerosCount = 0, maxZerosCount = 0; + bool first = true; + + for (uint_fast8_t i = 0; i < 16; i += 2) { + if (buffer[i] == 0 && buffer[i + 1] == 0) { + if (zerosStart >= 0) + zerosCount++; + else { + zerosStart = i; + zerosCount = 1; + } + } else { + if (zerosCount > maxZerosCount) { + maxZerosStart = zerosStart; + maxZerosCount = zerosCount; + } + + zerosStart = -1; + } + } + if (zerosCount > maxZerosCount) { + maxZerosStart = zerosStart; + maxZerosCount = zerosCount; + } + + if (maxZerosCount >= 2) { + for (uint_fast8_t i = 0; i < maxZerosStart; i += 2) { + [data appendFormat: (first ? @"%x" : @":%x"), + (buffer[i] << 8) | buffer[i + 1]]; + first = false; + } + + [data appendString: @"::"]; + first = true; + + for (uint_fast8_t i = maxZerosStart + (maxZerosCount * 2); + i < 16; i += 2) { + [data appendFormat: (first ? @"%x" : @":%x"), + (buffer[i] << 8) | buffer[i + 1]]; + first = false; + } + } else { + for (uint_fast8_t i = 0; i < 16; i += 2) { + [data appendFormat: (first ? @"%x" : @":%x"), + (buffer[i] << 8) | buffer[i + 1]]; + first = false; + } + } + + [data makeImmutable]; + + return data; +} static id parseData(const unsigned char *buffer, size_t length, size_t i, size_t dataLength, of_dns_resource_record_class_t recordClass, of_dns_resource_record_type_t recordType) @@ -214,10 +273,17 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; + break; + case OF_DNS_RESOURCE_RECORD_TYPE_AAAA: + if (dataLength != 16) + @throw [OFInvalidServerReplyException + exception]; + + data = parseAAAA(&buffer[i]); break; default: data = [OFData dataWithItems: &buffer[i] count: dataLength]; break; Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -26,26 +26,37 @@ /*! * @brief The class of a DNS resource record. */ typedef enum { + /*! IN */ OF_DNS_RESOURCE_RECORD_CLASS_IN = 1, + /*! Any class. Only for queries. */ OF_DNS_RESOURCE_RECORD_CLASS_ANY = 255, } of_dns_resource_record_class_t; /*! * @brief The type of a DNS resource record. */ typedef enum { + /*! A */ OF_DNS_RESOURCE_RECORD_TYPE_A = 1, + /*! NS */ OF_DNS_RESOURCE_RECORD_TYPE_NS = 2, + /*! CNAME */ OF_DNS_RESOURCE_RECORD_TYPE_CNAME = 5, + /*! SOA */ OF_DNS_RESOURCE_RECORD_TYPE_SOA = 6, + /*! PTR */ OF_DNS_RESOURCE_RECORD_TYPE_PTR = 12, + /*! MX */ OF_DNS_RESOURCE_RECORD_TYPE_MX = 15, + /*! TXT */ OF_DNS_RESOURCE_RECORD_TYPE_TXT = 16, + /*! AAAA */ OF_DNS_RESOURCE_RECORD_TYPE_AAAA = 28, + /*! All types. Only for queries. */ OF_DNS_RESOURCE_RECORD_TYPE_ALL = 255, } of_dns_resource_record_type_t; /*! * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h