Beispiel #1
0
zbSize_t Mgmt_Direct_Join_req
(
  zbMgmtDirectJoinRequest_t *pMsgComingIn
)
{
  zdoNlmeMessage_t  *pZdoNlmeMsg;

#if ((gStandardSecurity_d || gHighSecurity_d) && gApsMaxEntriesForPermissionsTable_c)
  nlmeZdoMessage_t zdoMsg;
#endif

#if ((gStandardSecurity_d || gHighSecurity_d) && gApsMaxEntriesForPermissionsTable_c)
  if (!CommandHasPermission(NlmeGetRequest(gNwkShortAddress_c), gNetworkSettingsPermission_c))
  {
    zdoMsg.msgData.directJoinConf.status = gZdpNotAuthorized_c;
    Zdp_Mgmt_Direct_Join_conf((void *)&zdoMsg);
    return 0;
  }
#endif

  pZdoNlmeMsg = MSG_Alloc(MbrSizeof(zdoNlmeMessage_t, msgType) + sizeof(nlmeDirectJoinReq_t));

  if (pZdoNlmeMsg)
  {
    pZdoNlmeMsg->msgType = gNlmeDirectJoinRequest_c;

    FLib_MemCpy(&pZdoNlmeMsg->msgData.directJoinReq, pMsgComingIn, sizeof(nlmeDirectJoinReq_t));

    ZDO_SendEvent(gZdoEvent_ManagementCommand_c);

    (void)ZDO_NLME_SapHandler((void *)pZdoNlmeMsg);
  }

  return 0;
}
void ZDO_NwkManager
(
  nlmeZdoMessage_t *pZdoMsg  /*IN: Message received from ZDO*/
)
{

  nlmeJoinIndication_t  *pJoinIndication;
  uint8_t aNwkAddr[2];
  
  (void)aNwkAddr;
  gMemoryFreedByApplication = FALSE;
  switch (pZdoMsg->msgType)
  {

    /*************************************************************************************
      NLME-Formation.confirm: Formation confirm is only available for PAN Coordinator
      devices or combo devices acting like coordinator.
    **************************************************************************************/
    case gNlmeNetworkFormationConfirm_c:

#if ( gCoordinatorCapability_d || gComboDeviceCapability_d)

#if gComboDeviceCapability_d
      /*
        If a combo device is not acting like a PAN Coordinator should not do any further
        processing.
      */
      if (NlmeGetRequest(gDevType_c) != gCoordinator_c)
      {
        break;
      }
#endif

      /* Send an event to the ZDO state machine informing the fromation status. */
      if (pZdoMsg->msgData.networkFormationConf.status == gZbSuccess_c)
      {
        ZDO_SendEvent(gZdoEvent_FormationSuccess_c);
      }
      else
      {
        ZDO_SendEvent(gZdoEvent_FormationFailure_c);
      }
#endif
    break;

    /*************************************************************************************
      NLME-Discovery.confirm
    **************************************************************************************/
    case gNlmeNetworkDiscoveryConfirm_c:
      /*
        If the device is trying to associate it self to a PAN, the state machine changes
        to be on gZdoDiscoveringNetworksState_c.
      */
      if (ZDO_GetState() == gZdoDiscoveringNetworksState_c)
      {
        ZdoEvent_t event;
        /*
          The discovery information have already been stored by the NWK layer.
          Free up the confirm.
        */
        if(pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL)
        {
          MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor );
        }

        /* send an event to state machine task depending on the confirmation */
        event = (pZdoMsg->msgData.networkDiscoveryConf.status == gZbSuccess_c)? gZdoEvent_DiscoverySuccess_c : gZdoEvent_DiscoveryFailure_c;
        ZDO_SendEvent(event);

        /*
          Setting this variable to FALSE means that ZDO will free the message and not the
          application.
        */
        gMemoryFreedByApplication = FALSE;
        break;
      }

      /***********************************************************************************
        For any of this cases the tables does not need to be arround so lets free
        up the memory. IMPORTANT: The tables need to be freed to avoid memory leaks.
      ************************************************************************************/
      NWK_FreeUpDiscoveryTables();

      /*
        If the device is on running state this means that it may be the application the
        one commanding the discovery.
      */
      if(ZDO_IsRunningState())
      {
        /* Reprot the discovery information to hte application. */
        ( void ) ZDP_APP_SapHandler((zdpToAppMessage_t *)pZdoMsg);

        /*
          Setting this variable to TRUE means that the application is responsible of
          freeing the list inside the discovery message.
        */
        gMemoryFreedByApplication = TRUE;
      }

      /*
        Management commands prevent the ZDO stae machine for doing anything but finishing
        the process of the remote command.
      */
      else if (ZDO_GetState() == gZdoRemoteCommandsState_c)
      {
#if gMgmt_NWK_Disc_rsp_d
        /* Generate the response through zdpmanager */
        Zdp_Mgmt_Send_Nwk_disc_conf( pZdoMsg );
#endif
        ZDO_SendEvent(gZdoEvent_ManagementResponse_c);

        /*
          The information was copied in ZDP so the list inside the packet is no longer
          needed.
        */
        if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL)
        {
          MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor );
        }

        /*
          Setting this variable to FALSE means that all the buffers are free, no need to
          re-free it.
        */
        gMemoryFreedByApplication = FALSE;
      }

      
      else
      {
        /* Clean up the discovery tables in the stack */
        NWK_FreeUpDiscoveryTables();
        if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL)
        {
          MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor );
        }
        gMemoryFreedByApplication = FALSE;
      }
    break;

    /*************************************************************************************
      NLME-Join.confirm: We have join TO SOME ONE.
    **************************************************************************************/
    case gNlmeJoinConfirm_c:
#if gRouterCapability_d || gEndDevCapability_d || gComboDeviceCapability_d
      /*
        Make sure that the discovery tables have been freed after join request has been
        processed.
      */
      NWK_FreeUpDiscoveryTables();      

      /* If a combo device is not router or end device should not proceed. */
#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gCoordinator_c)
      {
        break;
      }
#endif

      /*
        If the device is already on running state the node may receive the unsolicited
        rejoin response because of and addressconflict, so ignore the join confirm.
      */
      if (ZDO_IsRunningState())
        break;

      /* If the device is not running then force it to parse the confirm. */
      ZDO_SetState(gZdoJoiningState_c);

      /* Send an event to the ZDO state machine informing about the joining state. */
      if( pZdoMsg->msgData.joinConf.status == gZbSuccess_c )
      {
        ZDO_SendEvent(gZdoEvent_JoinSuccess_c);
      }
      else
      {
        ZDO_SendEvent(gZdoEvent_JoinFailure_c);
      }
#endif
    break;

    /*************************************************************************************
      NLME-Join.indication: A device has join TO US.
    **************************************************************************************/
    case gNlmeJoinIndication_c:
      /*
        Do the casting for the message one time and in one place, Code saving.
      */
      pJoinIndication = &pZdoMsg->msgData.joinIndication;

      /*
        To avoid reject packets when the node join and comunicate multi ple times,
        the devices should flush the APS Duplicate table.
      */
      APS_RemoveEntryFromApsDuplicateTable(pJoinIndication->aShortAddress);

      /* Every child joined to us must be record, to avoid lossing it in case of reset. */
      ZdoNwkMng_SaveToNvm(zdoNvmObject_NeighborTable_c);

#if gRnplusCapability_d
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) != gEndDevice_c)
#endif
      {
        /* Remove the old routes to the joining device */
        RemoveRouteEntry(pJoinIndication->aShortAddress);
      }
#endif
#endif


