OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [ns/] [dns/] [v2_0/] [include/] [dns_impl.inl] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
#ifndef CYGONCE_NS_DNS_DNS_IMPL_H
#ifndef CYGONCE_NS_DNS_DNS_IMPL_H
#define CYGONCE_NS_DNS_DNS_IMPL_H
#define CYGONCE_NS_DNS_DNS_IMPL_H
//=============================================================================
//=============================================================================
//
//
//      dns_impl.inl
//      dns_impl.inl
//
//
//      DNS client code implementation.
//      DNS client code implementation.
//
//
//=============================================================================
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
//
// eCos is free software; you can redistribute it and/or modify it under
// 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
// 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.
// 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
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
//
// As a special exception, if other files instantiate templates or use macros
// 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
// 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
// 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
// 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
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
// 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 exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
// this file might be covered by the GNU General Public License.
//
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//=============================================================================
//#####DESCRIPTIONBEGIN####
//#####DESCRIPTIONBEGIN####
//
//
// Author(s):   andrew.lunn
// Author(s):   andrew.lunn
// Contributors:andrew.lunn, jskov
// Contributors:andrew.lunn, jskov
// Date:        2001-09-18
// Date:        2001-09-18
// Description: The code is kept in this separate file to allow it to be
// Description: The code is kept in this separate file to allow it to be
//              used from RedBoot.
//              used from RedBoot.
//
//
//####DESCRIPTIONEND####
//####DESCRIPTIONEND####
//
//
//=============================================================================
//=============================================================================
#include 
#include 
/* Validate a hostname is legal as defined in RFC 1035 */
/* Validate a hostname is legal as defined in RFC 1035 */
static int
static int
valid_hostname(const char *hostname)
valid_hostname(const char *hostname)
{
{
    const char * label;
    const char * label;
    const char * label_end;
    const char * label_end;
    if (!hostname) {
    if (!hostname) {
        return false;
        return false;
    }
    }
    label = hostname;
    label = hostname;
    while (*label) {
    while (*label) {
        if (!isalpha(*label))
        if (!isalpha(*label))
            return false;
            return false;
        label_end = strchr(label, (int)'.') - 1;
        label_end = strchr(label, (int)'.') - 1;
        if (label_end == (char *)-1) {
        if (label_end == (char *)-1) {
            label_end = strchr(label, (int)'\0') - 1;
            label_end = strchr(label, (int)'\0') - 1;
        }
        }
        while (label != label_end) {
        while (label != label_end) {
            if (!isalnum(*label) && (*label != '-')) {
            if (!isalnum(*label) && (*label != '-')) {
                return false;
                return false;
            }
            }
            label++;
            label++;
        }
        }
        label = label_end+1;            /* Move onto the . or the null. */
        label = label_end+1;            /* Move onto the . or the null. */
        if (*label == '.') {            /* Move over the . if there is one */
        if (*label == '.') {            /* Move over the . if there is one */
            label++;
            label++;
        }
        }
    }
    }
    return true;
    return true;
}
}
/* Build a qname structure. The structure consists of pairs of
/* Build a qname structure. The structure consists of pairs of
   
   
   the length of the label. */
   the length of the label. */
static int
static int
build_qname(char *ptr, const char *hostname)
build_qname(char *ptr, const char *hostname)
{
{
    const char *label = hostname;
    const char *label = hostname;
    char *end_label;
    char *end_label;
    int total_len = 0;
    int total_len = 0;
    int len;
    int len;
    while (*label) {
    while (*label) {
        end_label = strchr(label, (int)'.') - 1;
        end_label = strchr(label, (int)'.') - 1;
        if (end_label == (char *)-1) {
        if (end_label == (char *)-1) {
            end_label = strchr(label, (int)'\0') - 1;
            end_label = strchr(label, (int)'\0') - 1;
        }
        }
        len = end_label - label + 1;
        len = end_label - label + 1;
        if (len > 63) {
        if (len > 63) {
            return -1;
            return -1;
        }
        }
        *ptr++ = (char) len;            /* Put the length of the label */
        *ptr++ = (char) len;            /* Put the length of the label */
        memcpy(ptr, label, len);        /* and now the label */
        memcpy(ptr, label, len);        /* and now the label */
        ptr += len;
        ptr += len;
        total_len += len +1;
        total_len += len +1;
        label = end_label+1;            /* Move onto the . or the null. */
        label = end_label+1;            /* Move onto the . or the null. */
        if (*label == '.') {            /* Move over the . if there is one */
        if (*label == '.') {            /* Move over the . if there is one */
            label++;
            label++;
        }
        }
    }
    }
    *ptr = 0;                           /* Add the last length of zero
    *ptr = 0;                           /* Add the last length of zero
                                           to mark the end */
                                           to mark the end */
    return (total_len+1);
    return (total_len+1);
}
}
/* Given a pointer to a qname, find the length of the qname. This is
/* 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
   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
   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. */
   into another qname. This pointer has the top two bits set. */
