<jupyter_start><jupyter_text>This is a visualization of our DNS Zones![zones_telematik.png](zones_telematik.png)  This class is representing a DNS server and is handing all requests and responses to a DNS server<jupyter_code>class NpEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return super(NpEncoder, self).default(obj)
  
#     def load_config(self):
#         ## load all entries for my zone
#         with open('names.json') as dnsnamedata:
#             data = json.load(dnsnamedata)
#             dns_zone = data[zone_number]
class DNS(object):
    stop_threads= False
    #socket = None
#     address = None
#     port = None
    #is_authorative = 0 #is this server an authorative server?
    #is_root = 0        #is this server a root server?
    #dns_zone = None    #own dns zone as json
    #records_in_own_zone = None #all ns and a records in own zone. (this information is alreay 
                                    #conrained in the dns_zone variable but we are keeping this sepearate variable for now )  
#     def __init__(self, zone_number, authorative, is_root, seconds=2000,addr='127.0.0.11', port=53053): 
#         self.address = addr
#         self.port    = port
    def __init__(self, config, seconds=2000): 
        self.config = config
        self.origin = config["$origin"]
        self.ip = config["$ip"]
        self.port    = config["$port"]
        self.is_authorative = config["$authorative"]
        self.root = config["$root"]
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.run_thread = True
        #self.is_root = is_root
        self.records_in_own_zone = self.load_records()
        self.socket.bind((self.ip,self.port))

    '''loads all entrys for own zone from our json file. 
    (e.g. zonename: telematik for zone (telematik, swith, router))'''
    def load_records(self):
        ## load the records from the config
        
        telematik_dns_dict = {'ns': pd.DataFrame(self.config['ns'])['host'].tolist(),
                              'a':pd.DataFrame(self.config['a'])['value'].tolist(),
                              'ttl':pd.DataFrame(self.config['a'])['ttl'].tolist()}
        records_in_own_zone = pd.DataFrame(telematik_dns_dict, columns = ['ns','a','ttl' ])
        return records_in_own_zone

    
    '''checks if a requested entry is in own zone. 
    (e.g. this zonename is telematik and requested address is for dns name www.swith.telematik.
    Means that swith is in our zone and we can send the adress for switch.telematik)
    Returns None if not. '''
    def is_in_own_zone(self, qry_name):
        #names_i_know = pd.DataFrame(data[0]['ns'])['host'].tolist()
        
        print('check if {} is in our zone'.format(qry_name))
        
        ns = None
        a = None
        ttl = None
        for counter,name in enumerate (self.records_in_own_zone['ns']):
            
            #if authorative server then check if the adress match with one of the adresses in my zone.
            if(self.is_authorative):
                print("Authorative")
                if(name == qry_name):
                    print("Strings matching")
                    ns = self.records_in_own_zone['ns'][counter]
                    a = self.records_in_own_zone['a'][counter]
                    ttl = self.records_in_own_zone['ttl'][counter]  
            else:
                #server is not authorative
                #define pattern somestring.name
                pattern = re.compile(r'(.*?)(\.'+str(name)+')?$')

                #apply the qry_name we are looking for to the patter and return a list with results
                # e.g. ['www.switch', '.telematik'] for mattching or ['www.switch.telematik1', None] for not matching
                groups = pattern.match(qry_name).groups()
                if(groups[1] != None): 
                    ns = self.records_in_own_zone['ns'][counter]
                    a = self.records_in_own_zone['a'][counter]
                    ttl = self.records_in_own_zone['ttl'][counter]
        return ns, a, ttl
        #return telematik_dns_df[telematik_dns_df['ns'] == forward_to]
    
    #check if this dns can send directly the authorative answer?
    #def have_authorative_answer():
    
    def build_response(self, msg_json):
        payload= {}
        msg = json.loads(msg_json)
        if not msg['dns.flags.response']:  # if a question set this flag to 1 (answer)
            payload['dns.flags.response'] = 1
        else:
            payload['dns.flags.response'] = 0  # do nothing??????????????????????
        payload['dns.flags.recavail'] = 0
        payload['dns.qry.name'] = msg['dns.qry.name']
        payload['dns.qry.type'] =  msg['dns.qry.type']                # 1steht für a record "????????????????????????????????????????"
        ns, a, ttl  = self.is_in_own_zone(msg['dns.qry.name'])
        if a == None:
            payload['dns.flags.rcode'] = 3
        else:
            payload['dns.flags.rcode'] = 0
        payload['dns.count.answers'] = 1 # es können auch mehrere ip's einen dns vertreten!!!
        payload['dns.flags.authoritative'] = self.is_authorative
        payload['dns.a'] = a
        payload['dns.rsp.ttl.a'] = ttl
        payload['dns.ns'] = ns
        return payload
    
