error_t nbnsSendQuery(DnsCacheEntry *entry) { error_t error; size_t length; size_t offset; NetBuffer *buffer; NbnsHeader *message; DnsQuestion *dnsQuestion; IpAddr destIpAddr; //Allocate a memory buffer to hold the NBNS query message buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset); //Failed to allocate buffer? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the NBNS header message = netBufferAt(buffer, offset); //Format NBNS query message message->id = htons(entry->id); message->qr = 0; message->opcode = DNS_OPCODE_QUERY; message->aa = 0; message->tc = 0; message->rd = 0; message->ra = 0; message->z = 0; message->b = 1; message->rcode = DNS_RCODE_NO_ERROR; //The NBNS query contains one question message->qdcount = HTONS(1); message->ancount = 0; message->nscount = 0; message->arcount = 0; //Length of the NBNS query message length = sizeof(DnsHeader); //Encode the NetBIOS name length += nbnsEncodeName(entry->name, message->questions); //Point to the corresponding question structure dnsQuestion = DNS_GET_QUESTION(message, length); //Fill in question structure dnsQuestion->qtype = HTONS(DNS_RR_TYPE_NB); dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN); //Update the length of the NBNS query message length += sizeof(DnsQuestion); //Adjust the length of the multi-part buffer netBufferSetLength(buffer, offset + length); //Debug message TRACE_INFO("Sending NBNS message (%" PRIuSIZE " bytes)...\r\n", length); //Dump message dnsDumpMessage((DnsHeader *) message, length); //The destination address is the broadcast address destIpAddr.length = sizeof(Ipv4Addr); ipv4GetBroadcastAddr(entry->interface, &destIpAddr.ipv4Addr); //A request packet is always sent to the well known port 137 error = udpSendDatagramEx(entry->interface, NBNS_PORT, &destIpAddr, NBNS_PORT, buffer, offset, IPV4_DEFAULT_TTL); //Free previously allocated memory netBufferFree(buffer); //Return status code return error; }
error_t nbnsSendResponse(NetInterface *interface, const IpAddr *destIpAddr, uint16_t destPort, uint16_t id) { error_t error; size_t length; size_t offset; ChunkedBuffer *buffer; NbnsHeader *message; NbnsAddrEntry *addrEntry; DnsResourceRecord *resourceRecord; //Allocate a memory buffer to hold the NBNS response message buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset); //Failed to allocate buffer? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the NBNS header message = chunkedBufferAt(buffer, offset); //Take the identifier from the query message message->id = id; //Format NBNS response header message->qr = 1; message->opcode = DNS_OPCODE_QUERY; message->aa = 1; message->tc = 0; message->rd = 1; message->ra = 1; message->z = 0; message->b = 0; message->rcode = DNS_RCODE_NO_ERROR; //The NBNS response contains 1 answer resource record message->qdcount = 0; message->ancount = HTONS(1); message->nscount = 0; message->arcount = 0; //NBNS response message length length = sizeof(DnsHeader); //Encode the host name using the NBNS name notation length += nbnsEncodeName(interface->hostname, (uint8_t *) message + length); //Point to the corresponding resource record resourceRecord = DNS_GET_RESOURCE_RECORD(message, length); //Fill in resource record resourceRecord->rtype = HTONS(DNS_RR_TYPE_NB); resourceRecord->rclass = HTONS(DNS_RR_CLASS_IN); resourceRecord->ttl = HTONL(NBNS_DEFAULT_RESOURCE_RECORD_TTL); resourceRecord->rdlength = HTONS(sizeof(NbnsAddrEntry)); //Point to the address entry array addrEntry = (NbnsAddrEntry *) resourceRecord->rdata; //Fill in address entry addrEntry->flags = HTONS(NBNS_G_UNIQUE | NBNS_ONT_BNODE); addrEntry->addr = interface->ipv4Config.addr; //Update the length of the NBNS response message length += sizeof(DnsResourceRecord) + sizeof(NbnsAddrEntry); //Adjust the length of the multi-part buffer chunkedBufferSetLength(buffer, offset + length); //Debug message TRACE_INFO("Sending NBNS message (%" PRIuSIZE " bytes)...\r\n", length); //Dump message dnsDumpMessage((DnsHeader *) message, length); //A response packet is always sent to the source UDP port and //source IP address of the request packet error = udpSendDatagramEx(interface, NBNS_PORT, destIpAddr, destPort, buffer, offset, IPV4_DEFAULT_TTL); //Free previously allocated memory chunkedBufferFree(buffer); //Return status code return error; }