Webserver+3d print

Dependents:   Nucleo

Revision:
0:8918a71cdbe9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclone_tcp/netbios/nbns_client.c	Sat Feb 04 18:15:49 2017 +0000
@@ -0,0 +1,353 @@
+/**
+ * @file nbns_client.c
+ * @brief NBNS client (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_client.h"
+#include "netbios/nbns_common.h"
+#include "dns/dns_debug.h"
+#include "debug.h"
+
+//Check TCP/IP stack configuration
+#if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
+
+
+/**
+ * @brief Resolve a host name using NBNS
+ * @param[in] interface Underlying network interface
+ * @param[in] name Name of the host to be resolved
+ * @param[out] ipAddr IP address corresponding to the specified host name
+ **/
+
+error_t nbnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr)
+{
+   error_t error;
+   DnsCacheEntry *entry;
+
+#if (NET_RTOS_SUPPORT == ENABLED)
+   systime_t delay;
+
+   //Debug message
+   TRACE_INFO("Resolving host name %s (NBNS resolver)...\r\n", name);
+#endif
+
+   //Get exclusive access
+   osAcquireMutex(&netMutex);
+
+   //Search the DNS cache for the specified host name
+   entry = dnsFindEntry(interface, name, HOST_TYPE_IPV4, HOST_NAME_RESOLVER_NBNS);
+
+   //Check whether a matching entry has been found
+   if(entry)
+   {
+      //Host name already resolved?
+      if(entry->state == DNS_STATE_RESOLVED ||
+         entry->state == DNS_STATE_PERMANENT)
+      {
+         //Return the corresponding IP address
+         *ipAddr = entry->ipAddr;
+         //Successful host name resolution
+         error = NO_ERROR;
+      }
+      else
+      {
+         //Host name resolution is in progress...
+         error = ERROR_IN_PROGRESS;
+      }
+   }
+   else
+   {
+      //If no entry exists, then create a new one
+      entry = dnsCreateEntry();
+
+      //Record the host name whose IP address is unknown
+      strcpy(entry->name, name);
+
+      //Initialize DNS cache entry
+      entry->type = HOST_TYPE_IPV4;
+      entry->protocol = HOST_NAME_RESOLVER_NBNS;
+      entry->interface = interface;
+
+      //Initialize retransmission counter
+      entry->retransmitCount = NBNS_CLIENT_MAX_RETRIES;
+      //Send NBNS query
+      error = nbnsSendQuery(entry);
+
+      //NBNS message successfully sent?
+      if(!error)
+      {
+         //Save the time at which the query message was sent
+         entry->timestamp = osGetSystemTime();
+         //Set timeout value
+         entry->timeout = NBNS_CLIENT_INIT_TIMEOUT;
+         entry->maxTimeout = NBNS_CLIENT_MAX_TIMEOUT;
+         //Decrement retransmission counter
+         entry->retransmitCount--;
+
+         //Switch state
+         entry->state = DNS_STATE_IN_PROGRESS;
+         //Host name resolution is in progress
+         error = ERROR_IN_PROGRESS;
+      }
+   }
+
+   //Release exclusive access
+   osReleaseMutex(&netMutex);
+
+#if (NET_RTOS_SUPPORT == ENABLED)
+   //Set default polling interval
+   delay = DNS_CACHE_INIT_POLLING_INTERVAL;
+
+   //Wait the host name resolution to complete
+   while(error == ERROR_IN_PROGRESS)
+   {
+      //Wait until the next polling period
+      osDelayTask(delay);
+
+      //Get exclusive access
+      osAcquireMutex(&netMutex);
+
+      //Search the DNS cache for the specified host name
+      entry = dnsFindEntry(interface, name, HOST_TYPE_IPV4, HOST_NAME_RESOLVER_NBNS);
+
+      //Check whether a matching entry has been found
+      if(entry)
+      {
+         //Host name successfully resolved?
+         if(entry->state == DNS_STATE_RESOLVED)
+         {
+            //Return the corresponding IP address
+            *ipAddr = entry->ipAddr;
+            //Successful host name resolution
+            error = NO_ERROR;
+         }
+      }
+      else
+      {
+         //Host name resolution failed
+         error = ERROR_FAILURE;
+      }
+
+      //Release exclusive access
+      osReleaseMutex(&netMutex);
+
+      //Backoff support for less aggressive polling
+      delay = MIN(delay * 2, DNS_CACHE_MAX_POLLING_INTERVAL);
+   }
+
+   //Check status code
+   if(error)
+   {
+      //Failed to resolve host name
+      TRACE_INFO("Host name resolution failed!\r\n");
+   }
+   else
+   {
+      //Successful host name resolution
+      TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL));
+   }
+#endif
+
+   //Return status code
+   return error;
+}
+
+
+/**
+ * @brief Send a NBNS query message
+ * @param[in] entry Pointer to a valid DNS cache entry
+ * @return Error code
+ **/
+
+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 == NULL)
+      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;
+}
+
+
+/**
+ * @brief Process NBNS response 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 response message
+ * @param[in] length Length of the message
+ **/
+
+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 *record;
+   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
+   record = 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(record->rdlength)) > length)
+      return;
+
+   //Check the class and the type of the resource record
+   if(ntohs(record->rclass) != DNS_RR_CLASS_IN)
+      return;
+   if(ntohs(record->rtype) != DNS_RR_TYPE_NB)
+      return;
+
+   //Verify the length of the data field
+   if(ntohs(record->rdlength) < sizeof(NbnsAddrEntry))
+      return;
+
+   //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 *) record->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(record->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;
+            }
+         }
+      }
+   }
+}
+
+#endif
+