[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH] dns_request loest nun Namen in mehrere IP-Adressen auf. IPs werden
gethostbyname gibt nun mehrere IPs zurueck.
Signed-off-by: Roman Muentener <fmnssun@xxxxxxxxx>
---
src/modules/c/getip/Makefile.all | 7 ++
src/modules/c/getip/main.c | 116 ++++++++++++++++++++++++++++++++++++++
src/modules/lib/posix/net.c | 58 ++++++++++++++++++-
src/modules/tcpip/dns.c | 75 ++++++++++++++++++-------
src/modules/tcpip/include/dns.h | 10 +++-
src/modules/tcpip/lostio_if.c | 38 ++++++++++--
6 files changed, 273 insertions(+), 31 deletions(-)
create mode 100644 src/modules/c/getip/Makefile.all
create mode 100644 src/modules/c/getip/main.c
diff --git a/src/modules/c/getip/Makefile.all b/src/modules/c/getip/Makefile.all
new file mode 100644
index 0000000..59d796e
--- /dev/null
+++ b/src/modules/c/getip/Makefile.all
@@ -0,0 +1,7 @@
+shopt -s extglob
+source $LOST_BUILDMK_ROOT/config.sh
+
+echo "LD $1/apps/getip"
+$LOST_TOOLS_LD -ogetip -Ttext=0x40000000 *.o --start-group $2 --end-group
+
+mv getip $1/apps/
diff --git a/src/modules/c/getip/main.c b/src/modules/c/getip/main.c
new file mode 100644
index 0000000..57ebc32
--- /dev/null
+++ b/src/modules/c/getip/main.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2009 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Roman Muentener.
+ *
+ * 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 tyndur Project
+ * and its contributors.
+ * 4. Neither the name of the tyndur 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 "stdlib.h"
+#include "string.h"
+#include "netdb.h"
+#include "stdio.h"
+#include "arpa/inet.h"
+#include "errno.h"
+#include "network.h"
+
+int main(int argc, char* argv[])
+{
+ printf("getip\n-----\n\n");
+
+ if( argc != 2 )
+ {
+ printf("Falsche Parameter!\n");
+ return 1;
+ }
+
+ struct in_addr addr;
+
+ struct hostent* info;
+ info = gethostbyname(argv[1]);
+
+ if (info == NULL) {
+ printf("Fehler: %s!\n",hstrerror(h_errno));
+ return 2;
+ }
+
+ int i = 0;
+ while (info->h_addr_list[i] != 0)
+ {
+ addr.s_addr = *(unsigned long*) info->h_addr_list[i++];
+
+ printf("IP Adresse: %s \n", inet_ntoa(addr));
+ }
+
+ return 0;
+}
+
+/*
+int main(int argc, char* argv[])
+{
+ printf("getip\n-----\n\n");
+ if(argc != 2) {
+ printf("Incorrect usage!\n");
+ printf("Correct usage:\tgetip <hostname>\n");
+ return 1;
+ }
+ long count = 0;
+ char* path;
+ FILE* f;
+ asprintf(&path,"tcpip:/dns/%s",argv[1]);
+ f=fopen(path,"r");
+ if(!f) {
+ printf("Error: Abfrage gescheitert!\n");
+ return 3;
+ }
+ fseek(f,0,SEEK_END);
+ count = ftell(f);
+ if(count == 0) {
+ printf("Error: Abfrage gescheitert!\n");
+ return 2;
+ }
+ rewind(f);
+ char* buffer = calloc(count,sizeof(char));
+ fread(buffer,1,count,f);
+ count /= 16;
+ fclose(f);
+ if(count == 0) {
+ printf("Error: Abfrage gescheitert!\n");
+ return 3;
+ }
+ int i=0;
+ for(;i < count; i++) {
+ char* ip = (char*)(buffer+(i*16));
+ printf("IP Adresse: %s\n",ip);
+ }
+ return 0;
+}
+*/
diff --git a/src/modules/lib/posix/net.c b/src/modules/lib/posix/net.c
index f009585..d08b1c8 100644
--- a/src/modules/lib/posix/net.c
+++ b/src/modules/lib/posix/net.c
@@ -184,7 +184,13 @@ struct hostent* gethostbyname(const char* name)
static struct hostent hostent;
static char* aliases[] = { NULL };
static uint32_t ip;
- static uint32_t* h_addr_list[] = { &ip, NULL };
+ static uint32_t** h_addr_list;
+
+ // Also, falls h_addr_list nicht NULL ist... muessen wir mal bisschen rumfreen
+ while(h_addr_list != NULL) {
+ free(h_addr_list);
+ h_addr_list++;
+ }
// Erstmal schauen, ob es eine IP-Adresse ist
ip = string_to_ip(name);
@@ -193,17 +199,61 @@ struct hostent* gethostbyname(const char* name)
if (ip == 0) {
char* path;
FILE* f;
- char ip_str[16];
+ char* ip_str;
+ unsigned long count = 0;
asprintf(&path, "tcpip:/dns/%s", name);
+
+ // Datei oeffnen
f = fopen(path, "r");
+
+ // Dateigroesse feststellen
+ fseek(f,0,SEEK_END);
+ count = ftell(f);
+ rewind(f);
+
+ // Speicher fuer ip_str holen
+ ip_str = calloc(count+1,sizeof(char));
+
if (!f) {
return NULL;
}
- fread(ip_str, 1, 16, f);
+
+ // Daten einlesen
+ fread(ip_str, 1, count, f);
fclose(f);
- ip = string_to_ip(ip_str);
+ // \n beachten
+ char* p;
+ p = strtok(ip_str,"\n");
+ int i = 0;
+ while (p != NULL)
+ {
+ // Wir reallocen das ganze
+ h_addr_list = realloc(h_addr_list,sizeof(uint32_t*) * (i + 1));
+
+ // Wir brauchen Platz fuer die IP, auf die der Pointer zeigt
+ uint32_t* ip_q = malloc(sizeof(uint32_t));
+
+ // IP zuweisen
+ *ip_q = string_to_ip(p);
+
+ // Pointer zuweisen
+ h_addr_list[i] = ip_q;
+
+ // Inkrementieren
+ i++;
+
+ // Nach \n aufteilen, Teil nehmen
+ p = strtok (NULL, "\n");
+ }
+
+ // Wir muessen mit NULL terminieren
+ h_addr_list[i] = NULL;
+
+ // Speicher wieder freigeben
+ free(path);
+ free(ip_str);
}
// hostent aktualisieren
diff --git a/src/modules/tcpip/dns.c b/src/modules/tcpip/dns.c
index 0f6e18d..5b2c691 100644
--- a/src/modules/tcpip/dns.c
+++ b/src/modules/tcpip/dns.c
@@ -66,7 +66,7 @@
struct dns_cache_entry {
char* name;
- dword ip;
+ struct dns_request_result* result;
};
static list_t* dns_cache = NULL;
@@ -77,7 +77,7 @@ static list_t* dns_cache = NULL;
* @return Zum gegebenen Domainnamen passende IP-Adresse oder 0, wenn die
* Domain nicht im Cache ist.
*/
-static dword dns_cache_get(char* domain)
+static struct dns_request_result* dns_cache_get(char* domain)
{
struct dns_cache_entry* entry;
int i;
@@ -87,12 +87,12 @@ static dword dns_cache_get(char* 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;
+ return entry->result;
}
DEBUG_MSG1(" -- %s: Treffer\n", entry->name);
}
-
- return 0;
+ DEBUG_MSG1(" -- %s: Keine Treffer\n",domain);
+ return NULL;
}
/**
@@ -100,52 +100,71 @@ static dword dns_cache_get(char* domain)
* ein alter Eintrag geloescht, um den Cache auf einer ertraeglichen Groesse zu
* halten.
*/
-static void dns_cache_add(char* domain, dword ip)
+static void dns_cache_add(char* domain, struct dns_request_result* result)
{
struct dns_cache_entry* entry = malloc(sizeof(*entry));
size_t domain_len = strlen(domain);
- entry->ip = ip;
+ entry->result = result;
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);
+ DEBUG_MSG1("dns: cache_add: %s\n", entry->name);
list_push(dns_cache, entry);
if (list_size(dns_cache) > DNS_CACHE_SIZE) {
+ dns_free_result(list_get_element_at(dns_cache,DNS_CACHE_SIZE));
list_remove(dns_cache, DNS_CACHE_SIZE);
}
}
+
+/**
+ * Gibt die Ressourcen eines dns_request_result wieder frei
+ * @param result Das freizugebene Resultat
+ */
+void dns_free_result(struct dns_request_result* result) {
+ // Speicher fuer IP-Adressen freigeben.
+ free(result->ip_address);
+ // Speicher fuer das Resultat freigeben.
+ free(result);
+}
+
/**
- * Loest einen Domainnamen in eine IP-Adresse auf.
+ * Loest einen Domainnamen in eine IP-Adressen auf.
*
* @param domain Der aufzuloesende Domainname als nullterminierter String,
* wobei die Labels durch Punkte getrennt sind
*/
-dword dns_request(char* domain)
+struct dns_request_result* dns_request(char* domain)
{
+ // Resultat
+ struct dns_request_result* dns_result = dns_cache_get(domain);
+ uint32_t result;
+
// Cache anlegen, falls noch keiner da ist
if (dns_cache == NULL) {
+ DEBUG_MSG("DNS: Erzeuge Cache\n");
dns_cache = list_create();
}
- // Wenn es im Cache ist, daraus nehmen
- dword result = dns_cache_get(domain);
- if (result) {
- return result;
+
+ if(dns_cache_get(domain) != NULL) {
+ return dns_result;
}
+ dns_result = malloc(sizeof(struct dns_request_result));
+
// Ansonsten brauchen wir eine Verbindung zum DNS-Server
- dword dns_ip = options.nameserver;
+ uint32_t 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;
+ return NULL;
}
// Puffer fuer die Nachricht reservieren:
@@ -219,6 +238,8 @@ dword dns_request(char* domain)
// Auf Antwort warten
DEBUG_MSG("DNS: Warte auf Antwort\n");
struct tcp_in_buffer* in_buffer;
+ // Index fuer dns_result
+ int dns_result_index = 0;
while(1) {
if ((in_buffer = list_pop(conn->to_lostio))) {
void* reply = in_buffer->data;
@@ -233,6 +254,14 @@ dword dns_request(char* domain)
big_endian_word(((struct dns_header*) reply)->an_count);
reply += sizeof(struct dns_header);
+ // Speicher fuer die IPs holen
+ //if(an_count == 0) return NULL;
+ dns_result->ip_address = malloc(sizeof(uint32_t) * an_count);
+ // Menge speichern
+ dns_result->ip_count = an_count;
+
+
+
// Question Section ignorieren
for (i = 0; i < qd_count; i++) {
// QNAMEs
@@ -271,14 +300,18 @@ dword dns_request(char* domain)
10 + big_endian_word(*((word*) (reply + 8)));
if (*((word*) reply) == 0x100) {
- result = *((dword*) (reply + 10));
- dns_cache_add(domain, result);
+ result = *((uint32_t*) (reply + 10));
+
// TODO Verbindung schliessen
- return result;
+ reply += answer_len;
} else {
+ result = 0;
reply += answer_len;
}
+
+ dns_result->ip_address[dns_result_index] = result;
+ dns_result_index++;
}
break;
@@ -288,5 +321,7 @@ dword dns_request(char* domain)
// TODO Verbindung schliessen
- return 0;
+ dns_cache_add(domain,dns_result);
+
+ return dns_result;
}
diff --git a/src/modules/tcpip/include/dns.h b/src/modules/tcpip/include/dns.h
index cc4281f..b1cf532 100644
--- a/src/modules/tcpip/include/dns.h
+++ b/src/modules/tcpip/include/dns.h
@@ -93,9 +93,17 @@ static inline void dns_set_opcode(struct dns_header* header, uint8_t opcode)
/// Reponse Code aus einem DNS-Header
#define dns_get_rcode(x) (((x) >> 8) & 0x0F)
+// Konstanten für die Header-Flags
#define QTYPE_A big_endian_word(1)
#define QCLASS_IN big_endian_word(1)
-dword dns_request(char* domain);
+struct dns_request_result {
+ uint32_t* ip_address;
+ uint32_t ip_count;
+};
+
+struct dns_request_result* dns_request(char* domain);
+
+void dns_free_result(struct dns_request_result* result);
#endif
diff --git a/src/modules/tcpip/lostio_if.c b/src/modules/tcpip/lostio_if.c
index a849f18..17e4b09 100644
--- a/src/modules/tcpip/lostio_if.c
+++ b/src/modules/tcpip/lostio_if.c
@@ -164,13 +164,35 @@ void lostio_add_device(struct device *device)
bool lostio_tcp_not_found(char** path, byte flags, pid_t pid, io_resource_t* ps)
{
DEBUG_MSG("Knoten anlegen");
-
+
if (strncmp(*path, "/dns/", 5) == 0) {
- dword ip = dns_request(strrchr(*path, '/') + 1);
- if (ip == 0)
+ // DNS Request absetzen
+ struct dns_request_result* result = dns_request(strrchr(*path, '/') + 1);
+
+ // Keine IP-Adresse erhalten?
+ if (result == NULL)
+ return FALSE;
+ if (result->ip_count == 0) {
return FALSE;
- char* data = ip_to_string(ip);
- return vfstree_create_node(*path, LOSTIO_TYPES_RAMFILE, strlen(data), data, 0);
+ }
+
+ char* data = calloc(16 * result->ip_count,sizeof(char));
+
+ int i=0;
+ for(;i < result->ip_count;i++) {
+ char* ip = ip_to_string(result->ip_address[i]);
+ DEBUG_MSG2("IP = %s , len = %d\n",ip,strlen(ip));
+ strcat(data,ip);
+ if((i+1) < result->ip_count) strcat(data,"\n");
+
+ // Speicher wieder freigeben.
+ free(ip);
+ }
+
+
+ // TODO: Data wird nicht gefreet. (vorerst!)
+
+ return vfstree_create_node(*path, LOSTIO_TYPES_RAMFILE, 16 * result->ip_count * sizeof(char), data, 0);
} else {
return vfstree_create_node(*path, LOSTIO_TYPES_TCPPORT, 0, NULL, 0);
}
@@ -195,7 +217,11 @@ bool lostio_tcp_pre_open(char** path, byte flags, pid_t pid, io_resource_t* ps)
*delim = '\0';
dword ip = string_to_ip(*path + 1);
if (!ip) {
- ip = dns_request(*path + 1);
+ // DNS Request absetzen
+ struct dns_request_result* result = dns_request(*path + 1);
+ if (result && (result->ip_count > 0)) {
+ ip = result->ip_address[0];
+ }
}
if (!ip) {
--
1.6.0.4