示例#1
0
void pal_encode_amp_assoc(FsmContext *context,
                          PalChannellist *connectedChannelList,
                          PalChannellist *preferredChannelList,
                          unifi_MACAddress *macAddress,
                          PAL_CoexCapabilities *capabilities,
                          CsrUint8 **data,
                          CsrUint16 *len)
{
    CsrUint8 *buffer;
    CsrUint8 i;
    USED_CHANNELS_LIST channelList;

    *data = CsrPmalloc(PAL_AMP_ASSOC_MAX_TOTAL_LENGTH); /* alloc memory big enough to hold the biggest assoc*/
    buffer = *data;
    sme_trace_entry((TR_PAL_LM_LINK_FSM,"encode_amp_assoc"));
    encode_amp_assoc_mac_address(&buffer,macAddress->data);

    CsrMemSet(&channelList, 0, sizeof(USED_CHANNELS_LIST));

    /* consider the preferred only if PAL has started the network (which means numChannels==1).
    * Otherwise regulatory domain can get the appropriate valid channel list
    */
    if (1 == preferredChannelList->numChannels)
    {
        channelList.listChangedFlag = TRUE;
        channelList.Dott11_b_g_ChanList[0].chan_scan_mode = channelScanMode_active;
        channelList.Dott11_b_g_ChanList[0].chan_number = preferredChannelList->number[0];
    }
    encode_amp_assoc_channel_list(context, &buffer, &channelList, AMP_ASSOC_PREFERRED_CHANNEL_LIST_TYPE);
    verify(TR_PAL_LM_LINK_FSM, (CsrUint16)(buffer-(*data))<=PAL_AMP_ASSOC_MAX_TOTAL_LENGTH);

    if (connectedChannelList && connectedChannelList->numChannels)
    {
        CsrMemSet(&channelList, 0, sizeof(USED_CHANNELS_LIST));
        channelList.listChangedFlag = TRUE;
        for (i=0; i<connectedChannelList->numChannels && i<HIGHEST_80211_b_g_CHANNEL_NUM; i++)
        {
            channelList.Dott11_b_g_ChanList[i].chan_scan_mode = channelScanMode_active;
            channelList.Dott11_b_g_ChanList[i].chan_number = connectedChannelList->number[i];
        }
        encode_amp_assoc_channel_list(context, &buffer,&channelList, AMP_ASSOC_CONNECTED_CHANNEL_TYPE);
        verify(TR_PAL_LM_LINK_FSM, (CsrUint16)(buffer-(*data))<=PAL_AMP_ASSOC_MAX_TOTAL_LENGTH);
    }
    encode_amp_assoc_capabilities(&buffer,capabilities);
    encode_amp_assoc_pal_version(&buffer);

    *len = (CsrUint16)(buffer-(*data));
    verify(TR_PAL_LM_LINK_FSM,*len <= PAL_AMP_ASSOC_MAX_TOTAL_LENGTH);
    sme_trace_info((TR_PAL_LM_LINK_FSM,"encode_amp_assoc:encoded %d bytes",*len));
}
示例#2
0
int main(int argc, char **argv)
{
    /* Create the Application Context */
    linuxContext = (LinuxUserSpaceContext*) CsrPmalloc(sizeof(LinuxUserSpaceContext));
    CsrMemSet(linuxContext, 0x00, sizeof(LinuxUserSpaceContext));

    linuxContext->mainData = (MainData*) CsrPmalloc(sizeof(MainData));
#ifdef IPC_IP
    getMainData(linuxContext)->ipIpcCon = NULL;
#endif
#ifdef IPC_CHARDEVICE
    getMainData(linuxContext)->charIpcCon = NULL;
#endif

    /* Set Trace levels from the command line */
    sme_trace_initialise((CsrUint32)argc, argv);

    /* Send the first trace message */
    sme_trace_entry((TR_STARTUP_SAP, "%s(%d)", __FUNCTION__, argc));

    /* Initialise SME and scheduling */
    sme_schedule_init(linuxContext, argc, argv);

    fsm_schedule(linuxContext);
    return 0;
}
示例#3
0
/* --------------------------------------------------------------------------
 *
 * Retrieves statistics on the operation of the payload manager subsystem
 */
