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 + -
显示快捷键?