#     def build_dataframe():
        
        
#     def write_log():
    def response_to_client(payload, client_addr):
        
        try:
            payload['dns.flags.response'] = 'Changed!'
            payload_json = json.dumps(payload)
            time.sleep(0.5)
            server_socket.sendto(bytes(payload_json, 'utf-8'), client_addr)
            # nachricht kommt rein 
            # nachricht wird geschickt
        except:
            print('could not respond to client: ',client_addr)
        
    def send_request(self, ip, port, payload_json):
        self.socket.sendto(bytes(payload_json, 'utf-8'),(ip, port))
        print("message successfull sended to ip:{} port:{}\n".format(ip,port), payload_json)
    #this method is to start a thread to listen and handle requests and responses.
    def start(self):
        print(self.ip,self.port,"is listening")
        while self.run_thread:
            
            client_message, client_addr = self.socket.recvfrom(1024)
            client_ip = client_addr[0]
            client_port = client_addr[1]
            client_message_json = json.dumps(json.loads(client_message), cls=NpEncoder, indent=4) 
            print("server ({}) got message from:{}:{}\n".format( self.origin, client_ip, client_port), client_message_json)
            payload = self.build_response(client_message)
            payload_json = json.dumps(payload, cls=NpEncoder, indent=4)

            
            
#             if DNS.stop_threads:
#                 #self.socket.close()
#                 break
            #print(type(payload))
#             try:
           # tt =json.dumps(payload, cls=NpEncoder)
#             except:
#                 e = sys.exc_info()[0]
            #print(payload)
            #print(tt)
            self.send_request(client_ip, client_port, payload_json)
            
    
        
def create_dns_servers():
    ## load all entries for my zone
    dns_servers=[]
    with open('names.json') as dnsnamedata:
        dns_server_configs = json.load(dnsnamedata)
    for dns_server_config in dns_server_configs:
        dns_servers.append(DNS(dns_server_config))
    return dns_servers

def start_dns_servers(dns_servers):
    ## load all entries for my zone
    dns_threads=[]
    for dns in dns_servers:
        time.sleep(0.5)
        resolver_thread = threading.Thread(target=dns.start)
        dns_threads.append(resolver_thread)
        resolver_thread.start()
    return dns_threads
dns_servers = create_dns_servers()
dns_threads =  start_dns_servers(dns_servers)
#t = DNS(zone0)
len(dns_threads)
dns_servers[0].run_thread
dns_servers[0].socket
t = dns_threads[0]
t
DNS.stop_threads =True
for x in dns_servers:
    print(x.ip)
t = DNS(zone0)
resolver_thread = threading.Thread(target=t.start)
resolver_thread.start()
a = {'dns.flags.response': 1, 'dns.flags.recavail': 0, 'dns.qry.name': '.switch.telematik', 'dns.qry.type': 1, 'dns.flags.rcode': 0, 'dns.count.answers': 1, 'dns.flags.authoritative': 0, 'dns.a': '255.255.255.255', 'dns.rsp.ttl.a': 400, 'dns.ns': 'switch.telematik'}
json.dumps(a)
msg ={
    "dns.flags.response":0,
    "dns.flags.recdesired":1,
    "dns.qry.name":".switch.telematik",
    "dns.qry.type":1
}
msg_json = json.dumps(msg, indent=4)
t.build_response(msg_json)
payload_dict ={  
    "dns.flags.response": 1,
    "dns.flags.recdesired": "placeholder",
    "dns.qry.name": "placeholder",
    "dns.qry.type": "placeholder",
    "dns.flags.rcode": "placeholder",
    "dns.count.answers": "placeholder",
    "dns.flags.authoritative": "placeholder",
    "dns.a": "127.0.0.10",
    "dns.ns": "www.switch.telematik",
    "dns.resp.ttl": 1234,
    "dns.srv.name": "placeholder",
    "dns.srv.port": "placeholder",
    "dns.srv.proto": "placeholder",
    "dns.srv.service": "placeholder",
    "dns.srv.target": "placeholder"
}  
payload_dict
response_dict ={  
    "dns.flags.response": "1", #Boolean, Frage oder Antwort
    "dns.flags.recavail": "0",#"dns.flags.recdesired": "placeholder", #Boolean Rekursion oder nicht -> antwort dns.flags.recavail =0 antwort vom authorativen server
    "dns.qry.name": "wwlnawrocki.tns",    #Character string name der zu anfragen den seite wwlnawrocki.tns
    "dns.qry.type": "placeholder", # 	Unsigned integer, 2 bytes, 1= a record, 0 anscheinend nicht
    
    "dns.flags.rcode": "placeholder", # Unsigned integer, 2 bytes response code is 0=alles ist k
    "dns.count.answers": "placeholder", # Unsigned integer, 2 bytes wie viele antwortne=1
    "dns.flags.authoritative": "placeholder", # Boolean  die antwort ist autoritative
    
    "dns.a": " 127.0,0.101", #IPv4 address      dns.a =
    
    "dns.ns": "", #Character string   ttl : 300 , falls dns.qry.type=2
    
    "dns.resp.ttl": 1234, #ttl : 300
    
    
    
    
    
    
    "dns.srv.name": "placeholder",  #Character string
    "dns.srv.port": "placeholder",  #Unsigned integer, 2 bytes
    "dns.srv.proto": "placeholder",  #Character string
    "dns.srv.service": "placeholder", #Character string
    "dns.srv.target": "placeholder"  #Character string
}  

