void udpDiscardTask(void *param)
{
   error_t error;
   size_t length;
   uint16_t port;
   IpAddr ipAddr;
   DiscardServiceContext *context;

   //Get a pointer to the context
   context = (DiscardServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, DISCARD_BUFFER_SIZE, &length, 0);

      //Any datagram received?
      if(!error)
      {
         //Debug message
         TRACE_INFO("Discard service: %" PRIuSIZE " bytes received from %s port %" PRIu16 "\r\n",
            length, ipAddrToString(&ipAddr, NULL), port);

         //Throw away any received datagram...
      }
   }
}
Exemple #2
0
void udpChargenTask(void *param)
{
   error_t error;
   size_t i;
   size_t k;
   size_t n;
   size_t length;
   uint16_t port;
   IpAddr ipAddr;
   ChargenServiceContext *context;

   //Get a pointer to the context
   context = (ChargenServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, CHARGEN_BUFFER_SIZE, &n, 0);

      //Any datagram received?
      if(!error)
      {
         //When a datagram is received, an answering datagram is sent
         //containing a random number (between 0 and 512) of characters
         length = tcpIpStackGetRand() % 513;

         //Reset line counter
         n = 0;

         //Format output data
         for(i = 0; i < length; i += 74)
         {
            //Calculate the length of the current line
            k = min(length - i, 74);
            //Copy character pattern
            memcpy(context->buffer + i, pattern + n, k);

            //End each line with carriage return and line feed
            if(k == 74)
            {
               context->buffer[i + 72] = '\r';
               context->buffer[i + 73] = '\n';
            }

            //Increment line counter
            if(++n >= 95) n = 0;
         }

         //Send data to the remote host
         error = socketSendTo(context->socket, &ipAddr, port,
            context->buffer, length, &n, 0);

         //Debug message
         TRACE_INFO("Chargen service: %" PRIuSIZE " bytes sent to %s port %" PRIu16 "\r\n",
            n, ipAddrToString(&ipAddr, NULL), port);
      }
   }
}
Exemple #3
0
void udpEchoTask(void *param)
{
   error_t error;
   uint_t length;
   uint16_t port;
   IpAddr ipAddr;
   EchoServiceContext *context;

   //Get a pointer to the context
   context = (EchoServiceContext *) param;

   //Main loop
   while(1)
   {
      //Wait for an incoming datagram
      error = socketReceiveFrom(context->socket, &ipAddr, &port,
         context->buffer, ECHO_BUFFER_SIZE, &length, 0);

      //Any datagram received?
      if(!error)
      {
         //Debug message
         TRACE_INFO("Echo service: %u bytes received from %s port %u\r\n",
            length, ipAddrToString(&ipAddr, NULL), port);

         //Send the data back to the source
         error = socketSendTo(context->socket, &ipAddr, port,
            context->buffer, length, NULL, 0);
      }
   }
}
Exemple #4
0
error_t sntpClientTest(void)
{
   error_t error;
   time_t unixTime;
   IpAddr ipAddr;
   NtpTimestamp timestamp;
   DateTime date;

   //Debug message
   TRACE_INFO("\r\n\r\nResolving server name...\r\n");
   //Resolve SNTP server name
   error = getHostByName(NULL, "0.fr.pool.ntp.org", &ipAddr, 0);

   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to resolve server name!\r\n");
      //Exit immediately
      return error;
   }

   //Debug message
   TRACE_INFO("Requesting time from SNTP server %s\r\n", ipAddrToString(&ipAddr, NULL));
   //Retrieve current time from NTP server using SNTP protocol
   error = sntpClientGetTimestamp(NULL, &ipAddr, &timestamp);

   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to retrieve NTP timestamp!\r\n");
   }
   else
   {
      //Unix time starts on January 1st, 1970
      unixTime = timestamp.seconds - 2208988800;
      //Convert Unix timestamp to date
      convertUnixTimeToDate(unixTime, &date);

      //Debug message
      TRACE_INFO("Current date/time: %s\r\n", formatDate(&date, NULL));

      //Move cursor
      lcdSetCursor(8, 0);

      //Refresh LCD display
      printf("%04u/%02u/%02u %02u:%02u:%02u", date.year, date.month,
         date.day, date.hours, date.minutes, date.seconds);
   }

   //Return status code
   return error;
}
Exemple #5
0
char *
rawIpAddrToString(void *rawAddr, int len)
{
  struct ipAddr addr;

  if (len == 4) {
    memcpy(&addr.addr.v4, rawAddr, 4);
    addr.domain = PF_INET;
  }

  else {
    memcpy(&addr.addr.v6, rawAddr, 16);
    addr.domain = PF_INET6;
  }

  return ipAddrToString(&addr);
}
Exemple #6
0
error_t dnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr)
{
   error_t error;
   uint_t i;
   size_t length;
   uint16_t identifier;
   IpAddr serverIpAddr;
   Socket *socket;
   DnsHeader *dnsMessage;

   //Debug message
   TRACE_INFO("Trying to resolve %s...\r\n", name);

   //Use default network interface?
   if(!interface)
      interface = tcpIpStackGetDefaultInterface();

   //Allocate a memory buffer to hold DNS messages
   dnsMessage = memPoolAlloc(DNS_MESSAGE_MAX_SIZE);
   //Failed to allocate memory?
   if(!dnsMessage)
      return ERROR_OUT_OF_MEMORY;

   //Open a UDP socket
   socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_PROTOCOL_UDP);

   //Failed to open socket?
   if(!socket)
   {
      //Free previously allocated memory
      osMemFree(dnsMessage);
      //Return status code
      return ERROR_OPEN_FAILED;
   }