void pld_get_stats(PldContext* context, PldStats *userStats)
{
    require(TR_PAYLOAD_MGR, userStats != NULL);
#ifdef SME_TRACE_ENABLE
#ifdef FSM_MUTEX_ENABLE
    (void)CsrMutexLock(context->payloadLock);
#endif
    CsrMemCpy(userStats, (void *)&context->stats, sizeof(context->stats));
#ifdef FSM_MUTEX_ENABLE
    (void)CsrMutexUnlock(context->payloadLock);
#endif
#else
    CsrMemSet(userStats, 0x00, sizeof(PldStats));
#endif
}
示例#4
0
void initKeyPair( CsrWpsContext *pCtx )
{
    CsrUint8 base[192];
    CsrInt32 i, j;
    CsrInt32 clear_bytes = (1536 - keylen) / 8;
    CsrInt32 clear_bits = (1536 - keylen) % 8;
    CsrUint8 bit_mask, mask;
    CsrUint32 length;

    CsrMemSet(base, 0, sizeof(base));
    base[191] = g;
    sme_trace_info((TR_SECURITY_LIB, "Private key length = %d", keylen));
    CsrWifiSecurityRandom(pCtx->ePrvKey, sizeof(pCtx->ePrvKey));

    for(i = 0; i < clear_bytes; i++)
    {
        pCtx->ePrvKey[i] = 0;
    }

    if(i < 192)
    {
        for(bit_mask = 0x80, j = 0; j < clear_bits; j++) /*lint !e681*/
        {
            bit_mask >>= 1;
        }

        for(mask = 0, j = clear_bits; j < 8; j++)
        {
            mask |= bit_mask;
            bit_mask >>= 1;
        }

        sme_trace_info((TR_SECURITY_LIB, "Private key bit mask = 0x%02x", mask));
        pCtx->ePrvKey[i] &= mask;
    }

    CsrCryptoModExp(base, sizeof(base),
                    pCtx->ePrvKey, sizeof(pCtx->ePrvKey),
                    prime, sizeof(prime),
                    pCtx->ePubKey,
                    &length);

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Enrollee Public Key", pCtx->ePubKey, sizeof(pCtx->ePubKey)));
    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Enrollee Private Key", pCtx->ePrvKey, sizeof(pCtx->ePrvKey)));
}
/*---------------------------------------------------------------------------*/
CsrUint8* ie_dot11n_generate_ht_cap_ie(
                    CsrUint8 *pbuf)
{
    sme_trace_debug((TR_IE_ACCESS, "ie_dot11n_generate_ht_cap_ie "));
    CsrMemSet(pbuf, 0, IE_HT_CAPABILITIES__TOTAL_SIZE);

    /*
    pbuf[IE_DOT11N_HT_CAP__ID_OFFSET] = IE_DOT11N_ID_HT_CAPABILITIES;
    pbuf[IE_DOT11N_HT_CAP__LENGTH_OFFSET] = (IE_HT_CAPABILITIES__TOTAL_SIZE-2); */ /* remove the header size */

    pbuf[0] = IE_DOT11N_ID_HT_CAPABILITIES;
    pbuf[1] = (IE_HT_CAPABILITIES__TOTAL_SIZE-2); /* remove the header size */

    /* REMINDER:
     * The firmware will populate this IE, we just allocate the space
     */

    sme_trace_hex((TR_IE_PRINT, TR_LVL_DEBUG, "    data", pbuf, IE_HT_CAPABILITIES__TOTAL_SIZE));

    return pbuf + IE_HT_CAPABILITIES__TOTAL_SIZE;
}
示例#6
0
/* --------------------------------------------------------------------------
 *
 * Initialises the payload manager subsystem.
 */
