iPXE
Data Structures | Defines | Functions
dns.h File Reference

DNS protocol. More...

#include <stdint.h>
#include <ipxe/in.h>

Go to the source code of this file.

Data Structures

struct  dns_name
 An RFC1035-encoded DNS name. More...
struct  dns_header
 A DNS packet header. More...
struct  dns_question
 A DNS question. More...
struct  dns_rr_common
 A DNS resource record. More...
struct  dns_rr_a
 A DNS "A" record. More...
struct  dns_rr_aaaa
 A DNS "AAAA" record. More...
struct  dns_rr_cname
 A DNS "CNAME" record. More...
union  dns_rr
 A DNS resource record. More...

Defines

#define DNS_PORT   53
 DNS server port.
#define DNS_IS_COMPRESSED(byte)   ( (byte) & 0xc0 )
 Test for a DNS compression pointer.
#define DNS_COMPRESSED_OFFSET(word)   ( (word) & ~0xc000 )
 Extract DNS compression pointer.
#define DNS_LABEL_LEN(byte)   ( (byte) & ~0xc0 )
 Extract DNS label length.
#define DNS_MAX_LABEL_LEN   0x3f
 Maximum length of a single DNS label.
#define DNS_MAX_NAME_LEN   255
 Maximum length of a DNS name (mandated by RFC1035 section 2.3.4)
#define DNS_MAX_CNAME_RECURSION   32
 Maximum depth of CNAME recursion.
#define DNS_FLAG_RD   0x0100
 Recursion desired flag.
#define DNS_CLASS_IN   1
 DNS class "IN".
#define DNS_TYPE_A   1
 Type of a DNS "A" record.
#define DNS_TYPE_AAAA   28
 Type of a DNS "AAAA" record.
#define DNS_TYPE_CNAME   5
 Type of a DNS "NAME" record.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int dns_encode (const char *string, struct dns_name *name)
 Encode a DNS name using RFC1035 encoding.
int dns_decode (struct dns_name *name, char *data, size_t len)
 Decode RFC1035-encoded DNS name.
int dns_compare (struct dns_name *first, struct dns_name *second)
 Compare DNS names for equality.
int dns_copy (struct dns_name *src, struct dns_name *dst)
 Copy a DNS name.
int dns_skip (struct dns_name *name)
 Skip RFC1035-encoded DNS name.

Detailed Description

DNS protocol.

Definition in file dns.h.


Define Documentation

#define DNS_PORT   53

DNS server port.

Definition at line 16 of file dns.h.

#define DNS_IS_COMPRESSED (   byte)    ( (byte) & 0xc0 )

Test for a DNS compression pointer.

Parameters:
byteInitial byte
Return values:
is_compressedIs a compression pointer

Definition at line 34 of file dns.h.

Referenced by dns_label().

#define DNS_COMPRESSED_OFFSET (   word)    ( (word) & ~0xc000 )

Extract DNS compression pointer.

Parameters:
wordInitial word
Return values:
offsetOffset

Definition at line 42 of file dns.h.

Referenced by dns_label().

#define DNS_LABEL_LEN (   byte)    ( (byte) & ~0xc0 )

Extract DNS label length.

Parameters:
byteInitial byte
Return values:
lenLabel length

Definition at line 50 of file dns.h.

#define DNS_MAX_LABEL_LEN   0x3f

Maximum length of a single DNS label.

Definition at line 53 of file dns.h.

Referenced by dns_encode().

#define DNS_MAX_NAME_LEN   255

Maximum length of a DNS name (mandated by RFC1035 section 2.3.4)

Definition at line 56 of file dns.h.

#define DNS_MAX_CNAME_RECURSION   32

Maximum depth of CNAME recursion.

This is a policy decision.

Definition at line 62 of file dns.h.

Referenced by dns_xfer_deliver().

#define DNS_FLAG_RD   0x0100

Recursion desired flag.

Definition at line 81 of file dns.h.

Referenced by dns_resolv().

#define DNS_CLASS_IN   1

DNS class "IN".

Definition at line 92 of file dns.h.

Referenced by dns_question().

#define DNS_TYPE_A   1

Type of a DNS "A" record.

Definition at line 107 of file dns.h.