#if gStandardSecurity_d || gHighSecurity_d
      /* If the joining device is associated from scratch erase previous data. */
      if (pJoinIndication->rejoinNetwork == gAssociationJoin_c)
      {
        if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c)
        {
          APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress);
        }
        else
        {
          APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress);
        }

        /* Setting the last parameter to TRUE will erase APS secure material */
        ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE);
      }
      /*
        If security is active and the joining mode is other that association join,
        no further processing should be done to the join indication.
        Consider the unsecure join.
      */
      //else if ((pJoinIndication->rejoinNetwork == gNwkRejoin_c) && pJoinIndication->secureRejoin)
      //{
        /* Make sure the memory will be freed */
        //gMemoryFreedByApplication = FALSE;

        /* Do not process it further, no transport key will be needed. */
        //return;
      //}
      else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c && !pJoinIndication->secureRejoin)
      {
        /* Reset the Incoming frame counter of the dev that has left. */
        /* Setting the last parameter to TRUE will erase APS secure material */
        if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c)
        {
          APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress);
        }
        else
        {
          APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress);
        }
        /* Setting the last parameter to TRUE will erase APS secure material */
        ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE);
      }

      /*
        The device must be set as Unauthenticated child in the NT.
      */
      SSP_NwkSetRelationship(pJoinIndication->aExtendedAddress, gUnAuthenticatedChild_c);

      /* Keep the buffer around to be use in the state machine or the application. */
      gMemoryFreedByApplication = TRUE;

/***************************************************
  Trust center specific join indication processing.
****************************************************/
#if gTrustCenter_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (gTrustCenter)
#endif
      {
        /*
          Keep the information, we are going to start the joining state machine.
        */
        MSG_Queue(&gJoinIndicationQueue, pZdoMsg);

        /*
          Tell the ZDO Task that we got a joining device packet and ready for action.
        */
        TS_SendEvent(gZdoTaskID_c, gJoinIndicationArrive_c);
      }
#endif

#if !gTrustCenter_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (!gTrustCenter)
#endif
      {
        uint8_t joiningType;
        bool_t  isHighSecurity = FALSE;
        /*
          Every other device with joining capabilities should report the joining,
          using an APSME-UPDATE-DEVICE.request.
        */
        isHighSecurity = (pJoinIndication->capabilityInformation & gSecurityCapability_c)? TRUE : FALSE;
        if (pJoinIndication->rejoinNetwork == gAssociationJoin_c)
        {
          joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredJoin_c : gStandardDeviceUnsecuredJoin_c;
        }
        else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c)
        {
          if (pJoinIndication->secureRejoin)
          {
            joiningType = (isHighSecurity)? gHighSecurityDeviceSecuredReJoin_c : gStandardDeviceSecuredReJoin_c;
          }
          else
          {
            joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredRejoin_c : gStandardDeviceUnsecuredRejoin_c;
          }
        }

        // Always send the update device
        ZDO_APSME_Update_Device_request(pJoinIndication->aExtendedAddress,
                                        pJoinIndication->aShortAddress,
                                        joiningType,
                                        pJoinIndication->secureRejoin);
        (void)ZDP_APP_SapHandler((void *)pZdoMsg);
      }
#endif

/* #endif gStandardSecurity_d */
#endif
    break; /*break for join indication*/

    /*************************************************************************************
      NLME-StartRouter.confirm: Every time that a Coordinator or a Router starts, genrates
      a start router confirm.
    **************************************************************************************/
    case gNlmeStartRouterConfirm_c:
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

      /* Combo devices acting like ZED don't need this confirm. */
#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

      /* Indicate router has started (or not) */
      if (pZdoMsg->msgData.startRouterConf.status == gZbSuccess_c)
      {
        ZDO_SendEvent(gZdoEvent_StartRouterSuccess_c);
      }
      else
      {
        ZDO_SendEvent(gZdoEvent_StartRouterFailure_c);
      }
#endif
    break;

    /*************************************************************************************
      NLME-Sync.confirm
    **************************************************************************************/
    case gNlmeSyncConfirm_c:
#if gEndDevCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) != gEndDevice_c)
      {
        break;
      }
#endif
      pZdoMsg->msgType = gSyncConf_c;
      ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );
      /* The application is responsible of freen the buffers. */
      gMemoryFreedByApplication = TRUE;
#endif
    break;

    /*************************************************************************************
      NLME-PermitJoining.confirm
    **************************************************************************************/
    case gNlmePermitJoiningConfirm_c:
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

      if(ZDO_IsRunningState())
      {
        /* let application know about the permit join */
        pZdoMsg->msgType = gPermitjoinConf_c;
        ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );

        /* indicate this SAP handler won't be freeing the memory */
        gMemoryFreedByApplication = TRUE;
      }

#endif
      break;

    /*************************************************************************************
      NLME-DirectJoin.confirm
    **************************************************************************************/
    case gNlmeDirectJoinConfirm_c:
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

      /*
        The may come because the network layer start the direct join and the confirm must
        be pass up to the application.
      */
      if (ZDO_IsRunningState())
      {
        /* Send message on to app. Tell this SAP handler not to free it. */
        (void) ZDP_APP_SapHandler( (void *)pZdoMsg );
        gMemoryFreedByApplication = TRUE;
      }

      else if (ZDO_GetState() == gZdoRemoteCommandsState_c)
      {
        ZDO_SendEvent(gZdoEvent_ManagementResponse_c);
#if gMgmt_Direct_Join_rsp_d && (gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d)
#if gComboDeviceCapability_d
        if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
        {
          break;
        }
#endif
        /* Generate the response through zdpmanager */
        Zdp_Mgmt_Direct_Join_conf( pZdoMsg );
        /* Update the global variable to free the menory */
        gMemoryFreedByApplication = TRUE;
#endif
      }

#endif
      break;

    /*************************************************************************************
      NLME-Leave.indication
    **************************************************************************************/
    case gNlmeLeaveIndication_c:

      /* The local node is the one leaving the network. */
      if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress))
      {
        /* Only important to the local leave. Pick an appropiated leaving event. */
        ZdoStopMode_t stopMode;

        /*
          Send event to ZDO state machine to initiate the reset procedure (r11, p272, ln31)
          The devices should not set the default mode to stop the node on a leave indication,
          the default mode send another leave.... and we just left.
        */
        stopMode = gZdoStopModeDefault_c | gZdoStopMode;
        if (pZdoMsg->msgData.leaveIndication.rejoin)
        {
          /* We will come back.! */
          stopMode |= gZdoStopMode_StopAndRestart_c;

          /* We are doing rejoin, we should not clear the tables. */
          stopMode &= ~gZdoStopMode_ResetTables_c;

        } /* End of if (pZdoMsg->msgData.leaveIndication.rejoin) */

        /* Tell ZDO to pull the breaks; */
        ZDO_StopEx(stopMode);
        break;
      } /* End of if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress)) */

      /* If we got the indiction and we are waiting for it, return to previous state. */
      if (ZDO_GetState() == gZdoRemoteCommandsState_c)
      {
        ZDO_SendEvent(gZdoEvent_ManagementResponse_c);
      }

#if gStandardSecurity_d || gHighSecurity_d
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

      /*
        Reset the Incoming frame counter of the dev that has left.
      */
      SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress );

      /*
        If the device is Link capable remove the link key information if it exists.
      */
      APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress);

      /*
        Let the trust center know about the leaving device.
      */
//      if (!IsSelfIeeeAddress(ApsmeGetRequest(gApsTrustCenterAddress_c)))
#if !gTrustCenter_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
       if (!gTrustCenter)
#endif
      
      {
        ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress,
                                        APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr),
                                        gDeviceLeft_c, 0x00);
      }
#endif      
#endif
#endif

     /* ZEDs dont porcess the removing of the children and removing of the routes. */
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d
#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

