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