static int
static int
qname_len(unsigned char * qname)
qname_len(unsigned char * qname)
{
{
    unsigned char * ptr = qname;
    unsigned char * ptr = qname;
    while ((*ptr != 0) && ((*ptr & 0xc0) != 0xc0)) {
    while ((*ptr != 0) && ((*ptr & 0xc0) != 0xc0)) {
        ptr += *ptr + 1;
        ptr += *ptr + 1;
    }
    }
    /* Pointers are two bytes */
    /* Pointers are two bytes */
    if ((*ptr & 0xc0) == 0xc0) {
    if ((*ptr & 0xc0) == 0xc0) {
        ptr++;
        ptr++;
    }
    }
    ptr++;                              /* Skip over the trailing byte */
    ptr++;                              /* Skip over the trailing byte */
    return (ptr - qname);
    return (ptr - qname);
}
}
/* Build a real name from a qname. Alloc the memory needed and return
/* Build a real name from a qname. Alloc the memory needed and return
   it. Return NULL on error */
   it. Return NULL on error */
char *
char *
real_name(char *msg, unsigned char *qname)
real_name(char *msg, unsigned char *qname)
{
{
    unsigned char * ptr = qname;
    unsigned char * ptr = qname;
    char * name;
    char * name;
    char * label;
    char * label;
    int len = 0;
    int len = 0;
    int offset;
    int offset;
    /* First pass works out the length of the name */
    /* First pass works out the length of the name */
    while (*ptr != 0) {
    while (*ptr != 0) {
        if ((*ptr & 0xc0) == 0xc0) {
        if ((*ptr & 0xc0) == 0xc0) {
            /* pointer to somewhere else. Follow the pointer */
            /* pointer to somewhere else. Follow the pointer */
            offset = ((*ptr & 0x3f) << 8) | *(ptr+1);
            offset = ((*ptr & 0x3f) << 8) | *(ptr+1);
            ptr = msg + offset;
            ptr = msg + offset;
        } else {
        } else {
            len += *ptr + 1;
            len += *ptr + 1;
            ptr += *ptr + 1;
            ptr += *ptr + 1;
        }
        }
    }
    }
    /* Now allocate the memory needed and copy the host name into it */
    /* Now allocate the memory needed and copy the host name into it */
    name = alloc_string(len+1);
    name = alloc_string(len+1);
    if (name) {
    if (name) {
        label = name;
        label = name;
        ptr = qname;
        ptr = qname;
        while (*ptr != 0) {
        while (*ptr != 0) {
            if ((*ptr & 0xc0) == 0xc0) {
            if ((*ptr & 0xc0) == 0xc0) {
                /* pointer to somewhere else. Follow the pointer */
                /* pointer to somewhere else. Follow the pointer */
                offset = ((*ptr & 0x3f) << 8) | *(ptr+1);
                offset = ((*ptr & 0x3f) << 8) | *(ptr+1);
                ptr = msg + offset;
                ptr = msg + offset;
            } else {
            } else {
                len = *ptr;
                len = *ptr;
                memcpy(label, (ptr+1), len);
                memcpy(label, (ptr+1), len);
                label += len;
                label += len;
                *label++ = '.';
                *label++ = '.';
                ptr += *ptr + 1;
                ptr += *ptr + 1;
            }
            }
        }
        }
        *label = '\0';
        *label = '\0';
    }
    }
    return name;
    return name;
}
}
/* Build a query message which can be sent to the server. If something
/* Build a query message which can be sent to the server. If something
   goes wrong return -1, otherwise the length of the query message */
   goes wrong return -1, otherwise the length of the query message */
