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

📄 dnsclnt.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * FILENAME: dnsclnt.c
 *
 * Copyright 1997- 2000 By InterNiche Technologies Inc. All rights reserved
 *
 * DNS Client code for NetPort IP stack
 *
 * MODULE: INET
 *
 * ROUTINES: dns_query(), dnc_sendreq(), dnc_copyout(), 
 * ROUTINES: dnc_copyin(), dnc_del(), dnc_makeroom(), dns_check(), 
 * ROUTINES: badreply(), dns_upcall(), dnc_lookup(), dns_lookup(), 
 * ROUTINES: t_gethostbyname(), *gethostbyname(), dns_state(), 
 *
 * PORTABLE: yes
 */


#include "ipport.h"

#ifdef DNS_CLIENT    /* ifdef out whole file */

#include "q.h"
#include "netbuf.h"
#include "net.h"
#include "ip.h"
#include "udp.h"
#include "dns.h"

/* static table for actual queries. Non-zero ipaddr means entry is active. */
struct dns_querys dns_qs[MAXDNSENTRY];

unshort  dnsids   =  0x1234;  /* seed for unique request IDs */

/* DNS client statistics: */
ulong      dnsc_errors = 0;      /* protocol/implementation runtime errors */
ulong      dnsc_requests = 0;    /* requests sent */
ulong      dnsc_replies = 0;     /* replys received */
ulong      dnsc_good = 0;        /* usable replys received */
ulong      dnsc_tmos = 0;        /* timeouts */
ulong      dnsc_retry = 0;       /* total retries */

#ifdef DNS_CLIENT_UPDT
ulong      dnsc_updates = 0;     /* Dynamic DNS Updates sent */
#endif /* DNS_CLIENT_UPDT */

/* pending requests, can be used as a flag to spin dnsc_check() task */
unsigned   dnsc_active = 0;

/* retry info, can be overwritten by application code */
unsigned dns_firsttry = 4; /* time to first retry, in seconds */
unsigned dns_trys = 5;     /* max number of retrys */

ip_addr dns_servers[MAXDNSSERVERS]; /* need to be set from NV parameters */

#ifdef  DNS_CLIENT_UPDT
char    soa_mname[MAXDNSNAME];

/* internal routines */
static struct hostent* getsoa(char *);
#endif  /* DNS_CLIENT_UPDT */

/* internal routines */
static int  dnc_sendreq(int entry);
static int  dnc_copyout(char * dest, char * src);
static int  dnc_copyin(char * dest, char * src, struct dns_hdr * dns);
static void dnc_del(int entry);
static void dnc_makeroom(void);
static int  badreply(struct dns_hdr * dns, char * text);



/* FUNCTION: dns_query()
 *
 * dns_query() - starts the process of sending out a DNS request for 
 * a domain name. This is hardwired for the basic question "what is 
 * the IP address of named host?". It creates the control structures 
 * and calls dnc_sendreq() to send the actual packet. Called should 
 * poll dns_lookup for results. 
 *
 * PARAM1: char * name
 * PARAM2: ip_addr * ip
 *
 * RETURNS: Returns 0 if IP address was filled in 
 * from cache, ENP_SEND_PENDING if query was launched OK, or one of 
 * the ENP error codes. 
 */

int
dns_query(char * name, ip_addr * ip)
{
   int   entry;   /* dns entry index */
   int   e;

   /* see if we already have an entry for this name in the cache */
   e = dns_lookup(ip, name);
   if (e >= 0)
      return e;

   /* else find a free entry so we can start a query */
   dnc_makeroom();
   for (entry = 0; entry < MAXDNSENTRY; entry++)
   {
      if (dns_qs[entry].id == 0) /* found empty entry? */
         break;
   }

   /* sanity check to make sure we really have a free entry */
   if (entry >= MAXDNSENTRY)
   {
      dtrap("dnsclnt 0\n"); /* may need to increase DNS_MAXENTRY */
      return ENP_RESOURCE;
   }

   /* prepare entry for use and copy in name */
   MEMSET(&dns_qs[entry], 0, sizeof(dns_qs[entry]));     /* clear entry */
   strncpy(dns_qs[entry].dns_name, name, MAXDNSNAME-1);  /* copy in name */
   dns_qs[entry].tries = 0;      /* no retries yet */
   dns_qs[entry].id = dnsids++;  /* set ID for this transaction */
   dns_qs[entry].ipaddr_list[0] = 0L;  /* non-zero when it succeeds */
   if (dnsids == 0)              /* don't allow ID of 0 */
      dnsids++;

   /* get UDP port for packet, keep for ID */
   dns_qs[entry].lport = udp_socket();
   dnsc_active++;       /* maintain global dns pending count */
   dnsc_requests++;     /* count this request */

#ifdef DNS_CLIENT_UPDT
   dns_qs[entry].type = 1; /* Set type to A */
#endif /* DNS_CLIENT_UPDT */
   e = dnc_sendreq(entry);
   if (e == 0) /* first packet sent OK */
      return ENP_SEND_PENDING;
   else  /* some kind of error */
      return e;
}



