[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Lost] [Patch] tcpip: DNS



Nach den vielen Rückmeldungen hier die von meiner Seite aus endgültige Version.
Index: src/modules/tcpip/include/dns.h
===================================================================
--- src/modules/tcpip/include/dns.h	(Revision 0)
+++ src/modules/tcpip/include/dns.h	(Revision 0)
@@ -0,0 +1,98 @@
+/*  
+ * Copyright (c) 2007 The LOST Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the LOST Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the LOST Project
+ *     and its contributors.
+ * 4. Neither the name of the LOST Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DNS_H_
+#define _DNS_H_
+
+#include <stdint.h>
+
+#define DNS_PORT 53
+
+struct dns_header {
+    uint16_t    id;
+    uint16_t    flags;
+    uint16_t    qd_count;
+    uint16_t    an_count;
+    uint16_t    ns_count;
+    uint16_t    ar_count;
+} __attribute__((packed));
+
+
+// Konstanten für die Header-Flags
+
+/// 0 = Query; 1 = Response
+#define DNS_QR 0x80
+
+/// Authoritative Answer? (Nur in Antwort)
+#define DNS_AA 0x04
+
+/// Truncation - Nachricht ist abgeschnitten
+#define DNS_TC 0x02
+
+/// Recursion Desired
+#define DNS_RD 0x01
+
+/// Recursion Available
+#define DNS_RA 0x8000
+
+/// Opcode aus einem DNS-Header
+#define dns_get_opde(x) (((x) >> 3) & 0x0F)
+
+/// Opcode in einem DNS-Header setzen
+static inline void dns_set_opcode(struct dns_header* header, uint8_t opcode)
+{
+    header->flags &= ~0x78;
+    header->flags |= (opcode << 3);
+}
+
+// Opcodes
+#define DNS_OPCODE_QUERY    0x00
+#define DNS_OPCODE_IQUERY   0x01
+#define DNS_OPCODE_STATUS   0x02
+
+// Response Codes
+#define DNS_RCODE_OK        0x00
+#define DNS_RCODE_EFORMAT   0x01
+#define DNS_RCODE_ESERVER   0x02
+#define DNS_RCODE_ENAME     0x03
+#define DNS_RCODE_EIMPL     0x04
+#define DNS_RCODE_EREFUSED  0x05
+
+/// Reponse Code aus einem DNS-Header
+#define dns_get_rcode(x) (((x) >> 8) & 0x0F)
+
+dword dns_request(char* domain);
+
+#endif

Eigenschaftsänderungen: src/modules/tcpip/include/dns.h
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/modules/tcpip/include/main.h
===================================================================
--- src/modules/tcpip/include/main.h	(Revision 0)
+++ src/modules/tcpip/include/main.h	(Revision 0)
@@ -0,0 +1,46 @@
+/*  
+ * Copyright (c) 2007 The LOST Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the LOST Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the LOST Project
+ *     and its contributors.
+ * 4. Neither the name of the LOST Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+struct module_options {
+    dword   gateway;
+    dword   nameserver;
+};
+
+extern struct module_options options;
+
+#endif

Eigenschaftsänderungen: src/modules/tcpip/include/main.h
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/modules/tcpip/main.c
===================================================================
--- src/modules/tcpip/main.c	(Revision 655)
+++ src/modules/tcpip/main.c	(Arbeitskopie)
@@ -43,19 +43,18 @@
 #include "ip.h"
 #include "tcp.h"
 #include "lostio_if.h"
+#include "dns.h"
 
+#include "main.h"
 
 #define _USE_START_
 #include "init.h"
 
-struct module_options {
-    dword   gateway;
+struct module_options options = {
+    .gateway = 0x0202000a,
+    .nameserver = 0x7cad61c2
 };
 
-static struct module_options options = {
-    .gateway = 0x0202000a
-};
-
 void init_routing(pid_t driver, dword device, dword ip);
 void init_ip_receive(pid_t driver);
 void rpc_register_driver(pid_t pid, dword cid, size_t data_size, void* data);
@@ -92,6 +91,8 @@
 
     init_routing(pid, driver->device, driver->ip);
     init_ip_receive(pid);
+    
+//    printf("DNS: www.google.de = %08x\n", dns_request("www.google.de"));
 }
 
 void init_routing(pid_t driver, dword device, dword ip)
@@ -142,7 +143,11 @@
         dword gateway = string_to_ip(&param[3]);        
         printf("Gateway: %08x\n", gateway);
         options->gateway = gateway;
+    } else if (strncmp(param, "ns=", 3) == 0) {
+        dword nameserver = string_to_ip(&param[3]);        
+        printf("Nameserver: %08x\n", nameserver);
+        options->nameserver = nameserver;
     } else {
         printf("Unbekannter Parameter %s\n", param);
     }
-}        
+}
Index: src/modules/tcpip/dns.c
===================================================================
--- src/modules/tcpip/dns.c	(Revision 0)
+++ src/modules/tcpip/dns.c	(Revision 0)
@@ -0,0 +1,278 @@
+/*  
+ * Copyright (c) 2007 The LOST Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the LOST Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the LOST Project
+ *     and its contributors.
+ * 4. Neither the name of the LOST Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <types.h>
+#include <string.h>
+#include <network.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dns.h"
+#include "tcp.h"
+#include "main.h"
+
+#define DEBUG 0
+
+#if DEBUG == 1
+    #define DEBUG_MSG(s) printf("[ TCPIP ] debug: %s() '%s'\n",__FUNCTION__,s)
+    #define DEBUG_MSG1(x, y) \
+        printf("[ TCPIP ] debug: %s() '", __FUNCTION__); \
+        printf(x, y); \
+        printf("'\n");
+    #define DEBUG_MSG2(x, y, z) \
+        printf("[ TCPIP ] debug: %s() '", __FUNCTION__); \
+        printf(x, y, z); \
+        printf("'\n");
+#else
+    #define DEBUG_MSG(s)
+    #define DEBUG_MSG1(s,x)
+    #define DEBUG_MSG2(s,x,y)
+#endif
+
+#define DNS_CACHE_SIZE 64
+
+struct dns_cache_entry {
+    char*   name;
+    dword   ip;
+};
+
+static list_t* dns_cache = NULL;
+
+
+/**
+ * Holt eine IP-Adresse aus dem DNS-Cache
+ *
+ * @return Zum gegebenen Domainnamen passende IP-Adresse oder 0, wenn die
+ * Domain nicht im Cache ist.
+ */
+static dword dns_cache_get(char* domain)
+{
+    struct dns_cache_entry* entry;
+    int i;
+    
+    DEBUG_MSG1("dns: cache_get: %s\n", domain);
+
+    for (i = 0; (entry = list_get_element_at(dns_cache, i)); i++) {
+        if (strcmp(domain, entry->name) == 0) {
+            DEBUG_MSG1(" -- %s: Treffer\n", entry->name);
+            return entry->ip;
+        }
+        DEBUG_MSG1(" -- %s: Treffer\n", entry->name);
+    }
+
+    return 0;
+}
+
+/**
+ * Fuegt dem DNS-Cache einen neuen Eintrag hinzu. Dabei wird unter Umstaenden
+ * ein alter Eintrag geloescht, um den Cache auf einer ertraeglichen Groesse zu
+ * halten.
+ */
+static void dns_cache_add(char* domain, dword ip)
+{
+    struct dns_cache_entry* entry = malloc(sizeof(*entry));
+    size_t domain_len = strlen(domain);
+
+    entry->ip = ip;
+    entry->name = malloc(domain_len + 1);
+    strncpy(entry->name, domain, domain_len);
+    entry->name[domain_len] = '\0';
+
+    DEBUG_MSG2("dns: cache_add: %s => %08x\n", entry->name, entry->ip);
+
+    list_push(dns_cache, entry);
+
+    if (list_size(dns_cache) > DNS_CACHE_SIZE) {
+        list_remove(dns_cache, DNS_CACHE_SIZE);
+    }
+}
+
+/**
+ * Loest einen Domainnamen in eine IP-Adresse auf.
+ * 
+ * @param domain Der auszulösender Domainname als nullterminierter String,
+ * wobei die Labels durch Punkte getrennt sind
+ */
+dword dns_request(char* domain)
+{
+    // Cache anlegen, falls noch keiner da ist
+    if (dns_cache == NULL) {
+        dns_cache = list_create();
+    }
+
+    // Wenn es im Cache ist, daraus nehmen
+    dword result = dns_cache_get(domain);
+    if (result) {
+        return result;
+    }
+
+    // Ansonsten brauchen wir eine Verbindung zum DNS-Server
+    dword dns_ip = options.nameserver;
+
+    DEBUG_MSG("DNS: Oeffne Verbindung\n");
+    struct tcp_connection* conn = tcp_open_connection(dns_ip, DNS_PORT);
+    if (conn == NULL) {
+        DEBUG_MSG("DNS: Konnte Verbindung nicht aufbauen.\n");
+        return 0;
+    }
+
+    size_t domain_len = strlen(domain);
+    char data[2 + sizeof(struct dns_header) + domain_len + 6];
+
+    // 2 Bytes Präfix für TCP-Transport
+    *((word*) data) = 
+        big_endian_word(sizeof(struct dns_header) + domain_len + 6);
+    
+    // DNS-Header
+    struct dns_header* header = (struct dns_header*) &data[2];
+    header->id = 0;
+    header->flags = DNS_RD;
+    header->qd_count = big_endian_word(1);
+    header->an_count = 0;
+    header->ns_count = 0;
+    header->ar_count = 0;
+    
+    // Question Section
+    // Die Question Section besteht aus einzelnen Labels, d.h. Bestandteilen
+    // einer Domain (www.xyz.de hat die drei Labels www, xyz und de).
+    // Vor jedem Label gibt ein Byte die Länge dieses Labels an. Daher von
+    // hinten durchgehen und mitzählen und bei jedem Punkt den aktuellen
+    // Zählerstand setzen.
+    char* qname = &data[2 + sizeof(struct dns_header)];
+    size_t label_len = 0;
+    int i;
+
+    for (i = domain_len; i; i--) {
+        if (domain[i - 1] != '.') {
+            qname[i] = domain[i - 1];
+            label_len++;
+        } else {
+            qname[i] = label_len;
+            label_len = 0;
+        }
+    }
+    qname[0] = label_len;
+
+    // Das Ende wird durch ein Label der Laenge 0 markiert
+    qname[domain_len + 1] = '\0';
+
+    // QTYPE = A und QCLASS = IN
+    *((word*) &data[2 + sizeof(struct dns_header) + domain_len + 2]) =
+        big_endian_word(1);
+    *((word*) &data[2 + sizeof(struct dns_header) + domain_len + 4]) =
+        big_endian_word(1);
+
+    // Senden 
+    struct tcp_out_buffer out_buffer = {
+        .size = 2 + sizeof(struct dns_header) + domain_len + 6,
+        .data = data
+    };
+    list_insert(conn->out_buffer, list_size(conn->out_buffer), &out_buffer);
+    tcp_send_ack(conn);
+
+    // Auf Antwort warten
+    DEBUG_MSG("DNS: Warte auf Antwort\n");
+    struct tcp_in_buffer* in_buffer;
+    while(1) {
+        if ((in_buffer = list_pop(conn->to_lostio))) {
+            void* reply = in_buffer->data;
+
+            // 2 Bytes TCP-Präfix
+            reply += 2;
+
+            // Header ignorieren
+            int qd_count = 
+                big_endian_word(((struct dns_header*) reply)->qd_count);
+            int an_count = 
+                big_endian_word(((struct dns_header*) reply)->an_count);
+            reply += sizeof(struct dns_header);
+
+            // Question Section ignorieren
+            for (i = 0; i < qd_count; i++) {                
+                // QNAMEs
+                int label_len;
+                while ((label_len = *((byte*) reply))) {
+                    reply += label_len + 1;
+                }
+
+                // Null-Label, QTYPE und QCLASS
+                reply += 5;
+            }
+
+            // Hier kommt die Antwort - alles ignorieren, was den falschen
+            // Typ hat, und beim ersten Treffer die IP zurückgeben.
+            for (i = 0; i < an_count; i++) 
+            {
+                // QNAMEs - interessieren nicht
+                int label_len;
+                while ((label_len = *((byte*) reply))) {
+                    
+                    if (label_len & 0xC0) {
+                        // Pointer
+                        reply += 2;
+                        break;
+                    } else {
+                        int j;
+                        for (j = 0; j < label_len; j++) {
+                            printf(" %02hhx", *((byte*) reply + j));
+                        }
+                        reply += label_len + 1;
+                    }
+                }
+
+                // QTYPE - Hostadressen (A = 0x1 big-endian)  interessieren
+                size_t answer_len = 
+                    10 + big_endian_word(*((word*) (reply + 8)));
+
+                if (*((word*) reply) == 0x100) {
+                    result = *((dword*) (reply + 10));
+                    dns_cache_add(domain, result);
+                    
+                    // TODO Verbindung schliessen
+                    return result;
+                } else {
+                    reply += answer_len;
+                }
+            }
+            
+            break;
+        }
+        wait_for_rpc();
+    }
+
+    // TODO Verbindung schliessen
+
+    return 0;
+}

