URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/ecos-2.0/packages/net/ns/dns
- from Rev 27 to Rev 174
- ↔ Reverse comparison
Rev 27 → Rev 174
/v2_0/cdl/dns.cdl
0,0 → 1,152
# ==================================================================== |
# |
# dns.cdl |
# |
# DNS configuration data |
# |
# ==================================================================== |
#####ECOSGPLCOPYRIGHTBEGIN#### |
## ------------------------------------------- |
## This file is part of eCos, the Embedded Configurable Operating System. |
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
## Copyright (C) 2003 Andrew Lunn <andrew.lunn@ascom.ch> |
## |
## eCos is free software; you can redistribute it and/or modify it under |
## the terms of the GNU General Public License as published by the Free |
## Software Foundation; either version 2 or (at your option) any later version. |
## |
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
## WARRANTY; without even the implied warranty of MERCHANTABILITY or |
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
## for more details. |
## |
## You should have received a copy of the GNU General Public License along |
## with eCos; if not, write to the Free Software Foundation, Inc., |
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
## |
## As a special exception, if other files instantiate templates or use macros |
## or inline functions from this file, or you compile this file and link it |
## with other works to produce a work based on this file, this file does not |
## by itself cause the resulting work to be covered by the GNU General Public |
## License. However the source code for this file must still be made available |
## in accordance with section (3) of the GNU General Public License. |
## |
## This exception does not invalidate any other reasons why a work based on |
## this file might be covered by the GNU General Public License. |
## |
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
## at http://sources.redhat.com/ecos/ecos-license/ |
## ------------------------------------------- |
#####ECOSGPLCOPYRIGHTEND#### |
# ==================================================================== |
######DESCRIPTIONBEGIN#### |
# |
# Author(s): jskov |
# Original data: jskov |
# Contributors: andrew.lunn@ascom.ch |
# Date: 2001-09-18 |
# |
#####DESCRIPTIONEND#### |
# |
# ==================================================================== |
|
cdl_package CYGPKG_NS_DNS { |
display "DNS client" |
include_dir cyg/ns/dns |
doc ref/net-ns-dns.html |
|
cdl_option CYGPKG_NS_DNS_BUILD { |
display "Build DNS NS client package" |
default_value 1 |
implements CYGINT_ISO_DNS |
requires { CYGBLD_ISO_DNS_HEADER == "<cyg/ns/dns/dns.h>" } |
|
requires CYGPKG_NET |
requires CYGINT_ISO_CTYPE |
requires CYGINT_ISO_MALLOC |
requires CYGINT_ISO_STRING_STRFUNCS |
requires CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD |
|
compile dns.c |
} |
|
cdl_component CYGPKG_NS_DNS_DEFAULT { |
display "Provide a hard coded default server address" |
flavor bool |
active_if CYGPKG_NS_DNS_BUILD |
default_value 0 |
description " |
This option controls the use of a default, hard coded DNS |
server. When this is enabled, the IP address in the CDL |
option CYGDAT_NS_DNS_DEFAULT_SERVER is used in |
init_all_network_interfaces() to start the resolver using |
the specified server. The DHCP client or user code may |
override this by restarting the resolver." |
|
cdl_option CYGDAT_NS_DNS_DEFAULT_SERVER { |
display "IP address of the default DNS server" |
flavor data |
default_value { "192.168.1.1" } |
} |
} |
cdl_component CYGPKG_NS_DNS_DOMAINNAME { |
display "Provide a hard coded default domain name" |
flavor bool |
active_if CYGPKG_NS_DNS_BUILD |
default_value 0 |
description " |
This option controls the use of a default, hard coded |
domain name to be used when querying a DNS server. When |
this is enabled, the name in the CDL option |
CYGDAT_NS_DNS_DOMAINNAME_NAME is used in |
init_all_network_interfaces() to set the domain name as |
accessed by getdomainname()." |
|
cdl_option CYGDAT_NS_DNS_DOMAINNAME_NAME { |
display "Domain name for this device" |
flavor data |
default_value { "default.domain.com" } |
} |
} |
cdl_component CYGPKG_NS_DNS_OPTIONS { |
display "DNS support build options" |
flavor none |
no_define |
|
cdl_option CYGPKG_NS_DNS_CFLAGS_ADD { |
display "Additional compiler flags" |
flavor data |
no_define |
default_value { "-D_KERNEL -D__ECOS" } |
description " |
This option modifies the set of compiler flags for |
building the DNS package. |
These flags are used in addition |
to the set of global flags." |
} |
|
cdl_option CYGPKG_NS_DNS_CFLAGS_REMOVE { |
display "Suppressed compiler flags" |
flavor data |
no_define |
default_value { "" } |
description " |
This option modifies the set of compiler flags for |
building the DNS package. These flags are removed from |
the set of global flags if present." |
} |
} |
|
cdl_option CYGPKG_NS_DNS_TESTS { |
display "Networking tests" |
flavor data |
active_if CYGPKG_NS_DNS_BUILD |
no_define |
calculated { "tests/dns1 tests/dns2" } |
|
description " |
This option specifies the set of tests for the DNS package." |
} |
} |
|
# EOF dns.cdl |
/v2_0/tests/dns1.c
0,0 → 1,185
//========================================================================== |
// |
// tests/dns1.c |
// |
// Simple test of DNS client support |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors: andrew.lunn, jskov |
// Date: 2001-09-18 |
// Purpose: |
// Description: Test DNS functions. Note that the _XXX defines below |
// control what addresses the test uses. These must be |
// changed to match the particular testing network in which |
// the test is to be run. |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
#include <network.h> |
#include <netdb.h> |
|
#include <arpa/inet.h> |
|
#include <cyg/infra/testcase.h> |
|
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) |
static char stack[STACK_SIZE]; |
static cyg_thread thread_data; |
static cyg_handle_t thread_handle; |
|
#define __string(_x) #_x |
#define __xstring(_x) __string(_x) |
|
// Change the following if you aren't using BOOTP! It's almost certainly not right for you. |
#define _DNS_IP __xstring(172.16.1.254) // test farm host addr |
#define _LOOKUP_FQDN __xstring(b.root-servers.net.) // should stay the same? |
#define _LOOKUP_DOMAINNAME __xstring(root-servers.net.) |
#define _LOOKUP_HOSTNAME __xstring(b) |
#define _LOOKUP_IP __xstring(128.9.0.107) // must be same as _LOOKUP_FQDN |
#define _LOOKUP_IP_BAD __xstring(10.0.0.0) |
|
void |
dns_test(cyg_addrword_t p) |
{ |
struct in_addr addr; |
struct hostent *hent; |
char dn[256]; |
int i; |
|
CYG_TEST_INIT(); |
|
init_all_network_interfaces(); |
|
CYG_TEST_INFO("Starting dns1 test"); |
|
setdomainname(NULL,0); |
|
for (i=0; i<2; i++) { |
/* Expect _LOOKUP_IP as the answer. This is a CNAME lookup */ |
inet_aton(_LOOKUP_IP, &addr); |
hent = gethostbyname(_LOOKUP_FQDN); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
if (0 != memcmp((void*)&addr, (void*)(hent->h_addr), sizeof(struct in_addr))) { |
diag_printf("FAIL:<expected " _LOOKUP_FQDN " to be " _LOOKUP_IP ">\n"); |
} |
break; |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_FQDN ". No answer: %s>\n", hstrerror(h_errno)); |
CYG_TEST_INFO("Retrying with explicit DNS server"); |
CYG_TEST_INFO("Connecting to DNS at " _DNS_IP); |
inet_aton(_DNS_IP, &addr); |
CYG_TEST_CHECK(cyg_dns_res_init(&addr) == 0, "Failed to initialize resolver"); |
} |
} |
|
/* Reverse lookup the _LOOKUP_IP addres, expect _LOOKUP_FQDN |
as the answer. */ |
hent = gethostbyaddr((char *)&addr, sizeof(struct in_addr), AF_INET); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
if (0 != strcmp(_LOOKUP_FQDN, hent->h_name)) { |
diag_printf("FAIL:<expected " _LOOKUP_IP " to be " _LOOKUP_FQDN ">\n"); |
} |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_IP ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
/* This does not require a DNS lookup. Just turn the value into |
binary */ |
hent = gethostbyname(_LOOKUP_IP); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_IP ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
/* Reverse lookup an address this is not in the server. Expect a |
NULL back */ |
inet_aton(_LOOKUP_IP_BAD, &addr); |
hent = gethostbyaddr((char *)&addr, sizeof(struct in_addr), AF_INET); |
if (hent != NULL) { |
diag_printf("FAIL:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
} else { |
diag_printf("PASS:<Asked for bad IP " _LOOKUP_IP_BAD ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
/* Setup a domainname. We now don't have to use fully qualified |
domain names */ |
setdomainname(_LOOKUP_DOMAINNAME, sizeof(_LOOKUP_DOMAINNAME)); |
getdomainname(dn, sizeof(dn)); |
diag_printf("INFO:<Domainname is now %s>\n", dn); |
|
/* Make sure FQDN still work */ |
hent = gethostbyname(_LOOKUP_FQDN); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_FQDN ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
/* Now just the hostname */ |
hent = gethostbyname(_LOOKUP_HOSTNAME); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", _LOOKUP_HOSTNAME, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_HOSTNAME ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
CYG_TEST_FINISH("dns1 test completed"); |
} |
|
void |
cyg_start(void) |
{ |
// Create a main thread, so we can run the scheduler and have time 'pass' |
cyg_thread_create(10, // Priority - just a number |
dns_test, // entry |
0, // entry parameter |
"DNS test", // Name |
&stack[0], // Stack |
STACK_SIZE, // Size |
&thread_handle, // Handle |
&thread_data // Thread data structure |
); |
cyg_thread_resume(thread_handle); // Start it |
cyg_scheduler_start(); |
} |
/v2_0/tests/dns2.c
0,0 → 1,156
//========================================================================== |
// |
// tests/dns2.c |
// |
// Simple test of DNS client support. This time use DHCP |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors: andrew.lunn, jskov |
// Date: 2001-12-03 |
// Purpose: |
// Description: Test DNS functions. Use the server and domain name the |
// DHCP server told us. |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
#include <network.h> |
#include <netdb.h> |
|
#include <arpa/inet.h> |
|
#include <cyg/infra/testcase.h> |
|
#ifdef CYGPKG_NET_DHCP |
|
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) |
static char stack[STACK_SIZE]; |
static cyg_thread thread_data; |
static cyg_handle_t thread_handle; |
|
#define __string(_x) #_x |
#define __xstring(_x) __string(_x) |
|
#define USE_HARDCODED_DOMAIN 1 |
|
// Change the following if you aren't using BOOTP! It's almost certainly not right for you. |
#define _DNS_IP __xstring(172.16.1.254) // test farm host addr |
#define _LOOKUP_FQDN __xstring(b.root-servers.net.) // should stay the same? |
#define _LOOKUP_DOMAINNAME __xstring(root-servers.net.) |
#define _LOOKUP_HOSTNAME __xstring(b) |
#define _LOOKUP_IP __xstring(128.9.0.107) // must be same as _LOOKUP_FQDN |
#define _LOOKUP_IP_BAD __xstring(10.0.0.0) |
|
void |
dns_test(cyg_addrword_t p) |
{ |
struct in_addr addr; |
struct hostent *hent; |
char dn[256]; |
|
CYG_TEST_INIT(); |
|
init_all_network_interfaces(); |
|
CYG_TEST_INFO("Starting dns2 test"); |
|
getdomainname(dn,sizeof(dn)); |
diag_printf("INFO:<DHCP said domain name is %s>\n",dn); |
#ifndef USE_HARDCODED_DOMAIN |
// If not hard-coded we can't tell what it's _meant_ to be |
CYG_TEST_CHECK(!strncmp(dn,_LOOKUP_DOMAINNAME,sizeof(_LOOKUP_DOMAINNAME)), |
"DHCP got the wrong domainname"); |
#endif //ifdef _LOOKUP_DOMAINNAME |
|
/* Expect _LOOKUP_IP as the answer. This is a CNAME lookup */ |
inet_aton(_LOOKUP_IP, &addr); |
hent = gethostbyname(_LOOKUP_FQDN); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", hent->h_name, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
if (0 != memcmp((void*)&addr, (void*)(hent->h_addr), sizeof(struct in_addr))) { |
diag_printf("FAIL:<expected " _LOOKUP_FQDN " to be " _LOOKUP_IP ">\n"); |
} |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_FQDN ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
/* Now just the hostname */ |
#ifdef USE_HARDCODED_DOMAIN |
// set the domain by hand if required. |
setdomainname(_LOOKUP_DOMAINNAME, sizeof(_LOOKUP_DOMAINNAME)); |
#endif //ifdef _LOOKUP_DOMAINNAME |
hent = gethostbyname(_LOOKUP_HOSTNAME); |
if (hent != NULL) { |
diag_printf("PASS:<%s is %s>\n", _LOOKUP_HOSTNAME, inet_ntoa(*(struct in_addr *)hent->h_addr)); |
} else { |
diag_printf("FAIL:<Asked for " _LOOKUP_HOSTNAME ". No answer: %s>\n", hstrerror(h_errno)); |
} |
|
CYG_TEST_FINISH("dns2 test completed"); |
} |
|
void |
cyg_start(void) |
{ |
// Create a main thread, so we can run the scheduler and have time 'pass' |
cyg_thread_create(10, // Priority - just a number |
dns_test, // entry |
0, // entry parameter |
"DNS test", // Name |
&stack[0], // Stack |
STACK_SIZE, // Size |
&thread_handle, // Handle |
&thread_data // Thread data structure |
); |
cyg_thread_resume(thread_handle); // Start it |
cyg_scheduler_start(); |
} |
|
#else // CYGPKG_NET_DHCP |
|
externC void |
cyg_start( void ) |
{ |
CYG_TEST_INIT(); |
|
CYG_TEST_NA("This test needs DHCP enabled"); |
} |
|
#endif |
/v2_0/include/dns_impl.inl
0,0 → 1,619
#ifndef CYGONCE_NS_DNS_DNS_IMPL_H |
#define CYGONCE_NS_DNS_DNS_IMPL_H |
//============================================================================= |
// |
// dns_impl.inl |
// |
// DNS client code implementation. |
// |
//============================================================================= |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//============================================================================= |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors:andrew.lunn, jskov |
// Date: 2001-09-18 |
// Description: The code is kept in this separate file to allow it to be |
// used from RedBoot. |
// |
//####DESCRIPTIONEND#### |
// |
//============================================================================= |
|
#include <cyg/ns/dns/dns_priv.h> |
|
/* Validate a hostname is legal as defined in RFC 1035 */ |
static int |
valid_hostname(const char *hostname) |
{ |
const char * label; |
const char * label_end; |
|
if (!hostname) { |
return false; |
} |
label = hostname; |
while (*label) { |
if (!isalpha(*label)) |
return false; |
label_end = strchr(label, (int)'.') - 1; |
if (label_end == (char *)-1) { |
label_end = strchr(label, (int)'\0') - 1; |
} |
while (label != label_end) { |
if (!isalnum(*label) && (*label != '-')) { |
return false; |
} |
label++; |
} |
label = label_end+1; /* Move onto the . or the null. */ |
if (*label == '.') { /* Move over the . if there is one */ |
label++; |
} |
} |
return true; |
} |
|
/* Build a qname structure. The structure consists of pairs of |
<len><label> where <label> is eg ma in tux.ma.tech.ascom.ch. len is |
the length of the label. */ |
static int |
build_qname(char *ptr, const char *hostname) |
{ |
const char *label = hostname; |
char *end_label; |
int total_len = 0; |
int len; |
|
while (*label) { |
end_label = strchr(label, (int)'.') - 1; |
if (end_label == (char *)-1) { |
end_label = strchr(label, (int)'\0') - 1; |
} |
len = end_label - label + 1; |
if (len > 63) { |
return -1; |
} |
*ptr++ = (char) len; /* Put the length of the label */ |
memcpy(ptr, label, len); /* and now the label */ |
ptr += len; |
|
total_len += len +1; |
label = end_label+1; /* Move onto the . or the null. */ |
if (*label == '.') { /* Move over the . if there is one */ |
label++; |
} |
} |
*ptr = 0; /* Add the last length of zero |
to mark the end */ |
return (total_len+1); |
} |
|
/* Given a pointer to a qname, find the length of the qname. This is |
the number of bytes needed to represent the qname, not the length |
of the name. A qname is terminated by either a 00, or a pointer |
into another qname. This pointer has the top two bits set. */ |
static int |
qname_len(unsigned char * qname) |
{ |
unsigned char * ptr = qname; |
|
while ((*ptr != 0) && ((*ptr & 0xc0) != 0xc0)) { |
ptr += *ptr + 1; |
} |
/* Pointers are two bytes */ |
if ((*ptr & 0xc0) == 0xc0) { |
ptr++; |
} |
ptr++; /* Skip over the trailing byte */ |
|
return (ptr - qname); |
} |
|
/* Build a real name from a qname. Alloc the memory needed and return |
it. Return NULL on error */ |
char * |
real_name(char *msg, unsigned char *qname) |
{ |
unsigned char * ptr = qname; |
char * name; |
char * label; |
int len = 0; |
int offset; |
|
/* First pass works out the length of the name */ |
while (*ptr != 0) { |
if ((*ptr & 0xc0) == 0xc0) { |
/* pointer to somewhere else. Follow the pointer */ |
offset = ((*ptr & 0x3f) << 8) | *(ptr+1); |
ptr = msg + offset; |
} else { |
len += *ptr + 1; |
ptr += *ptr + 1; |
} |
} |
|
/* Now allocate the memory needed and copy the host name into it */ |
name = alloc_string(len+1); |
if (name) { |
label = name; |
ptr = qname; |
while (*ptr != 0) { |
if ((*ptr & 0xc0) == 0xc0) { |
/* pointer to somewhere else. Follow the pointer */ |
offset = ((*ptr & 0x3f) << 8) | *(ptr+1); |
ptr = msg + offset; |
} else { |
len = *ptr; |
memcpy(label, (ptr+1), len); |
label += len; |
*label++ = '.'; |
ptr += *ptr + 1; |
} |
} |
*label = '\0'; |
} |
return name; |
} |
|
/* Build a query message which can be sent to the server. If something |
goes wrong return -1, otherwise the length of the query message */ |
static int |
build_query(char * msg, const char * hostname, short rr_type) |
{ |
struct dns_header *dns_hdr; |
char *ptr; |
int len; |
|
/* Fill out the header */ |
dns_hdr = (struct dns_header *) msg; |
dns_hdr->id = htons(id++); |
dns_hdr->rd = true; |
dns_hdr->opcode = DNS_QUERY; |
dns_hdr->qdcount = htons(1); |
|
/* Now the question we want to ask */ |
ptr = (char *)&dns_hdr[1]; |
|
len = build_qname(ptr, hostname); |
|
if (len < 0) { |
h_errno = NO_RECOVERY; |
return -1; |
} |
ptr += len; |
|
/* Set the type and class fields */ |
*ptr++ = (rr_type >> 8) & 0xff; |
*ptr++ = rr_type & 0xff; |
*ptr++ = (DNS_CLASS_IN >> 8) & 0xff; |
*ptr++ = DNS_CLASS_IN & 0xff; |
|
len = ptr - msg; |
|
return len; |
} |
|
/* Check if the hostname is actually of dot format. If so convert it |
and return host entity structure. If not, return NULL. */ |
static struct hostent * |
dot_hostname(const char *hostname) |
{ |
struct hostent *hent = NULL; |
struct in_addr addr; |
|
if (inet_aton(hostname, &addr)) { |
hent = alloc_hent(); |
if (hent) { |
memcpy(hent->h_addr_list[0], &addr, sizeof(struct in_addr)); |
hent->h_addrtype = AF_INET; |
hent->h_length = sizeof(struct in_addr); |
hent->h_name = alloc_string(strlen(hostname)+1); |
if (!hent->h_name) { |
free_hent(hent); |
return NULL; |
} |
strcpy(hent->h_name, hostname); |
} |
} |
return hent; |
} |
|
/* Decode the answer from the server. Returns NULL if failed, or |
a hostent structure containing different data depending on the |
query type: |
DNS_TYPE_A: |
h_name: a pointer to the hostname |
h_addr_list[0]: a pointer to in_addr structure |
DNS_TYPE_PTR: |
h_name: a pointer to the hostname |
h_addr_list[0]: a pointer to an empty in_addr structure. Caller |
must fill out! |
*/ |
static struct hostent * |
parse_answer(char * msg, short rr_type) |
{ |
static struct hostent *hent; |
struct dns_header *dns_hdr; |
struct resource_record rr, *rr_p = NULL; |
char *qname = NULL; |
char *ptr; |
|
dns_hdr = (struct dns_header *)msg; |
|
if (DNS_REPLY_NAME_ERROR == dns_hdr->rcode) { |
h_errno = HOST_NOT_FOUND; |
return NULL; |
} |
|
if ((dns_hdr->qr != 1) || |
(dns_hdr->opcode != DNS_QUERY) || |
(dns_hdr->rcode != DNS_REPLY_NOERR)) { |
h_errno = NO_RECOVERY; |
return NULL; |
} |
|
dns_hdr->ancount = ntohs(dns_hdr->ancount); |
dns_hdr->qdcount = ntohs(dns_hdr->qdcount); |
ptr = (char *)&dns_hdr[1]; |
|
/* Skip over the query section */ |
if (dns_hdr->qdcount > 0) { |
while (dns_hdr->qdcount) { |
ptr += qname_len(ptr); |
ptr += 4; /* skip type & class */ |
dns_hdr->qdcount--; |
} |
} |
/* Skip over the answers resource records to find an answer of the |
correct type. */ |
while (dns_hdr->ancount) { |
qname = ptr; |
ptr += qname_len(ptr); |
rr_p = (struct resource_record *)ptr; |
memcpy(&rr, ptr, sizeof(rr)); |
if ((rr.rr_type == htons(rr_type)) && |
(rr.class == htons(DNS_CLASS_IN))) { |
break; |
} |
ptr += sizeof(struct resource_record) - sizeof(rr.rdata) + ntohs(rr.rdlength); |
dns_hdr->ancount--; |
} |
|
/* If we found one. decode it */ |
if (dns_hdr->ancount > 0) { |
hent = alloc_hent(); |
if (!hent) |
return NULL; |
switch (rr_type) { |
case DNS_TYPE_A: |
hent->h_name = real_name(msg, qname); |
if (!hent->h_name) { |
free_hent(hent); |
return NULL; |
} |
memcpy(hent->h_addr_list[0], rr_p->rdata, sizeof(struct in_addr)); |
hent->h_addrtype = AF_INET; |
hent->h_length = sizeof(struct in_addr); |
return hent; |
case DNS_TYPE_PTR: |
hent->h_name = real_name(msg, rr_p->rdata); |
if (!hent->h_name) { |
free_hent(hent); |
return NULL; |
} |
hent->h_addrtype = AF_INET; |
hent->h_length = sizeof(struct in_addr); |
return hent; |
default: |
free_hent(hent); |
} |
} |
h_errno = NO_DATA; |
return NULL; |
} |
|
/* Given an address, find out the hostname. */ |
struct hostent * |
gethostbyaddr(const char *addr, int len, int type) |
{ |
unsigned char msg[MAXDNSMSGSIZE]; |
char hostname[40]; |
struct hostent * hent; |
|
CYG_REPORT_FUNCNAMETYPE( "gethostbyaddr", "returning %08x" ); |
CYG_REPORT_FUNCARG3( "addr=%08x, len=%d, type=%d", addr, len, type ); |
|
if ( !addr || 0 == len) { |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
CYG_CHECK_DATA_PTR( addr, "addr is not a valid pointer!" ); |
|
/* Has the socket to the DNS server been opened? */ |
if (s < 0) { |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* See if there is an answer to an old query. If so free the memory |
it uses. */ |
free_stored_hent(); |
|
/* Only IPv4 addresses accepted */ |
if ((type != AF_INET) || (len != sizeof(struct in_addr))) { |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
cyg_drv_mutex_lock(&dns_mutex); |
|
/* Build the 'hostname' we want to lookup. */ |
sprintf(hostname, "%d.%d.%d.%d.IN-ADDR.ARPA.", |
(unsigned char)addr[3], |
(unsigned char)addr[2], |
(unsigned char)addr[1], |
(unsigned char)addr[0]); |
|
memset(msg, 0, sizeof(msg)); |
|
/* Build a PTR type request using the hostname */ |
len = build_query(msg, hostname, DNS_TYPE_PTR); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Send the request and wait for an answer */ |
len = send_recv(msg, len, sizeof(msg)); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Fill in the missing address */ |
hent = parse_answer(msg, DNS_TYPE_PTR); |
if (hent) { |
memcpy(hent->h_addr_list[0], addr, sizeof(struct in_addr)); |
store_hent(hent); |
} |
cyg_drv_mutex_unlock(&dns_mutex); |
|
CYG_REPORT_RETVAL( hent ); |
return hent; |
} |
|
/* Given a hostname find out the IP address */ |
struct hostent * |
gethostbyname(const char * hostname) |
{ |
unsigned char msg[MAXDNSMSGSIZE]; |
char name[256]; |
struct hostent *hent; |
int len; |
|
CYG_REPORT_FUNCNAMETYPE( "gethostbyname", "returning %08x" ); |
CYG_REPORT_FUNCARG1( "hostname=%08x", hostname ); |
|
if ( !hostname ) { |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
CYG_CHECK_DATA_PTR( hostname, "hostname is not a valid pointer!" ); |
|
/* Has the socket to the DNS server been opened? */ |
if (s < 0) { |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* See if there is an answer to an old query. If so free the memory |
it uses */ |
free_stored_hent(); |
|
if (!valid_hostname(hostname)) { |
/* It could be a dot address */ |
hent = dot_hostname(hostname); |
store_hent(hent); |
CYG_REPORT_RETVAL( hent ); |
return hent; |
} |
|
cyg_drv_mutex_lock(&dns_mutex); |
|
/* First try the name as passed in */ |
memset(msg, 0, sizeof(msg)); |
len = build_query(msg, hostname, DNS_TYPE_A); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Send the query and wait for an answer */ |
len = send_recv(msg, len, sizeof(msg)); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Decode the answer */ |
hent = parse_answer(msg, DNS_TYPE_A); |
if (hent) { |
cyg_drv_mutex_unlock(&dns_mutex); |
store_hent(hent); |
CYG_REPORT_RETVAL( hent ); |
return hent; |
} |
|
/* If no match, try appending the domainname if we have one */ |
if (domainname) { |
if ((strlen(hostname) + strlen(domainname)) > 254) { |
h_errno = NO_RECOVERY; |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
strcpy(name, hostname); |
strcat(name, "."); |
strcat(name, domainname); |
|
memset(msg, 0, sizeof(msg)); |
len = build_query(msg, name, DNS_TYPE_A); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Send the query and wait for an answer */ |
len = send_recv(msg, len, sizeof(msg)); |
if (len < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( NULL ); |
return NULL; |
} |
|
/* Decode the answer */ |
hent = parse_answer(msg, DNS_TYPE_A); |
} |
|
cyg_drv_mutex_unlock(&dns_mutex); |
store_hent(hent); |
CYG_REPORT_RETVAL( hent ); |
return hent; |
} |
|
/* Set the domain names, as used by the DNS server */ |
int |
setdomainname(const char *name, size_t len) |
{ |
char * ptr; |
|
CYG_REPORT_FUNCNAMETYPE( "setdomainname", "returning %d" ); |
CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len ); |
|
if ((len < 0) || (len > 255)) { |
h_errno = NO_RECOVERY; |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
if (len != 0) { |
CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" ); |
ptr = alloc_string(len+1); |
if (!ptr) { |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
memcpy(ptr, name, len); |
ptr[len]=0; |
} else { |
ptr = NULL; |
} |
|
if (domainname) { |
free_string(domainname); |
} |
domainname = ptr; |
CYG_REPORT_RETVAL( 0 ); |
return 0; |
} |
|
/* Return the domain name as used by the DNS server */ |
int |
getdomainname(char *name, size_t len) |
{ |
CYG_REPORT_FUNCNAMETYPE( "getdomainname", "returning %d" ); |
CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len ); |
|
if ( !name || 0 == len) { |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
|
CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" ); |
|
/* No domainname set, return a 0 */ |
if (!domainname) { |
if (len == 0) { |
h_errno = HOST_NOT_FOUND; |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
name[0]='\0'; |
} else { |
if ((strlen(domainname) + 1) > len) { |
h_errno = NO_RECOVERY; |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
strncpy(name, domainname, len); |
} |
CYG_REPORT_RETVAL( 0 ); |
return 0; |
} |
|
int h_errno = DNS_SUCCESS; |
|
const char* |
hstrerror(int err) |
{ |
CYG_REPORT_FUNCNAMETYPE( "hstrerror", "returning %08x" ); |
CYG_REPORT_FUNCARG1( "err=%d", err ); |
|
switch (err) { |
case DNS_SUCCESS: |
return "No error"; |
case HOST_NOT_FOUND: |
return "No such host is known"; |
case TRY_AGAIN: |
return "Timeout"; |
case NO_RECOVERY: |
return "Server failure or invalid input"; |
case NO_DATA: |
return "No data for type"; |
default: |
return "Uknown error"; |
} |
} |
|
//----------------------------------------------------------------------------- |
#endif // CYGONCE_NS_DNS_DNS_IMPL_H |
// End of dns_impl.h |
/v2_0/include/dns.h
0,0 → 1,88
#ifndef CYGONCE_NS_DNS_DNS_H |
#define CYGONCE_NS_DNS_DNS_H |
//============================================================================= |
// |
// dns.h |
// |
// DNS client code. |
// |
//============================================================================= |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//============================================================================= |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors:andrew.lunn, jskov |
// Date: 2001-09-18 |
// |
//####DESCRIPTIONEND#### |
// |
//============================================================================= |
|
#include <network.h> |
#include <netinet/in.h> |
|
#ifndef _POSIX_SOURCE |
/* Initialise the DNS client with the address of the server */ |
externC int cyg_dns_res_init(struct in_addr *dns_server); |
externC int getdomainname(char *name, size_t len); |
externC int setdomainname(const char *name, size_t len); |
#endif |
|
// Host name / IP mapping |
struct hostent { |
char *h_name; /* official name of host */ |
char **h_aliases; /* alias list */ |
int h_addrtype; /* host address type */ |
int h_length; /* length of address */ |
char **h_addr_list; /* list of addresses */ |
}; |
#define h_addr h_addr_list[0] /* for backward compatibility */ |
|
externC struct hostent *gethostbyname(const char *host); |
externC struct hostent *gethostbyaddr(const char *addr, int len, int type); |
|
// Error reporting |
externC int h_errno; |
externC const char* hstrerror(int err); |
|
#define DNS_SUCCESS 0 |
#define HOST_NOT_FOUND 1 |
#define TRY_AGAIN 2 |
#define NO_RECOVERY 3 |
#define NO_DATA 4 |
|
//----------------------------------------------------------------------------- |
#endif // CYGONCE_NS_DNS_DNS_H |
// End of dns.h |
/v2_0/include/dns_priv.h
0,0 → 1,127
#ifndef CYGONCE_NS_DNS_DNS_PRIV_H |
#define CYGONCE_NS_DNS_DNS_PRIV_H |
//============================================================================= |
// |
// dns-priv.h |
// |
// Private DNS client definitions. |
// |
//============================================================================= |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//============================================================================= |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors:andrew.lunn, jskov |
// Date: 2001-09-18 |
// |
//####DESCRIPTIONEND#### |
// |
//============================================================================= |
|
struct dns_header { |
#if (CYG_BYTEORDER == CYG_LSBFIRST) |
unsigned id :16; /* query identification number */ |
/* fields in third byte */ |
unsigned rd :1; /* recursion desired */ |
unsigned tc :1; /* truncated message */ |
unsigned aa :1; /* authoritive answer */ |
unsigned opcode :4; /* purpose of message */ |
unsigned qr :1; /* response flag */ |
/* fields in fourth byte */ |
unsigned rcode :4; /* response code */ |
unsigned cd: 1; /* checking disabled by resolver */ |
unsigned ad: 1; /* authentic data from named */ |
unsigned unused :1; /* unused bits */ |
unsigned ra :1; /* recursion available */ |
/* remaining bytes */ |
unsigned qdcount :16; /* number of question entries */ |
unsigned ancount :16; /* number of answer entries */ |
unsigned nscount :16; /* number of authority entries */ |
unsigned arcount :16; /* number of resource entries */ |
#else |
unsigned id :16; /* query identification number */ |
/* fields in third byte */ |
unsigned qr :1; /* response flag */ |
unsigned opcode :4; /* purpose of message */ |
unsigned aa :1; /* authoritive answer */ |
unsigned tc :1; /* truncated message */ |
unsigned rd :1; /* recursion desired */ |
/* fields in fourth byte */ |
unsigned ra :1; /* recursion available */ |
unsigned unused :1; /* unused bits */ |
unsigned ad: 1; /* authentic data from named */ |
unsigned cd: 1; /* checking disabled by resolver */ |
unsigned rcode :4; /* response code */ |
/* remaining bytes */ |
unsigned qdcount :16; /* number of question entries */ |
unsigned ancount :16; /* number of answer entries */ |
unsigned nscount :16; /* number of authority entries */ |
unsigned arcount :16; /* number of resource entries */ |
#endif |
}; |
|
struct resource_record { |
unsigned rr_type : 16; /* Type of resourse */ |
unsigned class : 16; /* Class of resource */ |
unsigned ttl : 32; /* Time to live of this record */ |
unsigned rdlength: 16; /* Lenght of data to follow */ |
char rdata [2]; /* Resource DATA */ |
}; |
|
/* Opcodes */ |
#define DNS_QUERY 0 /* Standard query */ |
#define DNS_IQUERY 1 /* Inverse query */ |
#define DNS_STATUS 2 /* Name server status */ |
#define DNS_NOTIFY 4 /* Zone change notification */ |
#define DNS_UPDATE 5 /* Zone update message */ |
|
/* DNS TYPEs */ |
#define DNS_TYPE_A 1 /* Host address */ |
#define DNS_TYPE_NS 2 /* Authoritative name server */ |
#define DNS_TYPE_CNAME 5 /* Canonical name for an alias */ |
#define DNS_TYPE_PTR 12 /* Domain name pointer */ |
|
/* DNS CLASSs */ |
#define DNS_CLASS_IN 1 /* Internet */ |
|
/* DNS reply codes */ |
#define DNS_REPLY_NOERR 0 |
#define DNS_REPLY_NAME_ERROR 3 |
|
#define MAXDNSMSGSIZE 512 |
|
//----------------------------------------------------------------------------- |
#endif // CYGONCE_NS_DNS_DNS_PRIV_H |
// End of dns-priv.h |
/v2_0/doc/dns.sgml
0,0 → 1,118
<!-- {{{ Banner --> |
|
<!-- =============================================================== --> |
<!-- --> |
<!-- dns.sgml --> |
<!-- --> |
<!-- eCos TCP/IP Stacks --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- ####COPYRIGHTBEGIN#### --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. --> |
<!-- This material may be distributed only subject to the terms --> |
<!-- and conditions set forth in the Open Publication License, v1.0 --> |
<!-- or later (the latest version is presently available at --> |
<!-- http://www.opencontent.org/openpub/) --> |
<!-- Distribution of the work or derivative of the work in any --> |
<!-- standard (paper) book form is prohibited unless prior --> |
<!-- permission obtained from the copyright holder --> |
<!-- =============================================================== --> |
<!-- --> |
<!-- ####COPYRIGHTEND#### --> |
<!-- =============================================================== --> |
<!-- #####DESCRIPTIONBEGIN#### --> |
<!-- --> |
<!-- ####DESCRIPTIONEND#### --> |
<!-- =============================================================== --> |
|
<!-- }}} --> |
|
<PART ID="net-ns-dns"> |
<TITLE>DNS for eCos and RedBoot</TITLE> |
<PARTINTRO> |
<PARA> |
<productname>eCos</productname> and |
<productname>RedBoot</productname> |
can both use the DNS package to perform network name lookups. |
</PARA> |
</PARTINTRO> |
<CHAPTER id="net-ns-dns-api"> |
<TITLE>DNS</TITLE> |
<SECT1 id="net-ns-dns-api1"> |
<TITLE>DNS API</TITLE> |
<PARA>The DNS client uses the normal BSD API for performing lookups: |
<function>gethostbyname()</function> and |
<FUNCTION>gethostbyaddr()</FUNCTION>. |
</PARA> |
<PARA>There are a few restrictions:</PARA> |
<ITEMIZEDLIST> |
<LISTITEM> |
<PARA>Only IPv4 is supported, ie IPv6 addresses cannot be looked |
up.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>If the DNS server returns multiple authoritive records |
for a host name, the hostent will only contain a record for the |
first entry.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>The code has been made thread safe. ie multiple threads |
may call |
<FUNCTION>gethostbyname()</FUNCTION> |
without causing problems to the hostent structure returned. What |
is not safe is one thread using both |
<FUNCTION>gethostbyname()</FUNCTION> |
and |
<FUNCTION>gethostbyaddr()</FUNCTION>. |
A call to one will destroy the results from the previous call |
to the other function.</PARA> |
</LISTITEM> |
</ITEMIZEDLIST> |
<PARA>To initialise the DNS client the following function must be |
called:</PARA> |
<PROGRAMLISTING>#include <network.h> |
int cyg_dns_res_init(struct in_addr *dns_server)</PROGRAMLISTING> |
<PARA>where dns_server is the address of the DNS server |
the client should query. On Error this function returns -1, otherwise |
0 for success. If lookups are attemped before this function has |
been called, they will fail and return NULL.</PARA> |
|
<PARA>A default, hard coded, server may be specified in the CDL option |
<literal>CYGDAT_NS_DNS_DEFAULT_SERVER</literal>. The use of this is |
controlled by <literal>CYGPKG_NS_DNS_DEFAULT</literal>. If this is |
enabled, <literal>init_all_network_interfaces</literal> will |
initialize the resolver with the hard coded address. The DHCP client |
or user code my override this address by calling |
<literal>cyg_dns_res_init</literal> again. </PARA> |
|
<PARA>The DNS client understands the concepts of the target being |
in a domain. By default no domain will be used. Host name lookups |
should be for fully qualified names. The domain name can be set |
and retrieved using the functions: |
<funcsynopsis> |
<funcprototype> |
<funcdef>int <function>getdomainname</function></funcdef> |
<paramdef>char *<parameter>name</parameter></paramdef> |
<paramdef>size_t <parameter>len</parameter></paramdef> |
</funcprototype> |
<funcprototype> |
<funcdef>int <function>setdomainname</function></funcdef> |
<paramdef>const char *<parameter>name</parameter></paramdef> |
<paramdef>size_t <parameter>len</parameter></paramdef> |
</funcprototype> |
</funcsynopsis> |
</para> |
|
<PARA>Alternatively, a hard coded domain name can be set using CDL. |
The boolean <literal>CYGPKG_NS_DNS_DOMAINNAME</literal> enables this |
and the domain name is taken from |
<literal>CYGPKG_NS_DNS_DOMAINNAME_NAME</literal>.</PARA> |
|
<PARA>Once set, the DNS client will first perform a lookup with the domain |
name appended. If this fails it will then perform a second lookup |
without the appended domain name. </PARA> |
</SECT1> |
</CHAPTER> |
</PART> |
/v2_0/ChangeLog
0,0 → 1,238
2003-03-03 Jonathan Larmour <jifl@eCosCentric.com> |
|
* tests/dns1.c: Use BOOTP info where possible in preference to |
(likely incorrect!) hardcoded info. Use non-Red Hat test |
addresses. |
|
* tests/dns2.c: Use non-Red Hat test addresses. And don't check |
BOOTP-derived domainname as we don't know what it should be! |
|
2003-02-24 Jonathan Larmour <jifl@eCosCentric.com> |
|
* cdl/dns.cdl: Add doc link. |
|
2003-01-22 Jonathan Larmour <jifl@eCosCentric.com> |
|
* doc/dns.sgml: Use correct (and working!) docbook. |
|
2003-01-18 Jonathan Larmour <jifl@eCosCentric.com> |
|
* include/dns_impl.inl (setdomainname): define with const name |
argument. |
* include/dns.h: Ditto. |
* doc/dns.sgml: Document const in setdomainname proto here. |
|
2003-01-10 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* cdl/dns.cdl: Added the ability to hard code a domain name. |
Inspired by Motoya Kurotsu. |
* doc/dns.sgml: Documentation for this. |
|
2003-01-10 Motoya Kurotsu <kurotsu@allied-telesis.co.jp> |
|
* tests/dns2.c: Verify domain name from the DHCP server with |
_LOOKUP_DOMAINNAME, not _DNS_IP which is the address of the DNS |
server. |
|
2003-01-09 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* cdl/dns.cdl: Added the ability to hard code a DNS server |
address into the image which is used as the default. |
* doc/dns.sgml: Documentation for this. |
|
2002-10-18 Jonathan Larmour <jifl@eCosCentric.com> |
|
* cdl/dns.cdl: Move CYGBLD_ISO_DNS_HEADER requires in with |
CYGINT_ISO_DNS which is where it should always be beside. |
|
2002-10-11 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* cdl/dns.cdl: If CYGPKG_NS_DNS_BUILD is disable we don't |
implement the CYGINT_ISO_DNS interface. |
|
|
|
* include/dns_priv.h: Make dns_header structure endian dependent. |
|
* include/dns_impl.inl: Don't use htons() for bitfields <= 8 bit. |
Change the way setting the type and class fields in build_query() |
to work with big-endian. |
|
2002-05-30 Jesper Skov <jskov@redhat.com> |
|
* src/dns.c: fixed index->ptdindex oversight. |
|
2002-05-24 Jonathan Larmour <jlarmour@redhat.com> |
|
* src/dns.c (free_hent): Actually free hent itself! |
|
2002-05-23 Jonathan Larmour <jlarmour@redhat.com> |
|
* cdl/dns.cdl (CYGPKG_NS_DNS_BUILD): Require thread destructors in |
kernel. |
* include/dns_impl.inl: Instead of using cyg_thread_get_data |
and _set_data directly, instead use store_hent and free_stored_hent |
defined by includer. |
* src/dns.c: Define store_hent() and free_stored_hent() and make |
them use thread destructors thus fixing a memory leak. |
|
2002-05-14 Jesper Skov <jskov@redhat.com> |
|
* tests/dns2.c: Fix warning. |
|
2002-02-22 Hugo Tyson <hmt@redhat.com> |
|
* doc/dns.sgml: New file. Documentation separated from monolithic |
network component. |
|
2002-02-01 Gary Thomas <gthomas@redhat.com> |
|
* src/dns.c (cyg_dns_res_init): Need valid value for sin_len. |
|
2002-01-31 Jonathan Larmour <jlarmour@redhat.com> |
|
* cdl/dns.cdl: Don't build tests if no DNS! |
|
2001-12-06 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* src/dns.c (cyg_dns_res_init): Allow this to be called more than |
once. The DHCP client will do this when interfaces YoYo. |
Restarting requires closing the socket (if any) and freeing the |
per-thread-data slot number. |
|
* include/dns_impl.inl (setdomainname): Allow the name to be |
cleared. Check for NULL pointers variously before checking for |
valid pointer asserts. |
|
* tests/dns2.c: New file: Test the DNS configuration via DHCP. |
|
* tests/dns1.c: Initially clear the domainname. |
|
2001-11-29 Jonathan Larmour <jlarmour@redhat.com> |
|
* src/dns.c: Rename index -> ptdindex to avoid conflict with BSD |
index() function. |
* include/dns_impl.inl: Ditto. |
|
2001-09-28 Jesper Skov <jskov@redhat.com> |
|
* tests/dns1.c (_DNS_IP): Changed to IP used in farm. |
|
2001-09-27 Jesper Skov <jskov@redhat.com> |
|
* include/dns_priv.h: Added DNS_REPLY definitions. |
|
* include/dns_impl.inl: Handle NXDomain returns. |
|
* include/dns_impl.inl: Added tracing. |
* src/dns.c: Same. |
|
2001-09-26 Jesper Skov <jskov@redhat.com> |
|
* tests/dns1.c (dns_test): Use hstrerror instead of strerror. |
|
* include/dns.h: Added h_errno support. |
* include/dns_impl.inl: Use h_errno instead of errno. Added |
hstrerror(). Make hostname lookups before hostname.domainmain |
lookups. |
|
2001-09-25 Jesper Skov <jskov@redhat.com> |
|
* include/dns.h: Moved some more defs to.. |
* include/dns_priv.h: ...here. |
|
* src/dns-priv.h: [deleted] |
* include/dns_priv.h: [added] |
|
* tests/dns1.c: Include netdb.h instead of dns.h. |
|
* src/dns.c: Moved all DNS protocol functions into |
dns_impl.inl. Allow for RedBoot to share the implementation with a |
smaller overhead. |
* include/dns_impl.inl: Added. |
|
* cdl/dns.cdl: Moved compile statement and requirements into |
CYGPKG_NS_DNS_BUILD option which can be forced off by RedBoot. |
Moved headers to cyg/ns/dns. |
|
* src/dns.c (alloc_hent, free_hent, alloc_string, free_string): |
Added these wrapper functions for malloc/free calls - allow easier |
maintaining of cloned function in RedBoot which uses static |
variables for storage. Incidently removed a little code |
duplication. |
|
* include/dns.h: Only include exported information. |
* src/dns-priv.h: Everything else moved to this file. |
|
* cdl/dns.cdl: Added feature requirements and CYGINT_ISO_DNS |
magic. |
|
* include/dns.h: Renamed res_init to cyg_dns_res_init. |
* src/dns.c: Same. |
* tests/dns1.c: Same. |
|
* src/dns.c: Use drv_api mutex, removed some include statements. |
* include/dns.h: Provide hostent definition and function |
declarations. |
|
* tests/dns1.c: Use cambridge.redhat.com addresses. Changed to |
output PASS/FAIL. |
|
* src/dns.c (parse_answer): On PTR lookups, alloc space for |
in_addr, so caller can copy data there. Fix gethostbyaddr() to |
do so. |
Note that error values do not match gethostbyaddr(3). |
|
2001-09-20 Jesper Skov <jskov@redhat.com> |
|
* src/dns.c: More cosmetic changes, a few htons -> ntohs changes, |
reducing size of critical section a few places, rely on |
build_query setting errno, and set errno when getdomainname can't |
copy domain name out due to size limitation. |
|
2001-09-19 Jesper Skov <jskov@redhat.com> |
|
* tests/dns1.c (dns_test): Fix inet_aton check. |
* src/dns.c: A few comment and cosmetic changes. |
|
2001-09-18 Jesper Skov <jskov@redhat.com> |
|
* src/dns.c: Added DNS code contributed by Andrew Lunn |
<andrew.lunn@ascom.ch> |
* include/dns.h: Same. |
* tests/dns1.c: Same. |
|
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
/v2_0/src/dns.c
0,0 → 1,317
//============================================================================= |
// |
// dns.c |
// |
// DNS client code |
// |
//============================================================================= |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//============================================================================= |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors:andrew.lunn, jskov |
// Date: 2001-09-18 |
// Description: Provides DNS lookup as per RFC 1034/1035. |
// |
// Note: Does only support A and PTR lookups. Maybe add for other |
// types as well? |
// |
// parse_answer() only returns the first found record. |
// |
// Add tracing and assertions. |
// |
//####DESCRIPTIONEND#### |
// |
//============================================================================= |
|
#include <pkgconf/system.h> |
#ifdef CYGPKG_KERNEL |
# include <pkgconf/kernel.h> |
# include <cyg/kernel/kapi.h> |
#endif |
#include <cyg/hal/drv_api.h> |
#include <cyg/infra/cyg_type.h> |
#include <cyg/infra/cyg_trac.h> /* Tracing support */ |
|
#include <netdb.h> |
|
#include <sys/time.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <arpa/inet.h> |
|
#include <ctype.h> |
#include <unistd.h> |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
|
#include <cyg/ns/dns/dns_priv.h> |
|
static short id = 0; /* ID of the last query */ |
static int s = -1; /* Socket to the DNS server */ |
static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */ |
static cyg_ucount32 ptdindex; /* Index for the per thread data */ |
static char * domainname=NULL; /* Domain name used for queries */ |
|
/* Allocate space for string of length len. Return NULL on failure. */ |
static inline char* |
alloc_string(int len) |
{ |
return malloc(len); |
} |
|
static inline void |
free_string(char* s) |
{ |
free(s); |
} |
|
/* Deallocate the memory taken to hold a hent structure */ |
static void |
free_hent(struct hostent * hent) |
{ |
if (hent->h_name) { |
free_string(hent->h_name); |
} |
|
if (hent->h_addr_list) { |
int i = 0; |
while (hent->h_addr_list[i]) { |
free(hent->h_addr_list[i]); |
i++; |
} |
free(hent->h_addr_list); |
} |
free(hent); |
} |
|
/* Allocate hent structure with room for one in_addr. Returns NULL on |
failure. */ |
static struct hostent* |
alloc_hent(void) |
{ |
struct hostent *hent; |
|
hent = malloc(sizeof(struct hostent)); |
if (hent) { |
memset(hent, 0, sizeof(struct hostent)); |
hent->h_addr_list = malloc(sizeof(char *)*2); |
if (!hent->h_addr_list) { |
free_hent(hent); |
return NULL; |
} |
hent->h_addr_list[0] = malloc(sizeof(struct in_addr)); |
if (!hent->h_addr_list[0]) { |
free_hent(hent); |
return NULL; |
} |
hent->h_addr_list[1] = NULL; |
} |
|
return hent; |
} |
|
/* Thread destructor used to free stuff stored in per-thread data slot. */ |
static void |
thread_destructor(CYG_ADDRWORD data) |
{ |
struct hostent *hent; |
hent = (struct hostent *)cyg_thread_get_data(ptdindex); |
if (hent) |
free_hent(hent); |
return; |
data=data; |
} |
|
/* Store the hent away in the per-thread data. */ |
static void |
store_hent(struct hostent *hent) |
{ |
// Prevent memory leaks by setting a destructor to be |
// called on thread exit to free per-thread data. |
cyg_thread_add_destructor( &thread_destructor, 0 ); |
cyg_thread_set_data(ptdindex, (CYG_ADDRWORD)hent); |
} |
|
/* If there is an answer to an old query, free the memory it uses. */ |
static void |
free_stored_hent(void) |
{ |
struct hostent *hent; |
hent = (struct hostent *)cyg_thread_get_data(ptdindex); |
if (hent) { |
free_hent(hent); |
cyg_thread_set_data(ptdindex, (CYG_ADDRWORD)NULL); |
cyg_thread_rem_destructor( &thread_destructor, 0 ); |
} |
} |
|
/* Send the query to the server and read the response back. Return -1 |
if it fails, otherwise put the response back in msg and return the |
length of the response. */ |
static int |
send_recv(char * msg, int len, int msglen) |
{ |
struct dns_header *dns_hdr; |
struct timeval timeout; |
int finished = false; |
int backoff = 1; |
fd_set readfds; |
int written; |
int ret; |
|
CYG_REPORT_FUNCNAMETYPE( "send_recv", "returning %d" ); |
CYG_REPORT_FUNCARG3( "msg=%08x, len=%d, msglen", msg, len, msglen ); |
|
CYG_CHECK_DATA_PTR( msg, "msg is not a valid pointer!" ); |
|
dns_hdr = (struct dns_header *) msg; |
|
do { |
written = write(s, msg, len); |
if (written < 0) { |
ret = -1; |
break; |
} |
|
FD_ZERO(&readfds); |
FD_SET(s, &readfds); |
|
timeout.tv_sec = backoff; |
timeout.tv_usec = 0; |
backoff = backoff << 1; |
|
ret = select(s+1, &readfds, NULL, NULL, &timeout); |
if (ret < 0) { |
ret = -1; |
break; |
} |
/* Timeout */ |
if (ret == 0) { |
if (backoff > 16) { |
h_errno = TRY_AGAIN; |
ret = -1; |
break; |
} |
} |
if (ret == 1) { |
ret = read(s, msg, msglen); |
if (ret < 0) { |
ret = -1; |
break; |
} |
|
/* Reply to an old query. Ignore it */ |
if (ntohs(dns_hdr->id) != (id-1)) { |
continue; |
} |
finished = true; |
} |
} while (!finished); |
|
CYG_REPORT_RETVAL( ret ); |
|
return ret; |
} |
|
/* Include the DNS client implementation code */ |
#include <cyg/ns/dns/dns_impl.inl> |
|
/* Initialise the resolver. Open a socket and bind it to the address |
of the server. return -1 if something goes wrong, otherwise 0. If |
we are being called a second time we have to be careful to allow |
any ongoing lookups to finish before we close the socket and |
connect to a different DNS server. The danger here is that we may |
have to wait for upto 32 seconds if the DNS server is down. |
*/ |
int |
cyg_dns_res_init(struct in_addr *dns_server) |
{ |
struct sockaddr_in server; |
struct servent *sent; |
static int init =0; |
|
CYG_REPORT_FUNCNAMETYPE( "cyg_dns_res_init", "returning %d" ); |
CYG_REPORT_FUNCARG1( "dns_server=%08x", dns_server ); |
|
CYG_CHECK_DATA_PTR( dns_server, "dns_server is not a valid pointer!" ); |
|
if (init) { |
cyg_drv_mutex_lock(&dns_mutex); |
cyg_thread_free_data_index(ptdindex); |
if (s >= 0) { |
close(s); |
} |
} else { |
init = 1; |
cyg_drv_mutex_init(&dns_mutex); |
cyg_drv_mutex_lock(&dns_mutex); |
} |
|
|
s = socket(PF_INET, SOCK_DGRAM, 0); |
if (s < 0) { |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
|
sent = getservbyname("domain", "udp"); |
if (sent == (struct servent *)0) { |
s = -1; |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
|
memcpy((char *)&server.sin_addr, dns_server, sizeof(server.sin_addr)); |
server.sin_port = sent->s_port; |
server.sin_family = AF_INET; |
server.sin_len = sizeof(server); |
|
if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) { |
s = -1; |
cyg_drv_mutex_unlock(&dns_mutex); |
CYG_REPORT_RETVAL( -1 ); |
return -1; |
} |
ptdindex = cyg_thread_new_data_index(); |
|
cyg_drv_mutex_unlock(&dns_mutex); |
|
CYG_REPORT_RETVAL( 0 ); |
return 0; |
} |