#if (IPV4_SUPPORT == ENABLED)
   //IP address of the DNS server
   serverIpAddr.length = sizeof(Ipv4Addr);
   serverIpAddr.ipv4Addr = interface->ipv4Config.dnsServer[0];
#elif (IPV6_SUPPORT == ENABLED)
   //IP address of the DNS server
   serverIpAddr.length = sizeof(Ipv6Addr);
   serverIpAddr.ipv6Addr = interface->ipv6Config.dnsServer[0];
#endif

   //Associate the socket with the relevant interface
   error = socketBindToInterface(socket, interface);

   //Any error to report?
   if(error)
   {
      //Free previously allocated memory
      osMemFree(dnsMessage);
      //Close socket
      socketClose(socket);
      //Return status code
      return error;
   }

   //Connect the newly created socket to the primary DNS server
   error = socketConnect(socket, &serverIpAddr, DNS_PORT);

   //Failed to connect?
   if(error)
   {
      //Free previously allocated memory
      osMemFree(dnsMessage);
      //Close socket
      socketClose(socket);
      //Return status code
      return error;
   }

   //An identifier is used by the client to match replies
   //with corresponding requests
   identifier = rand();

   //Try to retransmit the DNS message if the previous query timed out
   for(i = 0; i < DNS_MAX_RETRIES; i++)
   {
      //Send DNS query message
      error = dnsSendQuery(socket, dnsMessage, identifier, name);
      //Failed to send message ?
      if(error) break;

      //Adjust receive timeout
      error = socketSetTimeout(socket, DNS_REQUEST_TIMEOUT);
      //Any error to report?
      if(error) break;

      //Wait for the server response
      error = socketReceive(socket, dnsMessage, DNS_MESSAGE_MAX_SIZE, &length, 0);

      //Any response from the specified DNS server?
      if(!error)
      {
         //Parse DNS response
         error = dnsParseResponse(dnsMessage, length, identifier, ipAddr);
         //DNS response successfully decoded?
         if(!error) break;
      }
   }

   //The maximum number of retransmissions has been reached?
   if(i >= DNS_MAX_RETRIES)
      error = ERROR_TIMEOUT;

   //Free previously allocated memory
   osMemFree(dnsMessage);
   //Close socket
   socketClose(socket);

   //Debug message
   if(!error)
   {
      //Name resolution succeeds
      TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL));
   }
   else
   {
      //Report an error
      TRACE_ERROR("DNS resolution failed!\r\n");
   }

   //Return status code
   return error;
}
Exemple #7
0
void tcpEchoListenerTask(void *param)
{
   error_t error;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   Socket *serverSocket;
   Socket *clientSocket;
   EchoServiceContext *context;
   OsTask *task;

   //Point to the listening socket
   serverSocket = (Socket *) param;

   //Main loop
   while(1)
   {
      //Accept an incoming connection
      clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
      //Check whether a valid connection request has been received
      if(!clientSocket) continue;

      //Debug message
      TRACE_INFO("Echo service: connection established with client %s port %u\r\n",
         ipAddrToString(&clientIpAddr, NULL), clientPort);

      //The socket operates in non-blocking mode
      error = socketSetTimeout(clientSocket, 0);

      //Any error to report?
      if(error)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Allocate resources for the new connection
      context = osMemAlloc(sizeof(EchoServiceContext));

      //Failed to allocate memory?
      if(!context)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Record the handle of the newly created socket
      context->socket = clientSocket;

      //Create a task to service the current connection
      task = osTaskCreate("TCP Echo Connection", tcpEchoConnectionTask,
         context, ECHO_SERVICE_STACK_SIZE, ECHO_SERVICE_PRIORITY);

      //Did we encounter an error?
      if(task == OS_INVALID_HANDLE)
      {
         //Close socket
         socketClose(clientSocket);
         //Release resources
         osMemFree(context);
      }
   }
}
Exemple #8
0
error_t ftpClientTest(void)
{
   error_t error;
   size_t length;
   IpAddr ipAddr;
   FtpClientContext ftpContext;
   static char_t buffer[256];

   //Debug message
   TRACE_INFO("\r\n\r\nResolving server name...\r\n");
   //Resolve FTP server name
   error = getHostByName(NULL, "ftp.gnu.org", &ipAddr, 0);

   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to resolve server name!\r\n");
      //Exit immediately
      return error;
   }

   //Debug message
   TRACE_INFO("Connecting to FTP server %s\r\n", ipAddrToString(&ipAddr, NULL));
   //Connect to the FTP server
   error = ftpConnect(&ftpContext, NULL, &ipAddr, 21, FTP_NO_SECURITY | FTP_PASSIVE_MODE);

   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to connect to FTP server!\r\n");
      //Exit immediately
      return error;
   }

   //Debug message
   TRACE_INFO("Successful connection\r\n");

   //Start of exception handling block
   do
   {
      //Login to the FTP server using the provided username and password
      error = ftpLogin(&ftpContext, "anonymous", "password", "");
      //Any error to report?
      if(error) break;

      //Open the specified file for reading
      error = ftpOpenFile(&ftpContext, "welcome.msg", FTP_FOR_READING | FTP_BINARY_TYPE);
      //Any error to report?
      if(error) break;

      //Dump the contents of the file
      while(1)
      {
         //Read data
         error = ftpReadFile(&ftpContext, buffer, sizeof(buffer) - 1, &length, 0);
         //End of file?
         if(error) break;

         //Properly terminate the string with a NULL character
         buffer[length] = '\0';
         //Dump current data
         TRACE_INFO("%s", buffer);
      }

      //End the string with a line feed
      TRACE_INFO("\r\n");
      //Close the file
      error = ftpCloseFile(&ftpContext);

      //End of exception handling block
   } while(0);

   //Close the connection
   ftpClose(&ftpContext);
   //Debug message
   TRACE_INFO("Connection closed...\r\n");

   //Return status code
   return error;
}
error_t snmpParseMessage(SnmpAgentContext *context, const uint8_t *p, size_t length)
{
   error_t error;
   int32_t version;
   Asn1Tag tag;

   //Debug message
   TRACE_INFO("SNMP message received from %s port %" PRIu16 " (%" PRIuSIZE " bytes)...\r\n",
      ipAddrToString(&context->remoteIpAddr, NULL), context->remotePort, length);

   //Display the contents of the SNMP message
   TRACE_DEBUG_ARRAY("  ", p, length);

   //Dump ASN.1 structure
   error = asn1DumpObject(p, length, 0);
   //Any error to report?
   if(error) return error;

   //The SNMP message is encapsulated within a sequence
   error = asn1ReadTag(p, length, &tag);
   //Failed to decode ASN.1 tag?
   if(error) return error;

   //Enforce encoding, class and type
   error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
   //The tag does not match the criteria?
   if(error) return error;

   //Point to the first field of the sequence
   p = tag.value;
   length = tag.length;

   //Read version identifier
   error = asn1ReadInt32(p, length, &tag, &version);
   //Failed to decode ASN.1 tag?
   if(error) return error;

   //The SNMP agent verifies the version number. If there is a mismatch,
   //it discards the datagram and performs no further actions
   if(version != context->version)
      return ERROR_INVALID_VERSION;

   //Point to the next field
   p += tag.totalLength;
   length -= tag.totalLength;

   //Read SNMP community name
   error = asn1ReadTag(p, length, &tag);
   //Failed to decode ASN.1 tag?
   if(error) return error;

   //Enforce encoding, class and type
   error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OCTET_STRING);
   //The tag does not match the criteria?
   if(error) return error;

   //Save community name
   context->request.community = tag.value;
   context->request.communityLen = tag.length;

   //Point to the next field
   p += tag.totalLength;
   length -= tag.totalLength;

   //Read PDU
   error = asn1ReadTag(p, length, &tag);
   //Failed to decode ASN.1 tag?
   if(error) return error;

   //Check encoding
   if(tag.constructed != TRUE)
      return ERROR_WRONG_ENCODING;
   //Enforce class
   if(tag.class != ASN1_CLASS_CONTEXT_SPECIFIC)
      return ERROR_INVALID_CLASS;

   //Save PDU type
   context->request.pduType = (SnmpPduType) tag.type;

   //Process the protocol data unit
   switch(context->request.pduType)
   {
   case SNMP_PDU_GET_REQUEST:
   case SNMP_PDU_GET_NEXT_REQUEST:
      //Parse GetRequest-PDU or GetNextRequest-PDU
      error = snmpParseGetRequestPdu(context, tag.value, tag.length);
      break;
   case SNMP_PDU_GET_BULK_REQUEST:
      //Parse GetBulkRequest-PDU
      error = snmpParseGetBulkRequestPdu(context, tag.value, tag.length);
      break;
   case SNMP_PDU_SET_REQUEST:
      //Parse SetRequest-PDU
      error = snmpParseSetRequestPdu(context, tag.value, tag.length);
      break;
   default:
      //Invalid PDU type
      error = ERROR_INVALID_TYPE;
      break;
   }

   //Failed to parse PDU?
   if(error)
      return error;

   //Format response PDU header
   error = snmpWritePduHeader(context);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_INFO("SNMP message sent (%" PRIuSIZE " bytes)...\r\n", context->response.messageLen);
   //Display the contents of the SNMP message
   TRACE_DEBUG_ARRAY("  ", context->response.message, context->response.messageLen);

   //Display ASN.1 structure
   error = asn1DumpObject(context->response.message, context->response.messageLen, 0);
   //Any error to report?
   if(error) return error;

   //Send SNMP response message
   error = socketSendTo(context->socket, &context->remoteIpAddr, context->remotePort,
      context->response.message, context->response.messageLen, NULL, 0);

   //Return status code
   return error;
}
Exemple #10
0
error_t ssiProcessEchoCommand(HttpConnection *connection, const char_t *tag, size_t length)
{
   error_t error;
   char_t *separator;
   char_t *attribute;
   char_t *value;

   //Discard invalid SSI directives
   if(length < 4 || length >= HTTP_SERVER_BUFFER_SIZE)
      return ERROR_INVALID_TAG;

   //Skip the SSI echo command (4 bytes)
   memcpy(connection->buffer, tag + 4, length - 4);
   //Ensure the resulting string is NULL-terminated
   connection->buffer[length - 4] = '\0';

   //Check whether a separator is present
   separator = strchr(connection->buffer, '=');
   //Separator not found?
   if(!separator)
      return ERROR_INVALID_TAG;

   //Split the tag
   *separator = '\0';

   //Get attribute name and value
   attribute = strTrimWhitespace(connection->buffer);
   value = strTrimWhitespace(separator + 1);

   //Remove leading simple or double quote
   if(value[0] == '\'' || value[0] == '\"')
      value++;

   //Get the length of the attribute value
   length = strlen(value);

   //Remove trailing simple or double quote
   if(length > 0)
   {
      if(value[length - 1] == '\'' || value[length - 1] == '\"')
         value[length - 1] = '\0';
   }

   //Enforce attribute name
   if(strcasecmp(attribute, "var"))
      return ERROR_INVALID_TAG;

   //Remote address?
   if(!strcasecmp(value, "REMOTE_ADDR"))
   {
      //The IP address of the host making this request
      ipAddrToString(&connection->socket->remoteIpAddr, connection->buffer);
   }
   //Remote port?
   else if(!strcasecmp(value, "REMOTE_PORT"))
   {
      //The port number used by the remote host when making this request
      sprintf(connection->buffer, "%" PRIu16, connection->socket->remotePort);
   }
   //Server address?
   else if(!strcasecmp(value, "SERVER_ADDR"))
   {
      //The IP address of the server for this URL
      ipAddrToString(&connection->socket->localIpAddr, connection->buffer);
   }
   //Server port?
   else if(!strcasecmp(value, "SERVER_PORT"))
   {
      //The port number on this server to which this request was directed
      sprintf(connection->buffer, "%" PRIu16, connection->socket->localPort);
   }
   //Request method?
   else if(!strcasecmp(value, "REQUEST_METHOD"))
   {
      //The method used for this HTTP request
      strcpy(connection->buffer, connection->request.method);
   }
   //Document root?
   else if(!strcasecmp(value, "DOCUMENT_ROOT"))
   {
      //The root directory
      strcpy(connection->buffer, connection->settings->rootDirectory);
   }
   //Document URI?
   else if(!strcasecmp(value, "DOCUMENT_URI"))
   {
      //The URI for this request relative to the root directory
      strcpy(connection->buffer, connection->request.uri);
   }
   //Document name?
   else if(!strcasecmp(value, "DOCUMENT_NAME"))
   {
      //The full physical path and filename of the document requested
      httpGetAbsolutePath(connection, connection->request.uri,
         connection->buffer, HTTP_SERVER_BUFFER_SIZE);
   }
   //Query string?
   else if(!strcasecmp(value, "QUERY_STRING"))
   {
      //The information following the "?" in the URL for this request
      strcpy(connection->buffer, connection->request.queryString);
   }
   //User name?
   else if(!strcasecmp(value, "AUTH_USER"))
   {
#if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
      //The username provided by the user to the server
      strcpy(connection->buffer, connection->request.auth.user);
#else
      //Basic access authentication is not supported
      connection->buffer[0] = '\0';
#endif
   }
   //GMT time?
   else if(!strcasecmp(value, "DATE_GMT"))
   {
      //The current date and time in Greenwich Mean Time
      connection->buffer[0] = '\0';
   }
   //Local time?
   else if(!strcasecmp(value, "DATE_LOCAL"))
   {
      //The current date and time in the local timezone
      connection->buffer[0] = '\0';
   }
   //Unknown variable?
   else
   {
      //Report an error
      return ERROR_INVALID_TAG;
   }

   //Get the length of the resulting string
   length = strlen(connection->buffer);

   //Send the contents of the specified environment variable
   error = httpWriteStream(connection, connection->buffer, length);
   //Failed to send data?
   if(error) return error;

   //Successful processing
   return NO_ERROR;
}
void httpListenerTask(void *param)
{
   uint_t i;
   uint_t counter;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   HttpServerContext *context;
   HttpConnection* connection;
   Socket *socket;

   //Retrieve the HTTP server context
   context = (HttpServerContext *) param;

   //Process incoming connections to the server
   for(counter = 1; ; counter++)
   {
      //Debug message
      TRACE_INFO("Ready to accept a new connection...\r\n");

      //Limit the number of simultaneous connections to the HTTP server
      osWaitForSemaphore(&context->semaphore, INFINITE_DELAY);

      //Loop through available client connections
      for(i = 0; i < context->settings.maxConnections; i++)
      {
         //Point to the current connection
         connection = &context->connections[i];

         //Ready to service the client request?
         if(!connection->running)
         {
            //Accept an incoming connection
            socket = socketAccept(context->socket, &clientIpAddr, &clientPort);

            //Make sure the socket handle is valid
            if(socket != NULL)
            {
               //Debug message
               TRACE_INFO("Connection #%u established with client %s port %" PRIu16 "...\r\n",
                  counter, ipAddrToString(&clientIpAddr, NULL), clientPort);

               //Reference to the HTTP server settings
               connection->settings = &context->settings;
               //Reference to the HTTP server context
               connection->serverContext = context;
               //Reference to the new socket
               connection->socket = socket;

               //Set timeout for blocking functions
               socketSetTimeout(connection->socket, HTTP_SERVER_TIMEOUT);

               //The client connection task is now running...
               connection->running = TRUE;
               //Service the current connection request
               osSetEvent(&connection->startEvent);

               //We are done
               break;
            }
         }
      }
   }
}
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

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

   //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 to the DNS cache
   osReleaseMutex(&dnsCacheMutex);

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

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

      //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 to the DNS cache
      osReleaseMutex(&dnsCacheMutex);

      //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;
}
Exemple #13
0
error_t sslClientTest(void)
{
   error_t error;
   size_t length;
   IpAddr ipAddr;
   static char_t buffer[256];

   //Underlying socket
   Socket *socket = NULL;
   //SSL/TLS context
   TlsContext *tlsContext = NULL;

   //Debug message
   TRACE_INFO("Resolving server name...\r\n");

   //Resolve SSL server name
   error = getHostByName(NULL, APP_SERVER_NAME, &ipAddr, 0);
   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to resolve server name!\r\n");
      //Exit immediately
      return error;
   }

   //Create a new socket to handle the request
   socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
   //Any error to report?
   if(!socket)
   {
      //Debug message
      TRACE_INFO("Failed to open socket!\r\n");
      //Exit immediately
      return ERROR_OPEN_FAILED;
   }

   //Start of exception handling block
   do
   {
      //Debug message
      TRACE_INFO("Connecting to SSL server %s\r\n", ipAddrToString(&ipAddr, NULL));

      //Connect to the SSL server
      error = socketConnect(socket, &ipAddr, APP_SERVER_PORT);
      //Any error to report?
      if(error) break;

      //Initialize SSL/TLS context
      tlsContext = tlsInit();
      //Initialization failed?
      if(!tlsContext)
      {
         //Report an error
         error = ERROR_OUT_OF_MEMORY;
         //Exit immediately
         break;
      }

      //Bind TLS to the relevant socket
      error = tlsSetSocket(tlsContext, socket);
      //Any error to report?
      if(error) break;

      //Select client operation mode
      error = tlsSetConnectionEnd(tlsContext, TLS_CONNECTION_END_CLIENT);
      //Any error to report?
      if(error) break;

      //Set the PRNG algorithm to be used
      error = tlsSetPrng(tlsContext, YARROW_PRNG_ALGO, &yarrowContext);
      //Any error to report?
      if(error) break;

#if (APP_SET_CIPHER_SUITES == ENABLED)
      //Preferred cipher suite list
      error = tlsSetCipherSuites(tlsContext, cipherSuites, arraysize(cipherSuites));
      //Any error to report?
      if(error) break;
#endif

#if (APP_SET_SERVER_NAME == ENABLED)
      //Set the fully qualified domain name of the server
      error = tlsSetServerName(tlsContext, APP_SERVER_NAME);
      //Any error to report?
      if(error) break;
#endif

#if (APP_SET_TRUSTED_CA_LIST == ENABLED)
      //Import the list of trusted CA certificates
      error = tlsSetTrustedCaList(tlsContext, trustedCaList, trustedCaListLength);
      //Any error to report?
      if(error) break;
#endif

#if (APP_SET_CLIENT_CERT == ENABLED)
      //Import the client's certificate
      error = tlsAddCertificate(tlsContext, clientCert,
         clientCertLength, clientPrivateKey, clientPrivateKeyLength);
      //Any error to report?
      if(error) break;
#endif

      //Establish a secure session
      error = tlsConnect(tlsContext);
      //TLS handshake failure?
      if(error) break;

      //Format HTTP request
      sprintf(buffer, "GET %s HTTP/1.0\r\nHost: %s:%u\r\n\r\n",
         APP_REQUEST_URI, APP_SERVER_NAME, APP_SERVER_PORT);

      //Debug message
      TRACE_INFO("\r\n");
      TRACE_INFO("HTTP request:\r\n%s", buffer);

      //Send the request
      error = tlsWrite(tlsContext, buffer, strlen(buffer), 0);
      //Any error to report?
      if(error) break;

      //Debug message
      TRACE_INFO("HTTP response:\r\n");

      //Read the whole response
      while(1)
      {
         //Read data
         error = tlsRead(tlsContext, buffer, sizeof(buffer) - 1, &length, 0);
         //End of stream?
         if(error) break;

         //Properly terminate the string with a NULL character
         buffer[length] = '\0';
         //Debug message
         TRACE_INFO("%s", buffer);
      }

      //Successfull processing
      error = NO_ERROR;

      //End of exception handling block
   } while(0);

   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to communicate with SSL server!\r\n");
   }

   //Terminate TLS session
   tlsFree(tlsContext);
   //Close socket
   socketClose(socket);

   //Debug message
   TRACE_INFO("Connection closed...\r\n");

   //Return status code
   return error;
}
Exemple #14
0
error_t httpClientTest(void)
{
   error_t error;
   size_t length;
   IpAddr ipAddr;
   Socket *socket;
   static char_t buffer[256];

   //Debug message
   TRACE_INFO("\r\n\r\nResolving server name...\r\n");

   //Resolve HTTP server name
   error = getHostByName(NULL, CLIENT_SERVER_NAME, &ipAddr, 1, NULL, 0);
   //Any error to report?
   if(error)
   {
      //Debug message
      TRACE_INFO("Failed to resolve server name!\r\n");
      //Exit immedialtely
      return error;
   }

   //Create a new socket to handle the request
   socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_PROTOCOL_TCP);
   //Any error to report?
   if(!socket)
   {
      //Debug message
      TRACE_INFO("Failed to open socket!\r\n");
      //Exit immedialtely
      return error;
   }

   //Start of exception handling block
   do
   {
      //Debug message
      TRACE_INFO("Connecting to HTTP server %s\r\n", ipAddrToString(&ipAddr, NULL));

      //Connect to the HTTP server
      error = socketConnect(socket, &ipAddr, CLIENT_SERVER_PORT);
      //Any error to report?
      if(error) break;

      //Debug message
      TRACE_INFO("Successful connection\r\n");

      //Format HTTP request
      length = sprintf(buffer, "GET %s HTTP/1.0\r\nHost: %s:%u\r\n\r\n",
         CLIENT_REQUEST_URI, CLIENT_SERVER_NAME, CLIENT_SERVER_PORT);

      //Debug message
      TRACE_INFO("\r\nHTTP request:\r\n%s", buffer);

      //Send HTTP request
      error = socketSend(socket, buffer, length, NULL, 0);
      //Any error to report?
      if(error) break;

      //Debug message
      TRACE_INFO("HTTP response header:\r\n");

      //Parse HTTP response header
      while(1)
      {
         //Read the header line by line
         error = socketReceive(socket, buffer, sizeof(buffer) - 1, &length, SOCKET_FLAG_BREAK_CRLF);
         //End of stream?
         if(error) break;

         //Properly terminate the string with a NULL character
         buffer[length] = '\0';
         //Dump current data
         TRACE_INFO("%s", buffer);

         //The end of the header has been reached?
         if(!strcmp(buffer, "\r\n"))
            break;
      }

      //Debug message
      TRACE_INFO("HTTP response body:\r\n");

      //Parse HTTP response body
      while(1)
      {
         //Read response body
         error = socketReceive(socket, buffer, sizeof(buffer) - 1, &length, 0);
         //End of stream?
         if(error) break;

         //Properly terminate the string with a NULL character
         buffer[length] = '\0';
         //Dump current data
         TRACE_INFO("%s", buffer);
      }

      //End of exception handling block
   } while(0);

   //Close the connection
   socketClose(socket);
   //Debug message
   TRACE_INFO("\r\nConnection closed...\r\n");

   //Return status code
   return error;
}
Exemple #15
0
error_t dnsResolve(NetInterface *interface,
   const char_t *name, HostType type, IpAddr *ipAddr)
{
   error_t error;
   systime_t delay;
   DnsCacheEntry *entry;

   //Debug message
   TRACE_INFO("Resolving host name %s (DNS resolver)...\r\n", name);

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

   //Search the DNS cache for the specified host name
   entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_DNS);

   //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 = type;
      entry->protocol = HOST_NAME_RESOLVER_DNS;
      entry->interface = interface;
      //Select primary DNS server
      entry->dnsServerNum = 0;
      //Get an ephemeral port number
      entry->port = socketGetEphemeralPort();

      //An identifier is used by the DNS client to match replies
      //with corresponding requests
      entry->id = tcpIpStackGetRand();

      //Callback function to be called when a DNS response is received
      error = udpAttachRxCallback(interface, entry->port, dnsProcessResponse, NULL);

      //Check status code
      if(!error)
      {
         //Initialize retransmission counter
         entry->retransmitCount = DNS_CLIENT_MAX_RETRIES;
         //Send DNS query
         error = dnsSendQuery(entry);

         //DNS message successfully sent?
         if(!error)
         {
            //Save the time at which the query message was sent
            entry->timestamp = osGetTickCount();
            //Set timeout value
            entry->timeout = DNS_CLIENT_INIT_TIMEOUT;
            entry->maxTimeout = DNS_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;
         }
         else
         {
            //Unregister callback function
            udpDetachRxCallback(interface, entry->port);
         }
      }
   }

   //Release exclusive access to the DNS cache
   osMutexRelease(dnsCacheMutex);

   //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
      osDelay(delay);

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

      //Search the DNS cache for the specified host name
      entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_DNS);

      //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 to the DNS cache
      osMutexRelease(dnsCacheMutex);

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

   //Return status code
   return error;
}
Exemple #16
0
error_t ping(NetInterface *interface, const IpAddr *ipAddr, time_t timeout, time_t *rtt)
{
   error_t error;
   uint_t i;
   size_t length;
   uint16_t identifier;
   uint16_t sequenceNumber;
   time_t startTime;
   time_t roundTripTime;
   Socket *socket;
   IcmpEchoMessage *message;

   //Debug message
   TRACE_INFO("Pinging %s with 64 bytes of data...\r\n", ipAddrToString(ipAddr, NULL));

   //Length of the complete ICMP message including header and data
   length = sizeof(IcmpEchoMessage) + PING_DATA_SIZE;

   //Allocate memory buffer to hold an ICMP message
   message = osMemAlloc(length);
   //Failed to allocate memory?
   if(!message) return ERROR_OUT_OF_MEMORY;

   //Identifier field is used to help matching requests and replies
   identifier = rand();
   //Sequence Number field is increment each time an Echo Request is sent
   sequenceNumber = osAtomicInc16(&pingSequenceNumber);

   //Format ICMP Echo Request message
   message->type = ICMP_TYPE_ECHO_REQUEST;
   message->code = 0;
   message->checksum = 0;
   message->identifier = identifier;
   message->sequenceNumber = sequenceNumber;

   //Copy data
   for(i = 0; i < PING_DATA_SIZE; i++)
      message->data[i] = i;

#if (IPV4_SUPPORT == ENABLED)
   //Target address is an IPv4 address?
   if(ipAddr->length == sizeof(Ipv4Addr))
   {
      Ipv4Addr srcIpAddr;

      //Select the source IPv4 address and the relevant network
      //interface to use when pinging the specified host
      error = ipv4SelectSourceAddr(&interface, ipAddr->ipv4Addr, &srcIpAddr);

      //Any error to report?
      if(error)
      {
         //Free previously allocated memory
         osMemFree(message);
         //Return the corresponding error code
         return error;
      }

      //ICMP Echo Request message
      message->type = ICMP_TYPE_ECHO_REQUEST;
      //Message checksum calculation
      message->checksum = ipCalcChecksum(message, length);

      //Open a raw socket
      socket = socketOpen(SOCKET_TYPE_RAW, SOCKET_PROTOCOL_ICMP);
   }
   else
#endif
#if (IPV6_SUPPORT == ENABLED)
   //Target address is an IPv6 address?
   if(ipAddr->length == sizeof(Ipv6Addr))
   {
      Ipv6PseudoHeader pseudoHeader;

      //Select the source IPv6 address and the relevant network
      //interface to use when pinging the specified host
      error = ipv6SelectSourceAddr(&interface, &ipAddr->ipv6Addr, &pseudoHeader.srcAddr);

      //Any error to report?
      if(error)
      {
         //Free previously allocated memory
         osMemFree(message);
         //Return the corresponding error code
         return error;
      }

      //ICMPv6 Echo Request message
      message->type = ICMPV6_TYPE_ECHO_REQUEST;
      //Format IPv6 pseudo header
      pseudoHeader.destAddr = ipAddr->ipv6Addr;
      pseudoHeader.length = htonl(length);
      pseudoHeader.reserved = 0;
      pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;

      //Message checksum calculation
      message->checksum = ipCalcUpperLayerChecksum(
         &pseudoHeader, sizeof(Ipv6PseudoHeader), message, length);

      //Open a raw socket
      socket = socketOpen(SOCKET_TYPE_RAW, SOCKET_PROTOCOL_ICMPV6);
   }
   else
#endif
   //Target address is not valid?
   {
      //Free previously allocated memory
      osMemFree(message);
      //Report an error
      return ERROR_INVALID_ADDRESS;
   }

   //Failed to open socket?
   if(!socket)
   {
      //Free previously allocated memory
      osMemFree(message);
      //Report an error
      return ERROR_OPEN_FAILED;
   }

   //Associate the newly created socket with the relevant interface
   error = socketBindToInterface(socket, interface);

   //Unable to bind the socket to the desired interface?
   if(error)
   {
      //Free previously allocated memory
      osMemFree(message);
      //Close socket
      socketClose(socket);
      //Return status code
      return error;
   }

   //Connect the socket to the target host
   error = socketConnect(socket, ipAddr, 0);

   //Any error to report?
   if(error)
   {
      //Free previously allocated memory
      osMemFree(message);
      //Close socket
      socketClose(socket);
      //Return status code
      return error;
   }

   //Send Echo Request message
   error = socketSend(socket, message, length, NULL, 0);

   //Failed to send message ?
   if(error)
   {
      //Free previously allocated memory
      osMemFree(message);
      //Close socket
      socketClose(socket);
      //Return status code
      return error;
   }

   //Save the time at which the request was sent
   startTime = osGetTickCount();

   //Timeout value exceeded?
   while((osGetTickCount() - startTime) < timeout)
   {
      //Adjust receive timeout
      error = socketSetTimeout(socket, timeout);
      //Any error to report?
      if(error) break;

      //Wait for an incoming ICMP message
      error = socketReceive(socket, message,
         sizeof(IcmpEchoMessage) + PING_DATA_SIZE, &length, 0);
      //Any error to report?
      if(error) break;

      //Check message length
      if(length != (sizeof(IcmpEchoMessage) + PING_DATA_SIZE))
         continue;
      //Verify message type
      if(ipAddr->length == sizeof(Ipv4Addr) && message->type != ICMP_TYPE_ECHO_REPLY)
         continue;
      if(ipAddr->length == sizeof(Ipv6Addr) && message->type != ICMPV6_TYPE_ECHO_REPLY)
         continue;
      //Response identifier matches request identifier?
      if(message->identifier != identifier)
         continue;
      //Make sure the sequence number is correct
      if(message->sequenceNumber != sequenceNumber)
         continue;

      //Loop through data field
      for(i = 0; i < PING_DATA_SIZE; i++)
      {
         //Compare received data against expected data
         if(message->data[i] != i) break;
      }

      //Valid Echo Reply message received?
      if(i == PING_DATA_SIZE)
      {
         //Calculate round-trip time
         roundTripTime = osGetTickCount() - startTime;
         //Debug message
         TRACE_INFO("Echo received (round-trip time = %ums)...\r\n", roundTripTime);

         //Free previously allocated memory
         osMemFree(message);
         //Close socket
         socketClose(socket);

         //Return round-trip time
         if(rtt) *rtt = roundTripTime;

         //No error to report
         return NO_ERROR;
      }
   }

   //Debug message
   TRACE_INFO("No echo received!\r\n");
   //Free previously allocated memory
   osMemFree(message);
   //Close socket
   socketClose(socket);

   //No Echo Reply received from host...
   return ERROR_NO_RESPONSE;
}
void tcpDiscardListenerTask(void *param)
{
   error_t error;
   uint16_t clientPort;
   IpAddr clientIpAddr;
   Socket *serverSocket;
   Socket *clientSocket;
   DiscardServiceContext *context;
   OsTask *task;

   //Point to the listening socket
   serverSocket = (Socket *) param;

   //Main loop
   while(1)
   {
      //Accept an incoming connection
      clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
      //Check whether a valid connection request has been received
      if(!clientSocket) continue;

      //Debug message
      TRACE_INFO("Discard service: connection established with client %s port %" PRIu16 "\r\n",
         ipAddrToString(&clientIpAddr, NULL), clientPort);

      //Adjust timeout
      error = socketSetTimeout(clientSocket, DISCARD_TIMEOUT);

      //Any error to report?
      if(error)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Allocate resources for the new connection
      context = osAllocMem(sizeof(DiscardServiceContext));

      //Failed to allocate memory?
      if(!context)
      {
         //Close socket
         socketClose(clientSocket);
         //Wait for an incoming connection attempt
         continue;
      }

      //Record the handle of the newly created socket
      context->socket = clientSocket;

      //Create a task to service the current connection
      task = osCreateTask("TCP Discard Connection", tcpDiscardConnectionTask,
         context, DISCARD_SERVICE_STACK_SIZE, DISCARD_SERVICE_PRIORITY);

      //Did we encounter an error?
      if(task == OS_INVALID_HANDLE)
      {
         //Close socket
         socketClose(clientSocket);
         //Release resources
         osFreeMem(context);
      }
   }
}