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

📄 dnsclnt.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
 * dnc_makeroom() - tries to make an empty entry (ready for re-use) 
 * in the cache. 
 *
 * 
 * PARAM1: void
 *
 * RETURNS: void
 */

static void
dnc_makeroom(void)
{
   /* if the DNS table is full... */
   if (dnsc_active >= MAXDNSENTRY)
   {
      ulong min_expire_time = ~((ulong) 0L);    /* all 1s in a long */
      int   min_expire_entry  =  -1;   /* entry with earliest expiration time */
      int   entry;

      /* find the one with the earliest expiration time */
      for (entry = 0; entry < MAXDNSENTRY; entry++)
      {
         /* don't use entries that haven't resolved yet */
         if (dns_qs[entry].ipaddr_list[0])
         {
            /* if this one is the earliest one seen so far */
            if (dns_qs[entry].expire_time < min_expire_time)
            {
               /* remember it */
               min_expire_time = dns_qs[entry].expire_time;
               min_expire_entry = entry;
            }
         }
      }

      /* if we've identified an earliest expirable resolved entry,
       *  delete it
       */
      if (min_expire_entry >= 0)
         dnc_del(min_expire_entry);
   }
}


/* FUNCTION: dns_check()
 *
 * dns_second() - poll once a second to drive DNS timeouts and 
 * retrys. Can be skipped when dnsc_active == 0 
 * 
 * PARAM1: 
 *
 * RETURNS: void
 */

void
dns_check(void)
{
   int   entry;   /* dns entry index */
   int   trysec;  /* seconds to wait for next try */

   for (entry = 0; entry < MAXDNSENTRY; entry++)
   {
      if (dns_qs[entry].id == 0) /* skip non-active request entrys */
         continue;

      if (dns_qs[entry].ipaddr_list[0] != 0) /* resolved request, check timeout */
      {
         if (dns_qs[entry].expire_time <= (cticks/TPS))
            dnc_del(entry);
         continue;
      }

      /* active request, see if it's time to retry */
      trysec = dns_firsttry << dns_qs[entry].tries;
      if ((dns_qs[entry].send_time + (TPS*(unsigned long)trysec)) < cticks)
      {
         if (dns_qs[entry].tries >= dns_trys)   /* retried out */
         {
            dnc_del(entry);
            dnsc_tmos++;      /* count timeouts */
            continue;
         }
         dnsc_retry++;           /* count total retries */
         dns_qs[entry].tries++;  /* count entry retries */
         dnc_sendreq(entry);
      }
   }
}


/* FUNCTION: badreply()
 *
 * dns_badreply() - per-port handler for less than ideal DNS replys. 
 * 
 * 
 * PARAM1: struct dns_hdr * dns
 * PARAM2: char * text
 *
 * RETURNS: Returns ENP code if problem should kill transaction, else 0 
 */

static int 
badreply(struct dns_hdr * dns, char * text)
{
   dnsc_errors++;
#ifdef NPDEBUG
   dprintf("DNS error: %s; flags %x\n", text, htons(dns->flags));
#endif   /* NPDEBUG */
   /* don't kill request, let it retry with another server */
   USE_ARG(dns);
   USE_ARG(text);
   return 0;
}


/* FUNCTION: dns_upcall()
 *
 * dns_upcall() - called from the UDP layer whenever we receive a DNS 
 * packet (one addressed to port 53). p_nb_prot points to UYDP data, 
 * which should be DNS header. Return 0 if OK, or ENP code. 
 *
 * 
 * PARAM1: PACKET pkt
 * PARAM2: unshort lport
 *
 * RETURNS: 
 */