PldContext* pld_init(CsrUint16 tableSize, CsrUint16 maxPayloads)
{
    PldContext* context = (PldContext*)CsrPmalloc(sizeof(PldContext));

    sme_trace_entry((TR_PAYLOAD_MGR, "pld_init() maxPayloads %d", maxPayloads));

    /* Initialise the context */
#ifdef FSM_MUTEX_ENABLE
    (void)CsrMutexCreate(&context->payloadLock);
#endif
    csr_list_init(&context->payloads);
    context->payloadMax = maxPayloads;
    context->payloadCount = 0;
    context->lastHandle = 0; /* handle 0 should never be used */
    context->nextUsedHandle = PLDREFERENCEMASK;

#ifdef SME_TRACE_ENABLE
    CsrMemSet(&context->stats, 0, sizeof(context->stats));
    context->stats.maxPayloads = maxPayloads;
#endif

    return context;
}
/*
 * ---------------------------------------------------------------------------
 *  parse_xbv1
 *
 *      Scan the firmware file to find the TLVs we are interested in.
 *      Actions performed:
 *        - check we support the file format version in VERF
 *      Store these TLVs if we have a firmware image:
 *        - SLTP Symbol Lookup Table Pointer
 *        - FWDL firmware download segments
 *        - FWOL firmware overlay segment
 *        - VMEQ Register probe tests to verify matching h/w
 *      Store these TLVs if we have a patch file:
 *        - FWID the firmware build ID that this file patches
 *        - PTDL The actual patches
 *
 *      The structure pointed to by fwinfo is cleared and
 *      'fwinfo->mode' is set to 'unknown'.  The 'fwinfo->mode'
 *      variable is set to 'firmware' or 'patch' once we know which
 *      sort of XBV file we have.
 *
 *  Arguments:
 *      readfn          Pointer to function to call to read from the file.
 *      dlpriv          Opaque pointer arg to pass to readfn.
 *      fwinfo          Pointer to fwinfo struct to fill in.
 *
 *  Returns:
 *      CSR_RESULT_SUCCESS on success, CSR error code on failure
 * ---------------------------------------------------------------------------
 */
CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo)
{
    ct_t ct;
    tag_t tag;
    xbv_stack_t stack;

    ct.dlpriv = dlpriv;
    ct.ioffset = 0;
    ct.iread = readfn;

    CsrMemSet(fwinfo, 0, sizeof(xbv1_t));
    fwinfo->mode = xbv_unknown;

    /* File must start with XBV1 triplet */
    if (read_tag(card, &ct, &tag) <= 0)
    {
        unifi_error(NULL, "File is not UniFi firmware\n");
        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
    }

    DBG_TAG(tag.t_name);

    if (!TAG_EQ(tag.t_name, "XBV1"))
    {
        unifi_error(NULL, "File is not UniFi firmware (%s)\n", tag.t_name);
        return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
    }

    stack.ptr = 0;
    stack.s[stack.ptr].container = xbv_xbv1;
    stack.s[stack.ptr].ioffset_end = XBV_MAX_OFFS;

    /* Now scan the file */
    while (1)
    {
        CsrInt32 n;

        n = read_tag(card, &ct, &tag);
        if (n < 0)
        {
            unifi_error(NULL, "No tag\n");
            return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
        }
        if (n == 0)
        {
            /* End of file */
            break;
        }

        DBG_TAG(tag.t_name);

        /* File format version */
        if (TAG_EQ(tag.t_name, "VERF"))
        {
            CsrUint32 version;

            if (xbv_check(fwinfo, &stack, xbv_unknown, xbv_xbv1) ||
                (tag.t_len != 2) ||
                read_uint(card, &ct, &version, 2))
            {
                return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
            }
            if (version != 0)
            {
                unifi_error(NULL, "Unsupported firmware file version: %d.%d\n",
                            version >> 8, version & 0xFF);
                return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
            }
        }
示例#8
0
static void sme_schedule_init(LinuxUserSpaceContext* context, int argc, char **argv)
{
    CsrBool wifion = FALSE;
    CsrBool flightmode = FALSE;
    int i;
#ifdef IPC_IP
    CsrUint32 ipc_portNumber = PORT_NUMBER_Q;
#ifdef CSR_AMP_ENABLE
    CsrUint32 ipc_hciPortNumber = HCI_PORT_NUMBER_Q;
    CsrUint32 ipc_aclPortNumber = ACL_PORT_NUMBER_Q;
#endif
#endif

#ifdef IPC_CHARDEVICE
    const char* connectStr = CHAR_DEVICE_Q;
#endif

    sme_trace_entry((TR_FSM, "sme_schedule_init()"));


    CsrMemSet(&getMainData(linuxContext)->address, 0xFF, sizeof(unifi_MACAddress));
    getMainData(linuxContext)->mibfiles.numElements = 0;
    getMainData(linuxContext)->mibfiles.dataList = (unifi_DataBlock*)CsrPmalloc(sizeof(unifi_DataBlock) * MAX_MIB_FILES);
    getMainData(linuxContext)->calibrationDataFile = NULL;
    getMainData(linuxContext)->calibrationData.length = 0;
    getMainData(linuxContext)->calibrationData.data = NULL;
    getMainData(linuxContext)->nextCaldataSaveTime = fsm_get_time_of_day_ms(context->fsmContext) + CALDATA_SAVE_INTERVAL_MS;
    getMainData(linuxContext)->exitOnError = FALSE;
    getMainData(linuxContext)->stopOnError = FALSE;

#ifdef CSR_AMP_ENABLE
    context->palDataFsmContext = paldata_init(linuxContext);
    sme_install_wakeup_callback(context->palDataFsmContext, fsm_wakeup_callback);
#endif

    /* Initialise basic constructs used by the SME */
    context->fsmContext = sme_init(context, NULL);
    sme_install_wakeup_callback(context->fsmContext, fsm_wakeup_callback);

#ifdef CSR_WIFI_NME_ENABLE
    context->nmeFsmContext = csr_wifi_nme_init(linuxContext, NULL);
    csr_wifi_nme_install_wakeup_callback(context->nmeFsmContext, fsm_wakeup_callback);
#endif

#ifdef FSM_DEBUG
    fsm_install_on_transition_callback(context->fsmContext, fsm_on_transition_trace_callback);
    fsm_install_unhandled_event_callback(context->fsmContext, fsm_on_unhandled_trace_callback);
    fsm_install_save_event_callback(context->fsmContext, fsm_on_saved_trace_callback);
    fsm_install_invalid_event_callback(context->fsmContext, fsm_on_invalid_trace_callback);
    fsm_install_ignore_event_callback(context->fsmContext, fsm_on_ignored_trace_callback);

#ifdef CSR_WIFI_NME_ENABLE
    fsm_install_on_transition_callback(context->nmeFsmContext, nme_on_transition_trace_callback);
    fsm_install_unhandled_event_callback(context->nmeFsmContext, nme_on_unhandled_trace_callback);
    fsm_install_save_event_callback(context->nmeFsmContext, nme_on_saved_trace_callback);
    fsm_install_invalid_event_callback(context->nmeFsmContext, nme_on_invalid_trace_callback);
    fsm_install_ignore_event_callback(context->nmeFsmContext, nme_on_ignored_trace_callback);
#endif

#endif

    registerSignalHandlers();

    /* If no args print the usage incase the user does not know what the help option is */
    if (argc == 1)
    {
        print_usage();
    }

    for (i = 1; i < argc; i++) {

        if (CsrStrNCmp(argv[i], "-ipc_port:", 10) == 0)
        {
#ifdef IPC_IP
            ipc_portNumber = (CsrUint32)atoi(&argv[i][10]);
            sme_trace_info((TR_IPC, "sme_schedule_init() : IPC Port override -> %s :: %d", argv[i], ipc_portNumber));
#endif
            continue;
        }

#ifdef CSR_AMP_ENABLE
        if (CsrStrNCmp(argv[i], "-ipc_hciport:", 13) == 0)
        {
#ifdef IPC_IP
            ipc_hciPortNumber = (CsrUint32)atoi(&argv[i][13]);
            sme_trace_info((TR_IPC, "sme_schedule_init() : HCI IPC Port override -> %s :: %d", argv[i], ipc_hciPortNumber));
#endif
            continue;
        }

        if (CsrStrNCmp(argv[i], "-ipc_aclport:", 13) == 0)
        {
#ifdef IPC_IP
            ipc_aclPortNumber = (CsrUint32)atoi(&argv[i][13]);
            sme_trace_info((TR_IPC, "sme_schedule_init() : ACL IPC Port override -> %s :: %d", argv[i], ipc_aclPortNumber));
#endif
            continue;
        }
#endif

        /* TODO :: This is depricated... Remove! */
        if (CsrStrNCmp(argv[i], "-ipc_connect=", 13) == 0)
        {
#ifdef IPC_CHARDEVICE
            connectStr = &argv[i][13];
            sme_trace_crit((TR_IPC, "sme_schedule_init() : -ipc_connect option is depricated. DO NOT USE!"));
            sme_trace_info((TR_IPC, "sme_schedule_init() : IPC Connect String -> %s :: %s", argv[i], connectStr));
#endif
            continue;
        }

        if (CsrStrNCmp(argv[i], "-dev=", 5) == 0)
        {
#ifdef IPC_CHARDEVICE
            connectStr = &argv[i][5];
            sme_trace_info((TR_IPC, "sme_schedule_init() : char device -> %s :: %s", argv[i], connectStr));
#endif
            continue;
        }
        if (CsrStrNCmp(argv[i], "-paldatadev=", 12) == 0)
        {
            continue;
        }
#ifdef CSR_AMP_ENABLE
        if (CsrStrNCmp(argv[i], "-palselectchannel=", 18) == 0)
        {
            int len = CsrStrLen(argv[i]);
            char* str = (char*)CsrPmalloc(len);
            CsrMemCpy(str,&(argv[i][1]), len-1);
            str[len-1] = '\0';

            sme_trace_info((TR_IPC, "sme_schedule_init() : pal channel to select -> %s :: %d , len-%d,str-%s", argv[i], (CsrUint8)atoi(&argv[i][18]),len,str));
            unifi_dbg_cmd_req(context->fsmContext, str);
            continue;
        }

        if (CsrStrNCmp(argv[i], "-paldisableqos", 18) == 0)
        {
            int len = CsrStrLen(argv[i]);
            char* str = (char*)CsrPmalloc(len);
            CsrMemCpy(str,&(argv[i][1]), len-1);
            str[len-1] = '\0';

            sme_trace_info((TR_IPC, "sme_schedule_init() : disable qos to select -%s , len-%d,str-%s", argv[i],len,str));
            unifi_dbg_cmd_req(context->fsmContext, str);

            continue;
        }

        if (CsrStrNCmp(argv[i], "-paldisablesecurity", 18) == 0)
        {
            int len = CsrStrLen(argv[i]);
            char* str = (char*)CsrPmalloc(len);
            CsrMemCpy(str,&(argv[i][1]), len-1);
            str[len-1] = '\0';

            sme_trace_info((TR_IPC, "sme_schedule_init() : disable qos to select -%s", argv[i]));
            unifi_dbg_cmd_req(context->fsmContext, str);

            continue;
        }
#endif
        if (CsrStrNCmp(argv[i], "-flightmode", 11) == 0)
        {
            flightmode = TRUE;
            sme_trace_info((TR_IPC, "sme_schedule_init() : unifi_mgt_wifi_flightmode_req will be sent on connect -> %s", argv[i]));
            continue;
        }

        if (CsrStrNCmp(argv[i], "-wifion", 7) == 0)
        {
            wifion = TRUE;
            sme_trace_info((TR_IPC, "sme_schedule_init() : unifi_mgt_wifi_on_req will be sent on connect -> %s", argv[i]));
            continue;
        }

        if (CsrStrNCmp(argv[i], "-mac=", 5) == 0)
        {
            loadMacAddress(&argv[i][5], &getMainData(linuxContext)->address);
            sme_trace_info((TR_IPC, "sme_schedule_init() : macAddress file -> %s", argv[i]));
            sme_trace_info((TR_IPC, "sme_schedule_init() : macAddress -> %s", trace_unifi_MACAddress(getMainData(linuxContext)->address, getMainData(linuxContext)->traceMacAddressBuffer)));
            continue;
        }
        if (CsrStrNCmp(argv[i], "-mib=", 5) == 0)
        {
            loadMibfile(&argv[i][5], &getMainData(linuxContext)->mibfiles);
            sme_trace_info((TR_IPC, "sme_schedule_init() : mib file -> %s", argv[i]));
            continue;
        }
        if (CsrStrNCmp(argv[i], "-cal=", 5) == 0)
        {
            getMainData(linuxContext)->calibrationDataFile = &argv[i][5];
            (void)loadfile(getMainData(linuxContext)->calibrationDataFile, &getMainData(linuxContext)->calibrationData);
            sme_trace_info((TR_IPC, "sme_schedule_init() : cal file -> %s", getMainData(linuxContext)->calibrationDataFile));
            continue;
        }
        /* Skip -sme_trace:... as the sme trace module will handle these */
        if (CsrStrNCmp(argv[i], "-sme_trace:", 11) == 0)
        {
            continue;
        }

        if (CsrStrNCmp(argv[i], "-v", CsrStrLen(argv[i])) == 0)
        {
            print_versions();
            exit(EXIT_CODE_NORMAL_EXIT);
        }

        if (CsrStrNCmp(argv[i], "-exitOnError", CsrStrLen(argv[i])) == 0)
        {
            getMainData(linuxContext)->exitOnError = TRUE;
            continue;
        }

        if (CsrStrNCmp(argv[i], "-stopOnError", CsrStrLen(argv[i])) == 0)
        {
            getMainData(linuxContext)->stopOnError = TRUE;
            continue;
        }

        if (CsrStrNCmp(argv[i], "-h", CsrStrLen(argv[i])) == 0)
        {
            print_usage();
            exit(EXIT_CODE_WIFION_ERROR);
        }

        print_usage();
        sme_trace_error((TR_IPC, "error : Unknown commandline option : %s", argv[i]));
        exit(EXIT_CODE_WIFION_ERROR);
    }

#ifdef IPC_CHARDEVICE
    if (connectStr)
    {
        getMainData(context)->charIpcCon = ipc_chardevice_connect(connectStr, NULL, NULL, NULL, NULL);
        if (getMainData(context)->charIpcCon == NULL)
        {
            sme_trace_crit((TR_IPC, "sme_schedule_init() : char device connect to %s failed", connectStr));
            exit(EXIT_CODE_WIFION_ERROR);
        }
    }
#endif

#ifdef IPC_IP
    getMainData(context)->ipIpcCon = ipc_ip_create((int)ipc_portNumber, NULL, NULL, NULL, NULL);
    if (getMainData(context)->ipIpcCon == NULL)
    {
        sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_portNumber));
        exit(EXIT_CODE_WIFION_ERROR);
    }

#ifdef CSR_AMP_ENABLE
    getMainData(context)->ipHciIpcCon = ipc_ip_create((int)ipc_hciPortNumber, NULL, NULL, NULL, NULL);
    if (getMainData(context)->ipHciIpcCon == NULL)
    {
        sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_hciPortNumber));
        exit(EXIT_CODE_WIFION_ERROR);
    }
    getMainData(context)->ipAclIpcCon = ipc_ip_create((int)ipc_aclPortNumber, NULL, NULL, NULL, NULL);
    if (getMainData(context)->ipAclIpcCon == NULL)
    {
        sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_aclPortNumber));
        exit(EXIT_CODE_WIFION_ERROR);
    }