#if gRnplusCapability_d
      /* Remove the old routes for the leaving device */
      RemoveRouteEntry(APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr));
#endif

      /* Clean up address map if there is no bindings referencing address map entry
         consider deleting all bindings first.
       */
      (void)APS_RemoveDeviceFromAddressMap(pZdoMsg->msgData.leaveIndication.aDeviceAddress);

      /* Tells the network layer to remove the leaving device from its tables. */
      NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress);
#endif

      /*
        Save the network data, to preserve that the leaving device is gone. Plus the
        counters for security (NWK and APS)that got reset.
      */
      ZdoNwkMng_SaveToNvm(zdoNvmObject_All_c);
    break;

    /*************************************************************************************
      NLME-Leave.confirm
    **************************************************************************************/
    case gNlmeLeaveConfirm_c:
      /* If we have received a management leave request, send the response */
      if (ZDO_GetState() == gZdoRemoteCommandsState_c)
      {
#if gMgmt_Leave_rsp_d
        Zdp_Mgmt_Send_leave_conf(pZdoMsg);
        /* The momery has been handled by the next higher layer. */
        gMemoryFreedByApplication = TRUE;
#endif
        ZDO_SendEvent(gZdoEvent_ManagementResponse_c);
      }

      /* The local node is the one leaving the network. */
      if (Cmp8BytesToZero(pZdoMsg->msgData.leaveConf.aDeviceAddress))
      {
        /* The self leave is handle in the indication. */
        break;
      }

#if gStandardSecurity_d || gHighSecurity_d
#if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d

#if gComboDeviceCapability_d
      if (NlmeGetRequest(gDevType_c) == gEndDevice_c)
      {
        break;
      }
#endif

      /*
        Reset the Incoming frame counter of the dev that has left.
      */
      SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress );

      /*
        If the device is Link capable remove the link key information if it exists.
      */
      APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress);

      /*
        Let the trust center know about the leaving device.
      */
      ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress,
                                      APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr),
                                      gDeviceLeft_c, 0x00);

      /*
        Tells the network layer to remove the leaving device from its tables.
      */
      NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress);
#endif

/* #endif gStandardSecurity_d */
#endif
    break;

    /*************************************************************************************
      NLME-RouteDiscovery.confirm
    **************************************************************************************/
    case  gNlmeNetworkStatusCnf_c:
    case  gNlmeRouteDiscoveryCnf_c:
      /* This packet will be freed by the application*/
      gMemoryFreedByApplication = TRUE;
      /* Pass the packet to the App */
      ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );
    break;

    /*************************************************************************************
      NLME-EnergyScan.confirm: An Energy Scan Confirm has come back. Was it due to the
      forming process, or due to FA/ZDP.
    **************************************************************************************/
    case  gNlmeEnergyScanConfirm_c:           
      
      if(ZDO_GetState() == gZdoDiscoveringNetworksState_c)
      {
        if (pZdoMsg->msgData.EnergyScanConf.status == gZbSuccess_c)
        {
          ZDO_SendEvent(gZdoEvent_EnergyScanComplete_c);
        }
        else
        {
          ZDO_StopEx(gZdoStopModeDefault_c);
        }
      }

      /* Send to application layer */
      ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );

      /* Update the global variable to free the memory */
      gMemoryFreedByApplication = TRUE;
    break;

    case gNlmeNetworkStatusInd_c:
    case gNlmeTxReport_c:
      /* Send to application layer */
      ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );

      /* Update the global variable to free the memory */
      gMemoryFreedByApplication = TRUE;
    break;

    case gNwkProcessFrameConf_c:
#if gStandardSecurity_d || gHighSecurity_d
      /* Send to application layer */
      ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg );

      /* Update the global variable to free the memory */
      gMemoryFreedByApplication = TRUE;
#else
      gMemoryFreedByApplication = FALSE;
#endif
    break;

    default:
    break;
  } /* End of switch */
}