int
dns_upcall(PACKET pkt, unshort lport)
{
   int   entry;      /* dns entry index */
   struct dns_hdr *  dns;  /* incoming dns header */
   char *   cp;         /* scratch pointer for building question field */
   unshort  flags;   /* dns->flags in local endian */
   unshort  rcode;   /* response code */
   unshort  answers; /* number of answer records in reply */
#ifdef DNS_CLIENT_UPDT
   unshort  addtnl;  /* number of additional resource records */
   unshort  opcode;  /* opcode of the response- 5=UPDATE,0=QUERY */
#endif /* DNS_CLIENT_UPDT */
   unshort  type;    /* various fields from the reply */
   unshort  cls;
   u_long   ttl;
   unshort  rdlength;
   unshort  offset;  /* offset to domain name text */
   unshort  i;
   int   ip_count =  0; /* count of IP addresses in response */

   dnsc_replies++;
   dns = (struct dns_hdr *)pkt->nb_prot;

   for (entry = 0; entry <= MAXDNSENTRY; entry++)
   {
      if ((dns_qs[entry].id == dns->id) &&
          (dns_qs[entry].lport == lport))
      {
         break;
      }
   }

   /* make sure we found our entry in the table */
   if (entry >= MAXDNSENTRY)
      return ENP_NOT_MINE;         /* do not free pkt here */

   dns_qs[entry].replies++;        /* count total replies */
   flags = htons(dns->flags);      /* extract data fromheader */
   rcode = flags & DNSF_RCMASK;    /* Response code */
   answers = htons(dns->ancount);  /* number of answers */

#ifdef DNS_CLIENT_UPDT
   opcode = (flags & DNSF_OPMASK) >> 11;   /* Op code */
   addtnl = htons(dns->arcount);   /* number of additional records */
#endif /* DNS_CLIENT_UPDT */

   /* check DNS flags for good response value */
   if (!(flags & DNSF_QR))
      return(badreply(dns, "not reply"));

#ifdef DNS_CLIENT_UPDT

   /* If UPDATE opcode, set the response code in dns query structure */
   /* and set the ip address field to non zero and return            */
   if (opcode == DNS_UPDT)
   {
      dns_qs[entry].rcode = rcode;
      dns_qs[entry].ipaddr_list[0] = 0xff;
      return 0;
   }
#endif /* DNS_CLIENT_UPDT */

   if (rcode != DNSRC_OK) 
      return(badreply(dns, "bad response code"));

   if (answers < 1)
      return(badreply(dns, "no answers"));

   /* looks like we got an answer to the query */
   dns_qs[entry].rcode = rcode;

   cp = (char*)(dns+1);    /* start after DNS entry */
   cp += dnc_copyin(dns_qs[entry].dns_name, cp, dns);   /* get back name */
   cp += 4; /* bump past two 16bit fields, point to answers */

   for (i = 0; i < answers; i++)
   {
      /* bump past name field in answer, keeping offset to text */
      if ((*cp & 0xC0) == 0xC0)  /* is it an offset? */
      {
         offset = (unshort)(*cp++); /* get first byte of offset code */
         offset &= 0x3f;   /* mask our high two bits */
         offset <<= 8;     /* make it high byte of word */
         offset += (unshort)(*cp++);   /* add low byte of word */
      }
      else  /* text for name is right here */
      {
         offset = (unshort)(cp - (char*)dns);   /* save offset */
         while (*cp++ != 0);  /* scan past name */
      }
      /* get DNS vars from packet bytes */
      type = (unshort)(*cp++ << 8);
      type += (unshort)(*cp++);
      cls = (unshort)(*cp++ << 8);
      cls += (unshort)(*cp++);
      if (cls != 1)
      {
         dtrap("dnsclnt 2\n");
         return badreply(dns, "class not internet");
      }
      ttl =  (ulong)(*cp++) << 24;     /* 4 byte time to live field */
      ttl += (ulong)(*cp++) << 16;
      ttl += (ulong)(*cp++) << 8;
      ttl += (*cp++);

      rdlength = (unshort)(*cp++ << 8);
      rdlength += (unshort)(*cp++);

      if (type == 1) /* this is it */
      {
         if (rdlength != 4)
            return(badreply(dns, "IPADDR len not 4"));
         dnsc_good++;
         /* save alias name */
         dnc_copyin(dns_qs[entry].dns_alias, offset + (char*)(dns), dns);
         /* save reply IP addresses in array of IP addresses so long
            as there is room for them */
         if (ip_count < MAXDNSADDRS)
         {
            MEMCPY(&dns_qs[entry].ipaddr_list[ip_count], cp, 4);
            ip_count++;
         }
         if (dns_qs[entry].expire_time == 0)
            dns_qs[entry].expire_time = (cticks/TPS) + (ttl);
      }
      else if (type == 5)  /* alias */
      {
         /* use alias timeout for entry */
         dns_qs[entry].expire_time = (cticks/TPS) + (ttl);
      }

#ifdef DNS_CLIENT_UPDT
      else if (type == DNS_TYPE_AUTHNS) /* authoritative name server */
      {
         dnc_copyin(dns_qs[entry].dns_soa, cp, dns);
      }
#endif /* DNS_CLIENT_UPDT */

      cp += rdlength;   /* bump past trailing data */
   }

#ifdef DNS_CLIENT_UPDT
   /* Parse additional data only if original request was for authoritative */
   /* name server */
   if (dns_qs[entry].type == DNS_TYPE_AUTHNS)
   {
      for (i = 0; i < addtnl; i++)
      {
         /* bump past name field in answer, keeping offset to text */
         if ((*cp & 0xC0) == 0xC0)  /* is it an offset? */
         {
            offset = (unshort)(*cp++); /* get first byte of offset code */
            offset &= 0x3f;            /* mask our high two bits */
            offset <<= 8;              /* make it high byte of word */
            offset += (unshort)(*cp++);/* add low byte of word */
         }
         else  /* text for name is right here */
         {
            offset = (unshort)(cp - (char*)dns);   /* save offset */
            while (*cp++ != 0);                    /* scan past name */
         }
         /* get DNS vars from packet bytes */
         type = (unshort)(*cp++ << 8);
         type += (unshort)(*cp++);
         cls = (unshort)(*cp++ << 8);
         cls += (unshort)(*cp++);
         if (cls != 1)
         {
            dtrap("dnsclnt 3\n");
            return badreply(dns, "class not internet");
         }
         ttl =  (ulong)(*cp++) << 24;     /* 4 byte time to live field */
         ttl += (ulong)(*cp++) << 16;
         ttl += (ulong)(*cp++) << 8;
         ttl += (*cp++);

         rdlength = (unshort)(*cp++ << 8);
         rdlength += (unshort)(*cp++);

         if (type == 1) /* Get the ip addresses of authoritative srvrs */
         {
            if (rdlength != 4)
               return(badreply(dns, "IPADDR len not 4"));
            dnsc_good++;
            /* save alias name */
            dnc_copyin(dns_qs[entry].dns_alias, offset + (char*)(dns), dns);
            /* save reply IP addresses in array of IP addresses so long
            as there is room for them */
            if (ip_count < MAXDNSADDRS)
            {
               MEMCPY(&dns_qs[entry].ipaddr_list[ip_count], cp, 4);
               ip_count++;
            }
            if (dns_qs[entry].expire_time == 0)
               dns_qs[entry].expire_time = (cticks/TPS) + (ttl);
         }
         else /* not expecting additional counts in other answers */
            {
               dtrap("dnsclnt 4\n");
               return badreply(dns, "additional records not expected");
            }
         cp += rdlength;   /* bump past trailing data */
         }
   }
#endif   /* DNS_CLIENT_UPDT */

   return 0;
}