static int
static int
build_query(char * msg, const char * hostname, short rr_type)
build_query(char * msg, const char * hostname, short rr_type)
{
{
    struct dns_header *dns_hdr;
    struct dns_header *dns_hdr;
    char *ptr;
    char *ptr;
    int len;
    int len;
    /* Fill out the header */
    /* Fill out the header */
    dns_hdr = (struct dns_header *) msg;
    dns_hdr = (struct dns_header *) msg;
    dns_hdr->id = htons(id++);
    dns_hdr->id = htons(id++);
    dns_hdr->rd = true;
    dns_hdr->rd = true;
    dns_hdr->opcode = DNS_QUERY;
    dns_hdr->opcode = DNS_QUERY;
    dns_hdr->qdcount = htons(1);
    dns_hdr->qdcount = htons(1);
    /* Now the question we want to ask */
    /* Now the question we want to ask */
    ptr = (char *)&dns_hdr[1];
    ptr = (char *)&dns_hdr[1];
    len = build_qname(ptr, hostname);
    len = build_qname(ptr, hostname);
    if (len < 0) {
    if (len < 0) {
        h_errno = NO_RECOVERY;
        h_errno = NO_RECOVERY;
        return -1;
        return -1;
    }
    }
    ptr += len;
    ptr += len;
    /* Set the type and class fields */
    /* Set the type and class fields */
    *ptr++ = (rr_type >> 8) & 0xff;
    *ptr++ = (rr_type >> 8) & 0xff;
    *ptr++ = rr_type & 0xff;
    *ptr++ = rr_type & 0xff;
    *ptr++ = (DNS_CLASS_IN >> 8) & 0xff;
    *ptr++ = (DNS_CLASS_IN >> 8) & 0xff;
    *ptr++ = DNS_CLASS_IN & 0xff;
    *ptr++ = DNS_CLASS_IN & 0xff;
    len = ptr - msg;
    len = ptr - msg;
    return len;
    return len;
}
}
/* Check if the hostname is actually of dot format. If so convert it
/* Check if the hostname is actually of dot format. If so convert it
   and return host entity structure. If not, return NULL. */
   and return host entity structure. If not, return NULL. */