Eigenschaftsänderungen: src/modules/tcpip/dns.c
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/modules/tcpip/lostio_if.c
===================================================================
--- src/modules/tcpip/lostio_if.c	(Revision 655)
+++ src/modules/tcpip/lostio_if.c	(Arbeitskopie)
@@ -44,6 +44,7 @@
 #include "network.h"
 #include "ip.h"
 #include "tcp.h"
+#include "dns.h"
 
 //Hier koennen die Debug-Nachrichten aktiviert werden
 #define DEBUG 0
@@ -79,6 +80,7 @@
 {
     lostio_init();
     lostio_type_directory_use();
+    lostio_type_ramfile_use();
 
     //Typ fuer eine TCP-Verbindung
     typehandle.id          = LOSTIO_TYPES_TCPPORT;
@@ -92,11 +94,12 @@
     typehandle.link        = NULL;
     typehandle.unlink      = NULL;
 
-
     lostio_register_typehandle(&typehandle);
 
     get_typehandle(LOSTIO_TYPES_DIRECTORY)->not_found = lostio_tcp_not_found;
    
+    vfstree_create_node("/dns", LOSTIO_TYPES_DIRECTORY, 0, NULL, 
+        LOSTIO_FLAG_BROWSABLE);
 /*   
     vfstree_create_node("/192.168.1.3:80", LOSTIO_TYPES_TCPPORT, 0, NULL, 0);
     vfstree_create_node("/192.168.1.3:1028", LOSTIO_TYPES_TCPPORT, 0, NULL, 0);
@@ -108,7 +111,14 @@
 bool lostio_tcp_not_found(char** path, byte flags, pid_t pid, io_resource_t* ps)
 {
     DEBUG_MSG("Knoten anlegen");
-    return vfstree_create_node(*path, LOSTIO_TYPES_TCPPORT, 0, NULL, 0);
+    
+    if (strncmp(*path, "/dns/", 5) == 0) {
+        dword ip = dns_request(strrchr(*path, '/') + 1);
+        char* data = ip_to_string(ip);
+        return vfstree_create_node(*path, LOSTIO_TYPES_RAMFILE, strlen(data), data, 0);
+    } else {
+        return vfstree_create_node(*path, LOSTIO_TYPES_TCPPORT, 0, NULL, 0);
+    }
 }
 
 bool lostio_tcp_pre_open(char** path, byte flags, pid_t pid, io_resource_t* ps)
@@ -129,6 +139,15 @@
 
     *delim = '\0';
     dword ip = string_to_ip(*path + 1);
+    if (!ip) {
+        ip = dns_request(*path + 1);
+    }
+
+    if (!ip) {
+        DEBUG_MSG("Konnte Adresse nicht aufloesen");
+        return FALSE;
+    }
+
     *delim = ':';
 
     char* port_string = delim + 1;
Index: src/modules/include/network.h
===================================================================
--- src/modules/include/network.h	(Revision 655)
+++ src/modules/include/network.h	(Arbeitskopie)
@@ -60,6 +60,7 @@
 };
 
 dword string_to_ip(char* ip);
+char* ip_to_string(dword ip);
 void register_netcard(dword device_numer, dword ip);
 
 #endif
Index: src/modules/lib/network.c
===================================================================
--- src/modules/lib/network.c	(Revision 655)
+++ src/modules/lib/network.c	(Arbeitskopie)
@@ -74,6 +74,21 @@
 
     return *((dword*) ip_bytes);
 }
+
+/**
+ * Wandelt eine IP-Adresse in einen String um
+ */
+char* ip_to_string(dword ip)
+{
+    char* result;
+    asprintf(&result, "%d.%d.%d.%d",
+        ip & 0xFF,
+        (ip >> 8) & 0xFF,
+        (ip >> 16) & 0xFF,
+        (ip >> 24) & 0xFF);
+
+    return result;
+}
     
 /**
  * (Nur für Netzwerkkartentreiber)