2009-05-03 20:53:31 +02:00
|
|
|
#include "dns.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves a domainname to an ip address
|
|
|
|
* It makes use of net_gethostbyname from libogc, which in turn makes use of a Wii BIOS function
|
|
|
|
* Just like the net_gethostbyname function this function is NOT threadsafe!
|
|
|
|
*
|
|
|
|
* @param char* The domain name to resolve
|
|
|
|
* @return u32 The ipaddress represented by four bytes inside an u32 (in network order)
|
|
|
|
*/
|
2010-09-19 01:16:05 +02:00
|
|
|
u32 getipbyname( char *domain )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
//Care should be taken when using net_gethostbyname,
|
|
|
|
//it returns a static buffer which makes it not threadsafe
|
|
|
|
//TODO: implement some locking mechanism to make below code atomic
|
2010-09-19 01:16:05 +02:00
|
|
|
struct hostent *host = net_gethostbyname( domain );
|
2009-07-30 07:41:12 +02:00
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
if ( host == NULL )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
u32 *ip = ( u32* )host->h_addr_list[0];
|
2009-07-30 07:41:12 +02:00
|
|
|
return *ip;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Defines how many DNS entries should be cached by getipbynamecached()
|
|
|
|
#define MAX_DNS_CACHE_ENTRIES 20
|
|
|
|
|
|
|
|
//The cache is defined as a linked list,
|
|
|
|
//The last resolved domain name will always be at the front
|
|
|
|
//This will allow heavily used domainnames to always stay cached
|
2010-09-19 01:16:05 +02:00
|
|
|
struct dnsentry
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
char *domain;
|
|
|
|
u32 ip;
|
|
|
|
struct dnsentry *nextnode;
|
2009-05-03 20:53:31 +02:00
|
|
|
} ;
|
|
|
|
|
|
|
|
static struct dnsentry *firstdnsentry = NULL;
|
|
|
|
static int dnsentrycount = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs the same function as getipbyname(),
|
|
|
|
* except that it will prevent extremely expensive net_gethostbyname() calls by caching the result
|
|
|
|
*/
|
2010-09-19 01:16:05 +02:00
|
|
|
u32 getipbynamecached( char *domain )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
//Search if this domainname is already cached
|
|
|
|
struct dnsentry *node = firstdnsentry;
|
|
|
|
struct dnsentry *previousnode = NULL;
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
while ( node != NULL )
|
|
|
|
{
|
|
|
|
if ( strcmp( node->domain, domain ) == 0 )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
//DNS node found in the cache, move it to the front of the list
|
2010-09-19 01:16:05 +02:00
|
|
|
if ( previousnode != NULL )
|
2009-07-30 07:41:12 +02:00
|
|
|
previousnode->nextnode = node->nextnode;
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
if ( node != firstdnsentry )
|
2009-07-30 07:41:12 +02:00
|
|
|
node->nextnode = firstdnsentry;
|
|
|
|
firstdnsentry = node;
|
|
|
|
|
|
|
|
return node->ip;
|
|
|
|
}
|
|
|
|
//Go to the next element in the list
|
|
|
|
previousnode = node;
|
|
|
|
node = node->nextnode;
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
u32 ip = getipbyname( domain );
|
2009-07-30 07:41:12 +02:00
|
|
|
|
|
|
|
//No cache of this domain could be found, create a cache node and add it to the front of the cache
|
2010-09-19 01:16:05 +02:00
|
|
|
struct dnsentry *newnode = malloc( sizeof( struct dnsentry ) );
|
|
|
|
if ( newnode == NULL )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
return ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
newnode->ip = ip;
|
2010-09-19 01:16:05 +02:00
|
|
|
newnode->domain = malloc( strlen( domain ) + 1 );
|
|
|
|
if ( newnode->domain == NULL )
|
|
|
|
{
|
|
|
|
free( newnode );
|
2009-07-30 07:41:12 +02:00
|
|
|
return ip;
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
strcpy( newnode->domain, domain );
|
2009-07-30 07:41:12 +02:00
|
|
|
|
|
|
|
newnode->nextnode = firstdnsentry;
|
|
|
|
firstdnsentry = newnode;
|
|
|
|
dnsentrycount++;
|
|
|
|
|
|
|
|
//If the cache grows too big delete the last (and probably least important) node of the list
|
2010-09-19 01:16:05 +02:00
|
|
|
if ( dnsentrycount > MAX_DNS_CACHE_ENTRIES )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
struct dnsentry *node = firstdnsentry;
|
|
|
|
struct dnsentry *previousnode = NULL;
|
|
|
|
|
|
|
|
//Fetch the last two elements of the list
|
2010-09-19 01:16:05 +02:00
|
|
|
while ( node->nextnode != NULL )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
previousnode = node;
|
|
|
|
node = node->nextnode;
|
|
|
|
}
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
if ( node == NULL )
|
|
|
|
{
|
|
|
|
printf( "Configuration error, MAX_DNS_ENTRIES reached while the list is empty\n" );
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
else if ( previousnode == NULL )
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
firstdnsentry = NULL;
|
2010-09-19 01:16:05 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-07-30 07:41:12 +02:00
|
|
|
previousnode->nextnode = NULL;
|
|
|
|
}
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
free( node->domain );
|
|
|
|
free( node );
|
2009-07-30 07:41:12 +02:00
|
|
|
dnsentrycount--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return newnode->ip;
|
2009-05-03 20:53:31 +02:00
|
|
|
}
|