Generate ctypes._fields_ dynamically

0

Good afternoon guys! This is my first post here, so have patience with the newbie;)

I am creating a DNS server taking into account the RFC 1035 specifications using the ctypes to improve code readability and make it more organized.

My problem is this. I have a class for the package header.

class DnsPacket(BigEndianStructure):
    """ Class representative to DNS header.
    This class handle a bytes buffer in ctypes field mode """

    def __new__(cls, buffer):
        return cls.from_buffer_copy(buffer)

    _fields_ = [('identification',       c_uint, 16),
                ('query_type',           c_uint,  1),
                ('optional_code',        c_uint,  4),
                ('authoritative_answer', c_uint,  1),
                ('truncation',           c_uint,  1),
                ('recursion_desired',    c_uint,  1),
                ('recursion_available',  c_uint,  1),
                ('reserved_for_future',  c_uint,  3),
                ('response_code',        c_uint,  4),
                ('question_count',       c_uint, 16),
                ('answer_count',         c_uint, 16),
                ('nameserver_count',     c_uint, 16),
                ('aditional_count',      c_uint, 16)]

It turns out that after the "aditional_count" field that is the end of the header comes the section that contains the question, according to the RFC in that format.

                               1  1  1  1  1  1
 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                     QNAME                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QTYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QCLASS                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

This QNAME field is represented as a sequence of labels, each label consists of an octet with the label size followed by the label.

Ex: 6google3com

I would like to dynamically generate a field according to this octet so that I can instantiate the label shortly afterwards.

class QuestionSection(BigEndianStructure):
    _fields_ = [('size',  c_uint),  # Primeiro octeto contendo o número de caracteres na label.
                ('name',  size)]    # Label em sí

I have a function that takes the domain name of the buffer only that is messed up and dynamically improves the structure and the use of the same for a future use.

def get_domain_name(self, data):
    array_data = bytearray(data[sizeof(self):])
    expected_lenght = array_data.pop(0)
    nameserver = ''
    while expected_lenght is not 0:
        for _ in range(expected_lenght):
            nameserver += chr(array_data.pop(0))
            expected_lenght = array_data.pop(0)
            if expected_lenght is not 0:
                nameserver += '.'
        return nameserver

Functions, methods like the above impair the readability and maintenance of the code.

I thank you all for helping me and giving me ideas to solve this problem.

    
asked by anonymous 25.06.2018 / 19:46

0 answers