#endif

#endif

    if (getMainData(linuxContext)->calibrationData.length)
    {
        unifi_AppValue appValue;
        appValue.id = unifi_CalibrationDataValue;
        appValue.unifi_Value_union.calibrationData = getMainData(linuxContext)->calibrationData;
        unifi_mgt_claim_sync_access(linuxContext->fsmContext);
        (void)unifi_mgt_set_value(linuxContext->fsmContext, &appValue);
        unifi_mgt_release_sync_access(linuxContext->fsmContext);
    }

    if (flightmode)
    {
        unifi_mgt_wifi_flightmode_req(linuxContext->fsmContext, NULL,
                                      &getMainData(context)->address,
                                      getMainData(linuxContext)->mibfiles.numElements,
                                      getMainData(linuxContext)->mibfiles.dataList);

    }

    if (wifion)
    {
        /* Set the nextCaldataSaveTime to 1 minute from now */
        getMainData(linuxContext)->nextCaldataSaveTime = fsm_get_time_of_day_ms(context->fsmContext) + CALDATA_INITIAL_SAVE_INTERVAL_MS;
        unifi_mgt_wifi_on_req(linuxContext->fsmContext, NULL,
                              &getMainData(context)->address,
                              getMainData(linuxContext)->mibfiles.numElements,
                              getMainData(linuxContext)->mibfiles.dataList);
    }
}
CsrBool encode_pac_file(FastContext *fastContext)
{
    eapfast_pac_file_format *pac;
    CsrUint8 *decyphered_pac_data;
    CsrUint8 digest[CSR_SHA1_DIGEST_LENGTH];
    CsrUint8 *scan;
    CsrUint8 *data_len;
    CsrUint16 length;
    CsrInt32 rounded_length;
    CsrUint8 padding;
    CsrUint8 key[CSR_SHA1_DIGEST_LENGTH];
    CsrUint8 iv[EAPFAST_PAC_CYPHER_IV_LENGTH];
    CsrInt32 i;

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC_key", fastContext->tls.PAC_key, 32));
    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC_opaque", fastContext->PAC_opaque, fastContext->PAC_opaque_length));

    pac = (eapfast_pac_file_format *)CsrPmalloc(CSR_WIFI_SECURITY_MAX_PAC_LENGTH);
    fastContext->context->setupData.fast_pac = (CsrUint8 *)pac;

    pac->version = EAPFAST_PAC_FILE_VERSION;
    pac->defpasswd = 1; /* Using default password */
    CsrMemCpy(pac->magicNum, eapfastPacFileMagicLittleEndian, EAPFAST_PAC_FILE_MAGIC_LEN);
    pac->cypher[0] = 0; /* AES-CBC-128 */
    pac->cypher[1] = 1;
    if ((decyphered_pac_data = CsrPmalloc(MAX_PAC_DATA)) == NULL)
    {
        sme_trace_error((TR_SECURITY_LIB, "encode_pac_file() :: memory allocation error."));
        return FALSE;
    }

    scan = decyphered_pac_data;
    *scan++ = 0x80; /* Set known values */
    *scan++ = 0x0b;

    data_len = scan; /* Keep pointer to data_len to fill in later */
    scan += 2;

    *scan++ = 0x00;
    *scan++ = 0x01; /* PAC Key type */
    *scan++ = 0x00;
    *scan++ = 0x20; /* PAC Key length = 32 */
    CsrMemCpy(scan, fastContext->tls.PAC_key, 32);
    scan += 32;

    *scan++ = 0x00;
    *scan++ = 0x02; /* PAC Opaque type */
    *scan++ = (fastContext->PAC_opaque_length >> 8) & 0xff;
    *scan++ = fastContext->PAC_opaque_length & 0xff;
    CsrMemCpy(scan, fastContext->PAC_opaque, fastContext->PAC_opaque_length);
    scan += fastContext->PAC_opaque_length;

    length = (CsrUint16)(scan - decyphered_pac_data);
    *data_len++ = (length >> 8) & 0xff;
    *data_len++ = length & 0xff;

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: decyphered_pac_data", decyphered_pac_data, length));

    /* Compute the encryption MAC */
    CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL,
                      decyphered_pac_data, length, digest);
    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: Encryption MAC", digest, EAPFAST_CHECK_SUM_LEN));
    CsrMemCpy(pac->cyphermac, digest, EAPFAST_CHECK_SUM_LEN);

    sme_trace_info((TR_SECURITY_LIB, "encode_pac_file() :: Decyphered length = %d", length));

    /* Need to adjust the length to be a multiple of 128 bits before encoding */
    rounded_length = ((length + 16) / 16) * 16;
    sme_trace_info((TR_SECURITY_LIB, "encode_pac_file() :: Rounded up length = %d", rounded_length));

    /* Work out how many padding bytes are required */
    padding = (CsrUint8)(rounded_length - length);
    if (padding == 0) padding = 16;

    /* Append the padding bytes */
    scan = decyphered_pac_data + length;
    for (i = 0; i < padding; i++)
    {
        *scan++ = padding;
    }
    length += padding;

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: Padded decyphered_pac_data", decyphered_pac_data, length));

    CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL,
                          pacfile_defPasswd, 17, (CsrUint8 *)"ENC", 3, key);
    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: AES key", key, CSR_SHA1_DIGEST_LENGTH));
    /* AES CBC encode the decrypted PAC data */

    {
        CsrUint32 outLength;

        /* FIXME - the IV should be initialized to a random value */
        CsrMemSet(pac->iv, 0, EAPFAST_PAC_CYPHER_IV_LENGTH);
        /* Make a copy of the IV as the AES encrypt function will not preserve it */
        CsrMemCpy(iv, pac->iv, EAPFAST_PAC_CYPHER_IV_LENGTH);

        CsrCryptoAes128CbcEncrypt(key, iv,
                decyphered_pac_data, length, pac->blob, &outLength, PAD_MODE_TLS);
    }

    /* Adjust to the total length for the integritymac calculation */
    length += (sizeof(eapfast_pac_file_format) - 1);

    /* Zero the MAC before computing */
    CsrMemSet(pac->integritymac, 0, EAPFAST_CHECK_SUM_LEN);
    CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL,
                      fastContext->context->setupData.fast_pac, length, digest);
    CsrMemCpy(pac->integritymac, digest, EAPFAST_CHECK_SUM_LEN);

    fastContext->context->setupData.fast_pac_length = length;

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC", fastContext->context->setupData.fast_pac, length));

    return TRUE;
}
/*---------------------------------------------------------------------------*/
CsrBool decode_pac_file(FastContext *fastContext, char *password)
{
    CsrUint8 *decyphered_pac_data;
    CsrUint16 pac_length = 0;
    eapfast_pac_file_format *pac;
    CsrUint8 old_mac[EAPFAST_CHECK_SUM_LEN];
    CsrUint8 new_mac[CSR_SHA1_DIGEST_LENGTH];
    CsrUint16 blob_length;
    CsrUint8 key[CSR_SHA1_DIGEST_LENGTH];
    CsrBool ret_val;

    sme_trace_info((TR_SECURITY_LIB, "decode_pac_file() :: fast_pac_length = %d", fastContext->context->setupData.fast_pac_length));

    if(fastContext->context->setupData.fast_pac_length == 0)
    {
        return FALSE;
    }

    pac = (eapfast_pac_file_format *)(fastContext->context->setupData.fast_pac);

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "decode_pac_file() :: PAC", fastContext->context->setupData.fast_pac, fastContext->context->setupData.fast_pac_length));

    if ((decyphered_pac_data = CsrPmalloc(MAX_PAC_DATA)) == NULL)
    {
        sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: memory allocation error."));
        return FALSE;
    }

    pac_length = (CsrUint16)(fastContext->context->setupData.fast_pac_length);

    /* Sanity check the header. */
    if ((pac->version != EAPFAST_PAC_FILE_VERSION)
        || (pac->cypher[0] != 0)
        || (pac->cypher[1] != 1)
        /* accept both endian magic numbers, although Cisco APs seem to put out little endian */
        || ( (CsrMemCmp(pac->magicNum,
                     eapfastPacFileMagicLittleEndian,
                     EAPFAST_PAC_FILE_MAGIC_LEN) != 0) &&
             (CsrMemCmp(pac->magicNum,
                     eapfastPacFileMagicBigEndian,
                     EAPFAST_PAC_FILE_MAGIC_LEN) != 0) )
        || (pac_length < sizeof(eapfast_pac_file_format) + 8/* Minimum PAC TLV size */)
       )
    {
        sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: Bad PAC file header."));
        CsrPfree(decyphered_pac_data);
        return FALSE;
    }

    /* Check the file integrity MAC */
    CsrMemCpy(old_mac, pac->integritymac, 16);
    CsrMemSet(pac->integritymac, 0, 16);
    CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL,
                      fastContext->context->setupData.fast_pac, pac_length, new_mac);
    if (CsrMemCmp(old_mac, new_mac, 16) != 0)
    {
        sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: File Integrity MAC failure."));
        CsrPfree(decyphered_pac_data);
        return FALSE;
    }

    /* Calculate the encryption key - HMAC-SHA1(password, "ENC") */
    if ((pac->defpasswd) || (password==NULL))
    {
        CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL,
                pacfile_defPasswd, 17, (CsrUint8 *)"ENC", 3, key);
    }
    else
    {
        CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL,
                (CsrUint8 *)password, CsrStrLen(password), (CsrUint8 *)"ENC", 3, key);
    }

    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "decode_pac_file() :: AES key", key, CSR_SHA1_DIGEST_LENGTH));
    {
        CsrUint32 outLength;

        blob_length = pac_length - (sizeof(eapfast_pac_file_format) - 1);
        CsrCryptoAes128CbcDecrypt(key, pac->iv,
                pac->blob, blob_length, decyphered_pac_data, &outLength, PAD_MODE_TLS);
    }

    /* Drop the padding bytes from the blob_length as they are not part of the encryption MAC computation*/
    blob_length -= (CsrUint16)(decyphered_pac_data[blob_length - 1]);
    sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Decrypted blob", decyphered_pac_data, blob_length));

    /* Check the encryption MAC */
    CsrMemSet(new_mac, 0, CSR_SHA1_DIGEST_LENGTH);
    CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL,
                      decyphered_pac_data, blob_length, new_mac);

#if (EAPFAST_CHECK_SUM_LEN > CSR_SHA1_DIGEST_LENGTH)
#error Something gone wrong with the EAP-FAST constants!
#endif

    if (CsrMemCmp(pac->cyphermac, new_mac, EAPFAST_CHECK_SUM_LEN) != 0)
    {
        sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: Encryption MAC failure."));
        sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Supplied MAC", pac->cyphermac, EAPFAST_CHECK_SUM_LEN));
        sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Computed MAC", new_mac, EAPFAST_CHECK_SUM_LEN));
        CsrPfree(decyphered_pac_data);
        return FALSE;
    }
    /* decyphered_pac_data should now contain a complete PAC TLV */
    ret_val = parse_PAC_TLV(fastContext, decyphered_pac_data, blob_length);

    CsrPfree(decyphered_pac_data);

    return ret_val;
}