/* FUNCTION: dnc_sendreq()
 *
 * dnc_sendreq() - Sends out a DNS request packet based on the query 
 * info in dns_qs[entry]. This is intended to be called from 
 * dns_query() or dns_check(). 
 *
 * 
 * PARAM1: int entry
 *
 * RETURNS: Returns 0 if OK, or one of the ENP error codes. 
 */

static int
dnc_sendreq(int entry)
{      
   PACKET pkt;
   struct dns_hdr *  dns;  /* outgoing dns header */
   char *   cp;   /* scratch pointer for building question field */
   int   server;  /* index of server to use */

   /* figure out which server to try */
   for (server = 0; server < MAXDNSSERVERS; server++)
   {
      if (dns_servers[server] == 0L)
         break;
   }
   if (server == 0)  /* no servers set? */
   {
      dtrap("dnsclnt 1\n");
      return ENP_LOGIC;
   }
   server = dns_qs[entry].tries % server;

   /* allocate packet for DNS request */
   if ((pkt = udp_alloc(MAXDNSUDP, 0)) == NULL)
      return ENP_RESOURCE;

   /* fill in DNS header. Most fields are cleared to 0s */
   dns = (struct dns_hdr *)pkt->nb_prot;
   MEMSET(dns, 0, sizeof(struct dns_hdr));
   dns->id = dns_qs[entry].id;

#ifdef DNS_CLIENT_UPDT
   /* If this is an UPDATE packet, format the DNS packet differently */
   
   if (dns_qs[entry].type == DNS_UPDT)
   {
      dns->qdcount = htons(1);  /* Set zone count to 1 */
      dns->nscount = htons(1);  /* Set update count to 1 */
      dns->flags = htons(0x2800); /* Set opcode field to 5 */

      /* format zone name into UPDATE packet */
      cp = (char*)(dns+1);      /* point at next byte past header */
      cp += dnc_copyout(cp, dns_qs[entry].h_z_name);

      /* finish off zone section. We write these two 16 bit words a
       * byte at a time since cp may be on an odd address and some
       * machines
       */
      *cp++ = 0;  /* high byte of type */
      *cp++ = 6;  /* type 6 = soa */
      *cp++ = 0;  /* high byte of class */
      *cp++ = 1;  /* class 1 == internet */

      cp += dnc_copyout(cp, dns_qs[entry].dns_name);

      /* Put in NAME and TYPE */
      *cp++ = 0;  /* high byte of type */

      /* If ttl value is 0, this is a delete operation. Set type to ANY */
      if (dns_qs[entry].h_ttl == 0)
         *cp++ = (unsigned char)255;
      else
         *cp++ = 1;  /* type 1 == host address, type 6 = soa */
      *cp++ = 0;     /* high byte of class */
      *cp++ = 1;     /* class 1 == internet */

      /* Put in TTL value */
      *cp++ = (unsigned char)(dns_qs[entry].h_ttl >> 24);
      *cp++ = (unsigned char)(dns_qs[entry].h_ttl >> 16);
      *cp++ = (unsigned char)(dns_qs[entry].h_ttl >> 8);
      *cp++ = (unsigned char)dns_qs[entry].h_ttl;

      /* Put in RDLENGTH which is length of ip address ie 4 */
      *cp++ = 0;  /* low byte of length */

      /* If ttl value is 0, this is a delete operation. Set RDLENGTH to 0 */
      if (dns_qs[entry].h_ttl == 0)
         *cp++ = 0;
      else
         *cp++ = 4;
      /* Put in IP address */
      MEMCPY(cp,&dns_qs[entry].h_add_ipaddr,4);
      cp += 4;
      dnsc_updates++;
   }
   else
   {
#endif  /* DNS_CLIENT_UPDT */

       dns->qdcount = htons(1);      /* 1 question */
       dns->flags = htons(DNSF_RD);  /* Recursion Desired */

   /* format name into question field after header */
       cp = (char*)(dns + 1);  /* point at next byte past header */
       cp += dnc_copyout(cp, dns_qs[entry].dns_name);

   /* finish off question field. We write these two 16 bit words a 
    * byte at a time since cp may be on an odd address and some 
    * machines 
    */
       *cp++ = 0;  /* high byte of type */
#ifdef DNS_CLIENT_UPDT
       *cp++ = dns_qs[entry].type;  /* type 1 == host address, type 6 = soa */
#else
       *cp++ = 1;
#endif /* DNS_CLIENT_UPDT */
       *cp++ = 0;  /* high byte of class */
       *cp++ = 1;  /* class 1 == internet */

#ifdef DNS_CLIENT_UPDT
   }
#endif /* DNS_CLIENT_UPDT */
   pkt->fhost = dns_servers[server];
   pkt->nb_plen = cp - (char*)dns;     /* length of packet */
   dns_qs[entry].send_time = cticks;   /* note time we send packet */
   return(udp_send(DNS_PORT, dns_qs[entry].lport, pkt));
}


