⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns_clnt.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
字号:
/***********************************************************************//*                                                                     *//*   Module:  dns_clnt.c                                               *//*   Release: 2001.3                                                   *//*   Version: 2001.1                                                   *//*   Purpose: DNS Client Implementation                                *//*                                                                     *//*---------------------------------------------------------------------*//*                                                                     *//*               Copyright 2001, Blunk Microsystems                    *//*                      ALL RIGHTS RESERVED                            *//*                                                                     *//*   Licensees have the non-exclusive right to use, modify, or extract *//*   this computer program for software development at a single site.  *//*   This program may be resold or disseminated in executable format   *//*   only. The source code may not be redistributed or resold.         *//*                                                                     *//*                                                                     *//***********************************************************************/#include "tcp_ipp.h"#include <string.h>/***********************************************************************//* Configuration                                                       *//***********************************************************************/#define DNS_NSIZE   24#define DNS_TSIZE   30#define DNS_TRIES   5/***********************************************************************//* Symbol Definitions                                                  *//***********************************************************************/#define IP_ADDRESS  1#define CNAME       5/***********************************************************************//* Type Definitions                                                    *//***********************************************************************/typedef struct{  ui16 identification;  ui16 flags;  ui16 num_questions;  ui16 num_answers;  ui16 num_authorities;  ui16 num_additionals;  ui8  question[500];} DnsReqType;/*** Format of entry in DNS cache*/typedef struct{  ui32 ip_addr;             /* cached IP address */  char name[DNS_NSIZE];     /* host name */} DnsEntry;/***********************************************************************//* Global Variable Definitions                                         *//***********************************************************************/static DnsEntry DnsTbl[DNS_TSIZE];static DnsEntry *OldestEntry = &DnsTbl[0];/***********************************************************************//* Local Function Definitions                                          *//***********************************************************************//***********************************************************************//*   skip_name: Move pointer past DNS encoded name                     *//*                                                                     *//***********************************************************************/static ui8 *skip_name(ui8 *name){  int i;  do  {    i = *name;    if (i & 0xC0)      return name + 2;    else      name += i + 1;  }  while (*name);  return name + 1;}/***********************************************************************//*  ask_server: Move pointer past DNS encoded name                     *//*                                                                     *//***********************************************************************/static ui32 ask_server(ui32 server, const char *name, uint nlen){  int i, rc, sock, timeo;  ui8 *dest, *mark;  struct sockaddr_in sockaddr;  DnsReqType *dns_req;  ui16 type, num_answers;  ui32 lword;  const char *cp;  /*-------------------------------------------------------------------*/  /* Allocate buffer for DNS request.                                  */  /*-------------------------------------------------------------------*/  semPend(Net.IntSem, WAIT_FOREVER);  dns_req = tcpGetBuf(sizeof(DnsReqType));  semPost(Net.IntSem);  if (dns_req == NULL)  {    NetError(NULL, ENOBUFS);    return 0;  }  /*-------------------------------------------------------------------*/  /* Form the request.                                                 */  /*-------------------------------------------------------------------*/  dns_req->identification = htons(33);  dns_req->flags = htons(0x0100);  dns_req->num_questions = htons(1);  dns_req->num_answers = htons(0);  dns_req->num_authorities = htons(0);  dns_req->num_additionals = htons(0);  /*-------------------------------------------------------------------*/  /* Put name into DNS name format.                                    */  /*-------------------------------------------------------------------*/  dest = dns_req->question;  for (cp = name; *cp;)  {    mark = dest++;    for (i = 0; *cp && (*cp != '.'); ++i)    {      *dest++ = (ui8)*cp++;      if (((dest - (ui8 *)dns_req) + 5) > sizeof(DnsReqType))      {        semPend(Net.IntSem, WAIT_FOREVER);        tcpRetBuf(&dns_req);        semPost(Net.IntSem);        NetError(NULL, EFAULT);        return 0;      }    }    *mark = (ui8)i;    if (*cp == '.')      ++cp;  }  *dest++ = 0;  /*-------------------------------------------------------------------*/  /* Append query type and class values (network order).               */  /*-------------------------------------------------------------------*/  *dest++ = 0;  *dest++ = 1;  *dest++ = 0;  *dest++ = 1;  /*-------------------------------------------------------------------*/  /* Create a socket.                                                  */  /*-------------------------------------------------------------------*/  sock = socket(AF_INET, SOCK_DGRAM, 0);  if (sock == -1)  {    semPend(Net.IntSem, WAIT_FOREVER);    tcpRetBuf(&dns_req);    semPost(Net.IntSem);    return 0;  }  /*-------------------------------------------------------------------*/  /* Initialize the address structure.                                 */  /*-------------------------------------------------------------------*/  memset(&sockaddr, 0, sizeof(struct sockaddr_in));  sockaddr.sin_family = AF_INET;  sockaddr.sin_port = htons(53);  sockaddr.sin_addr.s_addr = server;  /*-------------------------------------------------------------------*/  /* Bind destination address to socket.                               */  /*-------------------------------------------------------------------*/  rc = connect(sock, &sockaddr, sizeof(struct sockaddr_in));  if (rc == -1)    goto error;  /*-------------------------------------------------------------------*/  /* Send request and wait for response, with exponential backoff.     */  /*-------------------------------------------------------------------*/  for (i = 0, timeo = 750;; ++i, timeo *= 2)  {    /*-----------------------------------------------------------------*/    /* Pass request to server.                                         */    /*-----------------------------------------------------------------*/    rc = send(sock, (void *)dns_req, dest - (ui8 *)dns_req, 0);    if (rc == -1)      goto error;    /*-----------------------------------------------------------------*/    /* Set recv() timeout.                                             */    /*-----------------------------------------------------------------*/    rc = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(int));    if (rc < 0) goto error;    /*-----------------------------------------------------------------*/    /* Check for response.                                             */    /*-----------------------------------------------------------------*/    rc = recv(sock, dns_req, sizeof(DnsReqType), 0);    if (rc > 0)      break;    else if (errno != ETIMEDOUT)      goto error;    /*-----------------------------------------------------------------*/    /* Fail after so many tries.                                       */    /*-----------------------------------------------------------------*/    if (i == DNS_TRIES)      goto error;  }  /*-------------------------------------------------------------------*/  /* Check for error response.                                         */  /*-------------------------------------------------------------------*/  if (ntohs(dns_req->flags) & 0x000F)    goto error;  /*-------------------------------------------------------------------*/  /* Determine the number of answers provided.                         */  /*-------------------------------------------------------------------*/  memcpy(&num_answers, &dns_req->num_answers, sizeof(short));  num_answers = ntohs(num_answers);  /*-------------------------------------------------------------------*/  /* Loop through answers, looking for Host Address.                   */  /*-------------------------------------------------------------------*/  for (i = 0;;)  {    /*-----------------------------------------------------------------*/    /* Skip answer's name, advancing to and reading its type.          */    /*-----------------------------------------------------------------*/    dest = skip_name(dest);    memcpy(&type, dest, sizeof(short));    type = ntohs(type);    /*-----------------------------------------------------------------*/    /* Skip Canonical name answers.                                    */    /*-----------------------------------------------------------------*/    if (type == CNAME)    {      ui16 word;      dest += 8;        /* advance to data length field */      memcpy(&word, dest, sizeof(short));      word = ntohs(word);      dest += word + 2; /* advance to next resource record */    }    /*-----------------------------------------------------------------*/    /* Read IP address and break if answer is Host Address.            */    /*-----------------------------------------------------------------*/    else if (type == IP_ADDRESS)    {      memcpy(&lword, dest + 10, sizeof(long));      break;    }    /*-----------------------------------------------------------------*/    /* Anything else is an error.                                      */    /*-----------------------------------------------------------------*/    else      goto error;    /*-----------------------------------------------------------------*/    /* Return error if every answer has been checked.                  */    /*-----------------------------------------------------------------*/    if (++i == num_answers)      goto error;  }  /*-------------------------------------------------------------------*/  /* If the host name fits, save it in the DNS cache.                  */  /*-------------------------------------------------------------------*/  if (nlen < DNS_NSIZE)  {    OldestEntry->ip_addr = lword;    strcpy(OldestEntry->name, name);    if (++OldestEntry == &DnsTbl[DNS_TSIZE])      OldestEntry = &DnsTbl[0];  }  /*-------------------------------------------------------------------*/  /* Close socket and return IP address or 0 for success or failure.   */  /*-------------------------------------------------------------------*/  semPend(Net.IntSem, WAIT_FOREVER);  tcpRetBuf(&dns_req);  semPost(Net.IntSem);  closesocket(sock);  return lword;error:  semPend(Net.IntSem, WAIT_FOREVER);  tcpRetBuf(&dns_req);  semPost(Net.IntSem);  closesocket(sock);  NetError(NULL, EDNS_FAILED);  return 0;}/***********************************************************************//* Global Function Definitions                                         *//***********************************************************************//***********************************************************************//* getHostByName: Request IP address resolution from DNS server        *//*                                                                     *//*       Input: name = NULL-terminated host name                       *//*                                                                     *//*     Returns: IP address if no errors, else 0                        *//*                                                                     *//***********************************************************************/ui32 getHostByName(const char *name){  uint nlen;  DnsEntry *entry;  ui32 addr;  HostDesc *host;  /*-------------------------------------------------------------------*/  /* Check if name is in application's HostsTable.                     */  /*-------------------------------------------------------------------*/  for (host = &HostsTable[0]; host->ip_addr; ++host)  {    /*-----------------------------------------------------------------*/    /* Return if host name match is found.                             */    /*-----------------------------------------------------------------*/    if (strcmp(host->name, name) == 0)      return host->ip_addr;  }  /*-------------------------------------------------------------------*/  /* Acquire exclusive access to DNS client.                           */  /*-------------------------------------------------------------------*/  semPend(Net.DnsSem, WAIT_FOREVER);  /*-------------------------------------------------------------------*/  /* Check if host name is already in DNS cache.                       */  /*-------------------------------------------------------------------*/  nlen = strlen(name);  if (nlen < DNS_NSIZE)    for (entry = &DnsTbl[0]; entry < &DnsTbl[DNS_TSIZE]; ++entry)      if (strcmp(entry->name, name) == 0)      {        addr = entry->ip_addr;        goto exit;      }  /*-------------------------------------------------------------------*/  /* If primary DNS server provided, return if it responds.            */  /*-------------------------------------------------------------------*/  if (PriDnsServer)  {    addr = ask_server(PriDnsServer, name, nlen);    if (addr)      goto exit;  }  /*-------------------------------------------------------------------*/  /* If secondary DNS server provided, return if it responds.          */  /*-------------------------------------------------------------------*/  if (SecDnsServer)  {    addr = ask_server(SecDnsServer, name, nlen);    if (addr)      goto exit;  }  /*-------------------------------------------------------------------*/  /* Either no DNS server configured or none responsed.                */  /*-------------------------------------------------------------------*/  NetError(NULL, EDNS_SERVER);  addr = 0;exit:  /*-------------------------------------------------------------------*/  /* Release exclusive access to DNS client.                           */  /*-------------------------------------------------------------------*/  semPost(Net.DnsSem);  return addr;}

⌨️ 快捷键说明

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