コード例 #1
0
void dnsFlushCache(NetInterface *interface)
{
   uint_t i;
   DnsCacheEntry *entry;

   //Acquire exclusive access to the DNS cache
   osAcquireMutex(&dnsCacheMutex);

   //Go through DNS cache
   for(i = 0; i < DNS_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &dnsCache[i];

      //Check whether the entry is currently in used
      if(entry->state != DNS_STATE_NONE)
      {
         //Delete DNS entries only for the given network interface
         if(entry->interface == interface)
            dnsDeleteEntry(entry);
      }
   }

   //Release exclusive access to the DNS cache
   osReleaseMutex(&dnsCacheMutex);
}
コード例 #2
0
DnsCacheEntry *dnsCreateEntry(void)
{
   uint_t i;
   DnsCacheEntry *entry;
   DnsCacheEntry *oldestEntry;

   //Keep track of the oldest entry
   oldestEntry = &dnsCache[0];

   //Loop through DNS cache entries
   for(i = 0; i < DNS_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &dnsCache[i];

      //Check whether the entry is currently in used or not
      if(entry->state == DNS_STATE_NONE)
      {
         //Erase contents
         memset(entry, 0, sizeof(DnsCacheEntry));
         //Return a pointer to the DNS entry
         return entry;
      }

      //Keep track of the oldest entry in the table
      if(timeCompare(entry->timestamp, oldestEntry->timestamp) < 0)
         oldestEntry = entry;
   }

   //The oldest entry is removed whenever the table runs out of space
   dnsDeleteEntry(oldestEntry);
   //Erase contents
   memset(oldestEntry, 0, sizeof(DnsCacheEntry));
   //Return a pointer to the DNS entry
   return oldestEntry;
}
コード例 #3
0
void dnsTick(void)
{
   error_t error;
   uint_t i;
   systime_t time;
   DnsCacheEntry *entry;

   //Get current time
   time = osGetSystemTime();

   //Acquire exclusive access to the DNS cache
   osAcquireMutex(&dnsCacheMutex);

   //Go through DNS cache
   for(i = 0; i < DNS_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &dnsCache[i];

      //Name resolution in progress?
      if(entry->state == DNS_STATE_IN_PROGRESS)
      {
         //The request timed out?
         if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
         {
            //Check whether the maximum number of retransmissions has been exceeded
            if(entry->retransmitCount > 0)
            {
#if (DNS_CLIENT_SUPPORT == ENABLED)
               //DNS resolver?
               if(entry->protocol == HOST_NAME_RESOLVER_DNS)
               {
                  //Retransmit DNS query
                  error = dnsSendQuery(entry);
               }
               else
#endif
#if (MDNS_CLIENT_SUPPORT == ENABLED)
               //mDNS resolver?
               if(entry->protocol == HOST_NAME_RESOLVER_MDNS)
               {
                  //Retransmit mDNS query
                  error = mdnsSendQuery(entry);
               }
               else
#endif
#if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
               //NetBIOS Name Service resolver?
               if(entry->protocol == HOST_NAME_RESOLVER_NBNS)
               {
                  //Retransmit NBNS query
                  error = nbnsSendQuery(entry);
               }
               else
#endif
               //Unknown protocol?
               {
                  error = ERROR_FAILURE;
               }

               //Query message successfully sent?
               if(!error)
               {
                  //Save the time at which the query message was sent
                  entry->timestamp = time;
                  //The timeout value is doubled for each subsequent retransmission
                  entry->timeout = MIN(entry->timeout * 2, entry->maxTimeout);
                  //Decrement retransmission counter
                  entry->retransmitCount--;
               }
               else
               {
                  //The entry should be deleted since name resolution has failed
                  dnsDeleteEntry(entry);
               }
            }
#if (DNS_CLIENT_SUPPORT == ENABLED)
            //DNS resolver?
            else if(entry->protocol == HOST_NAME_RESOLVER_DNS)
            {
               //Select the next DNS server
               entry->dnsServerNum++;
               //Initialize retransmission counter
               entry->retransmitCount = DNS_CLIENT_MAX_RETRIES;
               //Send DNS query
               error = dnsSendQuery(entry);

               //DNS message successfully sent?
               if(!error)
               {
                  //Save the time at which the query message was sent
                  entry->timestamp = time;
                  //Set timeout value
                  entry->timeout = DNS_CLIENT_INIT_TIMEOUT;
                  //Decrement retransmission counter
                  entry->retransmitCount--;
               }
               else
               {
                  //The entry should be deleted since name resolution has failed
                  dnsDeleteEntry(entry);
               }
            }
#endif
            else
            {
               //The maximum number of retransmissions has been exceeded
               dnsDeleteEntry(entry);
            }
         }
      }
      //Name successfully resolved?
      else if(entry->state == DNS_STATE_RESOLVED)
      {
         //Check the lifetime of the current DNS cache entry
         if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
         {
            //Periodically time out DNS cache entries
            dnsDeleteEntry(entry);
         }
      }
   }

   //Release exclusive access to the DNS cache
   osReleaseMutex(&dnsCacheMutex);
}
コード例 #4
0
ファイル: dns_client.c プロジェクト: rpc-fw/analyzer
void dnsProcessResponse(NetInterface *interface, const IpPseudoHeader *pseudoHeader,
   const UdpHeader *udpHeader, const ChunkedBuffer *buffer, size_t offset, void *params)
{
   uint_t i;
   uint_t j;
   size_t n;
   size_t pos;
   size_t length;
   DnsHeader *message;
   DnsQuestion *question;
   DnsResourceRecord *resourceRecord;
   DnsCacheEntry *entry;

   //Retrieve the length of the DNS message
   length = chunkedBufferGetLength(buffer) - offset;

   //Ensure the DNS message is valid
   if(length < sizeof(DnsHeader))
      return;
   if(length > DNS_MESSAGE_MAX_SIZE)
      return;

   //Point to the DNS message header
   message = chunkedBufferAt(buffer, offset);
   //Sanity check
   if(!message) return;

   //Debug message
   TRACE_INFO("DNS message received (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump message
   dnsDumpMessage(message, length);

   //Acquire exclusive access to the DNS cache
   osMutexAcquire(dnsCacheMutex);

   //Loop through DNS cache entries
   for(i = 0; i < DNS_CACHE_SIZE; i++)
   {
      //Point to the current entry
      entry = &dnsCache[i];

      //DNS name resolution in progress?
      if(entry->state == DNS_STATE_IN_PROGRESS &&
         entry->protocol == HOST_NAME_RESOLVER_DNS)
      {
         //Check destination port number
         if(entry->port == ntohs(udpHeader->destPort))
         {
            //Compare identifier against expected one
            if(ntohs(message->id) != entry->id)
               break;
            //Check message type
            if(!message->qr)
               break;
            //The DNS message shall contain one question
            if(ntohs(message->qdcount) != 1)
               break;

            //Point to the first question
            pos = sizeof(DnsHeader);

            //Parse domain name
            n = dnsParseName(message, length, pos, NULL, 0);

            //Invalid name?
            if(!n)
               break;
            //Malformed mDNS message?
            if((n + sizeof(DnsQuestion)) > length)
               break;

            //Compare domain name
            if(!dnsCompareName(message, length, pos, entry->name, 0))
               break;

            //Point to the corresponding entry
            question = DNS_GET_QUESTION(message, n);

            //Check the class of the query
            if(ntohs(question->qclass) != DNS_RR_CLASS_IN)
               break;
            //Check the type of the query
            if(entry->type == HOST_TYPE_IPV4 && ntohs(question->qtype) != DNS_RR_TYPE_A)
               break;
            if(entry->type == HOST_TYPE_IPV6 && ntohs(question->qtype) != DNS_RR_TYPE_AAAA)
               break;

            //Make sure recursion is available
            if(!message->ra)
            {
               //The entry should be deleted since name resolution has failed
               dnsDeleteEntry(entry);
               //Exit immediately
               break;
            }

            //Check return code
            if(message->rcode != DNS_RCODE_NO_ERROR)
            {
               //The entry should be deleted since name resolution has failed
               dnsDeleteEntry(entry);
               //Exit immediately
               break;
            }

            //Point to the first answer
            pos = n + sizeof(DnsQuestion);

            //Parse answer resource records
            for(j = 0; j < ntohs(message->ancount); j++)
            {
               //Parse domain name
               pos = dnsParseName(message, length, pos, NULL, 0);
               //Invalid name?
               if(!pos) break;

               //Point to the associated resource record
               resourceRecord = DNS_GET_RESOURCE_RECORD(message, pos);
               //Point to the resource data
               pos += sizeof(DnsResourceRecord);

               //Make sure the resource record is valid
               if(pos >= length)
                  break;
               if((pos + ntohs(resourceRecord->rdlength)) > length)
                  break;

#if (IPV4_SUPPORT == ENABLED)
               //IPv4 address expected?
               if(entry->type == HOST_TYPE_IPV4)
               {
                  //A resource record found?
                  if(ntohs(resourceRecord->rtype) == DNS_RR_TYPE_A)
                  {
                     //Verify the length of the data field
                     if(ntohs(resourceRecord->rdlength) == sizeof(Ipv4Addr))
                     {
                        //Copy the IPv4 address
                        entry->ipAddr.length = sizeof(Ipv4Addr);
                        ipv4CopyAddr(&entry->ipAddr.ipv4Addr, resourceRecord->rdata);

                        //Save current time
                        entry->timestamp = osGetTickCount();
                        //Save TTL value
                        entry->timeout = ntohl(resourceRecord->ttl) * 1000;
                        //Limit the lifetime of the DNS cache entries
                        entry->timeout = min(entry->timeout, DNS_MAX_LIFETIME);

                        //Unregister UDP callback function
                        udpDetachRxCallback(interface, entry->port);
                        //Host name successfully resolved
                        entry->state = DNS_STATE_RESOLVED;
                        //Exit immediately
                        break;
                     }
                  }
               }
#endif
#if (IPV6_SUPPORT == ENABLED)
               //IPv6 address expected?
               if(entry->type == HOST_TYPE_IPV6)
               {
                  //AAAA resource record found?
                  if(ntohs(resourceRecord->rtype) == DNS_RR_TYPE_AAAA)
                  {
                     //Verify the length of the data field
                     if(ntohs(resourceRecord->rdlength) == sizeof(Ipv6Addr))
                     {
                        //Copy the IPv6 address
                        entry->ipAddr.length = sizeof(Ipv6Addr);
                        ipv6CopyAddr(&entry->ipAddr.ipv6Addr, resourceRecord->rdata);

                        //Save current time
                        entry->timestamp = osGetTickCount();
                        //Save TTL value
                        entry->timeout = ntohl(resourceRecord->ttl) * 1000;
                        //Limit the lifetime of the DNS cache entries
                        entry->timeout = min(entry->timeout, DNS_MAX_LIFETIME);

                        //Unregister UDP callback function
                        udpDetachRxCallback(interface, entry->port);
                        //Host name successfully resolved
                        entry->state = DNS_STATE_RESOLVED;
                        //Exit immediately
                        break;
                     }
                  }
               }
#endif
               //Point to the next resource record
               pos += ntohs(resourceRecord->rdlength);
            }

            //We are done
            break;
         }
      }
   }

   //Release exclusive access to the DNS cache
   osMutexRelease(dnsCacheMutex);
}