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); }