示例#1
0
void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader,
   const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
{
   size_t pos;
   DnsQuestion *question;

   //The NBNS query shall contain one question
   if(ntohs(message->qdcount) != 1)
      return;

   //Parse NetBIOS name
   pos = nbnsParseName(message, length, sizeof(DnsHeader), NULL);

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

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

   //Check the class and the type of the request
   if(ntohs(question->qclass) != DNS_RR_CLASS_IN)
      return;
   if(ntohs(question->qtype) != DNS_RR_TYPE_NB)
      return;

   //Compare NetBIOS names
   if(nbnsCompareName(message, length, sizeof(DnsHeader), interface->hostname))
   {
      uint16_t destPort;
      IpAddr destIpAddr;

      //A response packet is always sent to the source UDP port and
      //source IP address of the request packet
      destIpAddr.length = sizeof(Ipv4Addr);
      destIpAddr.ipv4Addr = pseudoHeader->srcAddr;

      //Convert the port number to host byte order
      destPort = ntohs(udpHeader->srcPort);

      //Send NBNS response
      nbnsSendResponse(interface, &destIpAddr, destPort, message->id);
   }
}
void nbnsProcessResponse(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader,
   const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
{
   uint_t i;
   size_t pos;
   DnsCacheEntry *entry;
   DnsResourceRecord *resourceRecord;
   NbnsAddrEntry *addrEntry;

   //The NBNS response shall contain one answer
   if(ntohs(message->qdcount) != 0 && ntohs(message->ancount) != 1)
      return;

   //Parse NetBIOS name
   pos = nbnsParseName(message, length, sizeof(DnsHeader), NULL);
   //Invalid name?
   if(!pos) return;

   //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)
      return;
   if((pos + ntohs(resourceRecord->rdlength)) > length)
      return;

   //Check the class and the type of the resource record
   if(ntohs(resourceRecord->rclass) != DNS_RR_CLASS_IN)
      return;
   if(ntohs(resourceRecord->rtype) != DNS_RR_TYPE_NB)
      return;

   //Verify the length of the data field
   if(ntohs(resourceRecord->rdlength) < sizeof(NbnsAddrEntry))
      return;

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

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

      //NBNS name resolution in progress?
      if(entry->state == DNS_STATE_IN_PROGRESS &&
         entry->protocol == HOST_NAME_RESOLVER_NBNS &&
         entry->type == HOST_TYPE_IPV4)
      {
         //Compare identifiers
         if(entry->id == ntohs(message->id))
         {
            //Compare NetBIOS names
            if(nbnsCompareName(message, length, sizeof(DnsHeader), entry->name))
            {
               //Point to the address entry array
               addrEntry = (NbnsAddrEntry *) resourceRecord->rdata;
               //Copy the IPv4 address
               entry->ipAddr.length = sizeof(Ipv4Addr);
               entry->ipAddr.ipv4Addr = addrEntry->addr;

               //Save current time
               entry->timestamp = osGetSystemTime();
               //Save TTL value
               entry->timeout = ntohl(resourceRecord->ttl) * 1000;
               //Limit the lifetime of the NBNS cache entries
               entry->timeout = MIN(entry->timeout, NBNS_MAX_LIFETIME);

               //Host name successfully resolved
               entry->state = DNS_STATE_RESOLVED;
            }
         }
      }
   }

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