dns_impl.inl

来自「ecos实时嵌入式操作系统」· INL 代码 · 共 620 行 · 第 1/2 页

INL
620
字号
#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 intvalid_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;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?