Example #1
0
error_t rawSocketReceiveEthPacket(Socket *socket,
   void *data, size_t size, size_t *received, uint_t flags)
{
   SocketQueueItem *queueItem;

   //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
   if(!(flags & SOCKET_FLAG_DONT_WAIT))
   {
      //The receive queue is empty?
      if(!socket->receiveQueue)
      {
         //Set the events the application is interested in
         socket->eventMask = SOCKET_EVENT_RX_READY;
         //Reset the event object
         osResetEvent(&socket->event);
         //Leave critical section
         osReleaseMutex(&socketMutex);
         //Wait until an event is triggered
         osWaitForEvent(&socket->event, socket->timeout);
         //Enter critical section
         osAcquireMutex(&socketMutex);
      }
   }

   //Check whether the read operation timed out
   if(!socket->receiveQueue)
   {
      //No data can be read
      *received = 0;
      //Report a timeout error
      return ERROR_TIMEOUT;
   }

   //Point to the first item in the receive queue
   queueItem = socket->receiveQueue;
   //Copy data to user buffer
   *received = netBufferRead(data, queueItem->buffer, queueItem->offset, size);

   //If the SOCKET_FLAG_PEEK flag is set, the data is copied
   //into the buffer but is not removed from the input queue
   if(!(flags & SOCKET_FLAG_PEEK))
   {
      //Remove the item from the receive queue
      socket->receiveQueue = queueItem->next;
      //Deallocate memory buffer
      netBufferFree(queueItem->buffer);
   }

   //Update the state of events
   rawSocketUpdateEvents(socket);

   //Successful read operation
   return NO_ERROR;
}
error_t pppSendEchoRep(PppContext *context,
                       const PppEchoPacket *echoReqPacket, PppProtocol protocol)
{
    error_t error;
    size_t length;
    size_t offset;
    NetBuffer *buffer;
    PppEchoPacket *echoRepPacket;

    //Retrieve the length of the Echo-Request packet
    length = ntohs(echoReqPacket->length);

    //Make sure the length is valid
    if(length < sizeof(PppEchoPacket))
        return ERROR_INVALID_LENGTH;
    if(length > context->peerConfig.mru)
        return ERROR_INVALID_LENGTH;

    //Allocate a buffer memory to hold the Echo-Reply packet
    buffer = pppAllocBuffer(sizeof(PppEchoPacket), &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the Echo-Reply packet
    echoRepPacket = netBufferAt(buffer, offset);

    //Format packet header
    echoRepPacket->code = PPP_CODE_CODE_REJ;
    echoRepPacket->identifier = echoReqPacket->identifier;
    echoRepPacket->length = htons(length);
    echoRepPacket->magicNumber = context->localConfig.magicNumber;

    //The data field of the Echo-Request packet is copied into the data
    //field of the Echo-Reply packet
    error = netBufferAppend(buffer, echoReqPacket->data, length - sizeof(PppEchoPacket));

    //Check status code
    if(!error)
    {
        //Debug message
        TRACE_INFO("Sending Echo-Reply packet (%" PRIuSIZE " bytes)...\r\n", length);

        //Send PPP frame
        error = pppSendFrame(context->interface, buffer, offset, protocol);
    }

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
error_t pppSendProtocolRej(PppContext *context, uint8_t identifier,
                           uint16_t protocol, const uint8_t *information, size_t length)
{
    error_t error;
    size_t offset;
    NetBuffer *buffer;
    PppProtocolRejPacket *protocolRejPacket;

    //Calculate the length of the Protocol-Reject packet
    length += sizeof(PppProtocolRejPacket);

    //The Rejected-Information must be truncated to comply with
    //the peer's established MRU
    length = MIN(length, context->peerConfig.mru);

    //Allocate a buffer memory to hold the Protocol-Reject packet
    buffer = pppAllocBuffer(sizeof(PppProtocolRejPacket), &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the Protocol-Reject packet
    protocolRejPacket = netBufferAt(buffer, offset);

    //Format packet header
    protocolRejPacket->code = PPP_CODE_PROTOCOL_REJ;
    protocolRejPacket->identifier = identifier;
    protocolRejPacket->length = htons(length);
    protocolRejPacket->rejectedProtocol = htons(protocol);

    //The Rejected-Information field contains a copy of the
    //packet which is being rejected
    error = netBufferAppend(buffer, information,
                            length - sizeof(PppProtocolRejPacket));

    //Check status code
    if(!error)
    {
        //Debug message
        TRACE_INFO("Sending Protocol-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);

        //Send PPP frame
        error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
    }

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
Example #4
0
error_t chapSendResponse(PppContext *context, const uint8_t *value)
{
   error_t error;
   size_t n;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   ChapResponsePacket *responsePacket;

   //Retrieve the length of the username
   n = strlen(context->username);
   //Calculate the length of the Response packet
   length = sizeof(ChapResponsePacket) + MD5_DIGEST_SIZE + n;

   //Allocate a buffer memory to hold the Response packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the Response packet
   responsePacket = netBufferAt(buffer, offset);

   //Format packet header
   responsePacket->code = CHAP_CODE_RESPONSE;
   responsePacket->identifier = context->chapFsm.peerIdentifier;
   responsePacket->length = htons(length);
   responsePacket->valueSize = MD5_DIGEST_SIZE;

   //Copy the Response value
   memcpy(responsePacket->value, value, MD5_DIGEST_SIZE);

   //The Name field is one or more octets representing the
   //identification of the system transmitting the packet
   memcpy(responsePacket->value + MD5_DIGEST_SIZE, context->username, n);

   //Debug message
   TRACE_INFO("Sending CHAP Response packet (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) responsePacket, length, PPP_PROTOCOL_CHAP);

   //Send PPP frame
   error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP);

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
error_t pppSendTerminateAck(PppContext *context,
                            uint8_t identifier, PppProtocol protocol)
{
    error_t error;
    size_t length;
    size_t offset;
    NetBuffer *buffer;
    PppTerminatePacket *terminateAckPacket;

    //Length of the Terminate-Ack packet
    length = sizeof(PppTerminatePacket);

    //Allocate a buffer memory to hold the Terminate-Ack packet
    buffer = pppAllocBuffer(length, &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the Terminate-Ack packet
    terminateAckPacket = netBufferAt(buffer, offset);

    //Format packet header
    terminateAckPacket->code = PPP_CODE_TERMINATE_ACK;
    terminateAckPacket->identifier = identifier;
    terminateAckPacket->length = htons(length);

    //Debug message
    TRACE_INFO("Sending Terminate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length);
    //Dump packet contents for debugging purpose
    pppDumpPacket((PppPacket *) terminateAckPacket, length, protocol);

    //Send PPP frame
    error = pppSendFrame(context->interface, buffer, offset, protocol);

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
Example #6
0
error_t chapSendFailure(PppContext *context)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppPacket *failurePacket;

   //Retrieve the length of the Failure packet
   length = sizeof(PppPacket);

   //Allocate a buffer memory to hold the Failure packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the Failure packet
   failurePacket = netBufferAt(buffer, offset);

   //Format packet header
   failurePacket->code = CHAP_CODE_FAILURE;
   failurePacket->identifier = context->chapFsm.localIdentifier;
   failurePacket->length = htons(length);

   //Debug message
   TRACE_INFO("Sending CHAP Failure packet (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) failurePacket, length, PPP_PROTOCOL_CHAP);

   //Send PPP frame
   error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP);

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #7
0
error_t udpSendDatagram(Socket *socket, const IpAddr *destIpAddr,
                        uint16_t destPort, const void *data, size_t length, size_t *written)
{
    error_t error;
    size_t offset;
    NetBuffer *buffer;

    //Allocate a memory buffer to hold the UDP datagram
    buffer = udpAllocBuffer(0, &offset);
    //Failed to allocate buffer?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Copy data payload
    error = netBufferAppend(buffer, data, length);

    //Successful processing?
    if(!error)
    {
        //Send UDP datagram
        error = udpSendDatagramEx(socket->interface, socket->localPort,
                                  destIpAddr, destPort, buffer, offset, socket->ttl);
    }

    //Successful processing?
    if(!error)
    {
        //Total number of data bytes successfully transmitted
        if(written != NULL)
            *written = length;
    }

    //Free previously allocated memory
    netBufferFree(buffer);
    //Return status code
    return error;
}
Example #8
0
error_t rawSocketSendEthPacket(Socket *socket,
   const void *data, size_t length, size_t *written)
{
   error_t error;
   uint32_t crc;
   NetBuffer *buffer;
   NetInterface *interface;

   //Select the relevant network interface
   if(!socket->interface)
      interface = netGetDefaultInterface();
   else
      interface = socket->interface;

   //Allocate a buffer memory to hold the raw Ethernet packet
   buffer = netBufferAlloc(0);
   //Failed to allocate buffer?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Copy the raw data
   error = netBufferAppend(buffer, data, length);

   //Successful processing?
   if(!error)
   {
      //Automatic padding not supported by hardware?
      if(!interface->nicDriver->autoPadding)
      {
         //The host controller should manually add padding
         //to the packet before transmitting it
         if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE))
         {
            //Add padding as necessary
            size_t n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length;

            //Append padding bytes
            error = netBufferAppend(buffer, ethPadding, n);
            //Any error to report?
            if(error) return error;

            //Adjust frame length
            length += n;
         }
      }
      //CRC generation not supported by hardware?
      if(!interface->nicDriver->autoCrcGen)
      {
         //Compute CRC over the header and payload
         crc = ethCalcCrcEx(buffer, 0, length);
         //Convert from host byte order to little-endian byte order
         crc = htole32(crc);

         //Append the calculated CRC value
         error = netBufferAppend(buffer, &crc, sizeof(crc));
         //Any error to report?
         if(error) return error;

         //Adjust frame length
         length += sizeof(crc);
      }

      //Debug message
      TRACE_DEBUG("Sending raw Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);

      //Send the resulting packet over the specified link
      error = nicSendPacket(interface, buffer, 0);
   }

   //Successful processing?
   if(!error)
   {
      //Total number of bytes successfully transmitted
      if(written != NULL)
         *written = length;
   }

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #9
0
error_t rawSocketSendIpPacket(Socket *socket, const IpAddr *destIpAddr,
   const void *data, size_t length, size_t *written)
{
   error_t error;
   size_t offset;
   uint_t timeToLive;
   NetBuffer *buffer;
   NetInterface *interface;
   IpPseudoHeader pseudoHeader;

   //The socket may be bound to a particular network interface
   interface = socket->interface;

   //Allocate a buffer memory to hold the raw IP datagram
   buffer = ipAllocBuffer(0, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Start of exception handling block
   do
   {
      //Copy the raw data
      error = netBufferAppend(buffer, data, length);
      //Any error to report?
      if(error) break;

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

         //Select the source IPv4 address and the relevant network interface
         //to use when sending data to the specified destination host
         error = ipv4SelectSourceAddr(&interface, destIpAddr->ipv4Addr, &srcIpAddr);
         //Any error to report?
         if(error) break;

         //Format IPv4 pseudo header
         pseudoHeader.length = sizeof(Ipv4PseudoHeader);
         pseudoHeader.ipv4Data.srcAddr = srcIpAddr;
         pseudoHeader.ipv4Data.destAddr = destIpAddr->ipv4Addr;
         pseudoHeader.ipv4Data.reserved = 0;
         pseudoHeader.ipv4Data.protocol = socket->protocol;
         pseudoHeader.ipv4Data.length = htons(length);

         //Set TTL value
         timeToLive = IPV4_DEFAULT_TTL;
      }
      else
#endif
#if (IPV6_SUPPORT == ENABLED)
      //Destination address is an IPv6 address?
      if(destIpAddr->length == sizeof(Ipv6Addr))
      {
         //Select the source IPv6 address and the relevant network interface
         //to use when sending data to the specified destination host
         error = ipv6SelectSourceAddr(&interface,
            &destIpAddr->ipv6Addr, &pseudoHeader.ipv6Data.srcAddr);

         //Any error to report?
         if(error) break;

         //Format IPv6 pseudo header
         pseudoHeader.length = sizeof(Ipv6PseudoHeader);
         pseudoHeader.ipv6Data.destAddr = destIpAddr->ipv6Addr;
         pseudoHeader.ipv6Data.length = htonl(length);
         pseudoHeader.ipv6Data.reserved = 0;
         pseudoHeader.ipv6Data.nextHeader = socket->protocol;

         //Set Hop Limit value
         timeToLive = IPV6_DEFAULT_HOP_LIMIT;
      }
      else
#endif
      //Invalid destination address?
      {
         //An internal error has occurred
         error = ERROR_FAILURE;
         //Exit immediately
         break;
      }

      //Send raw IP datagram
      error = ipSendDatagram(interface, &pseudoHeader, buffer, offset, timeToLive);
      //Failed to send data?
      if(error) break;

      //Total number of bytes successfully transmitted
      if(written != NULL)
         *written = length;

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

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #10
0
error_t mdnsSendAnnouncement(NetInterface *interface)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   DnsHeader *message;
   IpAddr destIpAddr;

   //Initialize error code
   error = NO_ERROR;

   //Allocate a memory buffer to hold the mDNS query message
   buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
   //Failed to allocate buffer?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the mDNS header
   message = netBufferAt(buffer, offset);

   //Format mDNS query message
   message->id = 0;
   message->qr = 1;
   message->opcode = DNS_OPCODE_QUERY;
   message->aa = 1;
   message->tc = 0;
   message->rd = 0;
   message->ra = 0;
   message->z = 0;
   message->rcode = DNS_RCODE_NO_ERROR;

   //Multicast DNS responses must not contain any questions
   message->qdcount = 0;
   message->ancount = 0;
   message->nscount = 0;
   message->arcount = 0;

   //Length of the mDNS query message
   length = sizeof(DnsHeader);

   //Start of exception handling block
   do
   {
      //Format A resource record
      error = mdnsAddIpv4ResourceRecord(interface, message, &length, TRUE);
      //Any error to report?
      if(error) break;

      //Format AAAA resource record
      error = mdnsAddIpv6ResourceRecord(interface, message, &length, TRUE);
      //Any error to report?
      if(error) break;

      //Convert 16-bit value to network byte order
      message->ancount = htons(message->ancount);

      //Adjust the length of the multi-part buffer
      netBufferSetLength(buffer, offset + length);

      //Debug message
      TRACE_INFO("Sending mDNS announcement (%" PRIuSIZE " bytes)...\r\n", length);
      //Dump message
      dnsDumpMessage(message, length);

#if (IPV4_SUPPORT == ENABLED)
      //Select the relevant multicast address (224.0.0.251)
      destIpAddr.length = sizeof(Ipv4Addr);
      destIpAddr.ipv4Addr = MDNS_IPV4_MULTICAST_ADDR;

      //All multicast DNS queries should be sent with an IP TTL set to 255
      error = udpSendDatagramEx(interface, MDNS_PORT, &destIpAddr,
         MDNS_PORT, buffer, offset, MDNS_DEFAULT_IP_TTL);
      //Any error to report?
      if(error)break;
#endif

#if (IPV6_SUPPORT == ENABLED)
      //Select the relevant multicast address (ff02::fb)
      destIpAddr.length = sizeof(Ipv6Addr);
      destIpAddr.ipv6Addr = MDNS_IPV6_MULTICAST_ADDR;

      //All multicast DNS queries should be sent with an IP TTL set to 255
      error = udpSendDatagramEx(interface, MDNS_PORT, &destIpAddr,
         MDNS_PORT, buffer, offset, MDNS_DEFAULT_IP_TTL);
      //Any error to report?
      if(error)break;
#endif

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

   //Free previously allocated memory
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #11
0
error_t mdnsSendProbe(NetInterface *interface)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   DnsHeader *message;
   DnsQuestion *dnsQuestion;
   IpAddr destIpAddr;

   //Initialize error code
   error = NO_ERROR;

   //Allocate a memory buffer to hold the mDNS query message
   buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
   //Failed to allocate buffer?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the mDNS header
   message = netBufferAt(buffer, offset);

   //Format mDNS query message
   message->id = 0;
   message->qr = 0;
   message->opcode = DNS_OPCODE_QUERY;
   message->aa = 0;
   message->tc = 0;
   message->rd = 0;
   message->ra = 0;
   message->z = 0;
   message->rcode = DNS_RCODE_NO_ERROR;

   //The mDNS query contains one question
   message->qdcount = HTONS(1);
   message->ancount = 0;
   message->nscount = 0;
   message->arcount = 0;

   //Length of the mDNS query message
   length = sizeof(DnsHeader);

   //Encode the host name using the DNS name notation
   length += mdnsEncodeName(interface->hostname, "",
      ".local", (uint8_t *) message + length);

   //Point to the corresponding question structure
   dnsQuestion = DNS_GET_QUESTION(message, length);
   //Fill in question structure
   dnsQuestion->qtype = HTONS(DNS_RR_TYPE_ANY);
   dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN);

   //Update the length of the mDNS query message
   length += sizeof(DnsQuestion);

   //Adjust the length of the multi-part buffer
   netBufferSetLength(buffer, offset + length);

   //Debug message
   TRACE_INFO("Sending mDNS probe (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump message
   dnsDumpMessage(message, length);

#if (IPV4_SUPPORT == ENABLED)
   //Check status code
   if(!error)
   {
      //Select the relevant multicast address (224.0.0.251)
      destIpAddr.length = sizeof(Ipv4Addr);
      destIpAddr.ipv4Addr = MDNS_IPV4_MULTICAST_ADDR;

      //All multicast DNS queries should be sent with an IP TTL set to 255
      error = udpSendDatagramEx(interface, MDNS_PORT, &destIpAddr,
         MDNS_PORT, buffer, offset, MDNS_DEFAULT_IP_TTL);
   }
#endif

#if (IPV6_SUPPORT == ENABLED)
   //Check status code
   if(!error)
   {
      //Select the relevant multicast address (ff02::fb)
      destIpAddr.length = sizeof(Ipv6Addr);
      destIpAddr.ipv6Addr = MDNS_IPV6_MULTICAST_ADDR;

      //All multicast DNS queries should be sent with an IP TTL set to 255
      error = udpSendDatagramEx(interface, MDNS_PORT, &destIpAddr,
         MDNS_PORT, buffer, offset, MDNS_DEFAULT_IP_TTL);
   }
#endif

   //Free previously allocated memory
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #12
0
void mdnsProcessQuery(NetInterface *interface, const IpPseudoHeader *pseudoHeader,
   const UdpHeader *udpHeader, const DnsHeader *query, size_t queryLen)
{
   error_t error;
   uint_t i;
   size_t pos;
   size_t offset;
   size_t responseLen;
   DnsHeader *response;
   NetBuffer *buffer;

   //Check the state of the mDNS responder
   if(interface->mdnsContext.state != MDNS_STATE_DONE)
      return;

   //Initialize error code
   error = NO_ERROR;

   //This buffer will hold the mDNS response, if any
   buffer = NULL;
   //Point to the first question
   pos = sizeof(DnsHeader);

   //Parse question section
   for(i = 0; i < ntohs(query->qdcount); i++)
   {
      size_t n;
      uint16_t qclass;
      uint16_t qtype;
      DnsQuestion *question;

      //Parse domain name
      n = dnsParseName(query, queryLen, pos, NULL, 0);

      //Invalid name?
      if(!n)
         break;
      //Malformed mDNS message?
      if((n + sizeof(DnsQuestion)) > queryLen)
         break;

      //Point to the corresponding entry
      question = DNS_GET_QUESTION(query, n);
      //Convert the query class to host byte order
      qclass = ntohs(question->qclass);
      //Discard QU flag
      qclass &= ~MDNS_QCLASS_QU;
      //Convert the query type to host byte order
      qtype = ntohs(question->qtype);

      //Check the class of the query
      if(qclass == DNS_RR_CLASS_IN || qclass == DNS_RR_CLASS_ANY)
      {
#if (DNS_SD_SUPPORT == ENABLED)
         //PTR query?
         if(qtype == DNS_RR_TYPE_PTR || qtype == DNS_RR_TYPE_ANY)
         {
            uint_t j;

            //Service type enumeration meta-query received?
            if(mdnsCompareName(query, queryLen, pos, "", "_services._dns-sd._udp", ".local", 0))
            {
               //Any registered services?
               if(interface->numServices > 0 && interface->instanceName != NULL)
               {
                  //Create a mDNS response message only if necessary
                  if(!buffer)
                  {
                     //Allocate the mDNS response message
                     buffer = mdnsCreateResponse(query->id, &offset, &response, &responseLen);
                     //Failed to allocate memory?
                     if(!buffer) break;
                  }

                  //Loop through registered services
                  for(j = 0; j < interface->numServices; j++)
                  {
                     //Format PTR resource record
                     error = dnsSdAddPtrResourceRecord(interface,
                        &interface->services[j], TRUE, response, &responseLen);
                     //Any error to report?
                     if(error) break;
                  }

                  //Propagate exception if necessary...
                  if(error) break;
               }
            }
            else
            {
               //Loop through registered services
               for(j = 0; j < interface->numServices; j++)
               {
                  //Compare service name
                  if(mdnsCompareName(query, queryLen, pos, "",
                     interface->services[j].name, ".local", 0))
                  {
                     //The current service name matches a registered service
                     break;
                  }
               }

               //Any matching service name?
               if(j < interface->numServices && interface->instanceName != NULL)
               {
                  //Create a mDNS response message only if necessary
                  if(!buffer)
                  {
                     //Allocate the mDNS response message
                     buffer = mdnsCreateResponse(query->id, &offset, &response, &responseLen);
                     //Failed to allocate memory?
                     if(!buffer) break;
                  }

                  //Format PTR resource record
                  error = dnsSdAddPtrResourceRecord(interface,
                     &interface->services[j], FALSE, response, &responseLen);
                  //Any error to report?
                  if(error) break;

                  //Format TXT resource record
                  error = dnsSdAddTxtResourceRecord(interface,
                     &interface->services[j], response, &responseLen);
                  //Any error to report?
                  if(error) break;

                  //Format SRV resource record
                  error = dnsSdAddSrvResourceRecord(interface,
                     &interface->services[j], response, &responseLen);
                  //Any error to report?
                  if(error) break;

                  //Format A resource record
                  error = mdnsAddIpv4ResourceRecord(interface,
                     response, &responseLen, FALSE);
                  //Any error to report?
                  if(error) break;

                  //Format AAAA resource record
                  error = mdnsAddIpv6ResourceRecord(interface,
                     response, &responseLen, FALSE);
                  //Any error to report?
                  if(error) break;
               }
            }
         }
         //SRV or TXT query?
         else if(qtype == DNS_RR_TYPE_SRV || qtype == DNS_RR_TYPE_TXT)
         {
            uint_t j;

            //Loop through registered services
            for(j = 0; j < interface->numServices; j++)
            {
               //Compare service name
               if(mdnsCompareName(query, queryLen, pos, interface->instanceName,
                  interface->services[j].name, ".local", 0))
               {
                  //The current service name matches a registered service
                  break;
               }
            }

            //Any matching service name?
            if(j < interface->numServices && interface->instanceName != NULL)
            {
               //Create a mDNS response message only if necessary
               if(!buffer)
               {
                  //Allocate the mDNS response message
                  buffer = mdnsCreateResponse(query->id, &offset, &response, &responseLen);
                  //Failed to allocate memory?
                  if(!buffer) break;
               }

               //Check query type?
               if(qtype == DNS_RR_TYPE_TXT)
               {
                  //Format TXT resource record
                  error = dnsSdAddTxtResourceRecord(interface,
                     &interface->services[j], response, &responseLen);
                  //Any error to report?
                  if(error) break;
               }
               else if(qtype == DNS_RR_TYPE_SRV)
               {
                  //Format SRV resource record
                  error = dnsSdAddSrvResourceRecord(interface,
                     &interface->services[j], response, &responseLen);
                  //Any error to report?
                  if(error) break;

                  //Format A resource record
                  error = mdnsAddIpv4ResourceRecord(interface,
                     response, &responseLen, FALSE);
                  //Any error to report?
                  if(error) break;

                  //Format AAAA resource record
                  error = mdnsAddIpv6ResourceRecord(interface,
                     response, &responseLen, FALSE);
                  //Any error to report?
                  if(error) break;
               }
            }
         }
#endif
#if (IPV4_SUPPORT == ENABLED)
         //A query?
#if (DNS_SD_SUPPORT == ENABLED)
         if(qtype == DNS_RR_TYPE_A)
#else
         if(qtype == DNS_RR_TYPE_A || qtype == DNS_RR_TYPE_ANY)
#endif
         {
            //Compare domain name
            if(mdnsCompareName(query, queryLen, pos, interface->hostname, "", ".local", 0))
            {
               //Create a mDNS response message only if necessary
               if(!buffer)
               {
                  //Allocate the mDNS response message
                  buffer = mdnsCreateResponse(query->id, &offset, &response, &responseLen);
                  //Failed to allocate memory?
                  if(!buffer) break;
               }

               //Format A resource record
               error = mdnsAddIpv4ResourceRecord(interface, response, &responseLen, FALSE);
               //Any error to report?
               if(error) break;
            }
         }
#endif
#if (IPV6_SUPPORT == ENABLED)
         //AAAA query?
#if (DNS_SD_SUPPORT == ENABLED)
         if(qtype == DNS_RR_TYPE_AAAA)
#else
         if(qtype == DNS_RR_TYPE_AAAA || qtype == DNS_RR_TYPE_ANY)
#endif
         {
            //Compare domain name
            if(mdnsCompareName(query, queryLen, pos, interface->hostname, "", ".local", 0))
            {
               //Create a mDNS response message only if necessary
               if(!buffer)
               {
                  //Allocate the mDNS response message
                  buffer = mdnsCreateResponse(query->id, &offset, &response, &responseLen);
                  //Failed to allocate memory?
                  if(!buffer) break;
               }

               //Format AAAA resource record
               error = mdnsAddIpv6ResourceRecord(interface, response, &responseLen, FALSE);
               //Any error to report?
               if(error) break;
            }
         }
#endif
      }

      //Point to the next question
      pos = n + sizeof(DnsQuestion);
   }

   //Any response to send?
   if(buffer != NULL)
   {
      //Check status code
      if(!error)
      {
         //Send mDNS response message
         mdnsSendResponse(interface, pseudoHeader, udpHeader,
            buffer, offset, responseLen);
      }

      //Free previously allocated memory
      netBufferFree(buffer);
   }
}
Example #13
0
error_t chapSendChallenge(PppContext *context)
{
   error_t error;
   size_t n;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   ChapChallengePacket *challengePacket;

   //Retrieve the length of the username
   n = strlen(context->username);
   //Calculate the length of the Challenge packet
   length = sizeof(ChapChallengePacket) + MD5_DIGEST_SIZE + n;

   //Allocate a buffer memory to hold the Challenge packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the Challenge packet
   challengePacket = netBufferAt(buffer, offset);

   //Format packet header
   challengePacket->code = CHAP_CODE_CHALLENGE;
   challengePacket->identifier = ++context->chapFsm.localIdentifier;
   challengePacket->length = htons(length);
   challengePacket->valueSize = MD5_DIGEST_SIZE;

   //Make sure that the callback function has been registered
   if(context->settings.randCallback != NULL)
   {
      //Generate a random challenge value
      error = context->settings.randCallback(
         context->chapFsm.challenge, MD5_DIGEST_SIZE);
   }
   else
   {
      //Report an error
      error = ERROR_FAILURE;
   }

   //Check status code
   if(!error)
   {
      //Copy the challenge value
      memcpy(challengePacket->value, context->chapFsm.challenge, MD5_DIGEST_SIZE);

      //The Name field is one or more octets representing the
      //identification of the system transmitting the packet
      memcpy(challengePacket->value + MD5_DIGEST_SIZE, context->username, n);

      //Debug message
      TRACE_INFO("Sending CHAP Challenge packet (%" PRIuSIZE " bytes)...\r\n", length);
      //Dump packet contents for debugging purpose
      pppDumpPacket((PppPacket *) challengePacket, length, PPP_PROTOCOL_CHAP);

      //Send PPP frame
      error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP);

      //The restart counter is decremented each time a Challenge packet is sent
      if(context->chapFsm.restartCounter > 0)
         context->chapFsm.restartCounter--;

      //Save the time at which the packet was sent
      context->chapFsm.timestamp = osGetSystemTime();
   }

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #14
0
error_t dnsSendQuery(DnsCacheEntry *entry)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   DnsHeader *message;
   DnsQuestion *dnsQuestion;
   IpAddr destIpAddr;

#if (IPV4_SUPPORT == ENABLED)
   //An IPv4 address is expected?
   if(entry->type == HOST_TYPE_IPV4)
   {
      //Select the relevant DNS server
      destIpAddr.length = sizeof(Ipv4Addr);
      ipv4GetDnsServer(entry->interface, entry->dnsServerNum, &destIpAddr.ipv4Addr);

      //Make sure the IP address is valid
      if(destIpAddr.ipv4Addr == IPV4_UNSPECIFIED_ADDR)
         return ERROR_NO_DNS_SERVER;
   }
   else
#endif
#if (IPV6_SUPPORT == ENABLED)
   //An IPv6 address is expected?
   if(entry->type == HOST_TYPE_IPV6)
   {
      //Select the relevant DNS server
      destIpAddr.length = sizeof(Ipv6Addr);
      ipv6GetDnsServer(entry->interface, entry->dnsServerNum, &destIpAddr.ipv6Addr);

      //Make sure the IP address is valid
      if(ipv6CompAddr(&destIpAddr.ipv6Addr, &IPV6_UNSPECIFIED_ADDR))
         return ERROR_NO_DNS_SERVER;
   }
   else
#endif
   //Invalid host type?
   {
      //Report an error
      return ERROR_INVALID_PARAMETER;
   }

   //Allocate a memory buffer to hold the DNS query message
   buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
   //Failed to allocate buffer?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the DNS header
   message = netBufferAt(buffer, offset);

   //Format DNS query message
   message->id = htons(entry->id);
   message->qr = 0;
   message->opcode = DNS_OPCODE_QUERY;
   message->aa = 0;
   message->tc = 0;
   message->rd = 1;
   message->ra = 0;
   message->z = 0;
   message->rcode = DNS_RCODE_NO_ERROR;

   //The DNS query contains one question
   message->qdcount = HTONS(1);
   message->ancount = 0;
   message->nscount = 0;
   message->arcount = 0;

   //Length of the DNS query message
   length = sizeof(DnsHeader);

   //Encode the host name using the DNS name notation
   length += dnsEncodeName(entry->name, message->questions);

   //Point to the corresponding question structure
   dnsQuestion = DNS_GET_QUESTION(message, length);

#if (IPV4_SUPPORT == ENABLED)
   //An IPv4 address is expected?
   if(entry->type == HOST_TYPE_IPV4)
   {
      //Fill in question structure
      dnsQuestion->qtype = HTONS(DNS_RR_TYPE_A);
      dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN);
   }
#endif
#if (IPV6_SUPPORT == ENABLED)
   //An IPv6 address is expected?
   if(entry->type == HOST_TYPE_IPV6)
   {
      //Fill in question structure
      dnsQuestion->qtype = HTONS(DNS_RR_TYPE_AAAA);
      dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN);
   }
#endif

   //Update the length of the DNS query message
   length += sizeof(DnsQuestion);

   //Adjust the length of the multi-part buffer
   netBufferSetLength(buffer, offset + length);

   //Debug message
   TRACE_INFO("Sending DNS message (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump message
   dnsDumpMessage(message, length);

   //Send DNS query message
   error = udpSendDatagramEx(entry->interface, entry->port,
      &destIpAddr, DNS_PORT, buffer, offset, 0);

   //Free previously allocated memory
   netBufferFree(buffer);
   //Return status code
   return error;
}
error_t pppSendConfigureAckNak(PppContext *context,
                               const PppConfigurePacket *configureReqPacket, PppProtocol protocol, PppCode code)
{
    error_t error;
    size_t length;
    size_t offset;
    NetBuffer *buffer;
    PppConfigurePacket *configureAckNakPacket;
    PppOption *option;

    //Initialize status code
    error = NO_ERROR;
    //Retrieve the length of the Configure-Request packet
    length = ntohs(configureReqPacket->length);

    //Allocate a buffer memory to hold the Configure-Ack, Nak or Reject packet
    buffer = pppAllocBuffer(length, &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the beginning of the packet
    configureAckNakPacket = netBufferAt(buffer, offset);

    //Format packet header
    configureAckNakPacket->code = code;
    configureAckNakPacket->identifier = configureReqPacket->identifier;
    configureAckNakPacket->length = sizeof(PppConfigurePacket);

    //Retrieve the length of the option list
    length -= sizeof(PppConfigurePacket);
    //Point to the first option
    option = (PppOption *) configureReqPacket->options;

    //Parse configuration options
    while(length > 0)
    {
        //LCP protocol?
        if(protocol == PPP_PROTOCOL_LCP)
        {
            //Parse LCP option
            lcpParseOption(context, option, length, configureAckNakPacket);
        }
#if (IPV4_SUPPORT)
        //IPCP protocol?
        else if(protocol == PPP_PROTOCOL_IPCP)
        {
            //Parse IPCP option
            ipcpParseOption(context, option, length, configureAckNakPacket);
        }
#endif

        //Remaining bytes to process
        length -= option->length;
        //Jump to the next option
        option = (PppOption *) ((uint8_t *) option + option->length);
    }

    //Adjust the length of the multi-part buffer
    netBufferSetLength(buffer, offset + configureAckNakPacket->length);
    //Convert length field to network byte order
    configureAckNakPacket->length = htons(configureAckNakPacket->length);

    //Debug message
    if(code == PPP_CODE_CONFIGURE_ACK)
    {
        TRACE_INFO("Sending Configure-Ack packet (%" PRIuSIZE " bytes)...\r\n",
                   ntohs(configureAckNakPacket->length));
    }
    else if(code == PPP_CODE_CONFIGURE_NAK)
    {
        TRACE_INFO("Sending Configure-Nak packet (%" PRIuSIZE " bytes)...\r\n",
                   ntohs(configureAckNakPacket->length));
    }
    else if(code == PPP_CODE_CONFIGURE_REJ)
    {
        TRACE_INFO("Sending Configure-Reject packet (%" PRIuSIZE " bytes)...\r\n",
                   ntohs(configureAckNakPacket->length));
    }

    //Dump packet contents for debugging purpose
    pppDumpPacket((PppPacket *) configureAckNakPacket,
                  ntohs(configureAckNakPacket->length), protocol);

    //Send PPP frame
    error = pppSendFrame(context->interface, buffer, offset, protocol);

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
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;
}
Example #17
0
error_t lcpSendConfigureReq(PppContext *context)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppConfigurePacket *configureReqPacket;

   //Debug message
   TRACE_INFO("LCP Send-Configure-Request callback\r\n");

   //Calculate the maximum size of the Configure-Request packet
   length = sizeof(PppConfigurePacket) +
      sizeof(LcpMruOption) + sizeof(LcpAccmOption);

   //Allocate a buffer memory to hold the packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Point to the Configure-Request packet
   configureReqPacket = netBufferAt(buffer, offset);

   //Format packet header
   configureReqPacket->code = PPP_CODE_CONFIGURE_REQ;
   configureReqPacket->identifier = ++context->lcpFsm.identifier;
   configureReqPacket->length = sizeof(PppConfigurePacket);

   //Make sure the Maximum-Receive-Unit option has not been previously rejected
   if(!context->localConfig.mruRejected)
   {
      //Convert MRU to network byte order
      uint16_t value = htons(context->localConfig.mru);
      //Add option
      pppAddOption(configureReqPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t));
   }

   //Make sure the Async-Control-Character-Map option has not been previously rejected
   if(!context->localConfig.accmRejected)
   {
      //Convert ACCM to network byte order
      uint32_t value = htonl(context->localConfig.accm);
      //Add option
      pppAddOption(configureReqPacket, LCP_OPTION_ACCM, &value, sizeof(uint32_t));
   }

   //Save packet length
   length = configureReqPacket->length;
   //Convert length field to network byte order
   configureReqPacket->length = htons(length);

   //Adjust the length of the multi-part buffer
   netBufferSetLength(buffer, offset + length);

   //Debug message
   TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_LCP);

   //Send PPP frame
   error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);

   //The restart counter is decremented each time a Configure-Request is sent
   if(context->lcpFsm.restartCounter > 0)
      context->lcpFsm.restartCounter--;

   //Save the time at which the packet was sent
   context->lcpFsm.timestamp = osGetSystemTime();

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
Example #18
0
error_t ipv4FragmentDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   uint16_t id, const NetBuffer *payload, size_t payloadOffset, uint8_t timeToLive)
{
   error_t error;
   size_t offset;
   size_t length;
   size_t payloadLength;
   size_t fragmentOffset;
   size_t maxFragmentSize;
   NetBuffer *fragment;

   //Retrieve the length of the payload
   payloadLength = netBufferGetLength(payload) - payloadOffset;

   //Allocate a memory buffer to hold IP fragments
   fragment = ipAllocBuffer(0, &fragmentOffset);
   //Failed to allocate memory?
   if(!fragment)
      return ERROR_OUT_OF_MEMORY;

   //Maximum payload size for fragmented packets
   maxFragmentSize = interface->ipv4Config.mtu - sizeof(Ipv4Header);
   //The size shall be a multiple of 8-byte blocks
   maxFragmentSize -= (maxFragmentSize % 8);

   //Split the payload into multiple IP fragments
   for(offset = 0; offset < payloadLength; offset += length)
   {
      //Flush the contents of the fragment
      error = netBufferSetLength(fragment, fragmentOffset);
      //Sanity check
      if(error) break;

      //Process the last fragment?
      if((payloadLength - offset) <= maxFragmentSize)
      {
         //Size of the current fragment
         length = payloadLength - offset;
         //Copy fragment data
         netBufferConcat(fragment, payload, payloadOffset + offset, length);

         //Do not set the MF flag for the last fragment
         error = ipv4SendPacket(interface, pseudoHeader, id,
            offset / 8, fragment, fragmentOffset, timeToLive);
      }
      else
      {
         //Size of the current fragment (must be a multiple of 8-byte blocks)
         length = maxFragmentSize;
         //Copy fragment data
         netBufferConcat(fragment, payload, payloadOffset + offset, length);

         //Fragmented packets must have the MF flag set
         error = ipv4SendPacket(interface, pseudoHeader, id,
            IPV4_FLAG_MF | (offset / 8), fragment, fragmentOffset, timeToLive);
      }

      //Failed to send current IP packet?
      if(error) break;
   }

   //Free previously allocated memory
   netBufferFree(fragment);
   //Return status code
   return error;
}