static struct hostent *
static struct hostent *
dot_hostname(const char *hostname)
dot_hostname(const char *hostname)
{
{
    struct hostent *hent = NULL;
    struct hostent *hent = NULL;
    struct in_addr addr;
    struct in_addr addr;
    if (inet_aton(hostname, &addr)) {
    if (inet_aton(hostname, &addr)) {
        hent = alloc_hent();
        hent = alloc_hent();
        if (hent) {
        if (hent) {
            memcpy(hent->h_addr_list[0], &addr, sizeof(struct in_addr));
            memcpy(hent->h_addr_list[0], &addr, sizeof(struct in_addr));
            hent->h_addrtype = AF_INET;
            hent->h_addrtype = AF_INET;
            hent->h_length = sizeof(struct in_addr);
            hent->h_length = sizeof(struct in_addr);
            hent->h_name = alloc_string(strlen(hostname)+1);
            hent->h_name = alloc_string(strlen(hostname)+1);
            if (!hent->h_name) {
            if (!hent->h_name) {
                free_hent(hent);
                free_hent(hent);
                return NULL;
                return NULL;
            }
            }
            strcpy(hent->h_name, hostname);
            strcpy(hent->h_name, hostname);
        }
        }
    }
    }
    return hent;
    return hent;
}
}
/* Decode the answer from the server. Returns NULL if failed, or
/* Decode the answer from the server. Returns NULL if failed, or
   a hostent structure containing different data depending on the
   a hostent structure containing different data depending on the
   query type:
   query type:
    DNS_TYPE_A:
    DNS_TYPE_A:
      h_name:         a pointer to the hostname
      h_name:         a pointer to the hostname
      h_addr_list[0]: a pointer to in_addr structure
      h_addr_list[0]: a pointer to in_addr structure
    DNS_TYPE_PTR:
    DNS_TYPE_PTR:
      h_name:         a pointer to the hostname
      h_name:         a pointer to the hostname
      h_addr_list[0]: a pointer to an empty in_addr structure. Caller
      h_addr_list[0]: a pointer to an empty in_addr structure. Caller
                      must fill out!
                      must fill out!
*/
*/
static struct hostent *
static struct hostent *
parse_answer(char * msg, short rr_type)
parse_answer(char * msg, short rr_type)
{
{
    static struct hostent *hent;
    static struct hostent *hent;
    struct dns_header *dns_hdr;
    struct dns_header *dns_hdr;
    struct resource_record rr, *rr_p = NULL;
    struct resource_record rr, *rr_p = NULL;
    char *qname = NULL;
    char *qname = NULL;
    char *ptr;
    char *ptr;
    dns_hdr = (struct dns_header *)msg;
    dns_hdr = (struct dns_header *)msg;
    if (DNS_REPLY_NAME_ERROR == dns_hdr->rcode) {
    if (DNS_REPLY_NAME_ERROR == dns_hdr->rcode) {
        h_errno = HOST_NOT_FOUND;
        h_errno = HOST_NOT_FOUND;
        return NULL;
        return NULL;
    }
    }
    if ((dns_hdr->qr != 1) ||
    if ((dns_hdr->qr != 1) ||
        (dns_hdr->opcode != DNS_QUERY) ||
        (dns_hdr->opcode != DNS_QUERY) ||
        (dns_hdr->rcode != DNS_REPLY_NOERR)) {
        (dns_hdr->rcode != DNS_REPLY_NOERR)) {
        h_errno = NO_RECOVERY;
        h_errno = NO_RECOVERY;
        return NULL;
        return NULL;
    }
    }
    dns_hdr->ancount = ntohs(dns_hdr->ancount);
    dns_hdr->ancount = ntohs(dns_hdr->ancount);
    dns_hdr->qdcount = ntohs(dns_hdr->qdcount);
    dns_hdr->qdcount = ntohs(dns_hdr->qdcount);
    ptr = (char *)&dns_hdr[1];
    ptr = (char *)&dns_hdr[1];
    /* Skip over the query section */
    /* Skip over the query section */
    if (dns_hdr->qdcount > 0) {
    if (dns_hdr->qdcount > 0) {
        while (dns_hdr->qdcount) {
        while (dns_hdr->qdcount) {
            ptr += qname_len(ptr);
            ptr += qname_len(ptr);
            ptr += 4;                   /* skip type & class */
            ptr += 4;                   /* skip type & class */
            dns_hdr->qdcount--;
            dns_hdr->qdcount--;
        }
        }
    }
    }
    /* Skip over the answers resource records to find an answer of the
    /* Skip over the answers resource records to find an answer of the
       correct type. */
       correct type. */
    while (dns_hdr->ancount) {
    while (dns_hdr->ancount) {
        qname = ptr;
        qname = ptr;
        ptr += qname_len(ptr);
        ptr += qname_len(ptr);
        rr_p = (struct resource_record *)ptr;
        rr_p = (struct resource_record *)ptr;
        memcpy(&rr, ptr, sizeof(rr));
        memcpy(&rr, ptr, sizeof(rr));
        if ((rr.rr_type == htons(rr_type)) &&
        if ((rr.rr_type == htons(rr_type)) &&
            (rr.class == htons(DNS_CLASS_IN))) {
            (rr.class == htons(DNS_CLASS_IN))) {
            break;
            break;
        }
        }
        ptr += sizeof(struct resource_record) - sizeof(rr.rdata) + ntohs(rr.rdlength);
        ptr += sizeof(struct resource_record) - sizeof(rr.rdata) + ntohs(rr.rdlength);
        dns_hdr->ancount--;
        dns_hdr->ancount--;
    }
    }
    /* If we found one. decode it */
    /* If we found one. decode it */
    if (dns_hdr->ancount > 0) {
    if (dns_hdr->ancount > 0) {
        hent = alloc_hent();
        hent = alloc_hent();
        if (!hent)
        if (!hent)
            return NULL;
            return NULL;
        switch (rr_type) {
        switch (rr_type) {
        case DNS_TYPE_A:
        case DNS_TYPE_A:
            hent->h_name = real_name(msg, qname);
            hent->h_name = real_name(msg, qname);
            if (!hent->h_name) {
            if (!hent->h_name) {
                free_hent(hent);
                free_hent(hent);
                return NULL;
                return NULL;
            }
            }
            memcpy(hent->h_addr_list[0], rr_p->rdata, sizeof(struct in_addr));
            memcpy(hent->h_addr_list[0], rr_p->rdata, sizeof(struct in_addr));
            hent->h_addrtype = AF_INET;
            hent->h_addrtype = AF_INET;
            hent->h_length = sizeof(struct in_addr);
            hent->h_length = sizeof(struct in_addr);
            return hent;
            return hent;
        case DNS_TYPE_PTR:
        case DNS_TYPE_PTR:
            hent->h_name = real_name(msg, rr_p->rdata);
            hent->h_name = real_name(msg, rr_p->rdata);
            if (!hent->h_name) {
            if (!hent->h_name) {
                free_hent(hent);
                free_hent(hent);
                return NULL;
                return NULL;
            }
            }
            hent->h_addrtype = AF_INET;
            hent->h_addrtype = AF_INET;
            hent->h_length = sizeof(struct in_addr);
            hent->h_length = sizeof(struct in_addr);
            return hent;
            return hent;
        default:
        default:
            free_hent(hent);
            free_hent(hent);
        }
        }
    }
    }
    h_errno = NO_DATA;
    h_errno = NO_DATA;
    return NULL;
    return NULL;
}
}
/* Given an address, find out the hostname. */
/* Given an address, find out the hostname. */
struct hostent *
struct hostent *
gethostbyaddr(const char *addr, int len, int type)
gethostbyaddr(const char *addr, int len, int type)
{
{
    unsigned char msg[MAXDNSMSGSIZE];
    unsigned char msg[MAXDNSMSGSIZE];
    char hostname[40];
    char hostname[40];
    struct hostent * hent;
    struct hostent * hent;
    CYG_REPORT_FUNCNAMETYPE( "gethostbyaddr", "returning %08x" );
    CYG_REPORT_FUNCNAMETYPE( "gethostbyaddr", "returning %08x" );
    CYG_REPORT_FUNCARG3( "addr=%08x, len=%d, type=%d", addr, len, type );
    CYG_REPORT_FUNCARG3( "addr=%08x, len=%d, type=%d", addr, len, type );
    if ( !addr || 0 == len) {
    if ( !addr || 0 == len) {
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    CYG_CHECK_DATA_PTR( addr, "addr is not a valid pointer!" );
    CYG_CHECK_DATA_PTR( addr, "addr is not a valid pointer!" );
    /* Has the socket to the DNS server been opened? */
    /* Has the socket to the DNS server been opened? */
    if (s < 0) {
    if (s < 0) {
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* See if there is an answer to an old query. If so free the memory
    /* See if there is an answer to an old query. If so free the memory
       it uses. */
       it uses. */
    free_stored_hent();
    free_stored_hent();
    /* Only IPv4 addresses accepted */
    /* Only IPv4 addresses accepted */
    if ((type != AF_INET) || (len != sizeof(struct in_addr))) {
    if ((type != AF_INET) || (len != sizeof(struct in_addr))) {
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    cyg_drv_mutex_lock(&dns_mutex);
    cyg_drv_mutex_lock(&dns_mutex);
    /* Build the 'hostname' we want to lookup. */
    /* Build the 'hostname' we want to lookup. */
    sprintf(hostname, "%d.%d.%d.%d.IN-ADDR.ARPA.",
    sprintf(hostname, "%d.%d.%d.%d.IN-ADDR.ARPA.",
            (unsigned char)addr[3],
            (unsigned char)addr[3],
            (unsigned char)addr[2],
            (unsigned char)addr[2],
            (unsigned char)addr[1],
            (unsigned char)addr[1],
            (unsigned char)addr[0]);
            (unsigned char)addr[0]);
    memset(msg, 0, sizeof(msg));
    memset(msg, 0, sizeof(msg));
    /* Build a PTR type request using the hostname */
    /* Build a PTR type request using the hostname */
    len = build_query(msg, hostname, DNS_TYPE_PTR);
    len = build_query(msg, hostname, DNS_TYPE_PTR);
    if (len < 0) {
    if (len < 0) {
        cyg_drv_mutex_unlock(&dns_mutex);
        cyg_drv_mutex_unlock(&dns_mutex);
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* Send the request and wait for an answer */
    /* Send the request and wait for an answer */
    len = send_recv(msg, len, sizeof(msg));
    len = send_recv(msg, len, sizeof(msg));
    if (len < 0) {
    if (len < 0) {
        cyg_drv_mutex_unlock(&dns_mutex);
        cyg_drv_mutex_unlock(&dns_mutex);
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* Fill in the missing address */
    /* Fill in the missing address */
    hent = parse_answer(msg, DNS_TYPE_PTR);
    hent = parse_answer(msg, DNS_TYPE_PTR);
    if (hent) {
    if (hent) {
        memcpy(hent->h_addr_list[0], addr, sizeof(struct in_addr));
        memcpy(hent->h_addr_list[0], addr, sizeof(struct in_addr));
        store_hent(hent);
        store_hent(hent);
    }
    }
    cyg_drv_mutex_unlock(&dns_mutex);
    cyg_drv_mutex_unlock(&dns_mutex);
    CYG_REPORT_RETVAL( hent );
    CYG_REPORT_RETVAL( hent );
    return hent;
    return hent;
}
}
/* Given a hostname find out the IP address */
/* Given a hostname find out the IP address */
struct hostent *
struct hostent *
gethostbyname(const char * hostname)
gethostbyname(const char * hostname)
{
{
    unsigned char msg[MAXDNSMSGSIZE];
    unsigned char msg[MAXDNSMSGSIZE];
    char name[256];
    char name[256];
    struct hostent *hent;
    struct hostent *hent;
    int len;
    int len;
    CYG_REPORT_FUNCNAMETYPE( "gethostbyname", "returning %08x" );
    CYG_REPORT_FUNCNAMETYPE( "gethostbyname", "returning %08x" );
    CYG_REPORT_FUNCARG1( "hostname=%08x", hostname );
    CYG_REPORT_FUNCARG1( "hostname=%08x", hostname );
    if ( !hostname ) {
    if ( !hostname ) {
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    CYG_CHECK_DATA_PTR( hostname, "hostname is not a valid pointer!" );
    CYG_CHECK_DATA_PTR( hostname, "hostname is not a valid pointer!" );
    /* Has the socket to the DNS server been opened? */
    /* Has the socket to the DNS server been opened? */
    if (s < 0) {
    if (s < 0) {
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* See if there is an answer to an old query. If so free the memory
    /* See if there is an answer to an old query. If so free the memory
       it uses */
       it uses */
    free_stored_hent();
    free_stored_hent();
    if (!valid_hostname(hostname)) {
    if (!valid_hostname(hostname)) {
        /* It could be a dot address */
        /* It could be a dot address */
        hent = dot_hostname(hostname);
        hent = dot_hostname(hostname);
        store_hent(hent);
        store_hent(hent);
        CYG_REPORT_RETVAL( hent );
        CYG_REPORT_RETVAL( hent );
        return hent;
        return hent;
    }
    }
    cyg_drv_mutex_lock(&dns_mutex);
    cyg_drv_mutex_lock(&dns_mutex);
    /* First try the name as passed in */
    /* First try the name as passed in */
    memset(msg, 0, sizeof(msg));
    memset(msg, 0, sizeof(msg));
    len = build_query(msg, hostname, DNS_TYPE_A);
    len = build_query(msg, hostname, DNS_TYPE_A);
    if (len < 0) {
    if (len < 0) {
        cyg_drv_mutex_unlock(&dns_mutex);
        cyg_drv_mutex_unlock(&dns_mutex);
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* Send the query and wait for an answer */
    /* Send the query and wait for an answer */
    len = send_recv(msg, len, sizeof(msg));
    len = send_recv(msg, len, sizeof(msg));
    if (len < 0) {
    if (len < 0) {
        cyg_drv_mutex_unlock(&dns_mutex);
        cyg_drv_mutex_unlock(&dns_mutex);
        CYG_REPORT_RETVAL( NULL );
        CYG_REPORT_RETVAL( NULL );
        return NULL;
        return NULL;
    }
    }
    /* Decode the answer */
    /* Decode the answer */
    hent = parse_answer(msg, DNS_TYPE_A);
    hent = parse_answer(msg, DNS_TYPE_A);
    if (hent) {
    if (hent) {
        cyg_drv_mutex_unlock(&dns_mutex);
        cyg_drv_mutex_unlock(&dns_mutex);
        store_hent(hent);
        store_hent(hent);
        CYG_REPORT_RETVAL( hent );
        CYG_REPORT_RETVAL( hent );
        return hent;
        return hent;
    }
    }
    /* If no match, try appending the domainname if we have one */
    /* If no match, try appending the domainname if we have one */
    if (domainname) {
    if (domainname) {
        if ((strlen(hostname) + strlen(domainname)) > 254) {
        if ((strlen(hostname) + strlen(domainname)) > 254) {
            h_errno = NO_RECOVERY;
            h_errno = NO_RECOVERY;
            cyg_drv_mutex_unlock(&dns_mutex);
            cyg_drv_mutex_unlock(&dns_mutex);
            CYG_REPORT_RETVAL( NULL );
            CYG_REPORT_RETVAL( NULL );
            return NULL;
            return NULL;
        }
        }
        strcpy(name, hostname);
        strcpy(name, hostname);
        strcat(name, ".");
        strcat(name, ".");
        strcat(name, domainname);
        strcat(name, domainname);
        memset(msg, 0, sizeof(msg));
        memset(msg, 0, sizeof(msg));
        len = build_query(msg, name, DNS_TYPE_A);
        len = build_query(msg, name, DNS_TYPE_A);
        if (len < 0) {
        if (len < 0) {
            cyg_drv_mutex_unlock(&dns_mutex);
            cyg_drv_mutex_unlock(&dns_mutex);
            CYG_REPORT_RETVAL( NULL );
            CYG_REPORT_RETVAL( NULL );
            return NULL;
            return NULL;
        }
        }
        /* Send the query and wait for an answer */
        /* Send the query and wait for an answer */
        len = send_recv(msg, len, sizeof(msg));
        len = send_recv(msg, len, sizeof(msg));
        if (len < 0) {
        if (len < 0) {
            cyg_drv_mutex_unlock(&dns_mutex);
            cyg_drv_mutex_unlock(&dns_mutex);
            CYG_REPORT_RETVAL( NULL );
            CYG_REPORT_RETVAL( NULL );
            return NULL;
            return NULL;
        }
        }
        /* Decode the answer */
        /* Decode the answer */
        hent = parse_answer(msg, DNS_TYPE_A);
        hent = parse_answer(msg, DNS_TYPE_A);
    }
    }
    cyg_drv_mutex_unlock(&dns_mutex);
    cyg_drv_mutex_unlock(&dns_mutex);
    store_hent(hent);
    store_hent(hent);
    CYG_REPORT_RETVAL( hent );
    CYG_REPORT_RETVAL( hent );
    return hent;
    return hent;
}
}
/* Set the domain names, as used by the DNS server */
/* Set the domain names, as used by the DNS server */
int
int
setdomainname(const char *name, size_t len)
setdomainname(const char *name, size_t len)
{
{
    char * ptr;
    char * ptr;
    CYG_REPORT_FUNCNAMETYPE( "setdomainname", "returning %d" );
    CYG_REPORT_FUNCNAMETYPE( "setdomainname", "returning %d" );
    CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len );
    CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len );
    if ((len < 0) || (len > 255)) {
    if ((len < 0) || (len > 255)) {
        h_errno = NO_RECOVERY;
        h_errno = NO_RECOVERY;
        CYG_REPORT_RETVAL( -1 );
        CYG_REPORT_RETVAL( -1 );
        return -1;
        return -1;
    }
    }
    if (len != 0) {
    if (len != 0) {
        CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" );
        CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" );
        ptr = alloc_string(len+1);
        ptr = alloc_string(len+1);
        if (!ptr) {
        if (!ptr) {
            CYG_REPORT_RETVAL( -1 );
            CYG_REPORT_RETVAL( -1 );
            return -1;
            return -1;
        }
        }
        memcpy(ptr, name, len);
        memcpy(ptr, name, len);
        ptr[len]=0;
        ptr[len]=0;
    } else {
    } else {
        ptr = NULL;
        ptr = NULL;
    }
    }
    if (domainname) {
    if (domainname) {
        free_string(domainname);
        free_string(domainname);
    }
    }
    domainname = ptr;
    domainname = ptr;
    CYG_REPORT_RETVAL( 0 );
    CYG_REPORT_RETVAL( 0 );
    return 0;
    return 0;
}
}
/* Return the domain name as used by the DNS server */
/* Return the domain name as used by the DNS server */
int
int
getdomainname(char *name, size_t len)
getdomainname(char *name, size_t len)
{
{
    CYG_REPORT_FUNCNAMETYPE( "getdomainname", "returning %d" );
    CYG_REPORT_FUNCNAMETYPE( "getdomainname", "returning %d" );
    CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len );
    CYG_REPORT_FUNCARG2( "name=%08x, len=%d", name, len );
    if ( !name || 0 == len) {
    if ( !name || 0 == len) {
        CYG_REPORT_RETVAL( -1 );
        CYG_REPORT_RETVAL( -1 );
        return -1;
        return -1;
    }
    }
    CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" );
    CYG_CHECK_DATA_PTR( name, "name is not a valid pointer!" );
    /* No domainname set, return a 0 */
    /* No domainname set, return a 0 */
    if (!domainname) {
    if (!domainname) {
        if (len == 0) {
        if (len == 0) {
            h_errno = HOST_NOT_FOUND;
            h_errno = HOST_NOT_FOUND;
            CYG_REPORT_RETVAL( -1 );
            CYG_REPORT_RETVAL( -1 );
            return -1;
            return -1;
        }
        }
        name[0]='\0';
        name[0]='\0';
    } else {
    } else {
        if ((strlen(domainname) + 1) > len) {
        if ((strlen(domainname) + 1) > len) {
            h_errno = NO_RECOVERY;
            h_errno = NO_RECOVERY;
            CYG_REPORT_RETVAL( -1 );
            CYG_REPORT_RETVAL( -1 );
            return -1;
            return -1;
        }
        }
        strncpy(name, domainname, len);
        strncpy(name, domainname, len);
    }
    }
    CYG_REPORT_RETVAL( 0 );
    CYG_REPORT_RETVAL( 0 );
    return 0;
    return 0;
}
}
int h_errno = DNS_SUCCESS;
int h_errno = DNS_SUCCESS;
const char*
const char*
hstrerror(int err)
hstrerror(int err)
{
{
    CYG_REPORT_FUNCNAMETYPE( "hstrerror", "returning %08x" );
    CYG_REPORT_FUNCNAMETYPE( "hstrerror", "returning %08x" );
    CYG_REPORT_FUNCARG1( "err=%d", err );
    CYG_REPORT_FUNCARG1( "err=%d", err );
    switch (err) {
    switch (err) {
    case DNS_SUCCESS:
    case DNS_SUCCESS:
        return "No error";
        return "No error";
    case HOST_NOT_FOUND:
    case HOST_NOT_FOUND:
        return "No such host is known";
        return "No such host is known";
    case TRY_AGAIN:
    case TRY_AGAIN:
        return "Timeout";
        return "Timeout";
    case NO_RECOVERY:
    case NO_RECOVERY:
        return "Server failure or invalid input";
        return "Server failure or invalid input";
    case NO_DATA:
    case NO_DATA:
        return "No data for type";
        return "No data for type";
    default:
    default:
        return "Uknown error";
        return "Uknown error";
    }
    }
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#endif // CYGONCE_NS_DNS_DNS_IMPL_H
#endif // CYGONCE_NS_DNS_DNS_IMPL_H
// End of dns_impl.h
// End of dns_impl.h
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.