Webserver+3d print
Diff: cyclone_tcp/netbios/nbns_responder.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclone_tcp/netbios/nbns_responder.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,192 @@ +/** + * @file nbns_responder.c + * @brief NBNS responder (NetBIOS Name Service) + * + * @section License + * + * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneTCP Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 1.7.6 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL NBNS_TRACE_LEVEL + +//Dependencies +#include "core/net.h" +#include "netbios/nbns_responder.h" +#include "netbios/nbns_common.h" +#include "dns/dns_debug.h" +#include "debug.h" + +//Check TCP/IP stack configuration +#if (NBNS_RESPONDER_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) + + +/** + * @brief Process NBNS query message + * @param[in] interface Underlying network interface + * @param[in] pseudoHeader UDP pseudo header + * @param[in] udpHeader UDP header + * @param[in] message Pointer to the NBNS query message + * @param[in] length Length of the message + **/ + +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 NBNS query 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); + } +} + + +/** + * @brief Send NBNS response message + * @param[in] interface Underlying network interface + * @param[in] destIpAddr Destination IP address + * @param[in] destPort destination port + * @param[in] id 16-bit identifier to be used when sending NBNS query + **/ + +error_t nbnsSendResponse(NetInterface *interface, + const IpAddr *destIpAddr, uint16_t destPort, uint16_t id) +{ + error_t error; + size_t length; + size_t offset; + NetBuffer *buffer; + NbnsHeader *message; + NbnsAddrEntry *addrEntry; + DnsResourceRecord *record; + + //Allocate a memory buffer to hold the NBNS response message + buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset); + //Failed to allocate buffer? + if(buffer == NULL) + return ERROR_OUT_OF_MEMORY; + + //Point to the NBNS header + message = netBufferAt(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 + record = DNS_GET_RESOURCE_RECORD(message, length); + //Fill in resource record + record->rtype = HTONS(DNS_RR_TYPE_NB); + record->rclass = HTONS(DNS_RR_CLASS_IN); + record->ttl = HTONL(NBNS_DEFAULT_RESOURCE_RECORD_TTL); + record->rdlength = HTONS(sizeof(NbnsAddrEntry)); + + //Point to the address entry array + addrEntry = (NbnsAddrEntry *) record->rdata; + //Fill in address entry + addrEntry->flags = HTONS(NBNS_G_UNIQUE | NBNS_ONT_BNODE); + addrEntry->addr = interface->ipv4Context.addr; + + //Update the length of the NBNS response message + length += sizeof(DnsResourceRecord) + sizeof(NbnsAddrEntry); + + //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); + + //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 + netBufferFree(buffer); + //Return status code + return error; +} + +#endif +