/* FUNCTION: dnc_lookup()
 *
 * dnc_lookup() - check cache for a pending or completed DNS client 
 * request. Passed entry index is filled in if DNS query was resolved 
 * without error, else this returns non-zero ENP_ error code. 
 *
 * 
 * PARAM1: char * name
 * PARAM2: int * cacheindex
 *
 * RETURNS: ENP_SEND_PENDING if request is still on the net, or ENP_TIMEOUT
 * id request timed out (or was never made), or 0 (SUCCESS) if passed 
 * name found in cache, or ENP_PARAM if 
 */

static int
dnc_lookup(char * name, int * cacheindex)
{
   int   entry;

   /* look through the cache for the passed name */
   for (entry = 0; entry < MAXDNSENTRY; entry++)
      if (strcmp(dns_qs[entry].dns_name, name) == 0)
   break;

   /* if not found, return error */
   if (entry >= MAXDNSENTRY)
      return ENP_PARAM;

   /* else, prepare to return entry index */
   if (cacheindex != NULL)
      *cacheindex = entry;

   /* if completed request, return success */
#ifdef DNS_CLIENT_UPDT
   if (dns_qs[entry].ipaddr_list[0] || dns_qs[entry].dns_soa[0])
      return 0;
#else
   if (dns_qs[entry].ipaddr_list[0])
      return 0;
#endif /* DNS_CLIENT_UPDT */


   /* incomplete request -- return pending or timed-out status */
   if (dns_qs[entry].tries < dns_trys) /* still trying? */
      return ENP_SEND_PENDING;
   else
      return ENP_TIMEOUT;
}

⌨️ 快捷键说明

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