Referenced by dns_resolv(), dns_type(), and dns_xfer_deliver().

#define DNS_TYPE_AAAA   28

Type of a DNS "AAAA" record.

Definition at line 118 of file dns.h.

Referenced by dns_resolv(), dns_type(), and dns_xfer_deliver().

#define DNS_TYPE_CNAME   5

Type of a DNS "NAME" record.

Definition at line 129 of file dns.h.

Referenced by dns_type(), and dns_xfer_deliver().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int dns_encode ( const char *  string,
struct dns_name name 
)

Encode a DNS name using RFC1035 encoding.

Parameters:
stringDNS name as a string
nameDNS name to fill in
Return values:
lenLength of DNS name, or negative error

Definition at line 88 of file dns.c.

References dns_name::data, DNS_MAX_LABEL_LEN, EINVAL, end, dns_name::len, len, dns_name::offset, and start.

Referenced by apply_dns_search(), dns_encode_fail_okx(), dns_encode_okx(), and dns_resolv().

                                                             {
        uint8_t *start = ( name->data + name->offset );
        uint8_t *end = ( name->data + name->len );
        uint8_t *dst = start;
        size_t len = 0;
        char c;

        /* Encode name */
        while ( ( c = *(string++) ) ) {

                /* Handle '.' separators */
                if ( c == '.' ) {

                        /* Reject consecutive '.' */
                        if ( ( len == 0 ) && ( dst != start ) )
                                return -EINVAL;

                        /* Terminate if this is the trailing '.' */
                        if ( *string == '\0' )
                                break;

                        /* Reject initial non-terminating '.' */
                        if ( len == 0 )
                                return -EINVAL;

                        /* Reset length */
                        len = 0;

                } else {

                        /* Increment length */
                        len++;

                        /* Check for overflow */
                        if ( len > DNS_MAX_LABEL_LEN )
                                return -EINVAL;
                }

                /* Copy byte, update length */
                if ( ++dst < end ) {
                        *dst = c;
                        dst[-len] = len;
                }
        }

        /* Add terminating root marker */
        if ( len )
                dst++;
        if ( dst < end )
                *dst = '\0';
        dst++;

        return ( dst - start );
}
int dns_decode ( struct dns_name name,
char *  data,
size_t  len 
)

Decode RFC1035-encoded DNS name.

Parameters:
nameDNS name
dataOutput buffer
lenLength of output buffer
Return values:
lenLength of decoded DNS name, or negative error

Definition at line 204 of file dns.c.

References dns_name::data, dns_label(), EINVAL, dns_name::len, len, memcpy(), dns_name::offset, and offset.

Referenced by dns_decode_fail_okx(), dns_decode_okx(), dns_list_okx(), dns_name(), dns_progress(), and format_dnssl_setting().

                                                                 {
        unsigned int recursion_limit = name->len; /* Generous upper bound */
        int offset = name->offset;
        const uint8_t *label;
        size_t decoded_len = 0;
        size_t label_len;
        size_t copy_len;

        while ( recursion_limit-- ) {

                /* Find valid DNS label */
                offset = dns_label ( name, offset );
                if ( offset < 0 )
                        return offset;

                /* Terminate if we have reached the root */
                label = ( name->data + offset );
                label_len = *(label++);
                if ( label_len == 0 ) {
                        if ( decoded_len < len )
                                *data = '\0';
                        return decoded_len;
                }

                /* Prepend '.' if applicable */
                if ( decoded_len && ( decoded_len++ < len ) )
                        *(data++) = '.';

                /* Copy label to output buffer */
                copy_len = ( ( decoded_len < len ) ? ( len - decoded_len ) : 0);
                if ( copy_len > label_len )
                        copy_len = label_len;
                memcpy ( data, label, copy_len );
                data += copy_len;
                decoded_len += label_len;

                /* Move to next label */
                offset += ( sizeof ( *label ) + label_len );
        }

        /* Recursion limit exceeded */
        return -EINVAL;
}
int dns_compare ( struct dns_name first,
struct dns_name second 
)

Compare DNS names for equality.

Parameters:
firstFirst DNS name
secondSecond DNS name
Return values:
rcReturn status code

Definition at line 255 of file dns.c.

References dns_name::data, dns_label(), EINVAL, ENOENT, dns_name::len, len, dns_name::offset, and tolower().