t =DNS(0,authorative=0,is_root=0)
t.load_zone()
t.dns_zone
# t = [x for x in t.records_in_own_zone["ns"]]
t.is_in_own_zone('.router.telematik')
pattern = re.compile(r'(.*?)(\.'+str('switch.telematik')+')?$')
pattern
pattern = re.compile(r'(.*?)(\.'+str("test")+')?$')
pattern.match('mail.switch.telematik').groups()

city = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])

city
city.to_csv('city2.csv')
payload_dict ={  
    "dns.flags.response": 0,
    "dns.flags.recdesired": "placeholder",
    "dns.qry.name": "placeholder",
    "dns.qry.type": "placeholder",
    "dns.flags.rcode": "placeholder",
    "dns.count.answers": "placeholder",
    "dns.flags.authoritative": "placeholder",
    "dns.a": "127.0.0.10",
    "dns.ns": "www.switch.telematik",
    "dns.resp.ttl": 1234,
    "dns.srv.name": "placeholder",
    "dns.srv.port": "placeholder",
    "dns.srv.proto": "placeholder",
    "dns.srv.service": "placeholder",
    "dns.srv.target": "placeholder"
}  
keys = list(payload_dict.keys())
values = list(payload_dict.values())
testos = pd.DataFrame(values, keys)
testos.to_csv('city23.csv')
col_names = keys
titanic_data = pd.read_csv('city23.csv', names=col_names, header=None)
titanic_data
def load_zone(self, zone_number):
    ## load all entries for my zone
    with open('names.json') as dnsnamedata:
        data = json.load(dnsnamedata)
with open('names.json') as dnsnamedata:
    data = json.load(dnsnamedata)
[print(x) for x in data]
def is_in_own_zone(self, qry_name):
        #names_i_know = pd.DataFrame(data[0]['ns'])['host'].tolist()
        
        print('check if {} is in our zone'.format(qry_name))
        
        ns = None
        a = None
        ttl = None
        for counter,name in enumerate (records_in_own_zone):
            #define pattern somestring.name
            pattern = re.compile(r'(.*?)(\.'+str(name)+')?$')

            #apply the qry_name we are looking for to the patter and return a list with results
            # e.g. ['www.switch', '.telematik'] for mattching or ['www.switch.telematik1', None] for not matching
            groups = pattern.match(qry_name).groups()
            if(groups[1] != None): 
                ns = self.records_in_own_zone['ns'][counter]
                a = self.records_in_own_zone['a'][counter]
                ttl = self.records_in_own_zone['ttl'][counter]
        return ns, a, ttl
qry_name = "mail.switch.telematik"
name = ".mail.switch.telematik"

pattern = re.compile(r'(.*?)(\.'+str(name)+')?$')

groups = pattern.match(qry_name).groups()
print(groups)
records_in_own_zone = ["www.switch.telematik", "mail.switch.telematik"]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14232943837165474, 'fraction_numerical': 0.010855635130041463, 'mean_word_length': 2.6166848418756814, 'pattern_counts': {'":': 50, '<': 5, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '619140', 'license': 'MIT', 'n_tokens_mistral': 4568, 'n_tokens_neox': 4436, 'n_words': 948, 'path': 'Notebooks/.ipynb_checkpoints/Authoritative_DNS_telematik_class1-checkpoint.ipynb', 'repo_name': 'Alioio/telematics_project', 'size': '13265'}