/* * Copyright (c) 2017, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "openthread-core-config.h" #include "fuzzer_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "mac/mac_frame.hpp" using namespace ot; typedef struct AlarmState { uint32_t fire; bool isRunning; } AlarmState; enum { IEEE802154_ACK_LENGTH = 5, IEEE802154_FRAME_TYPE_ACK = 2 << 0, }; static uint32_t sAlarmNow; static AlarmState sAlarmMilli; static AlarmState sAlarmMicro; static uint32_t sRandomState = 1; static uint8_t sRadioTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE]; static otRadioFrame sRadioTransmitFrame; static uint8_t sRadioAckPsdu[OT_RADIO_FRAME_MAX_SIZE]; static otRadioFrame sRadioAckFrame; static bool sResetWasRequested = false; static otRadioState sRadioState = OT_RADIO_STATE_DISABLED; bool otMacFrameIsAckRequested(const otRadioFrame *aFrame) { return static_cast(aFrame)->GetAckRequest(); } otError otMacFrameGetSequence(const otRadioFrame *aFrame, uint8_t *aSequence) { otError error; if (static_cast(aFrame)->IsSequencePresent()) { *aSequence = static_cast(aFrame)->GetSequence(); error = kErrorNone; } else { error = kErrorParse; } return error; } void FuzzerPlatformInit(void) { sRandomState = 1; sAlarmNow = 0; memset(&sAlarmMilli, 0, sizeof(sAlarmMilli)); memset(&sAlarmMicro, 0, sizeof(sAlarmMicro)); sRadioTransmitFrame.mPsdu = sRadioTransmitPsdu; sRadioAckFrame.mPsdu = sRadioAckPsdu; } void FuzzerPlatformProcess(otInstance *aInstance) { if (sRadioState == OT_RADIO_STATE_TRANSMIT) { sRadioState = OT_RADIO_STATE_RECEIVE; if (otMacFrameIsAckRequested(&sRadioTransmitFrame)) { otError error; sRadioAckFrame.mLength = IEEE802154_ACK_LENGTH; sRadioAckFrame.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK; sRadioAckFrame.mPsdu[1] = 0; error = otMacFrameGetSequence(&sRadioTransmitFrame, &sRadioAckFrame.mPsdu[2]); OT_ASSERT(error == OT_ERROR_NONE); sRadioAckFrame.mChannel = sRadioTransmitFrame.mChannel; otPlatRadioTxDone(aInstance, &sRadioTransmitFrame, &sRadioAckFrame, OT_ERROR_NONE); } else { otPlatRadioTxDone(aInstance, &sRadioTransmitFrame, nullptr, OT_ERROR_NONE); } } if (sAlarmMilli.isRunning || sAlarmMicro.isRunning) { uint32_t fire = UINT32_MAX; if (sAlarmMilli.isRunning && fire > sAlarmMilli.fire) { fire = sAlarmMilli.fire; } if (sAlarmMicro.isRunning && fire > sAlarmMicro.fire) { fire = sAlarmMicro.fire; } sAlarmNow = fire; if (sAlarmMilli.isRunning && sAlarmNow >= sAlarmMilli.fire) { sAlarmMilli.isRunning = false; otPlatAlarmMilliFired(aInstance); } #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE if (sAlarmMicro.isRunning && sAlarmNow >= sAlarmMicro.fire) { sAlarmMicro.isRunning = false; otPlatAlarmMicroFired(aInstance); } #endif } } bool FuzzerPlatformResetWasRequested(void) { return sResetWasRequested; } extern "C" { uint32_t otPlatAlarmMilliGetNow(void) { return sAlarmNow / 1000; } void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) { OT_UNUSED_VARIABLE(aInstance); sAlarmMilli.fire = (aT0 + aDt) * 1000; sAlarmMilli.isRunning = true; } void otPlatAlarmMilliStop(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sAlarmMilli.isRunning = false; } uint32_t otPlatAlarmMicroGetNow(void) { return sAlarmNow; } void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) { OT_UNUSED_VARIABLE(aInstance); sAlarmMicro.fire = aT0 + aDt; sAlarmMicro.isRunning = true; } void otPlatAlarmMicroStop(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sAlarmMicro.isRunning = false; } bool otDiagIsEnabled(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return false; } otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aArgsLength); OT_UNUSED_VARIABLE(aArgs); OT_UNUSED_VARIABLE(aOutput); OT_UNUSED_VARIABLE(aOutputMaxLen); return OT_ERROR_NOT_IMPLEMENTED; } otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aString); OT_UNUSED_VARIABLE(aOutput); OT_UNUSED_VARIABLE(aOutputMaxLen); return OT_ERROR_NOT_IMPLEMENTED; } void otPlatReset(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sResetWasRequested = true; } otPlatResetReason otPlatGetResetReason(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return OT_PLAT_RESET_REASON_POWER_ON; } OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) { OT_UNUSED_VARIABLE(aLogLevel); OT_UNUSED_VARIABLE(aLogRegion); OT_UNUSED_VARIABLE(aFormat); } void otPlatWakeHost(void) {} otError otPlatMultipanGetActiveInstance(otInstance **) { return OT_ERROR_NOT_IMPLEMENTED; } otError otPlatMultipanSetActiveInstance(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; } void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aIeeeEui64); } void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aPanId); } void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddr) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aExtAddr); } void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aShortAddress); } void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnabled) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aEnabled); } void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnabled) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aEnabled); } bool otPlatRadioIsEnabled(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return true; } otError otPlatRadioEnable(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sRadioState = OT_RADIO_STATE_SLEEP; return OT_ERROR_NONE; } otError otPlatRadioDisable(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sRadioState = OT_RADIO_STATE_DISABLED; return OT_ERROR_NONE; } otError otPlatRadioSleep(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); sRadioState = OT_RADIO_STATE_SLEEP; return OT_ERROR_NONE; } otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aChannel); sRadioState = OT_RADIO_STATE_RECEIVE; return OT_ERROR_NONE; } otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) { sRadioState = OT_RADIO_STATE_TRANSMIT; otPlatRadioTxStarted(aInstance, aFrame); return OT_ERROR_NONE; } otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aPower); return OT_ERROR_NONE; } otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return &sRadioTransmitFrame; } int8_t otPlatRadioGetRssi(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return 0; } otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return OT_RADIO_CAPS_NONE; } bool otPlatRadioGetPromiscuous(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return false; } void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aEnable); } otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aShortAddress); return OT_ERROR_NONE; } otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aExtAddress); return OT_ERROR_NONE; } otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aShortAddress); return OT_ERROR_NONE; } otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aExtAddress); return OT_ERROR_NONE; } void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); } void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); } otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aScanChannel); OT_UNUSED_VARIABLE(aScanDuration); return OT_ERROR_NOT_IMPLEMENTED; } otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aPower); return OT_ERROR_NOT_IMPLEMENTED; } otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aThreshold); return OT_ERROR_NOT_IMPLEMENTED; } otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aThreshold); return OT_ERROR_NOT_IMPLEMENTED; } int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return 0; } otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) { for (uint16_t length = 0; length < aOutputLength; length++) { aOutput[length] = (uint8_t)rand(); } return OT_ERROR_NONE; } void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aSensitiveKeys); OT_UNUSED_VARIABLE(aSensitiveKeysLength); } void otPlatSettingsDeinit(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); } otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aIndex); OT_UNUSED_VARIABLE(aValue); OT_UNUSED_VARIABLE(aValueLength); return OT_ERROR_NOT_FOUND; } otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aValue); OT_UNUSED_VARIABLE(aValueLength); return OT_ERROR_NONE; } otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aValue); OT_UNUSED_VARIABLE(aValueLength); return OT_ERROR_NONE; } otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aIndex); return OT_ERROR_NONE; } void otPlatSettingsWipe(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); } void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aCallback); OT_UNUSED_VARIABLE(aContext); } otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aArgsLength); OT_UNUSED_VARIABLE(aArgs); return OT_ERROR_INVALID_COMMAND; } void otPlatDiagModeSet(bool aMode) { OT_UNUSED_VARIABLE(aMode); } bool otPlatDiagModeGet(void) { return false; } void otPlatDiagChannelSet(uint8_t aChannel) { OT_UNUSED_VARIABLE(aChannel); } void otPlatDiagTxPowerSet(int8_t aTxPower) { OT_UNUSED_VARIABLE(aTxPower); } void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aFrame); OT_UNUSED_VARIABLE(aError); } void otPlatDiagAlarmCallback(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); } otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); return OT_PLAT_DNSSD_STOPPED; } void otPlatDnssdRegisterService(otInstance *aInstance, const otPlatDnssdService *aService, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aService); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } void otPlatDnssdUnregisterService(otInstance *aInstance, const otPlatDnssdService *aService, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aService); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } void otPlatDnssdRegisterHost(otInstance *aInstance, const otPlatDnssdHost *aHost, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aHost); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } void otPlatDnssdUnregisterHost(otInstance *aInstance, const otPlatDnssdHost *aHost, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aHost); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } void otPlatDnssdRegisterKey(otInstance *aInstance, const otPlatDnssdKey *aKey, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } void otPlatDnssdUnregisterKey(otInstance *aInstance, const otPlatDnssdKey *aKey, otPlatDnssdRequestId aRequestId, otPlatDnssdRegisterCallback aCallback) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKey); OT_UNUSED_VARIABLE(aRequestId); OT_UNUSED_VARIABLE(aCallback); } otError otPlatMdnsSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aEnable); OT_UNUSED_VARIABLE(aInfraIfIndex); return OT_ERROR_NOT_IMPLEMENTED; } void otPlatMdnsSendMulticast(otInstance *aInstance, otMessage *aMessage, uint32_t aInfraIfIndex) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aMessage); OT_UNUSED_VARIABLE(aInfraIfIndex); } void otPlatMdnsSendUnicast(otInstance *aInstance, otMessage *aMessage, const otPlatMdnsAddressInfo *aAddress) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aMessage); OT_UNUSED_VARIABLE(aAddress); } bool otPlatInfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress) { OT_UNUSED_VARIABLE(aInfraIfIndex); OT_UNUSED_VARIABLE(aAddress); return false; } otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex, const otIp6Address *aDestAddress, const uint8_t *aBuffer, uint16_t aBufferLength) { OT_UNUSED_VARIABLE(aInfraIfIndex); OT_UNUSED_VARIABLE(aDestAddress); OT_UNUSED_VARIABLE(aBuffer); OT_UNUSED_VARIABLE(aBufferLength); return OT_ERROR_FAILED; } otError otPlatInfraIfDiscoverNat64Prefix(uint32_t aInfraIfIndex) { OT_UNUSED_VARIABLE(aInfraIfIndex); return OT_ERROR_FAILED; } } // extern "C"