Referenced by dns_compare_fail_okx(), dns_compare_okx(), and dns_xfer_deliver().

                                                                    {
        unsigned int recursion_limit = first->len; /* Generous upper bound */
        int first_offset = first->offset;
        int second_offset = second->offset;
        const uint8_t *first_label;
        const uint8_t *second_label;
        size_t label_len;
        size_t len;

        while ( recursion_limit-- ) {

                /* Find valid DNS labels */
                first_offset = dns_label ( first, first_offset );
                if ( first_offset < 0 )
                        return first_offset;
                second_offset = dns_label ( second, second_offset );
                if ( second_offset < 0 )
                        return second_offset;

                /* Compare label lengths */
                first_label = ( first->data + first_offset );
                second_label = ( second->data + second_offset );
                label_len = *(first_label++);
                if ( label_len != *(second_label++) )
                        return -ENOENT;
                len = ( sizeof ( *first_label ) + label_len );

                /* Terminate if we have reached the root */
                if ( label_len == 0 )
                        return 0;

                /* Compare label contents (case-insensitively) */
                while ( label_len-- ) {
                        if ( tolower ( *(first_label++) ) !=
                             tolower ( *(second_label++) ) )
                                return -ENOENT;
                }

                /* Move to next labels */
                first_offset += len;
                second_offset += len;
        }

        /* Recursion limit exceeded */
        return -EINVAL;
}
int dns_copy ( struct dns_name src,
struct dns_name dst 
)

Copy a DNS name.

Parameters:
srcSource DNS name
dstDestination DNS name
Return values:
lenLength of copied DNS name, or negative error

Definition at line 309 of file dns.c.

References dns_name::data, dns_label(), EINVAL, dns_name::len, len, memcpy(), and dns_name::offset.

Referenced by dns_copy_fail_okx(), dns_copy_okx(), dns_question(), and dns_xfer_deliver().

                                                            {
        unsigned int recursion_limit = src->len; /* Generous upper bound */
        int src_offset = src->offset;
        size_t dst_offset = dst->offset;
        const uint8_t *label;
        size_t label_len;
        size_t copy_len;
        size_t len;

        while ( recursion_limit-- ) {

                /* Find valid DNS label */
                src_offset = dns_label ( src, src_offset );
                if ( src_offset < 0 )
                        return src_offset;

                /* Copy as an uncompressed label */
                label = ( src->data + src_offset );
                label_len = *label;
                len = ( sizeof ( *label ) + label_len );
                copy_len = ( ( dst_offset < dst->len ) ?
                             ( dst->len - dst_offset ) : 0 );
                if ( copy_len > len )
                        copy_len = len;
                memcpy ( ( dst->data + dst_offset ), label, copy_len );
                src_offset += len;
                dst_offset += len;

                /* Terminate if we have reached the root */
                if ( label_len == 0 )
                        return ( dst_offset - dst->offset );
        }

        /* Recursion limit exceeded */
        return -EINVAL;
}
int dns_skip ( struct dns_name name)

Skip RFC1035-encoded DNS name.

Parameters:
nameDNS name
Return values:
offsetOffset to next name, or negative error

Definition at line 352 of file dns.c.

References dns_name::data, dns_label(), EINVAL, dns_name::len, dns_name::offset, and offset.

Referenced by dns_list_okx(), dns_skip_search(), and dns_xfer_deliver().

                                       {
        unsigned int recursion_limit = name->len; /* Generous upper bound */
        int offset = name->offset;
        int prev_offset;
        const uint8_t *label;
        size_t label_len;

        while ( recursion_limit-- ) {

                /* Find valid DNS label */
                prev_offset = offset;
                offset = dns_label ( name, prev_offset );
                if ( offset < 0 )
                        return offset;

                /* Terminate if we have reached a compression pointer */
                if ( offset != prev_offset )
                        return ( prev_offset + sizeof ( uint16_t ) );

                /* Skip this label */
                label = ( name->data + offset );
                label_len = *label;
                offset += ( sizeof ( *label ) + label_len );

                /* Terminate if we have reached the root */
                if ( label_len == 0 )
                        return offset;
        }

        /* Recursion limit exceeded */
        return -EINVAL;
}