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;
}
Beispiel #3
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;
}
Beispiel #5
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;
}
Beispiel #6
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;
}
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;
}
Beispiel #8
0
error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   uint16_t fragId, uint16_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl)
{
   error_t error;
   size_t length;
   Ipv4Header *packet;

   //Is there enough space for the IPv4 header?
   if(offset < sizeof(Ipv4Header))
      return ERROR_INVALID_PARAMETER;

   //Make room for the header
   offset -= sizeof(Ipv4Header);
   //Calculate the size of the entire packet, including header and data
   length = netBufferGetLength(buffer) - offset;

   //Point to the IPv4 header
   packet = netBufferAt(buffer, offset);

   //Format IPv4 header
   packet->version = IPV4_VERSION;
   packet->headerLength = 5;
   packet->typeOfService = 0;
   packet->totalLength = htons(length);
   packet->identification = htons(fragId);
   packet->fragmentOffset = htons(fragOffset);
   packet->timeToLive = ttl;
   packet->protocol = pseudoHeader->protocol;
   packet->headerChecksum = 0;
   packet->srcAddr = pseudoHeader->srcAddr;
   packet->destAddr = pseudoHeader->destAddr;

   //Calculate IP header checksum
   packet->headerChecksum = ipCalcChecksumEx(buffer, offset, packet->headerLength * 4);

   //Ensure the source address is valid
   error = ipv4CheckSourceAddr(interface, pseudoHeader->srcAddr);
   //Invalid source address?
   if(error) return error;

   //Destination address is the unspecified address?
   if(pseudoHeader->destAddr == IPV4_UNSPECIFIED_ADDR)
   {
      //Destination address is not acceptable
      return ERROR_INVALID_ADDRESS;
   }
   //Destination address is the loopback address?
   else if(pseudoHeader->destAddr == IPV4_LOOPBACK_ADDR)
   {
      //Not yet implemented...
      return ERROR_NOT_IMPLEMENTED;
   }

#if (ETH_SUPPORT == ENABLED)
   //Ethernet interface?
   if(interface->nicDriver->type == NIC_TYPE_ETHERNET)
   {
      Ipv4Addr destIpAddr;
      MacAddr destMacAddr;

      //Destination address is a broadcast address?
      if(ipv4IsBroadcastAddr(interface, pseudoHeader->destAddr))
      {
         //Destination IPv4 address
         destIpAddr = pseudoHeader->destAddr;
         //Make use of the broadcast MAC address
         destMacAddr = MAC_BROADCAST_ADDR;
         //No error to report
         error = NO_ERROR;
      }
      //Destination address is a multicast address?
      else if(ipv4IsMulticastAddr(pseudoHeader->destAddr))
      {
         //Destination IPv4 address
         destIpAddr = pseudoHeader->destAddr;
         //Map IPv4 multicast address to MAC-layer multicast address
         error = ipv4MapMulticastAddrToMac(pseudoHeader->destAddr, &destMacAddr);
      }
      //Destination host is in the local subnet?
      else if(ipv4IsInLocalSubnet(interface, pseudoHeader->destAddr))
      {
         //Destination IPv4 address
         destIpAddr = pseudoHeader->destAddr;
         //Resolve host address before sending the packet
         error = arpResolve(interface, pseudoHeader->destAddr, &destMacAddr);
      }
      //Destination host is outside the local subnet?
      else
      {
         //Make sure the default gateway is properly set
         if(interface->ipv4Config.defaultGateway != IPV4_UNSPECIFIED_ADDR)
         {
            //Use the default gateway to forward the packet
            destIpAddr = interface->ipv4Config.defaultGateway;
            //Perform address resolution
            error = arpResolve(interface, interface->ipv4Config.defaultGateway, &destMacAddr);
         }
         else
         {
            //There is no route to the outside world...
            error = ERROR_NO_ROUTE;
         }
      }

      //Successful address resolution?
      if(!error)
      {
         //Debug message
         TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
         //Dump IP header contents for debugging purpose
         ipv4DumpHeader(packet);

         //Send Ethernet frame
         error = ethSendFrame(interface, &destMacAddr, buffer, offset, ETH_TYPE_IPV4);
      }
      //Address resolution is in progress?
      else if(error == ERROR_IN_PROGRESS)
      {
         //Debug message
         TRACE_INFO("Enqueuing IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
         //Dump IP header contents for debugging purpose
         ipv4DumpHeader(packet);

         //Enqueue packets waiting for address resolution
         error = arpEnqueuePacket(interface, destIpAddr, buffer, offset);
      }
      //Address resolution failed?
      else
      {
         //Debug message
         TRACE_WARNING("Cannot map IPv4 address to Ethernet address!\r\n");
      }
   }
   else
#endif
#if (PPP_SUPPORT == ENABLED)
   //PPP interface?
   if(interface->nicDriver->type == NIC_TYPE_PPP)
   {
      //Debug message
      TRACE_INFO("Sending IPv4 packet (%" PRIuSIZE " bytes)...\r\n", length);
      //Dump IP header contents for debugging purpose
      ipv4DumpHeader(packet);

      //Send PPP frame
      error = pppSendFrame(interface, buffer, offset, PPP_PROTOCOL_IP);
   }
   else
#endif
   //Unknown interface type?
   {
      //Report an error
      error = ERROR_INVALID_INTERFACE;
   }

   //Return status code
   return error;
}
Beispiel #9
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;
}