/* FUNCTION: dnc_copyout()
 *
 * dnc_copyout() - copy a domain name from user "dot" text format to 
 * DNS header format. dest buffer is assumed to be large enough, 
 * which means at least as big as src string.
 * 
 * PARAM1: char * dest
 * PARAM2: char * src
 *
 * RETURNS:  Returns length of string copied. 
 */

static int
dnc_copyout(char * dest, char * src)
{
   int   namelen; /* length of name segment */
   char *   cp;   /* pointer to dest string we're building */
   char *   fld, *   next; /* pointers into src */

   cp = dest;
   next = src; /* will be assigned to "this" on first pass */

   while (next)   /* 1 loop per field in dot-delimited string */
   {
      fld = next;
      next = strchr(fld, '.');   /* find next dot in string */
      if (next)   /* if not last field... */
      {
         namelen = next - fld;   /* length of this field */
         next++;  /* bump next pointer past dot */
      }
      else  /* no dot means end of string */
         namelen = strlen(fld);

      *cp++ = (char)(namelen & 0xFF);  /* put length in dest buffer */
      MEMCPY(cp, fld, namelen);     /* follow with string data */
      cp += namelen;    /* point past name to next length byte */
   }
   *cp++ = 0;  /* null terminate string */
   return(cp - dest);
}


/* FUNCTION: dnc_copyin()
 *
 * dnc_copyin() - the inverse of copyout above - it copies a dns 
 * format domain name to "dot" formatting. 
 *
 * 
 * PARAM1: char * dest
 * PARAM2: char * src
 * PARAM3: struct dns_hdr * dns
 *
 * RETURNS: Returns length of string copied, 0 if error. 
 */

int
dnc_copyin(char * dest, char * src, struct dns_hdr * dns)
{
   unshort   namelen; /* length of name segment */
   char *   cp;   /* pointer to dest string we're building */
   char *   fld, *   next; /* pointers into src */
   int   donelen;    /* number of bytes moved */
   unshort offset;

   cp = dest;
   next = src; /* will be assigned to "this" on first pass */
   donelen = 0;

   while (next)   /* 1 loop per field in dot-delimited string */
   {
      fld = next;
      namelen = *fld++;
      if (namelen == 0)
      break;   /* done */
      if ((namelen & 0xC0) == 0xC0)
      {
         fld--;
         offset = (unshort)*fld; /* get first byte of offset code */
         fld++;
         offset &= 0x3f;             /* mask our high two bits */
         offset <<= 8;               /* make it high byte of word */
         offset += (unshort)*fld; /* add low byte of word */
         fld = offset + (char *)dns;  /* ptr into domain name */
         namelen = *fld++;
      }
      if (namelen + donelen > MAXDNSNAME) /* check for overflow */
         return 0;   /* error */
      MEMCPY(cp, fld, namelen);
      donelen += (namelen+1); /* allow for dot/len byte */
      cp += namelen;
      *cp++ = '.';
      next = fld + namelen;
   }
   *(cp-1) = 0;   /* null terminate string (over last dot) */
   return donelen + 1;  /* include null in count */
}



/* FUNCTION: dnc_del()
 *
 * Delete a DNS entry
 *
 * PARAM1: int entry
 *
 * RETURNS: void
 */

static void
dnc_del(int entry)
{
   MEMSET(&dns_qs[entry], 0, sizeof(struct dns_querys));
   dnsc_active--;    /* one less active entry */
}


/* FUNCTION: dnc_makeroom()
 *

⌨️ 快捷键说明

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